search_text returned a confident total: 0 for a literal its own variant scan found in the same reply, and asserted the spellings were DISJOINT searches while behaving separator-insensitively #195

Closed
opened 2026-09-06 16:46:07 +02:00 by buildagent · 1 comment
Member

Found by a triage lane whose conclusions it nearly inverted, then narrowed by that lane withdrawing its own first explanation. Filed at the strength the evidence actually supports: one self-inconsistent reply preserved, not currently reproducing.

The preserved reply

search_text("POPULATION_FLOOR")
{"results":[],"total":0,"next_cursor":null,
 "separator_scan":{
   "matched_as":"literal substring (FTS5 trigram) — a separator is content, not a word break,
                 so this spelling and the ones below are DISJOINT searches",
   "variants":[{"query":"POPULATION-FLOOR","total":0},
               {"query":"POPULATION FLOOR","total":2},
               {"query":"POPULATIONFLOOR","total":0}]}}

Why this is not staleness, provable from that reply alone

search_text returns one row per file, so total counts files.

  • POPULATION FLOOR with a space occurs in exactly one file (precision_gate.rs:983, inside a failure message).
  • POPULATION_FLOOR with the underscore occurs in two files (precision_gate.rs ×5, CLAUDE.md:73).

The failing reply's variant scan reported the spaced form as total: 2. At that instant it therefore matched CLAUDE.md — a file containing only the underscore form. Two consequences follow, both from the single reply:

  1. The index held both files when it returned zero. A stale index cannot answer 2 there. Staleness is refuted without a second observation.
  2. The variant scan behaved separator-INSENSITIVELY while the same reply's matched_as asserts the spellings are "DISJOINT searches" and that "a separator is content". Both cannot be true.

So: the primary query for an exact literal returned 0 while a separator-normalised variant of that same literal simultaneously returned the literal's true file population.

The second, weaker case

search_text("recv_proof") → total: 0, all three variants 0. That is consistent with staleness and cannot be proved independently — but it failed in the same tool-call batch, against the same index, as the case above, so one mechanism is the parsimonious reading rather than two.

Why it matters more than a missing result

The reply was not silent. It shipped an affirmative claim that the literal was searched. The caller was not told "I do not know" — it was told "I looked, and it is not there." A confident zero terminates a search; an absent answer does not.

The concrete cost, from the lane that hit it: "Without a grep cross-check I would have reported #188 and #189 as unimplemented." Two closed-with-evidence issues would have been reported as unbuilt work.

Status, stated honestly

Not currently reproducing. My later calls return 6 and 2; a controlled probe (a file written 8 seconds earlier, queried unquoted, with both a lowercase-underscore and an UPPERCASE-underscore token) found both. So underscore handling, case handling, and watcher latency are each ruled out as the standing mechanism.

That leaves an intermittent or state-dependent path. The obvious hypothesis, worth checking first: a query served while the index is mid-reconcile — see #192, filed today, where two daemon-leg suites failed against a reconciling index and passed in isolation, one signature, two victims.

Two separable pieces of work

  1. The contradiction stands on its own, regardless of index state. matched_as claims the spellings are disjoint searches; the variants demonstrate they are not. That is a false claim a reply makes about its own behaviour and can be fixed without reproducing the zero.
  2. The zero itself needs the reconcile-path hypothesis tested. If confirmed, the fix belongs with #181/#182: a reply whose index cannot answer authoritatively must say so, and a total: 0 from such a state must not render as a measured absence. empty_population already separates "matched nothing" from "a filter emptied it"; this is a third case, and the only one that produces wrong conclusions rather than merely unhelpful ones.

What must NOT be done

  • Do not close this as unreproducible and delete the reply — the matched_as contradiction is a standing defect with or without the zero.
  • Do not "fix" it by making matched_as vaguer. The claim should become true, or the variant scan should stop normalising separators.
  • Do not add a retry. If the reconcile hypothesis holds, a retry hides a disclosure defect behind better odds — the same argument #192 makes against retrying there.

#181 and #182 (the answer does not disclose what produced it), #192 (a reconciling index answering as though settled), #188 and #189 (the two issues this nearly caused to be reported as unimplemented).

🤖 Generated with Claude Code

https://claude.ai/code/session_01K1zj5VcFJvJt3pQxe9259K

