T-SW5E-worktree-init-verifies-clean-checkout
Status: closed/superseded · Impact: medium · Complexity: small
AUTO-DEFINED: this spec was best-effort machine-authored by /sdlc:task-auto-define on 2026-07-18 because the task is autonomy: autonomous/pr. Review the Goal, Approach, Today, Files-to-touch, and Acceptance-criteria carefully before trusting it.
A fresh task worktree can arrive dirty, and nothing in task-work Step 4 notices — the dirt surfaces later as a mysterious quality-gate failure the implementer must diagnose mid-task. From the originating post-mortem:
A fresh task worktree arrived with a broken uncommitted block comment (a
path/**/*.tsglob whose*/terminated the comment) that failed typecheck; origin unclear. task-work Step 4 should verify the fresh worktree is clean (git status --porcelainempty) right aftergit worktree addand again after running theworktree_initverbs, failing loud with a diagnostic instead of letting inherited dirt surface later as a mysterious quality-gate failure.
| Location | Role today |
|---|---|
apps/sdlc/skills/task-work/SKILL.md | Step 4 (”## 4. Create the worktree” and ”### Initialize the worktree”) runs git worktree add and then the worktree_init verbs via sdlc quality run --key worktree_init --allow-empty. Neither point checks the worktree is clean, so inherited dirt surfaces later as a mysterious Step 7 quality-gate failure. |
docs/skills/task-work.md | Per-skill doc; flowchart node S4 describes Step 4 as “Create the worktree + run worktree_init verbs” with no mention of a cleanliness gate. |
Proposed
Section titled “Proposed”Step 4 gains two fail-loud cleanliness verifications: one immediately after
git worktree add, one immediately after the worktree_init executor
returns. Each runs git status --porcelain in the fresh worktree and, when
output is non-empty, stops the run with a diagnostic that prints the dirty
paths and names which stage introduced them (present at creation vs.
introduced by the init verbs) instead of proceeding to Step 5.
Approach
Section titled “Approach”- In
apps/sdlc/skills/task-work/SKILL.mdStep 4, immediately after thegit worktree addcommand block, add a short “verify the fresh worktree is clean” instruction: rungit -C .sdlc/worktrees/<basename> status --porcelainand expect empty output. Non-empty output is a hard error — print the porcelain lines, state the dirt was present at worktree creation (inherited, e.g. from hooks or copy artifacts), and stop before Step 5. - In ”### Initialize the worktree”, after the executor’s exit-0 outcome,
add the second check: re-run the same
git status --porcelainprobe. Non-empty output now implicates the declaredworktree_initverbs — print the porcelain lines plus the verb list fromsdlc.yaml, and stop before Step 5. - Word both checks per the house rules in
apps/sdlc/skills/CLAUDE.md: gate on the bare command (no pipe that would mask output or exit code), positive framing, and keep each added block to a few constraints so Step 4’s constraint density stays within the S-0006 cap. - Update
docs/skills/task-work.md(flowchart node S4 and its Step 4 prose) to mention the two cleanliness verifications so the per-skill doc stays in lockstep with the skill. - Verify: run the repo quality checks from
sdlc.yaml(bunx tsc --noEmitand the scopedbun test, which includes the skill-prose contract testapps/sdlc/lib/services/gate/ops/_skill_prose_contract.test.ts) and confirm both new checks appear in Step 4 by re-reading it.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
apps/sdlc/skills/task-work/SKILL.md | modify | Add the two fail-loud git status --porcelain cleanliness checks to Step 4: after git worktree add and after the worktree_init executor. |
docs/skills/task-work.md | modify | Reflect the new Step 4 cleanliness gate in flowchart node S4 and the surrounding prose. |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
apps/sdlc/skills/task-work/SKILL.mdStep 4 instructs agit status --porcelaincheck immediately aftergit worktree add, with non-empty output a hard stop that prints the dirty paths. - AC-2: Step 4 instructs a second
git status --porcelaincheck after theworktree_initexecutor returns, and its diagnostic distinguishes dirt introduced by the init verbs from dirt present at creation. - AC-3: Neither new check pipes the gated command through a filter
(
grep -n "porcelain" apps/sdlc/skills/task-work/SKILL.mdshows both occurrences unpiped), per “Don’t pipe commands you gate on” inapps/sdlc/skills/CLAUDE.md. - AC-4:
docs/skills/task-work.mdmentions the Step 4 cleanliness verification. - AC-5:
bunx tsc --noEmitand the scopedbun testfromsdlc.yamlpass on the branch.
Out of scope
Section titled “Out of scope”- A new
sdlcCLI verb or co-located script for the check — two baregit status --porcelainprobes in prose don’t warrant deterministic tooling yet. - Auto-remediating a dirty worktree (
git checkout -- ./git clean) — the step fails loud; remediation stays with the operator. - Diagnosing the original broken-block-comment source reported in T-2KK8-capability-kind-grains-and-locations.
- Changes to
worktree_initverb discovery (/sdlc:find-worktree-init) or to thesdlc quality runexecutor itself.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Spawned by /sdlc:spawn-task-pr on 2026-07-18 UTC from T-2KK8-capability-kind-grains-and-locations in https://github.com/sksizer/dev.