Skip to content

fix(headless): resume session history in -p; better MCP files_changed - #406

Merged
yogthos merged 1 commit into
mainfrom
headless-session-resume
Jun 11, 2026
Merged

fix(headless): resume session history in -p; better MCP files_changed#406
yogthos merged 1 commit into
mainfrom
headless-session-resume

Conversation

@yogthos

@yogthos yogthos commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Two bugs found while testing the dirge mcp delegation loop end-to-end.

1. dirge -p --session <id> didn't resume history

The headless print path persisted the session (so message_count grew) but never resumed it: run_print passed Vec::new() as the model history regardless of --session, so every headless run started cold. Through the MCP server this meant a follow-up delegate ("fix the thing you just did") had no memory of the prior turn — it replied "I haven't created any file in this session."

Fix: the print path now threads convert_history(&session) (the resolved session's prior turns) into run_print. The --loop caller still passes Vec::new() (it drives its own prompt sequence). This is a general headless bug, not MCP-specific.

Verified live through the MCP server: in a fresh session, delegate #1 creates a file, delegate #2 ("append a line to the file you just created") now correctly finds and edits it.

2. MCP files_changed missed edits to already-dirty files

The server computed files_changed as a git status --porcelain line diff, which can't see a content edit to a file that was already dirty before the delegation — exactly the multi-delegation case (file created untracked in #1, edited in #2: ?? path is identical before and after). Switched to a (size, mtime) signature per dirty path, so further edits are attributed while the caller's pre-existing untouched changes aren't.

Unit-tested. Note: this runs in the long-lived dirge mcp server process, so it needs a Claude Code restart (respawns the server with the new binary) to take effect live.

Tests

4 mcp_server unit tests (signature diff + porcelain path/rename parsing), run_print tests, full suite 2612 pass.

Two bugs found testing the dirge MCP delegation loop:

1. dirge -p --session <id> persisted the session but never RESUMED it —
   run_print passed Vec::new() as history regardless of --session, so the
   model ran cold every call. A follow-up delegation ('fix the thing you
   just did') had no memory of the prior turn. The print path now threads
   convert_history(&session) into run_print; --loop still passes empty.

2. The MCP server's files_changed used a git-status porcelain-LINE diff,
   which misses content edits to a file that was already dirty before the
   delegation (common across delegations in one session: created in #1,
   edited in #2). Switch to a (size, mtime) signature per dirty path so
   further edits are attributed, without falsely claiming the caller's
   pre-existing untouched changes.

Resume verified live through the MCP server (a second delegate now knows
the file the first created). The files_changed change is in the long-lived
server process, so it needs a Claude Code restart to take effect live;
covered by unit tests.
@yogthos
yogthos merged commit 561cecf into main Jun 11, 2026
11 checks passed
@yogthos
yogthos deleted the headless-session-resume branch June 11, 2026 04:55
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