stitchgraph v3.1.0 — semantic-path test hardening + a clearer README
stitchgraph v3.1.0 — semantic-path test hardening + a clearer README
A small, safe release on top of v3.0.0. No source, API, or schema change — every operation
behaves exactly as in 3.0.0, and indexes don't need rebuilding. v3.1.0 closes a mutation-coverage
gap in find_similar's optional dense path and makes the README say plainly what the package
delivers.
Why
v3.0.0 shipped the body matrix with its own core mutation-pinned (structure.py 15/15, graphdiff
9/9). The release-readiness work flagged that core/similar.py's optional semantic/dense
(model2vec) retrieval path still had ~15 surviving mutants — un-pinned behaviour in the dense
ranking and the offline model-load — and parked it as a follow-up (docs/IDEAS.md §5d). This is
that follow-up.
Hardened — core/similar.py mutation coverage
The in-house differential mutation meta-oracle (scripts/mutate.py) injects one operator/boolean
mutation at a time and checks the suite kills it. New unit tests pin the previously-unpinned
behaviour:
- Ranking is strict (token + dense). The existing fixtures tied at the top (the dense test's
two nodes both scored 1.0; the token query tied at 0.447), so areverse=Trueflip left the
winner unchanged and the sort-direction mutants survived. New strict, tie-free fixtures (a 3-axis
fake embedder for the dense path; a distinct-overlap pair for the token path) make sort direction
and the drop-non-positive> 0filter observable. - Test isolation. The dense backend is module-global (
_EMBEDDER+ the_M2V_TRIEDonce-latch).
An autouse fixture now snapshots and resets it around every test, so leaked state can't change
which retrieval path a later test takes — which had made both the suite and the mutation kills
order-dependent (one mutant was killed only by a leaked embedder, masking a real gap). - Zero-norm embeddings degrade, never divide-by-zero. A zero-magnitude query or node
embedding must score 0.0; the two_dot_cosnorm guards (… or 1.0) are now pinned against the
andflip that would raiseZeroDivisionError. model2vecauto-load, tested offline. A fakemodel2vecmodule + fake config exercise the
auto-load without a network: the success path wires an embedder and selects the
configured-or-default model; the load is attempted at most once (the_M2V_TRIEDlatch); and
an import failure returns cleanly and stays on the token path (never calling_densewith no
embedder).
Result: 29/32 mutants killed. The 3 survivors are documented as justified-equivalent (not
test gaps) in the tests/test_similar.py module docstring — an or→and flip absorbed by a
downstream if dot == 0, a defensive zip(strict=False) that only differs on contract-violating
ragged vectors, and an or→and whose extra-permissive branch yields nothing downstream.
Docs
- README now opens with what stitchgraph delivers — the question each operation answers —
before the internals, with the v3.0.0 body matrix as the headline and a consistent language count.
Cardinal-safety & scope
Unchanged from 3.0.0: the body matrix and find_similar are advisory and read-only; they never
feed find_stale, so the cardinal rule (live code is never confidently flagged dead) is
unaffected. This release adds tests only — no runtime code changed.
Quality gate
- ruff + mypy clean; full suite 703 passing; differential oracle suite 85.
- Mutation meta-oracle:
structure.py15/15,graphdiff9/9,similar.py29/32 (3 justified
equivalent) — kill-signals named in the CHANGELOG. - Two-round full-diversity adversarial panel (opus / sonnet / haiku), clean.
Upgrading
Nothing to do — no behaviour, API, or schema change from 3.0.0.