Skip to content

feat(runtime): preserve writers during ordinary watcher startup - #399

Merged
bompus merged 1 commit into
fork/consolidatedfrom
fix/ordinary-watcher-startup
Oct 6, 2026
Merged

bompus merged 1 commit into
fork/consolidatedfrom
fix/ordinary-watcher-startup

Conversation

@bompus

@bompus bompus commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

Ordinary checkout startup previously had to use replacement-oriented MCP launch or promotion control, and a readable daemon did not prove that its watcher was active. Add startRuntimeWatcher(root, {expectedVersion, cliPath, runtimePath?, timeoutMs?}) and serve --mcp --path <root> --preserve-existing for startup that preserves existing writers.

The ordinary operation returns only after verifying the exact canonical root, build, active watcher, MCP status and unchanged daemon/writer ownership. Preservation covers initial connection, detached election, default and explicit project activation, fallback reads and reconnect. Live, legacy, uncertain, wrong-build, direct and promotion owners remain untouched. Timeouts leave a possibly shared daemon to its existing idle lifecycle.

Validation passed: 74 focused runtime-control, writer-lock and explicit-project lifecycle tests; the full engine/UI suite with 7,522 tests passed and 39 skipped across 587 files; TypeScript tsc --noEmit; kernel rules; agent-document size; whitespace. Reversing the writer-generation guard and disabling read-only fallback produced the intended successor-preservation and older -> older -> older failures. Both mutations were restored before the full suite. Lifecycle CI passed on Linux, Windows and macOS at this head.

README review covered the About this fork runtime-policy paragraph and embedding/runtime section. Language, framework and measured-result rows are unchanged. The API reference and Unreleased changelog describe the new operation. No installer, dependency, artifact promotion or installed-runtime change is included.

@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository YAML (base), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b0dfe6b5-ea85-47ed-a53a-c5cdaff3a7c2
📥 Commits

Reviewing files that changed from the base of the PR and between c2c196c and f82a0ea.

📒 Files selected for processing (14)
  • CHANGELOG.md
  • README.md
  • __tests__/mcp-projectpath-lifecycle.test.ts
  • __tests__/runtime-control.test.ts
  • __tests__/writer-lock.test.ts
  • site/src/content/docs/reference/api.md
  • src/bin/codegraph.ts
  • src/mcp/daemon-paths.ts
  • src/mcp/daemon.ts
  • src/mcp/engine.ts
  • src/mcp/index.ts
  • src/mcp/project-lifecycle.ts
  • src/mcp/writer-lock.ts
  • src/runtime-control.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Summary

Summary by CodeRabbit

  • New Features
    • Added --preserve-existing for MCP serving. When enabled, existing or uncertain daemons are left untouched; if a shared daemon cannot be verified, the connection provides read-only access.
    • Added runtime watcher startup that can reuse a verified watcher or start one when no existing owner is detected. Startup requires a ready index for the exact project root and a compatible build.
  • Documentation
    • Updated CLI and API documentation with watcher startup requirements, readiness checks, and preserve-existing behavior.

Walkthrough

The change adds runtime APIs for starting or reusing a verified watcher. It also adds an MCP option that prevents replacement of existing or uncertain daemon and writer owners, with exact-root checks and read-only fallback behavior.

Changes

Watcher and daemon lifecycle

