Skip to content

P0: Unchanged valid graphs block first MCP retrieval during startup reconciliation #564

Closed

Description

@mohanagy

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() forced rebuildOnStart: true;
  • graph-backed requests were rejected while startup status was starting / reconciling;
  • direct protocol tests needed approximately 15.7-15.8 seconds before stats became 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.ts
  • src/infrastructure/watcher-state.ts
  • src/runtime/stdio-server.ts
  • tests/unit/background-auto-refresh.test.ts
  • tests/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.

Related

Activity

  1. mohanagy commented on Jul 17, 2026

    @mohanagy
    OwnerAuthor

    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.

  2. mohanagy commented on Jul 18, 2026

    @mohanagy
    OwnerAuthor

    Implemented and verified in #566 (merged as e8f7d1d). The acceptance receipt and regression coverage are included in that PR.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions