Repository navigation
fix(mcp): run post-processing during auto-watch updates - #1108
3 commits merged into
Conversation
|
Thank you for this PR. I tested it with a real Before I can merge it, please fix these:
After you push the fix, I will test it again. |
Start the filesystem observer before startup reconciliation so edits made during post-processing are captured. Serialize startup work and event batches through the same processor lock, and prevent the initial debouncer wake-up from being lost. Add regression coverage for startup edits, event serialization, and first-event delivery.
|
Thanks for reproducing the startup issue and providing the regression test. I've pushed the follow-up fix in Root cause and fix The observer previously started after startup reconciliation and post-processing. Edits made during that interval were not captured, leaving affected files stale until another update. The fix:
Before vs. After sequenceDiagram
participant U as Editor
participant W as Startup
participant O as Observer
participant G as GraphStore
Note over W,O: BEFORE
W->>G: Reconcile files
W->>G: Post-processing
U->>U: Save file during startup
Note over O: Not started — event missed
W->>O: Start observer
Note over G: File remains stale until another update
sequenceDiagram
participant U as Editor
participant W as Startup
participant L as Processor Lock
participant O as Observer
participant D as Debouncer
participant G as GraphStore
Note over W,G: AFTER
W->>D: Start debouncer
W->>L: Acquire
W->>O: Start observer
W->>G: Reconcile files
W->>G: Post-processing
U->>O: Save file during startup
O->>D: Capture and buffer event
D->>L: Batch waits for lock
W->>L: Release
L-->>D: Lock acquired
D->>G: Update graph + refresh FTS
D->>L: Release
Verification
The changes are ready for your retest. Thanks again for the detailed reproduction. |
|
One additional finding from the shutdown/concurrency review: I opened a separate issue, #1121 — MCP auto-watch can close GraphStore while its watcher is still active. The MCP shutdown path currently closes This is a pre-existing defect, not introduced by #1108. However, the additional watcher post-processing in this PR may increase the exposure window; that impact has not been measured. I've kept the shutdown fix out of #1108 to preserve its scope. No SQLite crash or data corruption from MCP shutdown has been demonstrated. Would you prefer to merge #1108 independently and address #1121 in a follow-up PR, or resolve the shutdown lifecycle issue before merging #1108? |
There was a problem hiding this comment.
🟡 Changes recommended
A critical startup race allows queued event batches to write to a rejected foreign-root graph during cleanup; repository-root validation must precede observer creation, with regression coverage for queued events.
1 open issue
Review effort: Balanced
| if initial["files_updated"] > 0 and on_files_updated is not None: | ||
| postprocess_result = on_files_updated(store) | ||
| _raise_watch_postprocess_warnings(postprocess_result) | ||
| observer = Observer() |
There was a problem hiding this comment.
Thanks for catching this. Confirmed and fixed in [650510a](https://github.com/tirth8205/code-review-graph/commit/650510a7fd63df816e95d50c5bde3856838367bf).
The root cause was that the observer could queue an event before startup reconciliation rejected a foreign-root graph. Once the startup lock was released, the queued batch could bypass root validation via reconcile_stale=False and write to the wrong graph.
The fix moves repository-root validation before observer initialization, while preserving observer-first reconciliation for valid repositories.
Verification:
- Independently reproduced the original race with actual writes to a disposable foreign-root database (RED → GREEN).
- Added regression coverage for queued events and foreign-root rejection.
- Confirmed the maintainer's startup-window test still passes.
- Full local suite: 4,283 passed; Ruff and mypy passed.
Both GitHub Actions workflows are currently awaiting maintainer approval, so CI has not run yet.
Thanks again for the review!
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Legend icons were stretched to 104px by the page-wide svg rule, so the legend filled the screen and a sixth node kind pushed it under the filter panel. This is older than the train, and the icons are now 16px. Two tests also depended on their platform: Python 3.10 accepts the deep expression (#1133), and Windows paths have backslashes (#1108). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0160eb0
… of tirth8205#1108) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… post-processing Both PRs change start_watch_thread and main(). Keep the callback and the stop event. Tests that ended the watcher with a patched time.sleep now use the stop event, because the loop no longer sleeps when one is given. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…irth8205#1108) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Pull Request
Linked issue
Closes #1103
What & why
MCP
serve --auto-watchupdated graph nodes without refreshing derived indexes, leaving FTS inconsistent with the graph.Original root cause: MCP startup did not supply the existing
run_post_processingcallback, andstart_watch_thread()did not forward it towatch().Additional startup issue identified during review:
watch()ran startup reconciliation and post-processing before starting the filesystem observer. Edits made after reconciliation but before observer startup were not captured, leaving affected files stale until another update.Changes:
daemonargument compatibility.EventDebouncerwith a small project-local_WatchDebouncer. Its initial condition wait checks pending events and stop state under the same lock, preventing an early notification from being missed.The follow-up production changes are confined to
code_review_graph/incremental.py. The original callback-wiring fix remains intact.Recovery of previously stale indexes remains outside this PR and is tracked separately in #1104.
How it was tested
test_edit_saved_during_startup_postprocessing_reaches_graphpasses with itsxfailremoved. Its behavioral assertions are unchanged.review/pr-1108pass without modification, verified on Python 3.11 and 3.13.serve --auto-watchskips FTS post-processing after file updates #1103 regression tests: All five pass, covering callback wiring, startup reconciliation, and create/modify/delete events.The follow-up was not tested against the maintainer's full 17k-node workload or on Linux/Windows.
Commands executed:
The original #1103 implementation was also smoke-tested with a real MCP stdio server and a native WSL2 filesystem event, with no missing or stale FTS IDs observed.
Checklist