Skip to content

test(mcp): code-index warm-up waits for ready but asserts a fresh search #2391

Description

@ScriptedAlchemy

Symptom

mcp_suite mcp_handler_test::graph_query_test::test_ast_grep_search_respects_public_path_glob failed once on 061cd6267d in a focused run under lane load (hauler ticket cc-5457, unsealed_graph status_behavior_test graph_query_test: 50/51). The panic is not in the ast-grep assertion. It is in the shared fixture warm-up, support.rs:373:

assertion `left == right` failed: {... "freshness":{"indexing":{"latest_generation":"generation.v1.7c902c39.00000001.cf86…","rebuild_in_flight":false,"served_generation":"generation.v1.7c902c39.00000001.cf86…","staleness_state":"verifying","summary":"state=verifying rebuild_in_flight=false … progress=ready 3/3 files"},"state":"possibly_stale"} …}
  left: Object {"indexing": …, "state": String("possibly_stale")}
 right: Object {"state": String("fresh")}

Cause (test race)

wait_for_code_index_generation waits for tracedecay_status wait_for: ready and then asserts that the next tracedecay_search is fresh. ready means a complete generation serves. By the freshness ladder (CodeIndexFreshnessLadderV1::project, pinned by verifying_is_not_a_rebuild), a ready generation with a queued or running verification pass and no source change reads verifying. wait_for_readiness(Ready) requires the worker's pass to be finished (#2365), but a wake that is already queued is not part of that check. Under load the queued pass is still pending or running when the search reads freshness. The product reports this state truthfully. The helper waits for one state and asserts a different one.

The same gap is deterministic when the source changed without a hint: the ready wait returns right away, and the next search answers fresh from the old generation without the edit.

Repro

  • The flake itself: 1 failure in the focused run above. 128 focused runs (16 parallel processes, test binary evicted from page cache before each round) did not reproduce it.
  • Deterministic: write src/warm_probe.rs after the fixture warmed, call warm_code_index_search(&server, "warm_probe_marker"), then search warm_probe_marker. On master the search is fresh on generation …00000001 with no result for the new file (6/6 runs).

Fix

The warm-up waits for fresh, the state it asserts. That wait sweeps the source and requires a settled fresh ladder.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions