T-1QO7-task-work-resumes-from-verify-stamp-commit
Status: closed/done · Impact: medium · Complexity: small
Auto-generated from a /sdlc:task-work post-mortem. Review and
promote to open/ready before picking up.
When a previous /sdlc:task-work run exits prematurely between
Step 5a (ensure-ready ran, docs(tasks): verify <basename> implementation-ready committed on the feat branch) and Step 5b
(status flip + start-commit on main), the user is left in a
half-finished state with no clean way to resume. Today, restarting
/sdlc:task-work from scratch will re-run ensure-ready (a no-op
when the stamp is fresh) but the parent has no signal to skip
directly to Step 5b. A small auto-detect at start time closes this
loop and makes resume-after-crash a one-command operation instead
of a hand-crafted orchestrator prompt.
The premature-exit failure mode just bit
T-RNW9-task-close-out-verifies-pr-on-main: a sub-agent ran
ensure-ready (which emits READY: <basename>), then mistook that
marker for the task-work final verdict and exited. The actual
implementation never happened. Recovery required the orchestrator
to hand-craft a “resume at Step 5b” prompt that named the exact
worktree path, branch state, and step to jump to. The skill itself
offered no support.
Concretely, Step 2’s pre-flight checks today refuse to proceed if
“A worktree already exists at .claude/worktrees/<basename>” or
“A branch already exists named feat/<basename>” — so the natural
“just rerun task-work” recovery is actively blocked.
Proposed
Section titled “Proposed”Step 2’s pre-flight grows a resume-detection branch: if all of the following hold, skip Step 4 (worktree create) and Step 5a (ensure-ready) and jump directly to Step 5b:
- Task status on main is
open/ready(the start-commit never landed). - A worktree exists at
.claude/worktrees/<basename>. - A branch
feat/<basename>exists. - The feat branch HEAD commit subject matches
docs(tasks): verify <basename> implementation-ready(ensure-ready’s stamp commit). - No PR is open referencing this task.
The same logic should surface the resume as a visible decision to the user via AskUserQuestion (“Detected a prior task-work run that stalled after ensure-ready. Resume at Step 5b, or start over?”) rather than silently jumping — the user might prefer to nuke the worktree and rerun the gate.
Approach
Section titled “Approach”- Add the resume-detection check to
plugin/skills/task-work/SKILL.mdStep 2, between the existing pre-flight blocks and the relevance-check section. - Document the marker-confusion failure mode in the skill’s Notes (it’s the motivating example for why this check exists).
- Optionally: add an invariants entry pinning the literal commit
subject
docs(tasks): verify <basename> implementation-readyso the detection can’t drift from the ensure-ready stamp shape.
Files to touch
Section titled “Files to touch”plugin/skills/task-work/SKILL.md— Step 2 gains resume-detection branch; Notes gains the failure-mode explainer.plugin/skills/task-work/invariants.yaml— pin the verify-stamp commit subject so the detection logic doesn’t drift from ensure-ready’s stamp shape.
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Given a stale half-finished state (open/ready on main,
worktree exists, feat branch HEAD is the verify-stamp commit, no
PR),
/sdlc:task-work <slug>offers a resume option via AskUserQuestion and on accept jumps straight to Step 5b without re-creating the worktree or re-running ensure-ready. - AC-2: The pre-existing “worktree already exists” / “branch already exists” blockers remain in force for every other combination (e.g. branch exists but HEAD is not the verify-stamp; PR is open).
Out of scope
Section titled “Out of scope”- Detecting and recovering from premature exits at other steps (mid-Step 6 implementation, mid-Step 8 post-mortem). Each step has its own recovery shape; start with the most common failure mode (5a→5b boundary, which is the marker-confusion case).
- Auto-cleaning a stale worktree when the user picks “start over”.
Manual
git worktree remove --forceis fine for now.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Spawned by /sdlc:task-work post-mortem of
T-RNW9-task-close-out-verifies-pr-on-main on 2026-05-20.
The marker-confusion failure was directly observed when a parallel
sub-agent for this task exited after ensure-ready returned
READY:, requiring a hand-crafted resume prompt.
Post-mortem
Section titled “Post-mortem”Captured by /sdlc:task-work on 2026-05-21. PR: pending.
Acceptance criteria coverage
Section titled “Acceptance criteria coverage”- AC-1: agent-manual — read the new Step 2 “Resume detection” prose end-to-end; confirmed it spells out all five conditions, defers to AskUserQuestion, defaults to stop, and on resume jumps to Step 5b while skipping Step 4 and Step 5a. Cannot be auto-verified without simulating a stalled state and dispatching a sub-agent against it.
- AC-2: agent-manual — read the same prose; confirmed the “Any other combination … falls through to the existing pre-flight blockers above (they remain in force)” sentence preserves the pre-existing worktree/branch/PR blockers for every off-pattern shape. Same simulation caveat as AC-1.
What worked
Section titled “What worked”- The
lint_skill_prose.pyinvariant pin caught the new verify-stamp-subject phrase requirement immediately on the first quality-check run — no manual cross-check needed to confirm the Step 2 prose included the literal commit subject. - The Step 5b rebase conflict on frontmatter (start-commit’s fresh
last_reviewedvs verify-stamp’s freshreadiness_verified_at) was unambiguous once the conflict markers were visible: keep both fresh values, drop both stale ones. Took one Edit to resolve.
Friction and automation gaps
Section titled “Friction and automation gaps”start_task.pyrebase conflicted on the task frontmatter because the start-commit (on main) updatedlast_reviewedto today while the verify-stamp commit (on the feat branch) updatedreadiness_verified_atto the same day’s timestamp — both rewrote adjacent lines in the same hunk. This is the exact gap that T-H0W9-task-work-rebase-frontmatter-conflict exists to close, and it triggered cleanly on this run. No additional gap to spawn — that task is already in the queue and this run is more evidence for its impact. → T-H0W9-task-work-rebase-frontmatter-conflict- The orchestrator-dispatched flow had to interactively resolve the
rebase conflict inline. If
2026-05-20-task-work-rebase-frontmatter-conflictships a merge driver or a smarter merge instart_task.py, this whole class of friction goes away. → T-H0W9-task-work-rebase-frontmatter-conflict
Spawned follow-up tasks
Section titled “Spawned follow-up tasks”- T-H0W9-task-work-rebase-frontmatter-conflict — linked (existing task already covers the frontmatter rebase-conflict gap; appended this task to its related list)