Layer / File(s) Summary
Preserve uncertain writer records
src/mcp/writer-lock.ts, src/mcp/project-lifecycle.ts, __tests__/writer-lock.test.ts
Writer-lock acquisition can preserve uncertain records and checks for changes before stale-record cleanup. Project leases pass this setting to fallback lock acquisition. Tests cover uncertain records and changed successors.
Verify exact-root watcher readiness
src/mcp/daemon.ts, src/mcp/daemon-paths.ts, src/mcp/engine.ts, src/runtime-control.ts, __tests__/runtime-control.test.ts, site/src/content/docs/reference/api.md
Daemon hello messages report watcher root and state. Runtime identity and readiness checks can require an active, ready watcher for the exact root and verify daemon and writer ownership.
Start or reuse a runtime watcher
src/runtime-control.ts, __tests__/runtime-control.test.ts, README.md, site/src/content/docs/reference/api.md
startRuntimeWatcher validates the build, paths, and exact-root index, then reuses or launches a daemon and waits for verified watcher readiness. Tests and docs cover validation, election, races, and timeouts.
Preserve existing MCP owners
src/bin/codegraph.ts, src/mcp/index.ts, src/mcp/daemon.ts, src/mcp/engine.ts, __tests__/mcp-projectpath-lifecycle.test.ts, __tests__/runtime-control.test.ts, README.md, site/src/content/docs/reference/api.md, CHANGELOG.md
The MCP server and CLI accept preserveExisting and --preserve-existing. Preserving startup requires an initialized exact-root index, avoids replacement and takeover, and uses read-only fallback when it cannot verify a shared daemon.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to f82a0

No actionable ownership or watcher-startup issue remains identified. Complete the required platform lifecycle CI before landing.

Security Architecture Review

Security architecture risk: 🔵 Low · up to f82a0

Startup adds stronger checkout-readiness checks and preserves existing owners. No newly introduced ownership bypass was established, but validation of the latest lifecycle changes across supported platforms remains outstanding.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The inspected authority covers detached process execution with the caller environment, project ownership metadata, and local graph updates. The default startup targets one canonical checkout, while explicit project requests can involve additional roots. The available evidence does not establish a tenant-isolation or elevated-privilege boundary.

Security Findings and Attack Paths

  • observed — Read/write graph opening before project-lease acquisition can run migrations, repair, and WAL maintenance. That sequencing predates this PR; normal daemon startup acquires writer ownership before initialization, and preserving proxy fallback opens read-only. No introduced ownership bypass was established from this condition.

Trust Boundaries and Controls

  • observed — A failed identity probe is not permission to replace an owner. Preserving startup blocks live or uncertain ownership, skips older-daemon replacement, and uses read-only fallback when no shared daemon is verified. Candidate election revalidates stale daemon records before cleanup.

Resilience and Maintainability Implications

  • observed — Writer election and stale cleanup use a mutation-lock critical section. Preservation adds raw-record revalidation, and release checks current ownership and cancels deferred releases on reacquisition. Startup-failure and shutdown sequencing were compared with the base without establishing a newly weakened transition; these guarantees assume cooperating writers use the locking protocol.

Hardening Proposals

  • proposed — As a separate hardening change, consider fencing database migration and repair behind writer ownership, or opening non-owning project leases read-only. This would make preservation cover database side effects as well as ownership metadata; it is not an observed regression introduced by this PR.
🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
User-Visible Changes Documented ⚠️ Warning The PR adds the serve --preserve-existing CLI flag in src/bin/codegraph.ts and documents it in README.md. It does not update the matching MCP Server reference page, `site/src/content/docs/referenc… Update site/src/content/docs/reference/mcp-server.md with the serve --mcp --path <root> --preserve-existing option and its preservation behavior. Keep the README documentation.
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Suppressions Explained ✅ Passed No changed line adds or broadens a lint, type-check, or compiler suppression directive. The changed-file list also contains no lint or compiler configuration file with a new ignore entry.
Title check ✅ Passed The title clearly states the main change: preserving existing writers during ordinary watcher startup.
Description check ✅ Passed The description explains the new startup API and CLI option, the writer-preservation behavior, and the reported validation.
Full details: User-Visible Changes Documented

Explanation

The PR adds the serve --preserve-existing CLI flag in src/bin/codegraph.ts and documents it in README.md. It does not update the matching MCP Server reference page, site/src/content/docs/reference/mcp-server.md; that page still only shows codegraph serve --mcp and its existing daemon replacement behavior. The update to site/src/content/docs/reference/api.md documents the runtime-control API and mentions the flag, but does not update the MCP Server reference page for the CLI change.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@bompus
bompus merged commit 4a101f9 into fork/consolidated Oct 6, 2026
4 checks passed
@bompus
bompus deleted the fix/ordinary-watcher-startup branch October 6, 2026 00:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant