Skip to content

feat(mcp): show running sync progress in sync_status - #46

Merged
kyle-elliott merged 1 commit into
feat/nonblocking-index-codebasefrom
feat/first-index-upload-progress
Oct 10, 2026
Merged

kyle-elliott merged 1 commit into
feat/nonblocking-index-codebasefrom
feat/first-index-upload-progress

Conversation

@kyle-elliott

Copy link
Copy Markdown
Contributor

Part 4 of the #37 stack: #42 → #43 → #44 → this PR. It is a follow-up to #44.

Problem

After #44, index_codebase returns immediately and agents poll sync_status. During the first index: syncing phase, sync_status did not say how far the scan or upload had come. The background reconcile used the quiet sync::sync, so its progress went nowhere.

Change

  • The coordinator owns a progress slot (src/engine/coordinator/progress.rs, a tokio::sync::watch sender). ReconcileRun carries it, and SyncReconciler calls sync_with_progress and publishes each milestone. A drop guard around the reconcile clears the slot on success, failure, panic, and cancellation.
  • CoordinatorStatus.sync_progress: Option<SyncProgress> (#[serde(default)], so a status body from an older daemon still decodes). SyncProgress itself is the wire type (snake_case tags); no second shape exists.
  • One renderer: impl Display for SyncProgress. semctl index, the sync_status line, and semctl daemon status use it. The upload text changes from uploading: 3/8 files to uploading 3/8 files, so the status line does not read current sync: uploading: ….
  • sync_status prints current sync: <milestone> after the first index: line while a reconcile runs, for example current sync: uploading 1200/3607 files. The line is absent when nothing runs.
  • CoordinatorStatus and its Display move to src/engine/coordinator/status.rs, because coordinator.rs was at the 1,000-line limit (983 → 956).
  • The quiet sync::sync wrapper had no caller left, so it is removed.

Verification

  • Full gate passes (fmt, test, clippy, doc, git diff --check).
  • Tests:
    • The coordinator shows Uploading { 3, 10 } while a fake reconcile runs, and the slot is empty after success, failure, and cancellation.
    • Old-daemon status decoding and a round-trip with progress.
    • The renderer text for each milestone.
    • The position of the current sync: line in sync_status, and that it is absent when idle.
  • Live smoke test: I started an MCP server in ~/napbat/symtree with an isolated runtime directory and polled sync_status. It showed current sync: scanned 1294 files (0 filter decisions reused) — checking for changes during the startup reconcile, then no line after the reconcile ended. The checkout had no changed files, so the live run did not reach the upload step. Unit tests cover the upload counts.

A first index returns from index_codebase at once, so an agent has only
sync_status to follow it. The first-index phase said "syncing" and nothing
more. The agent could not tell a stalled upload from a slow one.

The coordinator now keeps the latest milestone of the reconcile that runs.
SyncReconciler publishes each SyncProgress step to that slot. A guard clears
the slot when the reconcile ends, fails, or is cancelled.

- CoordinatorStatus carries the milestone as sync_progress. The field has a
  serde default, so a status from an older daemon still decodes.
- SyncProgress is the wire type and has one Display. semctl index, the
  sync_status "current sync:" line, and semctl daemon status all use it.
- CoordinatorStatus moves to coordinator/status.rs, because coordinator.rs
  was at the file size limit.
- sync::sync, the quiet wrapper, had no caller left and is removed.

Refs #37
@kyle-elliott
kyle-elliott force-pushed the feat/first-index-upload-progress branch from d15a867 to 1da2fd5 Compare October 10, 2026 00:05
@kyle-elliott
kyle-elliott merged commit 08e21ab into main Oct 10, 2026
6 of 9 checks passed
@kyle-elliott
kyle-elliott deleted the feat/first-index-upload-progress branch October 10, 2026 00:09
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