Skip to content

v1.108.296 — Four ways a guard can be present without working

Choose a tag to compare

@jgravelle jgravelle released this 24 Aug 23:59
· 67 commits to main since this release

investigate_reuse_before_write — reuse-before-write as proof obligations rather than a keyword search. The claim under test is "Nothing in <repo> already implements <intent>, so writing it new is justified."

Verdicts: reuse_available / adapt_candidate / write_justified / lexical_only / not_established.

lexical_only is why this is not a search wrapper. An intent of "modal" shares no token with an existing Dialog, so only the embedding channel can connect them. A checker that reports "nothing matches" identically whether or not it could see synonyms is wrong exactly when the writer most needs it to be right — so an unavailable semantic channel goes UNESTABLISHED and degrades the verdict instead of licensing a write. no_provider and repo_not_embedded are separate states with opposite advice.

A dead match is not a reuse candidate. Pointing a writer at an unreferenced helper does not prevent duplication, it doubles the dead code — the failure a keyword matcher cannot detect, because the match looks identical either way. Liveness is tri-state: live is None blocks rather than permits.

Four defects found by running it

The module was written in one pass and never executed past import. It imported clean and read well. Three of the four are the same shape — a check that could not observe the thing it claimed to check.

  1. Every candidate scored 0.0. search_symbols emits score on a result row only under debug=True. Without it _squash returned 0.0 for every row, the match buckets were empty by construction, and the two tuning thresholds graded nothing — while match_strength was published as always-zero.
  2. write_justified was unreachable. The index-rewritten probe was sampled after the scan, and the module's own semantic read opens a read-write connection that moves the very mtime that probe compares. It reported a rebuild it had performed itself. Now sampled before any channel runs: a mtime is a proxy for "rows were rewritten", our own connection is a known false positive, and excluding a known false positive repairs the proxy rather than relaxing the guard.
  3. UNKNOWN collapsed into SATISFIED in the one obligation written to prevent it — an unreadable embedding store fell through to "searched and clean".
  4. A refutation backed only by dead code read as a reuse instruction, i.e. advice to depend on dead code. Now adapt_candidate plus dead_matches, naming the revive-or-delete decision.

Not exposed as a tool

Control-subset route@1 measured 40.0% (n=20) against the 55.0% exit bar, so the catalog moratorium's condition 1 is unmet and the ceiling stays at 91. An action the router would not propose is functionally absent however good it is, so exposing it is a separate decision from writing it — the same call already recorded for investigate_deletion_safety and explain_route. The moratorium withholds a surface, never a capability.

Also fixed

The moratorium guard raised NameError instead of explaining itself. Its ceiling assert interpolated two constants renamed when the gate moved to the control subset, so the message died while being built — on the exact path a contributor hits when they add a 92nd action. Message text is only reached on failure, so a green suite proved nothing about it.


Tests: 8315 passed, 17 skipped, 0 failed on Python 3.12 and 3.13 — same 8332 total, same skip split. ruff check src/ clean.

Install: pip install jcodemunch-mcp==1.108.296