answer_provenance names a commit the INDEX has not reached, so a watcher-lag miss and a measured absence are indistinguishable #260
Labels
No labels
code-review
correctness
dos
performance
security
severity/high
severity/low
severity/medium
tech-debt
Kind/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
h-dv/code-index#260
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What happened
Live, during the Lane P merge verification on
5b14a79.I merged, then ~25 s later asked:
The reply was
total: 0, with:grep -con disk at that moment: 4. Twenty-five seconds later the identicalquery returned those 4 matches (lines 26, 73, 123, 202) plus
CLAUDE.md:89.Both of the matching files are files the merge had just written. The index had
not caught up; the daemon was under a
cargo test --workspacerun and twoconcurrent corpus indexes.
Why this is a finding and not just watcher lag
The lag is expected and documented. What is not defensible is that every
disclosure beside the zero read clean:
answer_provenance.indexed_trees.primary=head: 5b14a79368d2,uncommitted_changes: false— i.e. "the tree I read is exactly this commit,with nothing uncommitted". It was not. The content answered from was
pre-merge.
empty_population.basis: "measured"— whichdocs/answer-provenance.mditself calls "this server's strongest claim …the only zero that is evidence of absence" (
docs/reason-codes).So the strongest claim in the product was false, and the block whose title is
"which build answered, which tree it had read" asserted the wrong tree.
headanduncommitted_changesare both read from git. Nothing in theblock is derived from the index, so no field in it can move when the index is
behind.
sibling_worktrees: 3was the only hint anything was off, and it isabout a different hazard entirely (#220/#238).
This is exactly the shape #182 forbids, one level deeper. The doc's rule is:
The block guards working tree vs commit. It has no guard for index vs
working tree — and that is the gap an agent hits at exactly the worst moment:
right after it wrote the file it is asking about.
Repro
cargo test --workspaceis enough).git mergeor write a file introducing a literal that appears nowhere else.search_textfor that literal.total: 0,basis: "measured", and ananswer_provenancenamingthe new HEAD with
uncommitted_changes: false.The window widens with load, which is when an agent is most likely to be
mid-task.
Shape of a fix
The machinery already exists: the I034 freshness barrier computes staleness,
doctorreports index freshness, andindex_healthis per-file. None of itreaches
answer_provenance.Add a fourth key to each
indexed_treesentry, three-state, followingsibling_worktrees' own measured rule that agreement emits nothing (analways-emitted
0there cost the plugin-wpf bench 578 tokens / 5.2 %):headindex_lag: { files: <n>, oldest_unindexed_age_ms: <n> }index_lag_unmeasured: "<why>"0And on a
basis: "measured"zero,empty_population.unsearchedmust narrowits quantifier in the same breath it makes the claim, the way #238 made it do
for
other_checkouts— a measured absence taken against a lagging index isnot an absence.
Anti-vacuity for the test
A test that writes a file and asserts the disclosure fires must prove it could
have not fired: assert the key is ABSENT on a settled index over the same
tree, then write and assert it PRESENT with a non-zero
files. A test thatonly ever sees the busy case grades nothing — and a test that asserts on a
quiet single-file tree will never reproduce the lag at all, which is the
corpus_watcher_replaypath, not a unit test.Notes
answering about their own repository — which is where CLAUDE.md says such a
gap is a finding about the product, not an inconvenience.
tree), #238 (the zero says so).
Relationship to #245 — adjacent, and this one disproves its carve-out
#245 is the same block and the same axis, and the two must not be read as
duplicates. Stated precisely:
basis: "measured"zero#245 explicitly sets this case aside:
That carve-out does not hold, and this issue is the measurement. The
reply here carried no staleness disclosure of any kind.
index_staleisthe I034 freshness barrier, which gates
changed_symbolsandreview_diff;search_texthas no such door and emitted nothing. So"the watcher is behind" is disclosed on some tools and silent on the
one whose answer was a counted absence.
Both fixes land in the same struct, and doing them together is cheaper
than doing either twice:
indexed_trees[<project>]gains the generation(#245) and an index-lag disclosure (this), both three-state, both
absent-on-agreement. The generation integer alone does not close this
one — it makes two replies comparable but still lets a single
basis: "measured"zero assert an absence the index could not haveseen.
The headroom constraint #245 records applies here unchanged: this must
be an absent-when-level key, not a per-reply paragraph.
code-index-plugin-hostcannot say which build it is — three of four shipped binaries answer--version, the fourth exits 21 with usage #262Released in v0.28.1, build
340a75a, via #264 and #265. Release CI passed, including the Windows archive round-trip smoke test. Freshness is a bounded working-tree observation with explicit lag/incompleteness, rather than a claim that git HEAD identifies indexed content. The installed public binaries passed both arms: a settled text miss reported metadata agreement; after adding a text-only file, the unchanged zero reported lag with added > 0 and narrowed empty_population scope to say working-tree absence was not established. The daemon subsequently indexed the new text and a later symbol edit. Observation timestamps were checked across the cache refresh. Closing the shipped disclosure fix.buildagent referenced this issue2026-09-11 20:25:15 +02:00