Skip to content

Split Git-aware daemon cursor from its baseline#79

Open
maxkle1nz wants to merge 1 commit into
mainfrom
codex/m1nd-daemon-git-cursor-v1
Open

Split Git-aware daemon cursor from its baseline#79
maxkle1nz wants to merge 1 commit into
mainfrom
codex/m1nd-daemon-git-cursor-v1

Conversation

@maxkle1nz
Copy link
Copy Markdown
Owner

Summary

  • split the Git-aware daemon state into startup baseline, moving cursor, current HEAD, and last clean ref
  • keep git_baseline_ref stable while git_since_ref advances after successful reconciliation
  • expose git_head_ref and git_last_clean_ref explicitly for status/debugging

Validation

  • 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 git_baseline_ref / git_since_ref / git_head_ref / git_last_clean_ref

Why 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/clock and Watchman-style semantics.

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
Copilot AI review requested due to automatic review settings April 5, 2026 22:38
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_ref to DaemonRuntimeState and include it in daemon start/status JSON payloads.
  • Initialize git_head_ref on 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.

Comment on lines 506 to +522
@@ -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());
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Comment thread m1nd-mcp/src/session.rs
Comment on lines 188 to 193
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>,
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
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.

2 participants