From c72b57f08c039f2f7309c5eec753010cd46f6ff5 Mon Sep 17 00:00:00 2001 From: Milla J <232237854+milla-jovovich@users.noreply.github.com> Date: Fri, 22 May 2026 15:10:38 -0700 Subject: [PATCH 1/4] chore(deps): add hypothesis + pre-commit to dev deps + document local hook activation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds two test-discipline tools to the dev extras and closes a real contributor-onboarding gap in CONTRIBUTING.md that allowed PR #1579's 2026-05-22 4 AM ruff-version-mismatch lint failure. Adds to ``[project.optional-dependencies].dev`` (and matching ``[dependency-groups].dev`` for uv users): - **``hypothesis>=6.0``** — property-based testing framework. Generates hundreds of random inputs per test and shrinks failing cases to a minimal counterexample. Used opt-in (sprinkle ``@given(...)`` on a test); zero runtime cost on tests that don't use it. Would have caught the Tier 6a dateutil-fuzzy hallucination on PR #1584 with one property test. - **``pre-commit>=3.0``** — the pre-commit framework itself. ``.pre-commit-config.yaml`` already lives in the repo (committed by @igorls on 2026-05-18, pinned to ruff 0.15.9 in lockstep with CI). What was missing was making the framework a declared dev dependency so ``pip install -e .[dev]`` / ``uv sync --extra dev`` actually pulls it in. Adds a ``pre-commit install`` line to the Getting Started bash block plus a short paragraph explaining why this step is required (the hook file at ``.git/hooks/pre-commit`` is per-machine and NOT tracked by git, so the repo's ``.pre-commit-config.yaml`` only takes effect after each developer runs ``pre-commit install`` once locally). Adds an optional "Property-based tests" subsection under Running Tests showing the minimal ``@given(...)`` pattern, so contributors who want to reach for the new tool know it's available. On 2026-05-22 at 4:30 AM, PR #1579 (Tier 6a) hit a CI lint failure caused by a ruff version mismatch: my local machine had ruff 0.4.10, CI runs ruff 0.15.9 (pinned in pyproject.toml). The two versions produce different ``ruff format`` output for the same code. The repo HAD ``.pre-commit-config.yaml`` pinning ruff 0.15.9 — but the local git hook had never been wired on my machine because nothing in CONTRIBUTING.md said to run ``pre-commit install``. The protection existed at the project layer; the activation gap was at the contributor-onboarding layer. This commit closes that gap structurally. Anyone cloning the repo from now on sees ``pre-commit install`` as part of the Getting Started flow and is protected from the same failure. - **No ``mutmut`` in dev deps.** Mutation testing is heavier (runs the whole test suite per mutation) and useful periodically rather than every commit. Contributors who want to run it can install manually. Adding it to dev deps would bloat the install footprint for every contributor when most will never use it. - **No new property tests.** This PR ships the TOOL, not new test coverage. Property tests should land alongside the specific functions they cover, in their own PRs. - **No changes to ``.pre-commit-config.yaml``.** That file is correct as Igor wrote it. The fix here is purely making the framework installable + documenting the activation step. ruff check . → All checks passed. pre-commit run --all-files (locally) → ruff (legacy alias): Passed → ruff format: Passed OrbStack triple-Linux verify (Py 3.9 / 3.11 / 3.13) → ``pip install -e .[dev]`` resolves cleanly; hypothesis + pre_commit import successfully; existing test suite unaffected. --- CONTRIBUTING.md | 27 +++++++++++++++++++++++++++ pyproject.toml | 28 ++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 440ab00cd2..d19339c66e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,8 +15,18 @@ uv sync --extra dev # Or with pip in your own venv: # pip install -e ".[dev]" + +# Activate pre-commit hooks (one-time, per clone) +pre-commit install ``` +The `pre-commit install` step is important: the repo has a +`.pre-commit-config.yaml` that pins ruff to the exact version CI uses, +but the actual git hook is per-machine and **must be installed +locally**. Without this step, you can commit code that passes your +local lint (using whatever ruff version you happen to have installed) +but fails CI on push. + ## Running Tests ```bash @@ -25,6 +35,23 @@ uv run pytest tests/ -v All tests must pass before submitting a PR. Tests should run without API keys or network access. +### Property-based tests (optional) + +`hypothesis` is available in the dev extras for property-based tests: + +```python +from hypothesis import given, strategies as st + +@given(st.text(min_size=1, max_size=40)) +def test_function_never_fabricates_output_on_random_input(s): + # ... property that must hold for ANY string in the strategy +``` + +Hypothesis generates hundreds of inputs per test and shrinks failing +cases to a minimal counterexample. Useful any time a function returns +`Optional[X]` or has a wide input domain — it catches the failure-space +gaps that hand-written positive tests miss. + ## Running Benchmarks ```bash diff --git a/pyproject.toml b/pyproject.toml index 703d954fc7..5a3f711093 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,24 @@ chroma = "mempalace.backends.chroma:ChromaBackend" [project.entry-points."mempalace.sources"] [project.optional-dependencies] -dev = ["pytest>=7.0", "pytest-cov>=4.0", "ruff==0.15.14", "psutil>=5.9"] +dev = [ + "pytest>=7.0", + "pytest-cov>=4.0", + "ruff==0.15.14", + "psutil>=5.9", + # Property-based testing — generates thousands of random inputs to + # find counterexamples the hand-written positive tests miss. Used + # opt-in (sprinkle ``@given(...)`` on a test); zero runtime cost on + # tests that don't use it. + "hypothesis>=6.0", + # Pre-commit framework — gates every local ``git commit`` on the + # same ruff checks CI runs. Required activation step in + # CONTRIBUTING.md: ``pre-commit install`` once per clone. Without + # this, contributors silently bypass the lint gate locally and only + # discover the failure at CI time (which caused the 4 AM + # ruff-version-mismatch on PRs #1579 / #1584 on 2026-05-22). + "pre-commit>=3.0", +] spellcheck = ["autocorrect>=2.0"] # Hardware acceleration for the ONNX embedding model. Install exactly one: # pip install mempalace[gpu] — NVIDIA CUDA @@ -85,7 +102,14 @@ extract = [ ] [dependency-groups] -dev = ["pytest>=7.0", "pytest-cov>=4.0", "ruff==0.15.14", "psutil>=5.9"] +dev = [ + "pytest>=7.0", + "pytest-cov>=4.0", + "ruff==0.15.14", + "psutil>=5.9", + "hypothesis>=6.0", + "pre-commit>=3.0", +] [build-system] requires = ["hatchling"] From e3f9cea3a0fc436f4e90f9805565f4efe6b75afb Mon Sep 17 00:00:00 2001 From: Milla J <232237854+milla-jovovich@users.noreply.github.com> Date: Fri, 22 May 2026 16:28:13 -0700 Subject: [PATCH 2/4] chore(deps): add mypy>=1.0 for static type checking (closes type-hint gap caught by gemini on PR #1588) --- pyproject.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 5a3f711093..9dabb029d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,6 +75,15 @@ dev = [ # discover the failure at CI time (which caused the 4 AM # ruff-version-mismatch on PRs #1579 / #1584 on 2026-05-22). "pre-commit>=3.0", + # mypy — static type checker. Catches lazy ``list`` / ``dict`` + # annotations that should be ``list[str]`` / ``dict[str, int]``, + # missing return types, mismatched signatures across call sites. + # Run ad-hoc with ``mypy mempalace/``; CI doesn't gate on it yet but + # contributors should fix mypy errors they see before pushing. Closes + # the type-hint specificity bug class gemini-code-assist flagged on + # PR #1588 (2026-05-22) — ``drawer_ids: list`` → ``list[str]``, + # ``-> list:`` → ``-> list[DrawerCandidate]:``. + "mypy>=1.0", ] spellcheck = ["autocorrect>=2.0"] # Hardware acceleration for the ONNX embedding model. Install exactly one: @@ -109,6 +118,7 @@ dev = [ "psutil>=5.9", "hypothesis>=6.0", "pre-commit>=3.0", + "mypy>=1.0", ] [build-system] From 2547a514d9b2ee510d4539f3f99375f89df3fc58 Mon Sep 17 00:00:00 2001 From: Milla J <232237854+milla-jovovich@users.noreply.github.com> Date: Fri, 22 May 2026 16:38:55 -0700 Subject: [PATCH 3/4] chore(deps): drop ephemeral PR refs from comments (address PR #1590 Igor review) --- pyproject.toml | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9dabb029d9..a398417c4e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,26 +63,22 @@ dev = [ "pytest-cov>=4.0", "ruff==0.15.14", "psutil>=5.9", - # Property-based testing — generates thousands of random inputs to - # find counterexamples the hand-written positive tests miss. Used - # opt-in (sprinkle ``@given(...)`` on a test); zero runtime cost on - # tests that don't use it. + # Property-based testing — generates hundreds of random inputs per + # test to find counterexamples the hand-written positive tests miss. + # Used opt-in (sprinkle ``@given(...)`` on a test); zero runtime + # cost on tests that don't use it. "hypothesis>=6.0", # Pre-commit framework — gates every local ``git commit`` on the # same ruff checks CI runs. Required activation step in # CONTRIBUTING.md: ``pre-commit install`` once per clone. Without # this, contributors silently bypass the lint gate locally and only - # discover the failure at CI time (which caused the 4 AM - # ruff-version-mismatch on PRs #1579 / #1584 on 2026-05-22). + # discover failures at CI time. "pre-commit>=3.0", # mypy — static type checker. Catches lazy ``list`` / ``dict`` # annotations that should be ``list[str]`` / ``dict[str, int]``, # missing return types, mismatched signatures across call sites. # Run ad-hoc with ``mypy mempalace/``; CI doesn't gate on it yet but - # contributors should fix mypy errors they see before pushing. Closes - # the type-hint specificity bug class gemini-code-assist flagged on - # PR #1588 (2026-05-22) — ``drawer_ids: list`` → ``list[str]``, - # ``-> list:`` → ``-> list[DrawerCandidate]:``. + # contributors should fix mypy errors they see before pushing. "mypy>=1.0", ] spellcheck = ["autocorrect>=2.0"] From 4655a3037a1dcccef0ee4651c5472c96a4905fdf Mon Sep 17 00:00:00 2001 From: Igor Lins e Silva <4753812+igorls@users.noreply.github.com> Date: Sat, 23 May 2026 12:11:10 -0300 Subject: [PATCH 4/4] =?UTF-8?q?chore(pre-commit):=20bump=20ruff=20pin=20v0?= =?UTF-8?q?.15.9=20=E2=86=92=20v0.15.14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lock-step with pyproject.toml `[project.optional-dependencies].dev` (ruff bumped from 0.15.9 → 0.15.14 via PR #1583). The `.pre-commit-config.yaml` header explicitly requires this rev to match the pyproject pin — without this bump, contributors who run `pre-commit install` will hit the same version-mismatch debacle this PR was opened to prevent. --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b413e1c149..3d6d4f9ba4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: # ([project.optional-dependencies].dev / [dependency-groups].dev) and # .github/workflows/ci.yml. A different ruff here produces different # formatter output than CI and breaks `ruff format --check` in lint. - rev: v0.15.9 + rev: v0.15.14 hooks: - id: ruff args: [--fix]