wg-done-silent

wg done: silent drop of staged-uncommitted changes in worktree

Metadata

Statusdone
Assignedagent-949
Agent identityf51439356729d112a6c404803d88015d5b44832c6c584c62b96732b63c2b0c7e
Modelclaude:opus
Created2026-04-28T21:28:43.315945945+00:00
Started2026-04-28T21:51:37.815280290+00:00
Completed2026-04-28T22:27:30.718892684+00:00
Tagseval-scheduled
Eval score0.86
└ blocking impact0.88
└ completeness0.95
└ constraint fidelity0.85
└ coordination overhead0.80
└ correctness0.92
└ downstream usability0.85
└ efficiency0.83
└ intent fidelity0.87
└ style adherence0.91

Description

Description

wg done silently drops staged-uncommitted changes in agent worktrees. When the worktree branch has 0 commits ahead of main but uncommitted/staged tracked files, the worktree-merge codepath returns WorktreeMergeResult::NoCommits and proceeds to mark the task done — losing the agent's work and cleaning up the worktree without surfacing any warning.

This was originally suspected to be a codex-handler-specific bug ("codex handler doesn't commit/merge like claude does"). It is not. The code path runs for every executor; claude tasks just usually escape it because their agent guide tells the agent to commit before wg done. Diagnostic doc: docs/codex-handler-merge-bug.md.

Source task that surfaced this: verify-agents-md (cycle iter 1/3, 2026-04-28). Concrete repro: .wg/agents/agent-933/output.log — codex agent for create-agents-md ran git add AGENTS.md && wg done, saw zero error output, AGENTS.md never landed on main.

Code locations

  • src/commands/done.rs:280-294commit_count == 0 short-circuit returns NoCommits without checking the working tree state.
  • src/commands/done.rs:2113-2117NoCommits is treated identically to NotInWorktree, no warning emitted.
  • wg show worktree block displays Merged to main: true even when the merge silently no-opped — flag is not gated on actual Merged result.

Suggested fix (conservative)

In attempt_worktree_merge, before the commit_count == 0 short-circuit, run git status --porcelain in the worktree. If there are staged or modified tracked files (entries that are not ?? untracked), refuse wg done with an actionable error:

Worktree has uncommitted changes (file1, file2). Run `git commit` in the worktree
before `wg done`, or pass `--abandon-uncommitted` to discard them explicitly.

Plus:

  • Fix the wg show "Merged to main: true" lie — must reflect actual Merged outcome.
  • Add a [merge] No commits on branch X — nothing to merge log line for the genuine NoCommits case so the agent at least sees what happened.

Validation

  • Failing test written first (TDD): tests/integration_done_uncommitted.rs — agent worktree with staged-but-uncommitted tracked file, calls wg done, expect non-zero exit + actionable error message + task NOT marked done.
  • Implementation makes the test pass.
  • wg show no longer reports Merged to main: true when the branch has 0 commits ahead.
  • Existing tests/integration_done_*.rs still pass (no regressions on the happy path or NoCommits-after-genuine-merge case at done.rs:374).
  • cargo build + cargo test pass.
  • Add a smoke scenario tests/smoke/scenarios/wg_done_refuses_uncommitted_worktree.sh that stages a file, runs wg done, and asserts (a) exit code != 0, (b) error mentions the file, (c) the file is NOT on main, (d) the task is NOT done. List this task id in owners.

Depends on

Required by

Log