T-VFGF-extract-start-task-script
Status: closed/done · Impact: high · Complexity: small
Auto-generated from a /sdlc:task-work post-mortem. Review and
promote to ready before picking up.
/sdlc:task-work Step 5b — the “flip the task to status: in-progress
on main, commit chore(tasks): start <basename>, rebase the feat
branch” sequence — currently lives as prose only. Sub-agents skip it
silently (twice now on
T-ZQ4H-task-ensure-ready-accepts-in-progress, where the task on
main is still status: ready even though a feat branch and PR exist).
A prose-only “now do this” step is too easy to drop. Lifting Step 5b
into a script the orchestrator must shell out to closes the gap the
same way new_task.py and migrate_entities.py closed theirs.
plugin/skills/task-work/SKILL.md Step 5b walks through seven sub-
steps (edit frontmatter, validate, stage, commit on main, sanity-check,
rebase the feat branch, surface conflicts). The skill expects the
implementer-agent to follow every sub-step manually. Two consecutive
runs on this very task skipped Step 5b entirely, leaving main in a
state where git log shows no start-commit and the task frontmatter
on main is still status: ready.
Proposed
Section titled “Proposed”plugin/skills/task-work/start_task.py is a PEP-723 self-bootstrapping
CLI that takes the task path and worktree path, flips the task to
status: in-progress on main, runs the frontmatter validator, commits
on main with the canonical message, then rebases the named feat branch
onto the new main tip. Step 5b in SKILL.md becomes “shell out to
plugin/skills/task-work/start_task.py with these args; surface any
non-zero exit to the user”. The script lives co-located with its single
caller (task-work) per plugin/skills/CLAUDE.md — promote to
plugin/scripts/ only when a second skill actually needs it.
Approach
Section titled “Approach”- Author
plugin/skills/task-work/start_task.pymirroring the shape ofplugin/scripts/new_task.py(PEP-723 shebang, argparse, no third-party runtime deps beyond pyyaml). - Replace Step 5b’s seven-step prose with a single shell-out
instruction in
plugin/skills/task-work/SKILL.md. - Add unit tests for
start_task.pyatplugin/skills/task-work/test_start_task.py. Cover the happy path (task flips toin-progresson main, start-commit lands, feat branch rebases) and at least one failure mode (rebase conflict surfaces a non-zero exit). Tests run against an ephemeral fixture git repo built in atmp_path— no SKILL eval harness, no live sub-agent fan-out.
Files to touch
Section titled “Files to touch”plugin/skills/task-work/start_task.py(new)plugin/skills/task-work/SKILL.md— replace Step 5b prose with shell-out.plugin/skills/task-work/test_start_task.py(new)plugin/skills/task-work/invariants.yaml— pinstart_task.pyas arequired_tool_refs.
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: A fresh
/sdlc:task-workrun lands achore(tasks): start <basename>commit on main automatically without sub-agent judgment. - AC-2:
plugin/skills/task-work/test_start_task.pyincludes a happy-path case asserting the start-commit lands on main and the feat branch rebases onto it, plus a rebase-conflict case assertingstart_task.pyexits non-zero with a message that names the conflicting paths. - AC-3:
lint_skill_prose.pyenforces thestart_task.pyreference inplugin/skills/task-work/SKILL.md.
Out of scope
Section titled “Out of scope”- Lifting the Step 11a close-out into a script (related but separate).
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Spawned by /sdlc:task-work post-mortem of T-ZQ4H-task-ensure-ready-accepts-in-progress on 2026-05-19.
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 — Step 5b in this very run shelled out to the new
script (after it was authored), landing commit
df5ac07 chore(tasks): start 2026-05-19-extract-start-task-scripton main with no sub-agent free-form judgment. Also covered bytest_happy_pathinplugin/skills/task-work/test_start_task.py, which asserts the start-commit subject and the rebased feat-branch history shape. - AC-2: auto —
plugin/skills/task-work/test_start_task.pyincludestest_happy_path(asserts the start-commit lands on main and the feat branch is rebased onto it) andtest_rebase_conflict(assertsstart_task.pyexits with status 3 and the diagnostic names the conflicting paths). Two further cases (test_idempotent_when_already _in_progress,test_rejects_closed_task) cover the script’s contract beyond the spec’s minimum. - AC-3: auto —
invariants.yamlnow listsstart_task.pyunderrequired_tool_refs. Verified during this run by deleting the reference from SKILL.md and observinglint_skill_prose.pyexit with status 1 and messagerequired tool reference 'start_task.py' not cited in SKILL.md.
What worked
Section titled “What worked”- The
new_task.pyPEP-723 script was a clean template — same shebang, same argparse shape, same YAML frontmatter round-trip. Reusing that shape kept the new script under 350 lines including docstrings. - The fixture-based test pattern in
plugin/entities/task/migrations/test_v1_to_v2.pyextended cleanly to a script that needs a real git repo.tempfile.TemporaryDirectorygit -Cwas enough; no test framework required.
Friction and automation gaps
Section titled “Friction and automation gaps”- The first run of the test suite caught a real YAML-date round-trip
bug (
yaml.safe_loadreturnsdatetime.datefor bare ISO dates; the script was comparing against a string and so flagged a spurious semantic change). Lesson: when a script edits frontmatter, always normalize dates toisoformat()before comparing — consider factoring a tiny_normalize_frontmatterhelper intoplugin/validators/so future frontmatter-mutating scripts inherit the same normalization for free. → T-07DV-frontmatter-edit-helpers-normalize-yaml-dates plugin/skills/task-work/test_start_task.pyis not currently listed insdlc.yaml’squality_checks:— it only runs if a contributor invokes it directly. The other co-located skill tests (plugin/skills/*/tests/run_evals.py) are listed. Either promote this test to the sametests/layout or add a one-linequality_ checks:entry; otherwise a regression instart_task.pywill pass CI silently. → T-8DQQ-start-task-tests-in-quality-checks- Step 5b’s rebase in this very run surfaced a non-trivial merge
conflict on
last_reviewed:because the feat branch’s ensure-ready commit edited the same field. The skill prose says “something is wrong with the local state” if the rebase conflicts — but in fact a same-field conflict is the expected shape when the start-commit on main and the verify-ready commit on feat both touchlast_reviewed:. The prose should be updated to say “trivial conflicts onlast_reviewed:are expected; resolve by taking HEAD” — or, more durably,start_task.pyshould setlast_reviewed:to a value that won’t conflict with whatever ensure-ready wrote (e.g. derive both stamps from the same UTC clock-call captured at task-work entry). → T-H0W9-task-work-rebase-frontmatter-conflict
Spawned follow-up tasks
Section titled “Spawned follow-up tasks”- T-07DV-frontmatter-edit-helpers-normalize-yaml-dates — factor a shared frontmatter-edit helper that normalizes YAML date/datetime fields before comparison (created).
- T-8DQQ-start-task-tests-in-quality-checks — list
test_start_task.pyinsdlc.yaml’squality_checks:so regressions instart_task.pyfail the pre-PR gate (created). - T-H0W9-task-work-rebase-frontmatter-conflict — same-field rebase conflict between start-commit and verify-ready commit (linked existing).