feat(resume): move the corpus query into step 4 β it fired 1/14 where it was - #1332
Conversation
β¦claims Round 1 of /audit-pr on #1332 returned six π‘, no π΄. Every one is fixed here. F1 (guard narrower than its name) β the test claimed to prove the command is UNCONDITIONAL and asserted only a shared step DIGIT. The audit built four isolated mutants; three survived a fully green suite. Renamed to what it checks, and widened: it now compares the FENCE, which kills M4 (a second list item re-labelled `4.`, gated, in its own block) with its own message. M2 and M3 β a gating sentence above the fence, a conditional comment inside it β STILL SURVIVE and are now named in the docstring as uncovered. They are prose-shaped; no structural check here sees them, and saying so is better than a keyword guard that would read as coverage. F2 (byte claim wrong by ~10x) β "a few hundred bytes" replaced with the measured figures: 3,941 B and 3,999 B for two real --limit 3 queries, 1,251 B for a no-match, which is the floor because the banner prints either way. Re-measured independently before changing it. F3 (the conditional came back) β the step-3 replacement sentence re-created an open-item-keyed instruction inside the block this PR measured at 0/6, told the reader to "re-run" something not yet run, was invisible from step 4, and dropped the tool's PURPOSE. Step 3 is now a pointer with no action; the item-level re-run and the "Ruled out: bullets stop you re-running a probe someone already ran" rationale both moved into step 4. F4 (asymmetric scope, unstated) β `cairn recall --repo` is repo-scoped while the query searches all four repos, two of them client repos, and routinely returns client sections above devrc ones. The step now says so and tells the reader to check each hit's repo before reusing it. Not narrowed to --repo: cross-repo reach is the point. F5 (report step named one surface) β step 5 said `from index`; handoff_search prints `from handoff docs`. Verified both banners by running them. Step 5 now carries each surface's own label. F6 (dangling referent) β "that doc's How to verify" had no antecedent and the nearest one was the wrong document. Named explicitly. F7 (denominators did not reconcile) β 8 - 1 = 7, not 6. The missing run is the measuring session itself, excluded as the instrument; that was true and never stated. Now stated in the skill, the test docstring and the handoff doc, with an as-of timestamp, since the corpus grows and a later re-run reports larger numbers rather than contradicting these. Also fixed the nit: a docstring said the recall posture sits "four steps earlier", which was wrong before this PR (cairn was one step LATER) and wrong after it (co-located). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7eZPAdX7nAeamShBnYNg2 Claude-Session-Id: 1de26f50-0e47-4964-b6ff-b87bea89b1fb
87989ef to
e8a273c
Compare
Audit round 1 β six π‘, no π΄, all fixed in
|
β¦claims Round 1 of /audit-pr on #1332 returned six π‘, no π΄. Every one is fixed here. F1 (guard narrower than its name) β the test claimed to prove the command is UNCONDITIONAL and asserted only a shared step DIGIT. The audit built four isolated mutants; three survived a fully green suite. Renamed to what it checks, and widened: it now compares the FENCE, which kills M4 (a second list item re-labelled `4.`, gated, in its own block) with its own message. M2 and M3 β a gating sentence above the fence, a conditional comment inside it β STILL SURVIVE and are now named in the docstring as uncovered. They are prose-shaped; no structural check here sees them, and saying so is better than a keyword guard that would read as coverage. F2 (byte claim wrong by ~10x) β "a few hundred bytes" replaced with the measured figures: 3,941 B and 3,999 B for two real --limit 3 queries, 1,251 B for a no-match, which is the floor because the banner prints either way. Re-measured independently before changing it. F3 (the conditional came back) β the step-3 replacement sentence re-created an open-item-keyed instruction inside the block this PR measured at 0/6, told the reader to "re-run" something not yet run, was invisible from step 4, and dropped the tool's PURPOSE. Step 3 is now a pointer with no action; the item-level re-run and the "Ruled out: bullets stop you re-running a probe someone already ran" rationale both moved into step 4. F4 (asymmetric scope, unstated) β `cairn recall --repo` is repo-scoped while the query searches all four repos, two of them client repos, and routinely returns client sections above devrc ones. The step now says so and tells the reader to check each hit's repo before reusing it. Not narrowed to --repo: cross-repo reach is the point. F5 (report step named one surface) β step 5 said `from index`; handoff_search prints `from handoff docs`. Verified both banners by running them. Step 5 now carries each surface's own label. F6 (dangling referent) β "that doc's How to verify" had no antecedent and the nearest one was the wrong document. Named explicitly. F7 (denominators did not reconcile) β 8 - 1 = 7, not 6. The missing run is the measuring session itself, excluded as the instrument; that was true and never stated. Now stated in the skill, the test docstring and the handoff doc, with an as-of timestamp, since the corpus grows and a later re-run reports larger numbers rather than contradicting these. Also fixed the nit: a docstring said the recall posture sits "four steps earlier", which was wrong before this PR (cairn was one step LATER) and wrong after it (co-located). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7eZPAdX7nAeamShBnYNg2 Claude-Session-Id: 1de26f50-0e47-4964-b6ff-b87bea89b1fb
e8a273c to
00e803a
Compare
Audit round 2 β all 8 round-1 claims verified fixed; 2 π‘ + 1 π’ found and fixed in
|
00e803a to
1ce2818
Compare
β¦claims Round 1 of /audit-pr on #1332 returned six π‘, no π΄. Every one is fixed here. F1 (guard narrower than its name) β the test claimed to prove the command is UNCONDITIONAL and asserted only a shared step DIGIT. The audit built four isolated mutants; three survived a fully green suite. Renamed to what it checks, and widened: it now compares the FENCE, which kills M4 (a second list item re-labelled `4.`, gated, in its own block) with its own message. M2 and M3 β a gating sentence above the fence, a conditional comment inside it β STILL SURVIVE and are now named in the docstring as uncovered. They are prose-shaped; no structural check here sees them, and saying so is better than a keyword guard that would read as coverage. F2 (byte claim wrong by ~10x) β "a few hundred bytes" replaced with the measured figures: 3,941 B and 3,999 B for two real --limit 3 queries, 1,251 B for a no-match, which is the floor because the banner prints either way. Re-measured independently before changing it. F3 (the conditional came back) β the step-3 replacement sentence re-created an open-item-keyed instruction inside the block this PR measured at 0/6, told the reader to "re-run" something not yet run, was invisible from step 4, and dropped the tool's PURPOSE. Step 3 is now a pointer with no action; the item-level re-run and the "Ruled out: bullets stop you re-running a probe someone already ran" rationale both moved into step 4. F4 (asymmetric scope, unstated) β `cairn recall --repo` is repo-scoped while the query searches all four repos, two of them client repos, and routinely returns client sections above devrc ones. The step now says so and tells the reader to check each hit's repo before reusing it. Not narrowed to --repo: cross-repo reach is the point. F5 (report step named one surface) β step 5 said `from index`; handoff_search prints `from handoff docs`. Verified both banners by running them. Step 5 now carries each surface's own label. F6 (dangling referent) β "that doc's How to verify" had no antecedent and the nearest one was the wrong document. Named explicitly. F7 (denominators did not reconcile) β 8 - 1 = 7, not 6. The missing run is the measuring session itself, excluded as the instrument; that was true and never stated. Now stated in the skill, the test docstring and the handoff doc, with an as-of timestamp, since the corpus grows and a later re-run reports larger numbers rather than contradicting these. Also fixed the nit: a docstring said the recall posture sits "four steps earlier", which was wrong before this PR (cairn was one step LATER) and wrong after it (co-located). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7eZPAdX7nAeamShBnYNg2 Claude-Session-Id: 1de26f50-0e47-4964-b6ff-b87bea89b1fb
π‘ THE DERIVED SCOPE PIN WAS DECORATION FOR ONE OF ITS FOUR ARMS. It searched the whole wiring block, and EXPECTED_COMMAND contains `~/workspace/devrc/scripts/lib/handoff_search.py`, so `"devrc" in block` was guaranteed true on every green run. Round 2's sweep picked DATAPACKET β a fixture that could only die β and read the kill as proof the pin worked. That is exactly RULES.md's "prove it REACHABLE, not merely breakable" and "pick fixtures distinct from any constant the assertion already names". Narrowing to the warning PARAGRAPH was NOT sufficient, and measuring said so: the paragraph itself says "a devrc-topic query" and "above the devrc ones", so dropping `devrc` from the enumerated list still left 8 passed. Fixed by matching BACKTICKED tokens β only the list is a code span. Now measured: control 8 passed Β· M6-devrc -> 1 failed, ['DEVRC'] Β· M7 (handle deleted from the list but mentioned in an unrelated sentence) -> 1 failed, ['CIVITAI'] Β· M5 and M1 still die with their own messages. All four arms are now reachable; before this, two of four were not. π‘ The `Claim:` line asserted a release that has not happened and dropped the command that performs it β wider on one axis, narrower on the other. Restored as STILL HELD with the explicit `claim-work --release`, and why an unreleased claim blocks the next rank 1 under a different identity. π‘ A THIRD site still said to build the fix: Open investigations -> Next probe told the reader to "promote the query to its own numbered step". Rounds 1-2 fixed State now and rank 1 and left this one, so the doc contradicted itself at the exact section /resume step 3 tells a session to read. Reworded to say the promotion landed and only the re-run remains. π’ The correction paragraph's own number was wrong: "~1.9 KB" was one commit's delta, not the PR's. Measured +3,688 B (41,852 -> 45,540, git cat-file -s at base 10d437c and head 00e803a) and labelled as a correction of a correction. π’ Rank 1 now says to raise check 1's CUT to #1332's merge time before re-running; left at #1295's, the 14 pre-fix runs stay in the denominator and a fully successful fix reports ~10/24 and reads as a failure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7eZPAdX7nAeamShBnYNg2 Claude-Session-Id: 1de26f50-0e47-4964-b6ff-b87bea89b1fb
β¦ it was
The handoff section index shipped with exactly one consumer, a conditional
buried in step 3's prose ("before working any open item..."). Over its first
34 h that consumer was invoked by 1 of 14 /resume runs across both hosts, and
the one that fired was reading origin/main because the SKILL block told it its
copy was stale β not because the step fired. Yield: 0.
The non-firing was NOT correct restraint. All six workbench non-firing runs
ran claim-work and five made edits, and five of six resumed a doc carrying an
## Open investigations section, so the trigger was met every time.
DISCRIMINATOR β placement, not the tool, its cost, or how loudly it is marked:
step 3's sibling check (git log --since; same trigger, same block, an ordinary
command) fired 0/6, while step 4 (cairn recall; numbered, unconditional,
fenced) fired 5/6. Two co-located conditionals at 0, one unconditional
numbered step next door at 5.
So the query becomes step 4's second command, keyed on the handoff's TOPIC
rather than an open item β every resume has a topic, and keying on an item is
the conditional this removes. It is NOT a new numbered step: ~15 prose
cross-references across skills and scripts pin "step 4" (cairn) and "step 6"
(claim-work), none machine-checked, and a renumber would falsify all of them.
The guard is STRUCTURAL, not spelled: a grep for "unconditional" passes on a
body that says the word and still gates the command. test_the_query_is_
UNCONDITIONAL__it_shares_a_numbered_step_with_cairn_recall asserts WHICH
numbered step the command physically sits in. Watched to fail two ways: red at
origin/main via the count arm, and an isolated mutant (query moved back into
step 3, wording untouched) fires the step-identity arm with its own message.
RESIDUAL, stated in the skill and the test: the 5/6 was measured with ONE
command in that step. Co-locating a second is a prediction, not a measurement
β re-measure with check 1 of the handoff's "How to verify".
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G7eZPAdX7nAeamShBnYNg2
Claude-Session-Id: 1de26f50-0e47-4964-b6ff-b87bea89b1fb
β¦claims Round 1 of /audit-pr on #1332 returned six π‘, no π΄. Every one is fixed here. F1 (guard narrower than its name) β the test claimed to prove the command is UNCONDITIONAL and asserted only a shared step DIGIT. The audit built four isolated mutants; three survived a fully green suite. Renamed to what it checks, and widened: it now compares the FENCE, which kills M4 (a second list item re-labelled `4.`, gated, in its own block) with its own message. M2 and M3 β a gating sentence above the fence, a conditional comment inside it β STILL SURVIVE and are now named in the docstring as uncovered. They are prose-shaped; no structural check here sees them, and saying so is better than a keyword guard that would read as coverage. F2 (byte claim wrong by ~10x) β "a few hundred bytes" replaced with the measured figures: 3,941 B and 3,999 B for two real --limit 3 queries, 1,251 B for a no-match, which is the floor because the banner prints either way. Re-measured independently before changing it. F3 (the conditional came back) β the step-3 replacement sentence re-created an open-item-keyed instruction inside the block this PR measured at 0/6, told the reader to "re-run" something not yet run, was invisible from step 4, and dropped the tool's PURPOSE. Step 3 is now a pointer with no action; the item-level re-run and the "Ruled out: bullets stop you re-running a probe someone already ran" rationale both moved into step 4. F4 (asymmetric scope, unstated) β `cairn recall --repo` is repo-scoped while the query searches all four repos, two of them client repos, and routinely returns client sections above devrc ones. The step now says so and tells the reader to check each hit's repo before reusing it. Not narrowed to --repo: cross-repo reach is the point. F5 (report step named one surface) β step 5 said `from index`; handoff_search prints `from handoff docs`. Verified both banners by running them. Step 5 now carries each surface's own label. F6 (dangling referent) β "that doc's How to verify" had no antecedent and the nearest one was the wrong document. Named explicitly. F7 (denominators did not reconcile) β 8 - 1 = 7, not 6. The missing run is the measuring session itself, excluded as the instrument; that was true and never stated. Now stated in the skill, the test docstring and the handoff doc, with an as-of timestamp, since the corpus grows and a later re-run reports larger numbers rather than contradicting these. Also fixed the nit: a docstring said the recall posture sits "four steps earlier", which was wrong before this PR (cairn was one step LATER) and wrong after it (co-located). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7eZPAdX7nAeamShBnYNg2 Claude-Session-Id: 1de26f50-0e47-4964-b6ff-b87bea89b1fb
Round 2 verified all eight of round 1's claims actually fixed, and found two π‘ plus one π’. All three fixed here. π‘ the handoff doc's STATUS contradicted the PR shipping it. `State now` said "No fix is built; awaits operator direction", and ranked next-step 1 still described this very change as pending. Both mitigations that made it survivable (the held claim, the open PR visible to step 6's sweep) end AT MERGE β so a /resume on that doc would have read "no fix is built" and re-implemented a merged change, which is precisely the re-derivation loop this PR exists to break. Status and rank 1 rewritten: rank 1 is now RE-MEASURE ADOPTION, which is the thing that is actually still open. π΄ That item also carried a FALSE claim I wrote and the audit caught: "SKILL.md is byte-capped, so promoting text means evicting text". It is not. The caps cover browser, handoff, prune-skill and RULES.md; this PR's own test says so. Corrected in place and labelled as a correction, not silently deleted. π‘ M5 β a fifth mutant the round-1 residual list did not anticipate: the command left in the fence but COMMENTED OUT. Every check in this module is a substring test, and `# python3 ...handoff_search.py ...` contains the pinned string, so the string pin, the step check and the fence check ALL went green over dead wiring β this module's founding failure, reachable by one character. Now killed by requiring the fence line to be live. The docstring no longer presents the mutant list as closed: M5 was found after round 1 called the residual settled. π’ the scope warning restated `handoff_index.REPO_ENV_HANDLES` membership instead of deriving it, in a module whose docstring says every claim is derived from the tool. Now pinned against the module. Scope of that pin stated: it checks the LABELS, not the "two of which are client repos" count, which is a human judgement no module holds. Mutants re-run under PYTHONDONTWRITEBYTECODE=1: control 8 passed; M5 killed by the live-line assert with its own message; M6 (drop a handle from the warning) killed by the derived pin, naming DATAPACKET. M2 and M3 still survive and are still named as uncovered. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7eZPAdX7nAeamShBnYNg2 Claude-Session-Id: 1de26f50-0e47-4964-b6ff-b87bea89b1fb
π‘ THE DERIVED SCOPE PIN WAS DECORATION FOR ONE OF ITS FOUR ARMS. It searched the whole wiring block, and EXPECTED_COMMAND contains `~/workspace/devrc/scripts/lib/handoff_search.py`, so `"devrc" in block` was guaranteed true on every green run. Round 2's sweep picked DATAPACKET β a fixture that could only die β and read the kill as proof the pin worked. That is exactly RULES.md's "prove it REACHABLE, not merely breakable" and "pick fixtures distinct from any constant the assertion already names". Narrowing to the warning PARAGRAPH was NOT sufficient, and measuring said so: the paragraph itself says "a devrc-topic query" and "above the devrc ones", so dropping `devrc` from the enumerated list still left 8 passed. Fixed by matching BACKTICKED tokens β only the list is a code span. Now measured: control 8 passed Β· M6-devrc -> 1 failed, ['DEVRC'] Β· M7 (handle deleted from the list but mentioned in an unrelated sentence) -> 1 failed, ['CIVITAI'] Β· M5 and M1 still die with their own messages. All four arms are now reachable; before this, two of four were not. π‘ The `Claim:` line asserted a release that has not happened and dropped the command that performs it β wider on one axis, narrower on the other. Restored as STILL HELD with the explicit `claim-work --release`, and why an unreleased claim blocks the next rank 1 under a different identity. π‘ A THIRD site still said to build the fix: Open investigations -> Next probe told the reader to "promote the query to its own numbered step". Rounds 1-2 fixed State now and rank 1 and left this one, so the doc contradicted itself at the exact section /resume step 3 tells a session to read. Reworded to say the promotion landed and only the re-run remains. π’ The correction paragraph's own number was wrong: "~1.9 KB" was one commit's delta, not the PR's. Measured +3,688 B (41,852 -> 45,540, git cat-file -s at base 10d437c and head 00e803a) and labelled as a correction of a correction. π’ Rank 1 now says to raise check 1's CUT to #1332's merge time before re-running; left at #1295's, the 14 pre-fix runs stay in the denominator and a fully successful fix reports ~10/24 and reads as a failure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7eZPAdX7nAeamShBnYNg2 Claude-Session-Id: 1de26f50-0e47-4964-b6ff-b87bea89b1fb
1ce2818 to
0d0f0b6
Compare
Audit round 3 β three findings, all fixed in
|
| round | fixes touched | payload lines |
|---|---|---|
| round 2 | test + handoff doc | 0 |
| round 3 | test + handoff doc | 0 |
Two consecutive rounds whose fixes changed zero payload lines β the skill body has been untouched since round 1. The ladder is auditing the guard and the notes it wrote, not the change. That is the documented stop condition, and it is a measurement, not a judgement call or a round cap.
Nothing is being left unfixed: all three round-3 findings are fixed above. The two known residuals (mutants M2 and M3 β a gating sentence above the fence, a conditional comment inside it) are not silently dropped: they are named as uncovered in the test docstring, which also states the mutant list is not closed.
Gate β merged tree, base f58d2df0, run one at a time
pytestsβ collected=21903 passed=21900 failed=0 (floor 18672)nodetestsβ suites=5 tests=1449 pass=1449 fail=0 (floor 1367)
Base re-confirmed unmoved after the run. Re-gated because f58d2df0 changed scripts/run-tests.sh, which owns the per-target floor table β the floor moved 18610 -> 18672, so that re-run was substantive.
β¦ just read (#1399) * fix(handoff-search): stop spending the top hit on the doc the session just read MEASURED over the 20 post-fix `/resume` runs that queried the corpus (2026-09-08): 23 of 60 hit slots were the session's OWN handoff β the document it had read minutes earlier in step 3 β and it was the #1 hit in 13 of 20 queries, taking all three slots twice. That is arithmetic, not a ranker bug. Step 4 tells the caller to query the handoff's TOPIC, and the best text match for a document's topic is that document. The re-keying that made the step unconditional in #1332 is the same thing that aimed it at itself. It matters because YIELD was answered in the same pass and it is 1 of 20: one session had a hit change what it did (it dropped the backlog it was resuming for an unclaimed forcing:security item in another effort, five hours later, off a hit it had carried in context). The other 19 got nothing β and a third of what they were shown, they had already read. --exclude-slug SLUG|PATH (repeatable) Takes the doc path `resume-state.sh` printed on its `handoff:` line, or a bare slug; a path is normalised through the indexer's own `slug_for`, never a second hand-rolled strip. `/resume` step 4's fence now passes it. It is a SCOPE filter, not a post-hoc drop of rows the query returned: * it goes through `_selected` / `_filter_predicates`, the single predicate both `stats` and `search` read, so the counter and the query cannot come to different views of what is in scope; * excluding everything is therefore `empty-scope` (rc 4) β "your filter emptied the corpus" β never `no-match` (rc 0), which would assert the corpus is silent about a topic it was never allowed to answer on; * it is NEVER silent: `excluded=` prints on the scope line of every status including the zeros, and `in_scope_*` appears beside `indexed_*`. Also corrects "How to verify" check 3, which could not have worked as written: the DB path needs `nix develop`, not just `KUBECONFIG` β a bare python3 dies with `psycopg2 is required`. Coverage: 13 new tests. An 8-mutant sweep (positive control included) was run under PYTHONDONTWRITEBYTECODE=1 with each mutant verified PRESENT in the file before scoring; all 8 died, each by its own named test. The two that matter most are the silent ones β scoped stats blind to the exclusion (turns "your filter emptied it" into "the corpus is silent") and the exclude list bound before sections in the Postgres params, which psycopg2 binds positionally and so yields a valid query against the wrong columns. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwwnnDzefhhE8cG9sqjafE Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0 * docs(handoff): name the PR that carries the fix Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwwnnDzefhhE8cG9sqjafE Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0 * fix(handoff-search): round-1 audit β the flag was deletable to INERT with a green suite Ten findings from the round-1 adversarial audit, all fixed. The one that mattered: every layer was pinned in isolation β exclusion_slug, the row filter, both backends' bound params, the renderer, `filtered` β and NOTHING pinned that main() hands `exclude` to run_search. Deleting `exclude=exclude` from the CLI call site left the flag completely inert (excluded doc back as hit #1, no `excluded=` line, no scope pair) with 304/304 tests green. The pre-existing guard whose docstring says "π΄ THE SEAM" proves only that argparse ACCEPTS the flag: it passes `--limit 0`, which returns rc 2 before any store is built. RULES.md β "verified in isolation is the new vacuous green"; "a count of DECLARATIONS is not a count of INSTANCES"; a guard's description claiming coverage it does not provide is worse than none, because it stops anyone looking. Both call sites are now covered: the offline one behaviourally, the postgres one β which no test here can execute β by an AST ledger that fails if a call site is added without `exclude=` as well as if one is removed. Also fixed: * The no-match remedy told exclusion-only runs to "widen --repo / --section". I had fixed exactly this class in the empty-scope branch and written a comment citing it, while its neighbour kept the defect β and no-match is the branch that matters (against a 401-doc corpus one exclusion can essentially never empty the scope). Now ONE function, `active_filter_flags`, answers it for both. * exclusion_slug silently no-opped on an absolute path, on a `handoff-x` basename with no `.md`, and on a trailing space β each printing a confident `excluded=<garbage>` while filtering nothing. Normalisation is unconditional now. A filter that declines to filter renders identically to one that worked. * SKILL.md stated rc 0 for a case measured at rc 4, contradicting this module's own comment and its own test, in the paragraph an agent reads to decide whether a zero is an answer. * The fenced command was not valid shell (`bash -n` rc 2) β an unquoted placeholder carrying an apostrophe and backticks. * "drops in_scope_docs by one" was false in both directions. * test_the_CLI_dedupes_repeats_without_reordering asserted on its own inline expression and never invoked the CLI. * A bare `str` exclude iterates per character (a wrong scope, not a no-op); a None element makes postgres return zero while memory returns everything. Both refused loudly. * scripts/README.md did not know the flag exists. Doc corrections, both mine: the "8-mutant sweep" was true but incomplete β an independent 13-mutant sweep found 3 survivors it never covered; and the adoption annotation claimed a session-id exclusion the published script does not perform (20/22 was reached by subtracting by hand afterwards). π΄ THE FIX ROUND RESET THE GATE, AND TWO OF ITS OWN FIXES SHIPPED UNGUARDED. Re-sweeping the fixes rather than the findings: restoring the silent-no-op exclusion_slug, and disabling the bare-str guard, both SURVIVED a 306-test green suite. Ten tests added; the re-sweep now kills all 8 mutants, each by its own named test, tree restored byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwwnnDzefhhE8cG9sqjafE Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0 * fix(handoff-search): round-2 audit β I unified WHICH flags and left WHAT TO DO wrong Six findings from the round-2 delta re-audit, all fixed. The instructive one: round 1 consolidated which flags each remedy branch names, and left the VERB open-coded β so the same two branches disagreed a second time, one level in. `no-match` told an exclusion-only run to "widen --exclude-slug", which is advice that guarantees the zero stays a zero: widening an exclusion excludes MORE. Its sibling three lines up already said "Widen or drop". Consolidation is a bug-finding instrument, and this PR has now been caught by that rule twice. * `_exclusion_list` was called unconditionally on the memory backend and inside `if exclude:` on postgres, so `exclude=""` raised on one and was silently accepted by the other β a NEW cross-backend divergence, in the guard whose docstring says divergence is what it prevents. Coerced before the bool() on both. Pinned as a RELATIONSHIP over a shared table of shapes, not two per-backend tests: two tests that each pass alone is exactly how it survived. * The AST ledger pinned that `exclude=` is PRESENT, not that it carries the value. `exclude=()` at the postgres site survived 314 tests β a guard on a NAME, walkable by supplying a different value under it. It now pins the value is the normalised local. * "the whole suite green at 304 passed" named a scope nobody measured: 304 is two files; the repo has ~21k tests. In the docstring of the guard against "verified in isolation". * Nothing asserted the FENCE parses. `bash -n` rc 0 was true of the line #1399 fixed and false of the block, because the untouched `cairn recall --repo <path>` line parses `<path>` as a redirect β and bash aborts the whole block, so a verbatim paste ran NEITHER command. Quoted, and pinned by a test over the whole fence with a positive control. * The "1,251 B no-match floor" was never a floor: the response echoes the query, so it is a function of query length (1,261 B at 15 chars, 1,289 at 43, ~1,436 when excluding). Corrected to state the dependency rather than swap in another falsifiable number. Two instrument failures during this round, both of which produced confident results that were worthless: π΄ The sweep script restored SKILL.md with `git checkout --`. Those edits were UNCOMMITTED, so it reverted them to the last commit and silently destroyed two of them. RULES.md says restore from `cp -a`, never `git checkout --`; I wrote the violation into my own tooling. Recovered and re-applied; the replacement uses `cp -a` and says why. π΄ Two mutants scored SURVIVED off runs that never executed. The tell was an empty summary β `SURVIVED ()`. zsh does not word-split unquoted parameters, so two test paths in a variable became one impossible filename; pytest errored and printed no verdict. The sweep now REQUIRES a summary line before scoring and prints VOID otherwise, runs a baseline control first, and uses a bash array. Re-run isolated (mutating the production value only, never the guard beside it): both KILLED, each by its own named test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwwnnDzefhhE8cG9sqjafE Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0 * fix(handoff-search): round-3 audit β no behavioural defect; sweep the shape, not the site Round 3 returned four π’ claim-corrections and NO behavioural defect. All four fixed, and the third is the one worth recording. * The comment claiming "one rule, one place β the phrasing included" was false: round 2 consolidated WHICH flags each remedy branch names and left the VERB as two literals. Rather than correct the sentence, this makes it true β `widen_or_drop_clause` is the single literal both branches read, pinned by a test that breaks BOTH when it breaks. * The refusal for `exclude=""` ended `Pass ['']`, and `[""]` IS accepted: it filters nothing while printing a confident `excluded=` line. An error message naming the next defect as its own remedy β the silent no-op this PR spent three rounds closing, offered as the fix for its own trigger. The worked example is now suppressed for the empty string and kept for every other shape. * π΄ AN UNSCOPED TEST COUNT, FOR THE FOURTH TIME IN THIS PR. "the whole suite green at 304", "SURVIVED all 314 tests", "a 306-test green suite", "304 of 304 tests passed" β every one numerically TRUE and every one naming ~300 tests across two files against a repo of ~21,000. Three rounds each caught one site and fixed that site. It only went away when swept at all four. When a round fixes an instance of a shape, grep for the shape β which is the rule I was quoting while breaking it. * `_step4_fence` checks a STRIPPED reconstruction, not the pasted bytes. Both forms are rc 0 today so nothing is masked; the residual is now named in the docstring rather than left implicit (a heredoc added to that fence would make the two disagree). Sweep: baseline green (321), D1 (shared clause back to bare "widen") and D2 (refusal offers [''] again) both KILLED, each by its own named test, tree restored byte-identical via cp -a. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwwnnDzefhhE8cG9sqjafE Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0 * fix(handoff-search): round-4 audit β my "consolidation" was dead-code-able with a green suite Round 4 returned category (b): only claim-corrections, no behavioural defect. All three fixed. The first is the round-1 seam lesson recurring one class over. * π΄ THE CONSOLIDATION PIN WAS TEXT-AGREEMENT, NOT STRUCTURE. Round 4 reverted both renderer branches to independent open-coded literals, leaving `widen_or_drop_clause` defined and ENTIRELY UNREFERENCED β and the suite passed 321/321. Every assertion I had written compared strings; none observed where the string came from, so the test whose NAME says "comes from ONE literal shared by both branches" could not see the branches stop sharing it. Now an AST ledger: both branches must CALL the helper, and the verb may not survive as a literal in render(). Same instrument, and same lesson, as the run_search seam. * The unscoped-count sweep I claimed was complete missed a FIFTH site β four quoted counts, five textual occurrences β and the survivor was inside the very test the doc bullet held up as the exemplar. The bullet asserting the sweep was done was itself an instance of the shape it describes. Corrected, and it now says to grep AND COUNT. * The example-suppression was keyed on emptiness while its own comment named the hazard as "accepted and filters nothing". `exclude=" "` β one character different β was still told to pass `[' ']`. Re-keyed on `.strip()`, the predicate the sentence actually described. NOT fixed, filed as rank 2 with a closing condition: `--exclude-slug " "` is still a silent no-op reachable from the CLI. The fix is an input rejection at main() (rc 2), which is a behaviour change β it would reset the gate and require another round, so it is recorded rather than absorbed. Sweep, in a DETACHED cp -a copy with .git removed (round 3 flagged that earlier sweeps mutated the shared checkout in place, where a concurrent session could read a mutant): baseline green 322; E1 (helper unreferenced β round 4's own survivor) and E2 (suppression back to emptiness) both KILLED by their own named tests. E2's first attempt returned NO VERDICT because the marker comment commented out a closing paren; the VOID guard caught it instead of scoring a survivor, and the re-run parse-checks the mutant before running it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwwnnDzefhhE8cG9sqjafE Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rank 1 of
handoff-handoff-search-index. The measurement that motivated it merged as #1329.What changed
The handoff section index had exactly one consumer: a conditional buried in step 3's prose ("before working any open itemβ¦"). It is now the second command of step 4, keyed on the handoff's topic rather than an open item β every resume has a topic, and keying on an item is the conditional being removed.
Why β measured, not argued
Over the 34 h after #1295 merged, 1 of 14
/resumeruns across both hosts invoked it, and that one was readingorigin/mainoff the staleness alarm rather than firing the step. Yield: 0.The non-firing was not correct restraint β all six workbench non-firing runs ran
claim-work, five made edits, and five of six resumed a doc with an## Open investigationssection.Discriminator β placement, not the tool: step 3's sibling check (
git log --since; same trigger, same block, an ordinary command) fired 0/6, while step 4 (cairn recall; numbered, unconditional, fenced) fired 5/6.Not a new numbered step, deliberately
~15 prose cross-references across skills and scripts pin "step 4" (cairn) and "step 6" (claim-work), none machine-checked. A renumber would falsify all of them.
The guard is structural, not spelled
A grep for "unconditional" passes on a body that says the word and still gates the command. The new test asserts which numbered step the command physically sits in. Watched to fail two ways: red at
origin/main(count arm), and an isolated mutant β query moved back into step 3, wording untouched β fires the step-identity arm with its own message.Residual, stated in both the skill and the test
The 5/6 was measured with one command in that step. Co-locating a second is a prediction, not a measurement. Re-measure with check 1 of the handoff's "How to verify".
Gate
Both tiers on the merged tree at base
f0b9c474:nix build .#checks.x86_64-linux.pytestsβ collected=21837 passed=21834 failed=0 (floor 18610)nix build .#checks.x86_64-linux.nodetestsβ suites=5 tests=1449 pass=1449 fail=0 (floor 1367)Run one at a time. Base re-confirmed unmoved after the run.
π€ Generated with Claude Code
https://claude.ai/code/session_01G7eZPAdX7nAeamShBnYNg2