Skip to content

fix(handoff-search): stop spending the top hit on the doc the session just read - #1399

Merged
ZacxDev merged 11 commits into
mainfrom
fix/handoff-search-exclude-own-doc
Sep 9, 2026
Merged

fix(handoff-search): stop spending the top hit on the doc the session just read#1399
ZacxDev merged 11 commits into
mainfrom
fix/handoff-search-exclude-own-doc

Conversation

@ZacxDev

@ZacxDev ZacxDev commented Sep 8, 2026

Copy link
Copy Markdown
Member

The measurement

Rank 1 of claudedocs/handoff-handoff-search-index.md was "does an index hit change what a session does?" — the question the whole effort rides on, because an index queried by every session and never useful is a cost, not a capability.

It is now answered, and a second finding falls out of the same read.

Adoption held. Re-ran check 1 at n=22 (the doc had n=4): 20 of 22 post-fix /resume runs on the workbench queried the corpus (91%), control cairn recall 21/22, against 2 of 11 (18%) pre-fix. The measuring session is excluded from both halves by session id. The laptop still contributes 0 runs — measured over ssh, not assumed.

Yield is 1 of 20. Nineteen sessions went straight from the tool result to claim-work or gh pr view; not one opened a hit document or reported the output. The single exception is real and is exactly the value proposition — a session dropped the entire backlog it was resuming for an unclaimed forcing: security item in a different effort, off a hit it had carried in context for five hours — but the delivery mechanism was context carryover, not the step.

Why the other 19 got nothing: 23 of 60 hit slots (38%) were the session's OWN handoff, read minutes earlier in step 3, and it was the #1 hit in 13 of 20 queries — all three slots in two of them.

That is arithmetic, not a ranker bug. Step 4 says 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.

The change

--exclude-slug SLUG|PATH (repeatable). Takes the doc path resume-state.sh already 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 passes it.

Measured differential on the live corpus, one flag apart:

before: devrc/handoff-search-index, devrc/handoff-search-index, devrc/cairn-oss-multi-instance
after : devrc/cairn-oss-multi-instance, devrc/mention-detection, devrc/cairn-task-linkage

It is a scope filter, not a post-hoc drop, and that distinction is the design:

  • 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. Verified: backend=postgres, indexed_sections=5125, the same number the timer's own run reported writing.

Coverage

13 new tests. An 8-mutant sweep with a positive control, run under PYTHONDONTWRITEBYTECODE=1, each mutant verified PRESENT in the file before scoring, tree restored byte-identical afterwards. All 8 killed, each by its own named test. The two that matter are the silent ones:

  • scoped stats blind to the exclusion — turns "your filter emptied it" into "the corpus is silent";
  • the exclude list bound before sections in the Postgres params — psycopg2 binds positionally, so this is a valid query against the wrong columns, returning rows a caller reads as an answer. No test in this repo reaches a database, so SQL text plus bound-parameter order is the only thing that can be pinned, and pinning one without the other is exactly the gap.

Instrument note

The 38% had to be rebuilt mid-measurement. The first pass grepped transcripts for claudedocs/handoff-<slug>.md and reported a suspiciously perfect 100% — because the search's own output prints each hit's doc path, so the needle was matching the instrument. Rebuilt from two sources the search cannot write (resume-state.sh's handoff: line and claim-work --slug-for arguments) it is 38%. Same family as the ~24× mention-vs-invocation overcount this effort already recorded.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SwwnnDzefhhE8cG9sqjafE

ZacxDev and others added 5 commits September 8, 2026 14:44
… 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
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
…clude-own-doc

Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0
…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
…clude-own-doc

Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0
@ZacxDev

ZacxDev commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

Round 1 — fixes landed

Round 1 audited 8d4ac541. All ten findings were addressed; the fixes land in 4973b415, merged with main at 6589f01d.

1. F1 — claimed: main()'s forwarding of `exclude` to run_search is now pinned on BOTH call sites; offline behaviourally, postgres by an AST ledger asserting exactly 2 call sites each passing `exclude=`.
2. F2 — claimed: the no-match remedy no longer names flags the run did not pass; both it and the empty-scope remedy now read one function, `active_filter_flags`.
3. F3 — claimed: SKILL.md no longer states rc 0 for the excluded-everything case; it states rc 4 / EMPTY SCOPE.
4. F4 — claimed: the "drops in_scope_docs by one" assertion is removed from SKILL.md and from the handoff doc's check 3b; both now say "lower than indexed_docs" and state that a shared basename drops two.
5. F5 — claimed: exclusion_slug normalises unconditionally; an absolute path, a `handoff-x` basename with no `.md`, a trailing space and a `./` prefix all derive the stored slug instead of silently no-opping.
6. F6 — claimed: the SKILL.md fence is valid shell verbatim (`bash -n` rc 0); the placeholder is double-quoted and carries no apostrophe or backticks.
7. F7 — claimed: exclusion_slug's docstring no longer cites the nested-doc case as its justification; it states explicitly that a nested doc's directory CANNOT be recovered from the basename the skill tells callers to pass.
8. F8 — claimed: scripts/README.md lists --exclude-slug and says what it is for.
9. F9 — claimed: test_the_CLI_dedupes_repeats_without_reordering now drives main() rather than asserting on its own inline expression.
10. F10 — claimed: a bare `str` exclude and a non-str element are both refused with TypeError on both backends.
11. Self-reported numbers — claimed: the commit's "8-mutant sweep" is restated as incomplete (an independent sweep found 3 survivors it did not cover), and the handoff doc now says the adoption script performs NO session-id exclusion and that 20/22 was reached by subtracting by hand.
12. Fix-round re-sweep — claimed: 8 mutants including a positive control all die, each by its own named test, with each mutant verified present in the file before scoring and the tree restored byte-identical. Two of these (A4 exclusion_slug no-op, A6 bare-str guard) SURVIVED the first pass and are the reason 10 tests were added.

Gate on the merged tree 6589f01d (main at 9300f234):

  • Tier 2 (the tier Tekton gates on): PASS on both checks, built one at a time — pytests collected=21369 passed=21367 skipped=2 failed=0; nodetests 1449/1449.
  • Tier 1: node PASS (1449/1449); pytest did NOT complete — it hit gate.sh's own 3600s budget at target 18 of 28 under a box load average of 88 from concurrent sessions. Zero failures: every one of the 16 targets that reported ended N passed. Per-target times were uniformly ~10–17% above the same targets in a completed run (e.g. browser-bridge 4:29 vs 3:49), which is the load signature — load inflates every test in a run, a failed assertion inflates exactly one. This is a throughput result, not a verdict on the code, and the sandbox tier ran the same tests hermetically to completion.

ZacxDev and others added 2 commits September 8, 2026 23:29
…HAT 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
…clude-own-doc

Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0
@ZacxDev

ZacxDev commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

Round 2 — fixes landed

Round 2 audited 6589f01d. All six findings addressed in a583d661, merged with main at f85ace49.

1. 🟡1 — claimed: neither remedy branch says bare "widen <flag>"; both say "widen or drop", via the same active_filter_flags helper. Widening an exclusion excludes MORE, so bare "widen" could not turn that zero into a hit.
2. 🟡2 — claimed: _exclusion_list is applied before the bool() on BOTH postgres methods, so memory and postgres now accept and refuse exactly the same exclude shapes, including the falsy-but-wrong "".
3. 🟡3 — claimed: the "304 passed" docstring names its scope (this file plus the wiring guard, not the ~21k suite); the 306 figure beside it says it is the same two-file scope.
4. 🟢4 — claimed: the AST ledger pins the VALUE is the normalised `exclude` local, not merely that the keyword is present; `exclude=()` at the postgres site is now caught.
5. 🟢5 — claimed: the "1,251 B no-match floor" is replaced by a statement that it was never a floor, with re-measured figures and the reason (the response echoes the query, so it scales with query length).
6. 🟢6 — claimed: the WHOLE step-4 fence is valid shell (`bash -n` rc 0), achieved by quoting the untouched `cairn recall --repo "<path>"` argument, and pinned by a test over the whole fence with a positive control.
7. Instrument — claimed: two mutants previously scored SURVIVED were VOID (zsh does not word-split, so the suite never ran); re-run isolated with a baseline control, both KILLED by their own named tests.
8. Instrument — claimed: a sweep that restored an UNCOMMITTED file with `git checkout --` destroyed two edits; they were re-applied and the tooling now restores with `cp -a`.

Gate on merged tree f85ace49 (main 8970142d):

  • Tier 2 — the tier the merge gates on — PASS on both, built one derivation at a time: pytests collected=21440 passed=21438 skipped=2 failed=0; nodetests 1449/1449.
  • Tier 1: node PASS (1449/1449); pytest could not complete — killed at gate.sh's 3600s budget mid-test_guard_core.py, with the box at load 74–92 from other sessions. Zero failures: all 16 reporting targets ended N passed, and grep -cE "^FAILED " returns 0 against a positive control that returns 1. This is a throughput limit on this host right now, not a verdict on the code; the sandbox tier ran the same tests hermetically to completion.

round 2 · payload lines changed THIS round: 35 (since round 1: 226) · scaffolding: 163

ZacxDev and others added 2 commits September 9, 2026 01:34
… 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
…clude-own-doc

Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0
@ZacxDev

ZacxDev commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

Round 3 — fixes landed

Round 3 audited f85ace49 and returned no behavioural defect — four 🟢 claim-corrections. All four fixed in 5106446a, merged with main at a56c4e38.

1. F1 — claimed: the verb is CONSOLIDATED, not merely corrected. `widen_or_drop_clause` is the single literal both remedy branches read, so breaking it breaks both; the false comment ("one rule, one place — the phrasing included") is now true rather than reworded.
2. F2 — claimed: the TypeError for `exclude=""` no longer offers `Pass ['']` as its remedy — `[""]` is accepted and filters nothing, i.e. the silent no-op this PR spent three rounds closing. The worked example is suppressed for the empty string and kept for every other refused shape.
3. F3 — claimed: the unscoped-test-count SHAPE is swept at all FOUR sites, not the one reported. Both handoff-doc sentences now name the two-file scope, and a gotcha bullet records that three rounds each fixed one site while the shape survived.
4. F4 — claimed: `_step4_fence`'s stripped-reconstruction residual is NAMED in the docstring (a heredoc added to that fence would make stripped and indented forms disagree), rather than left implicit.
5. Sweep — claimed: 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`.

Note for round 4: these fixes introduced new code, not only prose — widen_or_drop_clause in scripts/lib/handoff_search.py and a narrowed message in _exclusion_list. An audit fix resets the verification gate, which is why a further round runs despite round 3 finding no behavioural defect.

round 3 · payload lines changed THIS round: 50 (since round 1: 276) · scaffolding: 50

ZacxDev and others added 2 commits September 9, 2026 02:00
…-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
…clude-own-doc

Claude-Session-Id: f0fffa8e-a2ab-464e-bd7c-dfe9bd8955f0
@ZacxDev

ZacxDev commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

Round 4 — fixes landed, and the ladder STOPS here

1. 🟢-1 — claimed: the consolidation is pinned STRUCTURALLY, not by text agreement. An AST ledger asserts both renderer branches CALL widen_or_drop_clause and that the verb survives as no literal in render(). Round 4's own surviving mutant (both branches reverted to independent literals, helper unreferenced, 321/321 green) is now killed by test_BOTH_renderer_branches_CALL_the_helper_rather_than_agreeing_by_text.
2. 🟢-2 — claimed: the fifth unscoped-count site is scoped, and the doc bullet now says FOUR quoted counts / FIVE textual sites and tells the reader to grep AND COUNT.
3. 🟢-3 — claimed: the example-suppression is keyed on `.strip()`, the predicate its own comment names, so a blank string no longer gets `Pass [' ']` as its remedy.
4. NOT fixed, filed — `--exclude-slug "  "` is still a silent no-op reachable from the CLI. Recorded as rank 2 in the handoff doc with a closing condition, because the fix is an input rejection at main() (rc 2), i.e. a behaviour change that would reset the gate.
5. Sweep — claimed: run in a DETACHED cp -a copy with .git removed; baseline green 322; E1 and E2 killed by their own named tests; the first E2 attempt returned NO VERDICT (a marker comment commented out a closing paren) and the VOID guard caught it rather than scoring a survivor.

🔴 Why the ladder stops on a stated criterion rather than a clean round

Round 4 returned category (b): only claim-corrections, no behavioural defect. Round 3 did too. Under the findings-keyed rule a round with findings is followed by another round — and round 4 had three — so this stop is taken on the prose-payload criterion, and the reasoning is written here rather than left implicit, because a report that ENDS on that criterion is otherwise indistinguishable from one that converged.

All three conditions hold:

  • No 🔴 and no 🟡 in either of the last two rounds.
  • Blast radius no worse than "a sentence is false" — a test name wider than its assertions, a doc bullet claiming a completed sweep, a suppression predicate narrower than its comment.
  • The recurring shape swept at every site, not the one reported — the unscoped-count shape was chased to all five occurrences and the count itself corrected.

Why the rounds would not stop on their own: the payload here is substantially prose, so "fixed a defect" and "reworded a claim" are the same edit. Each round's fixes write new sentences for the next round to find; that is not convergence, and continuing would be indistinguishable from progress. The attribution gate cannot fire either (payload was 191 → 35 → 50 → 50, never two consecutive zero rounds).

What is deliberately left open is item 4 above, with a closing condition anyone can check.

The ladder, in full

round payload findings behavioural
1 191 10 1 — the flag was deletable to INERT with 304/304 green
2 35 6 2 — a backwards remedy verb; a cross-backend divergence inside the divergence guard
3 50 4 0
4 50 3 0

Three of the four rounds caught coverage claimed and not held — a seam nothing pinned, a "consolidation" that was dead-code-able, a sweep that missed a fifth site, four unscoped test counts. None was a logic bug. The shipped mechanism has been correct since round 1 and has been measured green in every round.

Final gate — merged tree 77698a5b (main 8a9ebba6)

Sandbox tier, the one the merge gates on, built one derivation at a time:

  • pytestscollected=21510 passed=21508 skipped=2 failed=0, RESULT: PASS (exit=0), timeout panics 0
  • nodetestssuites=5 files=41 tests=1449 pass=1449 fail=0, RESULT: PASS (exit=0), timeout panics 0

⚠ The dev-host tier's pytest leg hit gate.sh's 3600s budget on four separate runs, every time with zero failures in the 16–18 targets that reported, under box load 74–98 from concurrent sessions. That is a throughput limit on this host, not a verdict on the change; the sandbox tier runs the same tests hermetically and completed.

Not verified, and no amount of laddering fixes it: anything a real Postgres server does with slug <> ALL(%s) — no test in this repo reaches a database, so those are structural pins over code that was read — and the transcript-derived 23/60, 13/20 and 1/20 yield figures, which are judgement calls made reading sessions and cannot be mechanically re-derived.

@ZacxDev
ZacxDev merged commit 4a67ea7 into main Sep 9, 2026
0 of 2 checks passed
@ZacxDev
ZacxDev deleted the fix/handoff-search-exclude-own-doc branch September 9, 2026 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant