Auto-mode: ghost-completion execute-task turns cause oscillation loop with complete-slice
Problem
Auto-mode halts with an oscillation loop between execute-task and complete-slice when an execute-task LLM turn returns a "ghost completion" — the model finishes in <1s at $0 without writing the expected T##-SUMMARY.md artifact. The verification retry policy re-dispatches the same unit, producing an identical ghost turn, and stuck-detection eventually halts the session.
Root Cause
Two interacting defects in the auto-mode engine:
1. Phase flip-flop after complete-slice
deriveStateFromDb in state.ts picks phase purely from the first non-done task:
// state.ts (~line 601)
const nextTask = getSliceTasks(sliceId).find(t => !isStatusDone(t.status));
return nextTask ? { phase: 'executing', activeTask: nextTask.id } : { phase: 'summarizing' };When complete-slice runs but a prior execute-task turn skipped its DB write, derivation swings back to executing on the next iteration. auto-dispatch.ts (~line 979) then re-selects the same task with no guard against a just-executed loop.
2. Ghost completions treated as retryable verification failures
runPostUnitVerification / applyVerificationRetryPolicy in auto-recovery.ts (~line 727-733) and auto/phases.ts (~line 53) treat "unit finished with no artifact" as a normal verification-retry candidate:
verify-fail execute-task M031/S09/T04: existsSync false for .../tasks/T04-SUMMARY.mdA $0 / <1s execute-task turn that produced zero tool writes should be classified distinctly (ghost-turn) and pause with a clear message rather than loop.
Expected Behavior
- In
auto/phases.ts(verification gate), whenexecute-taskfinishes withcost == 0,duration < 1s, andverifyExpectedArtifactreturns false, emit aghost-turnverdict and route topause— notretry. - In
auto-dispatch.ts(~line 979), guard: if(unitType, unitId)was dispatched in the previous iteration with zero tool writes, exit withexecute-task ghost-loop: model did not write SUMMARY. - Optionally: in
state.tsderiveStateFromDb, if the previously-completed unit wascomplete-slice/<sliceId>and the derived next phase flips back toexecutingon the same slice, require an explicit DB transition rather than silently reverting.
Environment
- GSD version: 3.0.0
- Model: claude-opus-4-7
- Unit:
execute-task/M031/S09/T04↔complete-slice/M031/S09
Reproduction Context
Auto-mode was in slice-completion phase for M031/S09. After complete-slice finished successfully (2m24s, $1.58), the loop re-derived state, flipped back to executing on T04, and the LLM returned a no-op ghost turn (327ms, $0) without writing T04-SUMMARY.md. Verification failed, retry re-dispatched, ghost turn recurred, oscillation-detector halted the session.
Forensic Evidence
Journal (2026-07-12T00:03Z):
00:03:12 [post-unit-finalize-end] flow=06175c21 unit=M031/S09 (complete-slice)
00:03:12 [iteration-start] flow=ecb38a75
00:03:13 [dispatch-match] flow=ecb38a75 rule=executing → execute-task unit=M031/S09/T04
00:03:13 [unit-start] flow=ecb38a75 unit=M031/S09/T04
00:03:16 [unit-end] flow=ecb38a75 unit=M031/S09/T04 (327ms, $0)
00:03:24 [iteration-start] flow=auto-orc
00:03:26 [dispatch-match] flow=6f87fd8a rule=executing → execute-task unit=M031/S09/T04
00:03:26 [auto-exit] flow=37100019 (oscillation halt)Recent units table shows the pathological pattern:
| Unit | Cost | Duration |
|---|---|---|
| execute-task M031/S09/T04 | $0.0000 | 327ms |
| complete-slice M031/S09 | $1.58 | 2m 24s |
| execute-task M031/S09/T04 | $1.17 | 1m 34s |
| execute-task M031/S09/T04 | $0.0000 | 641ms |
Two zero-cost sub-second execute-task turns bracketing a real complete-slice — canonical ghost-completion signature.
Anomaly summary: 67 anomalies including numerous stuck-loop warnings for execute-task/complete-slice pairs across M027, M028, M029, M031 — same failure mode is recurring across sessions.
Auto-generated by /gsd forensics
Source: gsd-build/gsd-2