Two daemon-leg suites fail on a reconciling index and pass in isolation: one signature, two victims, so it is a missing barrier and not a flake #192
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#192
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?
Found by a lane that was auditing something else, and reported rather than retried — which is the only reason the shape is visible.
Measured
COSI_E2E_LEG=daemon cargo test -p code-index-mcpfailed on two consecutive runs, on a DIFFERENT test each time:index_coverage_facts_e2ecoverage_reasons: ["index_reconciling"]activation_offer_e2e"state": "reconciling",files: 0Both pass in isolation — 3/3 and 2/2 respectively.
Why this is not a flake to retry
Two different victims with one signature is the tell. A flaky test is a property of the test; a shared signature across unrelated suites is a property of the harness. Both assertions ran while the index was still reconciling, and both then described exactly that state — correctly. The product was not wrong; it was asked too early, and it said so.
Note what that means: the disclosure did its job.
index_reconcilingandstate: "reconciling"are the honest answers to "what do you know right now", and the tests treated them as failures because they expected a steady state they never waited for.The fix is a barrier, not a retry
A retry would make the symptom rarer and the diagnosis worse: it converts "the harness has no steady-state precondition" into "this test is occasionally slow", and the next suite to grow an early assertion inherits the same defect silently. What is needed is an explicit wait-for-steady-state before the assertion, with the wait itself able to FAIL — a barrier that gives up must say it gave up on the clock, not return and let the assertion speak for it.
This repo already owns the right idiom.
Phase::settlereturns how it stopped —Quiesced,StalledorDeadline— and callers assert they never stopped onDeadline; the payload-budget suites use it precisely so that "measured a server mid-pass" cannot masquerade as a measurement. That is the shape to reuse here.Do not fix this by asserting
reconcilingis acceptable in these two tests. That widens the assertion to accept the state it exists to exclude, and both suites are about what a caller SEES — a caller that getsfiles: 0because the index is mid-rebuild has been told something true and useless, which is the situation the offer surface is supposed to make legible.Scope worth checking while fixing
The two victims were found by two runs. The population is "every daemon-leg suite that asserts on index content without a steady-state precondition", and nobody has enumerated it. Treat two as a floor: grep the daemon leg for assertions that read
files,coverage_reasons,offersorstatewithout a preceding settle, and report the count. An audit that fixes two and leaves eight is the same defect with better odds.Related
#131 (the two settle guards), #126 (a ratchet whose failure mode was contention, closed by measuring under contention rather than by widening), and the session rule that a correctness suite cannot see a slowdown — this is its mirror: a correctness suite that measures a transient state and calls it a result.
🤖 Generated with Claude Code
https://claude.ai/code/session_01K1zj5VcFJvJt3pQxe9259K
total: 0for a literal its own variant scan found in the same reply, and asserted the spellings were DISJOINT searches while behaving separator-insensitively #195FIXED in
38ccbd2, merged asa3f2218.The root cause was one layer above the two victims this issue names. It was not two suites needing a wait; 31 suites and 99 assertions were running unbarriered against a
reconcilingindex, and the two that failed were simply the two whose timing exposed it. Fixing those two would have left the other 29 to fail later, on a different machine, looking like a new bug each time.So the barrier is shared and its population is PINNED rather than described:
LEG_ROUTED_USING_SHARED_INITIALIZE = 35inharness_settle_barrier.rs, with the three arrivals since named individually (answer_provenance_e2efor #181/#182,corpus_link_e2efor #191,line_text_e2efor #183) instead of absorbed into a bumped number. A count that moves without saying who moved it is how this class hides.Mutation run: 35 -> 34 gives exit 101,
left: 35 right: 34; restored, exit 0.Closing.