feat: terminal Run Worktree reconciliation - #39
Conversation
Roundfix-Spec: 0038-terminal-run-worktree-reconciliation Roundfix-Task: task_01
Roundfix-Spec: 0038-terminal-run-worktree-reconciliation Roundfix-Task: task_02
Roundfix-Spec: 0038-terminal-run-worktree-reconciliation Roundfix-Task: task_03
Roundfix-Spec: 0038-terminal-run-worktree-reconciliation Roundfix-Task: task_04
Roundfix-Spec: 0038-terminal-run-worktree-reconciliation Roundfix-Task: task_05
Roundfix-Spec: 0038-terminal-run-worktree-reconciliation Roundfix-Task: task_06
Roundfix-Spec: 0038-terminal-run-worktree-reconciliation Roundfix-Task: task_07
The 2026-07-26 tooling authorization covered exactly the two roundfix SKILL.md files, so task_07's authorized Skill edit could not carry its own deterministic digest fallout and settled failed for the third time today. Record the maintainer's 2026-07-27 express authorization of the five derived pins in both active Spec artifacts, as a supervisor-owned boundary commit rather than inside the Task commit it would authorize. Add three findings from this dogfood cycle: - derived Skill digest pins have no regeneration path, so every Skill edit needs five hashes transcribed by hand and fails its own Task's changed-path check - Force Stop reads owner identity by forking ps, so a host that cannot fork makes the escape hatch refuse exactly when a runaway Run is exhausting process slots, and a failed capture at Run creation leaves a Run silently without reuse protection - the Claude adapter should standardize on the official @agentclientprotocol/claude-agent-acp, which also exposes that Roundfix misreads advertised ids like opus[1m] as a reasoning effort Claude-Session: https://claude.ai/code/session_01KwYiSLnmzdHmrmV4XWmQge
QA finding RFQA-0038-01: task_04's commit added a 20.1 MiB Mach-O executable at the repository root. It came from running `go build ./cmd/roundfix` without -o, which writes ./roundfix, a path .gitignore did not cover because it only ignored /bin/. Remove the tracked binary and ignore that path so a bare build can no longer be swept into a commit. The Makefile keeps writing the real build output to the ignored bin/roundfix. Claude-Session: https://claude.ai/code/session_01KwYiSLnmzdHmrmV4XWmQge
Roundfix-Spec: 0038-terminal-run-worktree-reconciliation
The Spec 0038 QA gate flagged repair commit af03b5f for editing .gitignore, which docs/agents/agent-instructions.md prohibits without express maintainer authorization. The gate is right: removing the stray root binary was the required repair; adding the ignore entry exceeded it. Restore .gitignore and record the still-open recurrence risk as a finding instead. Claude-Session: https://claude.ai/code/session_01KwYiSLnmzdHmrmV4XWmQge
QA finding RFQA-0038-02: the previous revert restored .gitignore's content but added a trailing newline the base blob did not have, so the protected ignore file was still byte-modified without authorization. Restore blob 498dd1c exactly. Also record that sandboxed Agents cannot always reach the default GOCACHE, which blocked this Spec's QA gate before compilation and made part of a verdict rest on checks that never ran. Claude-Session: https://claude.ai/code/session_01KwYiSLnmzdHmrmV4XWmQge
Roundfix-Spec: 0038-terminal-run-worktree-reconciliation
All 7 Tasks completed, QA gate verdict pass on build 3744d03. Claude-Session: https://claude.ai/code/session_01KwYiSLnmzdHmrmV4XWmQge
Project Config change: review_source.include_nitpicks now true, so nitpick-severity findings become Review Issues that watch Runs triage and resolve instead of ignoring. Claude-Session: https://claude.ai/code/session_01KwYiSLnmzdHmrmV4XWmQge
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (8)
📒 Files selected for processing (7)
WalkthroughThis change adds terminal Run Worktree reconciliation with five-state inspection, evidence-backed cleanup, persisted reconciliation events, a new ChangesTerminal Run Worktree Reconciliation
Estimated code review effort: 5 (Critical) | ~90+ minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant RunStore
participant InspectTerminalRun
participant ApplyTerminalRun
participant Git
CLI->>RunStore: load terminal implementation runs
CLI->>InspectTerminalRun: classify Git and worktree state
InspectTerminalRun->>Git: inspect heads, ancestry, registration, and cleanliness
CLI->>ApplyTerminalRun: apply cleanup for safe runs
ApplyTerminalRun->>RunStore: persist reconciliation evidence
ApplyTerminalRun->>Git: remove worktree and run branches
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
internal/store/store.go (1)
481-650: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift
ReconcileIntegrationis ~170 lines and mixes validation, replay detection, transition, and journaling.The guideline limit is 120 lines per function. Extracting the stored-invariant checks (lines 508-540), the replay lookup (562-589), and the Integration Pending compare-and-set (606-630) into helpers would keep each concern independently testable without changing behavior.
As per coding guidelines: "Keep cyclomatic complexity at or below 13, avoid deeply nested conditionals, limit functions to 120 lines and 80 statements".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/store/store.go` around lines 481 - 650, Refactor ReconcileIntegration to stay under the 120-line guideline by extracting the stored-invariant checks, replay lookup, and Integration Pending compare-and-set into focused helpers. Preserve all existing validation, error messages, transaction behavior, replay handling, and state-transition semantics while keeping ReconcileIntegration responsible for orchestration and journaling.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/cli/runs.go`:
- Line 114: Update countRetainedTerminalRunWorktrees and its InspectTerminalRun
loop to avoid inspecting every terminal Run from the unbounded query: skip empty
WorkDir values and bound inspections to Runs relevant to the requested
state/limit, or otherwise enforce a safe cap. In the inspection error path
around the retained-worktree count, report the failure with diagnostic context
instead of silently treating it as retained.
- Around line 121-127: Update the note-rendering logic in the runs-list flow so
runsListRetainedWorktreeNote and runsListHiddenNote can both be emitted when
applicable, instead of the retained-worktree note suppressing hidden/older
guidance. Preserve the existing note formatting and update the exact stderr
expectations in the related CLI tests.
In `@internal/store/store.go`:
- Around line 532-540: The Run Branch prefix is duplicated in the reconciliation
check and worktree naming logic. Extract the prefix into a dependency-safe
shared symbol, or make it a store-owned exported constant consumed by
worktree.BranchName, then update the reconciliation validation around
expectedRunBranch to derive the expected name through that single source instead
of concatenating "roundfix/run-" directly.
In `@internal/worktree/worktree_test.go`:
- Around line 1552-1562: Remove the hand-rolled slicesEqual helper and import
the standard library slices package. Replace all three slicesEqual call sites in
the affected tests with slices.Equal, preserving the existing comparison
arguments and behavior.
- Around line 867-895: Add goleak coverage for the goroutines introduced by
TestInspectTerminalRunConcurrentSafe, using goleak.VerifyNone around the
concurrent test or goleak.VerifyTestMain via a package TestMain. Ensure leaked
goroutines cause the internal/worktree tests to fail while preserving the
existing inspection assertions.
In `@internal/worktree/worktree.go`:
- Around line 218-222: Update the worktree reconciliation flow around
recordedWorktree so an existing directory that is not registered in the Git root
produces reconciliationReasonWorktreeUnregistered, while genuinely unsafe paths
continue using reconciliationReasonWorktreePath. Distinguish these outcomes
using the recordedWorktree result and preserve the existing return behavior.
- Around line 849-857: Update the TerminalRunLookup function type to accept
context.Context as its first parameter, then pass the PruneTerminal ctx through
every lookup invocation within PruneTerminal and related reconciliation paths.
Update all implementations and callers to use the context-aware Run Store read,
preserving existing lookup behavior while propagating cancellation and
deadlines.
---
Outside diff comments:
In `@internal/store/store.go`:
- Around line 481-650: Refactor ReconcileIntegration to stay under the 120-line
guideline by extracting the stored-invariant checks, replay lookup, and
Integration Pending compare-and-set into focused helpers. Preserve all existing
validation, error messages, transaction behavior, replay handling, and
state-transition semantics while keeping ReconcileIntegration responsible for
orchestration and journaling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2548c3ce-5441-4a82-a37d-3f5db6149845
⛔ Files ignored due to path filters (29)
docs/findings/2026-07-27-bare-go-build-writes-an-untracked-root-binary.mdis excluded by none and included by nonedocs/findings/2026-07-27-claude-adapter-standardization.mdis excluded by none and included by nonedocs/findings/2026-07-27-derived-skill-digest-pins-have-no-regeneration-path.mdis excluded by none and included by nonedocs/findings/2026-07-27-owner-identity-forks-ps-and-fails-closed-under-load.mdis excluded by none and included by nonedocs/findings/2026-07-27-sandboxed-agents-cannot-reach-the-default-go-cache.mdis excluded by none and included by nonedocs/specs/0038-terminal-run-worktree-reconciliation/task_01.mdis excluded by none and included by nonedocs/specs/0038-terminal-run-worktree-reconciliation/task_02.mdis excluded by none and included by nonedocs/specs/0038-terminal-run-worktree-reconciliation/task_03.mdis excluded by none and included by nonedocs/specs/0038-terminal-run-worktree-reconciliation/task_04.mdis excluded by none and included by nonedocs/specs/0038-terminal-run-worktree-reconciliation/task_05.mdis excluded by none and included by nonedocs/specs/0038-terminal-run-worktree-reconciliation/task_06.mdis excluded by none and included by nonedocs/specs/0038-terminal-run-worktree-reconciliation/task_07.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/_prd.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/_tasks.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/_techspec.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/qa/evidence/2026-07-27-terminal-reconciliation-rerun/run-summary.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/qa/evidence/2026-07-27-terminal-reconciliation/run-summary.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/qa/qa-report-2026-07-27.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/task_01.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/task_02.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/task_03.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/task_04.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/task_05.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/task_06.mdis excluded by none and included by nonedocs/specs/_archived/0038-terminal-run-worktree-reconciliation/task_07.mdis excluded by none and included by nonedocs/user-guide/commands.mdis excluded by none and included by nonedocs/user-guide/usage.mdis excluded by none and included by noneinternal/baseline/testdata/catalog.digestis excluded by!**/*.digestand included by noneskills/roundfix/SKILL.mdis excluded by!skills/**and included by none
📒 Files selected for processing (19)
.agents/skills/roundfix/SKILL.md.roundfixrc.ymlCONTEXT.mddocs/specs/_archived/0038-terminal-run-worktree-reconciliation/qa/evidence/2026-07-27-terminal-reconciliation-rerun/fixture.gointernal/baseline/assets/setups/typescript-bun.jsoninternal/baseline/testdata/catalog.normalized.jsoninternal/baseline/testdata/parity-corpus/v1/fixtures/asset-sync.jsoninternal/baseline/testdata/parity-corpus/v1/manifest.jsoninternal/cli/cli.gointernal/cli/cli_test.gointernal/cli/implement.gointernal/cli/implement_test.gointernal/cli/reconcile.gointernal/cli/runs.gointernal/cli/settle_test.gointernal/store/store.gointernal/store/store_test.gointernal/worktree/worktree.gointernal/worktree/worktree_test.go
Implements spec 0038-terminal-run-worktree-reconciliation (archived in this branch after a passing QA gate).
What changed
ReconcileIntegration, which until now had no production caller.roundfix reconcileinspects retained terminal Run Worktrees, with dry-run and apply semantics.roundfix runs listreports retained terminal Run Worktrees and points at the command to inspect them.Verification
3744d03: verdict pass (docs/specs/_archived/0038-terminal-run-worktree-reconciliation/qa/qa-report-2026-07-27.md). Earlier failing reports are preserved in history.completedwith its declared Verification passing.make verifygreen on the delivered tree (2,563 tests across 23 packages).Findings recorded from this cycle
Five
pendingfindings underdocs/findings/, three of them defects in code shipped earlier today:ps, so a host that cannot fork makes the escape hatch refuse exactly when a runaway Run is exhausting process slots.go build ./cmd/roundfixwithout-owrites an unignored 20 MiB binary at the repository root; the one-line fix needs maintainer authorization for a protected ignore file.GOCACHE, which blocked this Spec's QA gate before compilation.@agentclientprotocol/claude-agent-acp, which also surfaced that Roundfix misreads advertised model ids likeopus[1m]as a reasoning effort.https://claude.ai/code/session_01KwYiSLnmzdHmrmV4XWmQge
Summary by CodeRabbit
reconcilecommand for inspecting retained terminal Run Worktrees, with dry-run reports in text or JSON and guarded cleanup via--apply.runs listnow highlights retained terminal worktrees and recommends reconciliation.