Split Git-aware daemon cursor from its baseline#79
Conversation
The Git-aware daemon now tracks three distinct references: an immutable startup baseline, a moving reconciliation cursor, and the current HEAD. This makes the SCM adapter more explicit and prepares the daemon for richer since/clock semantics without changing the public MCP tool surface. Constraint: Clarify SCM state without adding a new public tool or changing daemon_tick authority Rejected: Reusing git_since_ref for both baseline and cursor forever | hides important adapter state and makes later SCM upgrades more brittle Rejected: Introducing a separate cursor-management API | premature surface growth for internal daemon state Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep the startup baseline stable and let only the cursor advance; future Watchman-style clocks should layer on top of that split Tested: cargo fmt --check; cargo test -p m1nd-mcp daemon_start_detects_git_root_and_head -- --nocapture; cargo test -p m1nd-mcp daemon_start_prefers_merge_base_when_upstream_exists -- --nocapture; cargo test -p m1nd-mcp daemon_tick_uses_git_changed_set_when_available -- --nocapture; MCP smoke for baseline/head/cursor fields Not-tested: Long-running daemon sessions where upstream moves after startup
There was a problem hiding this comment.
Pull request overview
This PR refactors the daemon’s Git-aware runtime state to distinguish a stable baseline (git_baseline_ref) from an advancing cursor (git_since_ref), and surfaces the current Git HEAD (git_head_ref) for status/debugging in the MCP daemon start/status responses.
Changes:
- Add
git_head_reftoDaemonRuntimeStateand include it in daemon start/status JSON payloads. - Initialize
git_head_refon daemon start and refresh it during git-backed daemon ticks. - Extend daemon tests to assert correct initialization and advancement semantics for the new field.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| m1nd-mcp/src/session.rs | Extends persisted daemon runtime state with git_head_ref. |
| m1nd-mcp/src/daemon_handlers.rs | Computes/exposes git_head_ref on start/status and updates it (and git_since_ref) during git-backed ticks; updates tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -508,8 +517,9 @@ pub fn handle_daemon_tick( | |||
| changed_entries.push(entry); | |||
| } | |||
| } | |||
| state.daemon_state.git_head_ref = current_head.clone(); | |||
| state.daemon_state.git_since_ref = | |||
| git_head_ref(Path::new(&root)).or(state.daemon_state.git_since_ref.clone()); | |||
| current_head.or(state.daemon_state.git_since_ref.clone()); | |||
There was a problem hiding this comment.
git_since_ref (and git_head_ref) are updated immediately after computing the changed set, before the re-ingest loop runs. If handle_ingest(...) errors mid-tick, the function returns early (?) without persisting state, but the in-memory cursor will have advanced, which can cause the next tick to miss changes and contradicts the PR goal of advancing the cursor only after successful reconciliation. Consider staging current_head in a local variable and only assigning git_since_ref/git_head_ref after all ingests and state persistence succeed (and ideally add a regression test for the failure case).
| pub git_root: Option<String>, | ||
| pub git_baseline_ref: Option<String>, | ||
| pub git_baseline_kind: Option<String>, | ||
| pub git_since_ref: Option<String>, | ||
| pub git_head_ref: Option<String>, | ||
| pub last_git_scan_ms: Option<u64>, |
There was a problem hiding this comment.
PR description mentions exposing git_last_clean_ref, but this field isn't present in DaemonRuntimeState (and a repo-wide search for git_last_clean_ref finds no implementation). Either implement and surface git_last_clean_ref as described or adjust the PR description to match the actual changes to avoid misleading API consumers.
Summary
git_baseline_refstable whilegit_since_refadvances after successful reconciliationgit_head_refandgit_last_clean_refexplicitly for status/debuggingValidation
git_baseline_ref/git_since_ref/git_head_ref/git_last_clean_refWhy this matters
This makes the SCM-aware daemon state explicit and future-proof. The daemon now has a stable baseline and a moving cursor, which is the right substrate for later
since/clockand Watchman-style semantics.