Repository navigation
P0: Unchanged valid graphs block first MCP retrieval during startup reconciliation #564
Description
Problem
A real activation test against openstatusHQ/openstatus with the published @lubab/madar@0.31.3 artifact showed that a complete, policy-matching, unchanged graph is unavailable during every fresh madar serve --stdio --auto-refresh startup.
The OpenStatus worktree had approximately 2,443 indexed files and a 23 MB graph. There were no source changes after generation. Even so:
startGraphAutoRefresh()forcedrebuildOnStart: true;- graph-backed requests were rejected while startup status was
starting/reconciling; - direct protocol tests needed approximately 15.7-15.8 seconds before
statsbecame ready; - a real Claude Sonnet session retried the same Madar request four times, exhausted the advertised 1-second retry guidance, and fell back to 34 raw repository operations;
- after the fallback, watcher state was healthy:
idle,coverage=complete, policy fingerprints matched, and no stale refresh lease remained.
This is separate from #561. That issue fixed dead/live refresh-lease coordination and explicitly left serving or reusing a last-known-good graph as a non-goal.
Root cause
startGraphAutoRefresh() always starts watch(..., { rebuildOnStart: true }), while autoRefreshGraphReadiness() requires startup completion plus watcher status idle before any graph read. A valid unchanged graph therefore pays a full initial update and is treated as unusable until it completes.
Expected behavior
- Validate an existing graph, stored generation policy, and persisted source snapshot quickly at startup.
- If the graph is complete, policy-matching, and the source snapshot is unchanged, mark it ready immediately and start watching without an initial rebuild.
- If sources changed, reconcile incrementally before claiming full freshness.
- Prefer bounded server-side waiting/queuing for the first graph request during a genuine short reconciliation rather than requiring an agent to issue rapid retries.
- Continue to fail closed when no valid graph exists, coverage is incomplete, generation policy mismatches, or reconciliation genuinely fails.
Acceptance criteria
- An unchanged valid graph does not run an unconditional initial rebuild.
- An unchanged OpenStatus-sized graph accepts its first graph-backed request within 5 seconds on the documented test machine.
- A changed source file still triggers reconciliation and is not falsely reported as fresh.
- A missing graph, incomplete graph, or policy mismatch remains blocked until repaired.
- A graph request arriving during a genuine short reconciliation can wait for a bounded readiness deadline without requiring repeated client retries.
- MCP control methods remain responsive throughout startup and reconciliation.
- Existing dead-owner recovery, live-owner contention, and terminal rebuild-failure guarantees from P0: Auto-refresh becomes permanently unavailable after refresh lease contention #561 remain intact.
- Regression tests cover unchanged startup, changed startup, policy mismatch, missing graph, readiness timeout, and clean shutdown.
- A packed-artifact OpenStatus receipt records startup time, request count, readiness states, and raw fallback count.
Relevant code
src/infrastructure/watch.tssrc/infrastructure/watcher-state.tssrc/runtime/stdio-server.tstests/unit/background-auto-refresh.test.tstests/unit/stdio-server.test.ts
Non-goals
- Silently serving a graph whose source snapshot is known to be stale.
- Weakening policy or completeness checks to improve startup numbers.
Activity
mohanagy commentedon Jul 17, 2026
Implementation is now in draft PR #566.
Packed OpenStatus acceptance passed from a clean detached worktree: MCP initialized in 586 ms, the first and only graph-backed request completed in 3,893 ms, and the unchanged 24,446,369-byte graph was not rebuilt. The PR also adds changed/new/deleted/control-file, ignored-path, wait/timeout, and shutdown regressions.
Keeping this issue open until the PR is reviewed and merged.
mohanagy commentedon Jul 18, 2026
Implemented and verified in #566 (merged as e8f7d1d). The acceptance receipt and regression coverage are included in that PR.