Skip to content

fix(storage): unify direct-search echo detection behind one serialized-text chokepoint - #90

Merged
pablontiv merged 3 commits into
mainfrom
fm/bs-echo-chokepoint-hardening-r1
Sep 12, 2026
Merged

pablontiv merged 3 commits into
mainfrom
fm/bs-echo-chokepoint-hardening-r1

Conversation

@pablontiv

Copy link
Copy Markdown
Owner

Summary

Structural hardening of the echo-exclusion bug class (#64, PRs #86/#87/#89). The class was caused by 5–6 independent recognizers of "is this row a direct Backscroll search echo" across three representations, kept in sync only by prose "keep in lockstep" comments. This PR ships the approved fix: generalize the broad-SQL-prefilter + strict-Go-predicate split (proven for the Codex shell form in #87/#89) to all three serialized shapes, and give the boundary exactly one owner.

What changed

  • New chokepoint: directsearch.IsSerializedDirectSearchCall owns all three stored shapes — bash, exec_command, and the Codex shell wrapper (JSON argv decode moved here unchanged). No token-count floor before the shell decode (an all-escaped argv serializes to two tokens).
  • isDirectBackscrollSearchEcho is now SearchEcho || IsSerializedDirectSearchCall(text) behind the existing content_type guard — hand-rolled token indexing and the PR-fix(storage): exclude zero-valued Codex shell echoes from unfiltered search and relax IDF #89 guard-ordering hazard deleted.
  • SQL/Go equivalence-by-convention eliminated: directBackscrollSearchEchoSQL and unmarkedDirectSearchCallSQL (GLOB patterns with an ASCII-only separator alphabet) replaced by one shared, provable-superset prefilter (content_type='tool' AND COALESCE(search_echo,0)=0 AND text LIKE '%backscroll%' — every accepted shape contains the literal substring) + the Go chokepoint as the strict pass, for both call sites (recallFrequency IDF counting and PendingSearchEchoPaths/stalePaths requeue detection). This closes the NBSP/U+2028/U+2029/U+3000 page/IDF divergence as a class — no separator-alphabet point patch.
  • Dead code deleted: excludeDirectBackscrollSearchEchoes (no production caller); its boundary test rewired onto the production refillCandidatesWithoutDirectEchoes path.

Tests

  • RED → GREEN spike-first: new internal/storage/echo_parity_test.go generates shape {bash, exec_command, shell} × separator alphabet {ASCII controls, NBSP, U+2028, U+2029, U+3000, repeated/mixed runs} × leading/trailing runs and asserts three-way agreement (unfiltered page exclusion == --relax IDF exclusion == requeue detection). 48 subtests diverged on the old code; all pass now. Negative controls (status/searcher subcommands, absolute paths, env wrappers, folded case, nested bash -lc, prose mentions) unchanged. Spike note: docs/research/2026-09-12-echo-chokepoint-spike.md.
  • TestRecallFrequencySQLEchoPredicatePreservesBoundaries → TestEchoBoundaryCasesThreeWayParity: the SQL-equivalence column is obsolete by design (no SQL shape predicate remains); gained the requeue leg instead.
  • Mislabeled fixture fixed: "shell NBSP separator" carried plain ASCII spaces; now uses an explicit   escape (verified bytewise; runtime text carries raw 0xC2 0xA0 through the real json.Marshal + SerializeToolInput round-trip).
  • New unit table for the chokepoint in internal/directsearch/directsearch_test.go.
  • just ci green (aggregate coverage 86.6% ≥ 85%); all prior echo-exclusion regressions (fix(search): requeue search_echo=0 Codex and OpenCode calls #85–fix(storage): exclude zero-valued Codex shell echoes from unfiltered search and relax IDF #89) still pass. No schema migration; ordinary search behavior/output unchanged.

Docs

docs/search.md#query-echo-handling, the --relax section, and the regression-owner list now describe the single-chokepoint architecture; AGENTS.md's stale "keep in lockstep" paragraphs were rewritten to the shared-code-path description.

Out of scope (per captain decision)

Pi's unpaired-result-rows gap stays unbuilt — tracked separately as bs-echo-pi-result-unmarked-r1.

Note for local runs

cmd/backscroll/search_relaxation_echo_idf_e2e_test.go asserts !strings.Contains(out, "echo-") on full output paths; if your GOTMPDIR/temp root contains the substring echo-, the test fails on the temp path itself (pre-existing fragility, reproduces on unmodified main). Not caused by this PR.

🤖 Generated with a firstmate crewmate worker

…d-text chokepoint

The echo-exclusion bug class (#64, PRs #86/#87/#89) was caused by 5-6
independent recognizers of "is this row a direct backscroll search echo"
across three representations, kept in sync only by prose comments:

- isDirectBackscrollSearchEcho: hand-rolled bash/exec_command token checks
  plus a shell-only decode fallback
- directBackscrollSearchEchoSQL (recallFrequency IDF): SQL GLOB with an
  ASCII-only separator alphabet, shell form not matched at all
- unmarkedDirectSearchCallSQL (PendingSearchEchoPaths requeue): the same
  GLOB, plus a separate 'text LIKE shell %' prefilter for shell
- excludeDirectBackscrollSearchEchoes: dead duplicate with no production
  caller

strings.Fields accepts every unicode.IsSpace rune (NBSP, U+2028/2029,
U+3000, ...), so any separator outside the SQL alphabet — or any shell row
with leading whitespace under the anchored LIKE — made pages exclude a row
that IDF counting and requeue detection kept. Point-patching the SQL
whitespace alphabet cannot close this class.

Replace all of it with the broad-SQL-prefilter + strict-Go-predicate split
PRs #87/#89 proved for the shell form, generalized to every shape:

- directsearch.IsSerializedDirectSearchCall is the single strict predicate
  owning all three serialized shapes (bash, exec_command, shell argv
  decode); the shell decode moved here unchanged.
- recallFrequency and PendingSearchEchoPaths share one provable-superset
  prefilter (content_type='tool', search_echo zero, text LIKE
  '%backscroll%') and apply the chokepoint in Go; no SQL-side shape
  recognizer remains to drift.
- isDirectBackscrollSearchEcho is now SearchEcho || chokepoint, deleting
  the token indexing and the guard-ordering hazard.
- Dead excludeDirectBackscrollSearchEchoes removed; its boundary test
  rewired onto the production refill path.

Tests: new internal/storage/echo_parity_test.go asserts three-way
page/IDF/requeue agreement over shape x separator alphabet (ASCII controls,
NBSP, U+2028/2029, U+3000, raw vs JSON-escaped) x leading/trailing runs
(RED on the old code: 48 diverging subtests, GREEN now); the boundary
corpus in relaxation_echo_idf_test.go lost its SQL-equivalence column and
gained the requeue leg; the mislabeled "shell NBSP separator" fixture now
carries a real U+00A0 via an explicit escape (verified bytewise).

Spike note: docs/research/2026-09-12-echo-chokepoint-spike.md.
No schema migration. Ordinary search behavior/output unchanged; all prior
echo-exclusion regressions (#85-#89) still green.
…oll substring

Independent review of the chokepoint PR found the broad SQL prefilter
(text LIKE '%backscroll%') was a provable superset of the strict Go
predicate for the bash/exec_command shapes but not for the Codex shell
shape: the argv is stored as raw, un-decoded JSON bytes, so a JSON
\u-escaped letter of "backscroll" (e.g. \u0062ackscroll) would be
accepted by IsSerializedDirectSearchCall after decoding yet missed by
the prefilter — a one-row-wide three-way divergence.

The guard makes the documented provable-superset claim true for every
shape; it folds ASCII case to match LIKE semantics. Regression coverage:
unit case in directsearch plus a three-way parity corpus entry asserting
page, --relax IDF, and requeue agree (on not excluding the row).
Round-2 review found the round-1 guard folded case the wrong way for a
superset guarantee: Go's strings.ToLower folds U+212A KELVIN SIGN to 'k',
but SQLite LIKE folds only ASCII A-Z, so a row with an escaped-letter shell
argv plus a BAC<KELVIN>SCROLL near-miss elsewhere in the text passed the
guard while remaining invisible to the prefilter — the same three-way
divergence one code point over.

Case-sensitive strings.Contains(text, "backscroll") needs no folding
reasoning at all: literal-lowercase-substring present implies LIKE matches,
full stop, and every real-encoder row accepted by the predicate contains
the literal by construction (verified non-narrowing by the reviewer's
391,300-input differential). Regression fixture added to the parity
negatives; verified RED against the round-1 guard, GREEN here.
@pablontiv
pablontiv merged commit 474cfa8 into main Sep 12, 2026
8 checks passed
@pablontiv
pablontiv deleted the fm/bs-echo-chokepoint-hardening-r1 branch September 12, 2026 17:07
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