Problem
Madar currently detects when a graph is stale, but normal users must manually run madar generate . --update or keep madar watch . running. Agent installs provide routing guidance, not graph maintenance.
That breaks the expected agent-first workflow:
- An agent uses Madar to understand the repo.
- The agent (or a second agent, IDE, Git, or script) changes many files.
- A later Madar request can rely on an old graph unless the user remembered to refresh it.
Desired contract
Install Madar once; any supported workspace change is reflected before Madar gives its next graph-backed answer.
Normal users should not have to remember a refresh command. The graph need not rebuild after every keystroke, but Madar must not silently present stale graph context as current.
Why session-end is not the primary trigger
A rebuild only at agent-session end is insufficient:
- the same agent may ask follow-up questions after edits;
- another agent may query the repo before the first session ends;
- agent sessions can crash or be terminated without a reliable end event;
- IDE edits, Git operations, scripts, and other agents are outside one agent's lifecycle.
Session-end / post-write hooks can be a best-effort flush optimization, not the source of truth.
Proposed lifecycle
workspace source/config edit
-> one project-local refresh controller observes/marks it dirty
-> debounce and coalesce edits
-> one serialized incremental or full rebuild
-> validate the input snapshot
-> atomically publish a new graph generation
-> MCP resolves that generation on its next request
- Enable an automatic sync mode through
madar <agent> install, without requiring a separate foreground command for normal use.
- Use filesystem observation as the cross-agent source of truth; agent hooks may submit a lightweight dirty/flush request but must not run a full build synchronously.
- Before a graph-backed MCP response, perform a final freshness check. If a rebuild is pending or an event was missed, wait/refresh or explicitly return a refreshing/stale state instead of answering from an old graph.
- Coalesce bursts of edits (for example, a short debounce) and use incremental updates only when safe; use a conservative full rebuild for config, rename/delete, framework, or uncertain dependency changes.
- Expose
fresh, dirty, refreshing, and failed in madar status. Keep manual refresh as an escape hatch.
- A persistent daemon can be optional later; an agent-session-owned controller plus an on-demand freshness gate is a reasonable first UX.
Correctness and concurrency requirements
Do not let each MCP subprocess or agent independently rebuild out/.
- One repo-local owner/lease must serialize refreshes and coalesce changes that occur during a build.
- Build into a temporary immutable generation, validate it, then atomically switch the active generation/pointer.
- Readers must keep seeing the last known-good graph if a refresh crashes or is interrupted.
- Capture input fingerprints before and after a build; if the workspace changed during extraction, discard/requeue rather than marking a mixed snapshot fresh.
- Reconcile filesystem events with an authoritative fingerprint/discovery pass, including build-affecting config/ignore files and large repositories.
Existing foundations
madar watch already observes changes, debounces them, and invokes an incremental rebuild.
- The stdio MCP server already reloads a graph when its artifact changes.
- Freshness metadata and
--require-fresh-graph already provide a basis for the read-time correctness gate.
The missing work is making this lifecycle automatic, singleton-safe, and atomically published.
Acceptance criteria
- An edit made by Claude, Codex, Cursor, an IDE, Git, or a shell is reflected before the next freshness-required graph request, without a user command.
- Multiple agents changing/querying one repo result in one coordinated writer and no partial JSON, lost update, or mixed generation.
- A crash during refresh leaves the previous graph queryable and reports the repo as dirty/failed.
- Changes during a refresh cause one follow-up refresh rather than being lost.
- Build-affecting configuration changes and watcher coverage limits are surfaced and reconciled.
- Existing manual
generate / watch flows remain supported.
Problem
Madar currently detects when a graph is stale, but normal users must manually run
madar generate . --updateor keepmadar watch .running. Agent installs provide routing guidance, not graph maintenance.That breaks the expected agent-first workflow:
Desired contract
Install Madar once; any supported workspace change is reflected before Madar gives its next graph-backed answer.
Normal users should not have to remember a refresh command. The graph need not rebuild after every keystroke, but Madar must not silently present stale graph context as current.
Why session-end is not the primary trigger
A rebuild only at agent-session end is insufficient:
Session-end / post-write hooks can be a best-effort flush optimization, not the source of truth.
Proposed lifecycle
madar <agent> install, without requiring a separate foreground command for normal use.fresh,dirty,refreshing, andfailedinmadar status. Keep manual refresh as an escape hatch.Correctness and concurrency requirements
Do not let each MCP subprocess or agent independently rebuild
out/.Existing foundations
madar watchalready observes changes, debounces them, and invokes an incremental rebuild.--require-fresh-graphalready provide a basis for the read-time correctness gate.The missing work is making this lifecycle automatic, singleton-safe, and atomically published.
Acceptance criteria
generate/watchflows remain supported.