Found by a triage lane whose conclusions it nearly inverted, then **narrowed by that lane withdrawing its own first explanation**. Filed at the strength the evidence actually supports: **one self-inconsistent reply preserved, not currently reproducing.** ## The preserved reply ```json search_text("POPULATION_FLOOR") {"results":[],"total":0,"next_cursor":null, "separator_scan":{ "matched_as":"literal substring (FTS5 trigram) — a separator is content, not a word break, so this spelling and the ones below are DISJOINT searches", "variants":[{"query":"POPULATION-FLOOR","total":0}, {"query":"POPULATION FLOOR","total":2}, {"query":"POPULATIONFLOOR","total":0}]}} ``` ## Why this is not staleness, provable from that reply alone `search_text` returns **one row per file**, so `total` counts files. - `POPULATION FLOOR` **with a space** occurs in exactly **one** file (`precision_gate.rs:983`, inside a failure message). - `POPULATION_FLOOR` **with the underscore** occurs in **two** files (`precision_gate.rs` ×5, `CLAUDE.md:73`). The failing reply's variant scan reported the **spaced** form as `total: 2`. At that instant it therefore matched `CLAUDE.md` — a file containing **only the underscore form**. Two consequences follow, both from the single reply: 1. **The index held both files when it returned zero.** A stale index cannot answer 2 there. Staleness is refuted without a second observation. 2. **The variant scan behaved separator-INSENSITIVELY** while the same reply's `matched_as` asserts the spellings are *"DISJOINT searches"* and that *"a separator is content"*. Both cannot be true. So: **the primary query for an exact literal returned 0 while a separator-normalised variant of that same literal simultaneously returned the literal's true file population.** ## The second, weaker case `search_text("recv_proof")` → `total: 0`, all three variants `0`. That is consistent with staleness and cannot be proved independently — but it failed in the **same tool-call batch, against the same index**, as the case above, so one mechanism is the parsimonious reading rather than two. ## Why it matters more than a missing result The reply was **not silent**. It shipped an affirmative claim that the literal *was* searched. The caller was not told "I do not know" — it was told **"I looked, and it is not there."** A confident zero terminates a search; an absent answer does not. The concrete cost, from the lane that hit it: *"Without a grep cross-check I would have reported #188 and #189 as unimplemented."* Two closed-with-evidence issues would have been reported as unbuilt work. ## Status, stated honestly **Not currently reproducing.** My later calls return 6 and 2; a controlled probe (a file written 8 seconds earlier, queried unquoted, with both a lowercase-underscore and an UPPERCASE-underscore token) found both. So underscore handling, case handling, and watcher latency are each ruled out as the standing mechanism. That leaves an **intermittent or state-dependent** path. The obvious hypothesis, worth checking first: a query served while the index is mid-reconcile — see #192, filed today, where two daemon-leg suites failed against a `reconciling` index and passed in isolation, one signature, two victims. ## Two separable pieces of work 1. **The contradiction stands on its own, regardless of index state.** `matched_as` claims the spellings are disjoint searches; the variants demonstrate they are not. That is a false claim a reply makes about its own behaviour and can be fixed without reproducing the zero. 2. **The zero itself** needs the reconcile-path hypothesis tested. If confirmed, the fix belongs with #181/#182: a reply whose index cannot answer authoritatively must say so, and a `total: 0` from such a state must not render as a measured absence. `empty_population` already separates "matched nothing" from "a filter emptied it"; this is a third case, and the only one that produces wrong conclusions rather than merely unhelpful ones. ## What must NOT be done - Do not close this as unreproducible and delete the reply — the `matched_as` contradiction is a standing defect with or without the zero. - Do not "fix" it by making `matched_as` vaguer. The claim should become true, or the variant scan should stop normalising separators. - Do not add a retry. If the reconcile hypothesis holds, a retry hides a disclosure defect behind better odds — the same argument #192 makes against retrying there. ## Related #181 and #182 (the answer does not disclose what produced it), #192 (a `reconciling` index answering as though settled), #188 and #189 (the two issues this nearly caused to be reported as unimplemented). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01K1zj5VcFJvJt3pQxe9259K
Author
Member

REFUTED as filed, and the sentence that misled the reporter is fixed anyway. Merged as cbeb655.

The conclusion does not follow from the evidence. This issue argues that the variant scan behaved separator-insensitively, and therefore that the index held both files when it returned zero. Measured against the FTS5 trigram table, the four spellings return four disjoint sets, and live, search_text("POPULATION FLOOR") does not return the underscore-only file.

The arithmetic that drove the inference — "the spaced form occurs in exactly one file" — is a case-sensitive census. git grep -lic "population floor" at the contemporaneous 1bca87c returns three, two of which spell it lowercase. A spaced total of 2 is therefore fully consistent with the index simply not holding CLAUDE.md, which is the ordinary explanation.

But the reply's matched_as sentence was wrong in exactly the two ways that produced the misreading, so it now states them:

  1. matching is case-folded;
  2. the result sets are not disjoint — one file can carry several spellings, so the totals do not sum to a file census.

The "different literal" half, the part this issue disputed, survives and is now asserted rather than merely claimed. Mutation run: restore the old matched_as → RED, "must say it counted any casing".

So: no product defect of the kind filed, one real prose defect fixed, and a reminder that an inference from a count is only as good as the census it rests on. Closing as refuted-with-fix.

**REFUTED as filed, and the sentence that misled the reporter is fixed anyway.** Merged as `cbeb655`. The conclusion does not follow from the evidence. This issue argues that the variant scan behaved separator-**insensitively**, and therefore that the index held both files when it returned zero. Measured against the FTS5 trigram table, the four spellings return four **disjoint** sets, and live, `search_text("POPULATION FLOOR")` does **not** return the underscore-only file. The arithmetic that drove the inference — "the spaced form occurs in exactly **one** file" — is a **case-sensitive** census. `git grep -lic "population floor"` at the contemporaneous `1bca87c` returns **three**, two of which spell it lowercase. A spaced total of 2 is therefore fully consistent with the index simply not holding `CLAUDE.md`, which is the ordinary explanation. **But the reply's `matched_as` sentence was wrong in exactly the two ways that produced the misreading**, so it now states them: 1. matching is **case-folded**; 2. the result sets are **not disjoint** — one file can carry several spellings, so the totals do not sum to a file census. The "different literal" half, the part this issue disputed, survives and is now asserted rather than merely claimed. Mutation run: restore the old `matched_as` → RED, "must say it counted any casing". So: no product defect of the kind filed, one real prose defect fixed, and a reminder that an inference from a count is only as good as the census it rests on. Closing as refuted-with-fix.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
h-dv/code-index#195
No description provided.