/sdlc:task-auto-define
Generated from solutions/ontological/skills/task-auto-define/SKILL.md.
Description
Section titled “Description”Drive one or more task documents toward the implementation-ready contract (solutions/ontological/lib/model/entities/task/implementation-ready.md) by synthesizing best-effort content from each task’s existing prose plus codebase context, without prompting the user. Multiple tasks run in sequence, one commit and one slug-namespaced terminal marker each. —set-ready true also promotes each defined task to status: open/ready (default false); —make-pr pushes the run’s commits on a chore/ branch and opens a PR (default off — commit on the current branch only). Stamps a discoverable machine-authored marker on every synthesized spec; leaves readiness_verified_at for /sdlc:task-ensure-ready to stamp. Dispatched by /sdlc:task-ensure-ready when a task is autonomy: autonomous/pr and the deterministic verify reports a gap.
Allowed tools
Section titled “Allowed tools”ReadEditBashGrepGlob
Source
Section titled “Source”Usage:
/sdlc:task-auto-define <task> [<task> ...] [--set-ready true|false] [--make-pr]<task>— slug, filename, or absolute path (use absolute paths when invoking from another skill). Each task runs the per-task flow (Steps 2–7) in sequence; a failure on one task does not abort the rest.--set-ready true|false(defaultfalse) — on a successful define, also set the task’sstatus:toopen/readyin the same commit.--make-pr(default off) — after all tasks are processed, push the run’s commits on achore/branch and open a PR. Without it the skill commits on the caller’s current branch and never pushes.
Fill each task’s readiness gaps with content synthesized from its existing
prose and the surrounding codebase, mark the result as machine-authored, and
commit. This is how an autonomy: autonomous/pr task self-readies instead
of parking at a spec gap.
References:
${CLAUDE_PLUGIN_ROOT}/entities/task/implementation-ready.md— the contract this skill fills gaps against.sdlc task resolve <arg>— resolves each task argument to an absolute path (its spec doc is${CLAUDE_PLUGIN_ROOT}/entities/task/file-resolution.md; see${CLAUDE_PLUGIN_ROOT}cli/sdlc task resolve --help).
Terminal markers (slug-namespaced per solutions/ontological/skills/CLAUDE.md; one per
task, plus the PR marker when --make-pr produced one):
| Marker | Meaning |
|---|---|
TASK-AUTO-DEFINE-DEFINED: <basename> | The doc was edited (gap fills and/or --set-ready status flip), validated, and committed. |
TASK-AUTO-DEFINE-NO-CHANGES: <basename> | No fillable gap and no pending status flip; no edit, no commit. |
TASK-AUTO-DEFINE-INSUFFICIENT: <basename> | A gap exists but cannot be plausibly synthesized from the available prose + codebase context; no edit, no commit. |
TASK-AUTO-DEFINE-PR: <url> | --make-pr pushed the run’s commits and opened a PR. |
ERROR reason="..." | Shared cross-skill failure marker (bad argument, no task found, validator rejected the synthesized doc). Names the failing task in a multi-task run. |
1. Parse the invocation
Section titled “1. Parse the invocation”Split arguments into task references (positional) and flags. No task
reference → exit ERROR reason="no task argument". Run Steps 2–7 for each
task in argument order, recording its terminal marker; on a per-task
failure, continue with the next task. Then run Step 8 once.
2. Resolve the task file
Section titled “2. Resolve the task file”Run sdlc task resolve <argument> per
${CLAUDE_PLUGIN_ROOT}/entities/task/file-resolution.md — the canonical
call + outcome contract (no pipe — gate on the bare exit code, per
${CLAUDE_PLUGIN_ROOT}skills/CLAUDE.md). On success capture the absolute
path and basename and continue to Step 3.
This skill uses the non-interactive ambiguous-policy mode — it never
prompts. Map each failure to this skill’s ERROR marker, then move to
the next task:
AMBIGUOUS:→ERROR reason="ambiguous: <comma-separated candidates>".NO TASK FOUND→ERROR reason="no task found for <argument>".
3. Read inputs
Section titled “3. Read inputs”- Read the task file end-to-end.
- Read
${CLAUDE_PLUGIN_ROOT}/entities/task/implementation-ready.md(once per run is enough).
4. Identify gaps
Section titled “4. Identify gaps”Apply the contract from
${CLAUDE_PLUGIN_ROOT}/entities/task/implementation-ready.md. This skill
computes the same gap-detection FACTS the gate will re-verify — collapsed
from the four former separate op calls into one sdlc task gap-report call
(plus the separate corpus advisory), so this skill’s notion of “gap” matches
what the gate that re-verifies immediately after would reject. Gap detection
is TWO calls: the deterministic gap-report composite (this section) plus the
separate LLM-judged corpus advisory (last bullet). Run each directly (no pipe
— gate on the bare exit code, per ${CLAUDE_PLUGIN_ROOT}skills/CLAUDE.md):
-
Deterministic readiness-gap composite — shell out to the task noun’s
gap-reportop, which runs the four deterministic slices (scan-placeholders+parse-touchpoints+resolve-touchpoints+check-claims) PLUS required-section presence in ONE read-only, no-LLM call and returns ONE structured object:${CLAUDE_PLUGIN_ROOT}cli/sdlc task gap-report <path> --output json(
${CLAUDE_PLUGIN_ROOT}cli/sdlc task gap-report --help; the bare CLI prints aGAP-REPORT gaps=N sections=N placeholders=N touchpoints=N claims=Nmarker, exit 0; a missing file isINVALID_INPUT, exit 1.) This replaces the four separateparse-touchpoints/scan-placeholders/resolve-touchpoints/check-claimscalls this skill used to make. The op reports deterministic FACTS only — it makes none of the interpretation calls below; this skill owns them, reading the unified output. There is NO fallback to the v2 bulleted shape:- Body sections / frontmatter — read each
sections[]entry:present == falseis a required-section gap. That array is the authority on what is required; a section absent from it is optional and its absence costs nothing. Separately read the doc and mark each present section thin (header exists but body is empty, unchanged<...>template text, or too vague to inform the implementer); check each required frontmatter field. - Touchpoint shape — read
touchpoints.files_to_touch_kind/touchpoints.today_kind:files_to_touch_kind == "bulleted-legacy"→ hard fail (v3 is table-only);today_kind == "bulleted-legacy"→ rejected likewise.files_to_touch_kind == "missing"→ accepted; the section is optional in presence, andsections[]is the authority on what is required.today_kind == "prose"is accepted (greenfield);today_kind == "missing"handling is unchanged.
- Touchpoint parse errors — each entry in
touchpoints.parse_errors[](invalid kind, symbol-on-glob, malformed location) is a gap. (Dedup edge-lesson: a row the parser rejected is reported once here, not also as an unresolved row — the op already suppresses that double-count.) - Touchpoint resolution — each entry in
touchpoints.unresolved[]is a gap: a cited Location (Today ormodify/deleteFiles-to-touch row) that does not exist in the working tree (file-missing,symbol-missing,glob-no-match, …). Resolution is existence-only andnewrows fire no existence check — the op resolved each row exactly as the gate does (form: symbolis checked in-TS, historically thecommand grepstep; see Notes). Narrating any path drift to the user is left as it was. - Placeholders — each entry in
placeholders[](TBD / pick-one / angle-bracket / empty-table-cell) is a gap. No further filtering. - Claim resolvers — read
claims[]: eachseverity: "disqualifier"finding is a gap (relay itsmessage/line);severity: "warning"findings are informational only. The flatgaps[]array already aggregates every disqualifier across all of the above (section / placeholder / touchpoint / claim) for direct iteration — the per-category objects carry the detail.
- Body sections / frontmatter — read each
-
Corpus-assumption candidates (advisory) — shell out to the co-located scanner shared with the gate. This stays its OWN separate call: it is LLM-judged / confirm-before-gap and is deliberately NOT folded into
gap-report:bun run ${CLAUDE_PLUGIN_ROOT}skills/task-ensure-ready/scan_corpus_assumptions.ts <path>It emits one JSON line per candidate; empty stdout means none. This scanner is advisory, NOT a hard disqualifier — each candidate is uniform-corpus phrasing in
## Approach/## Proposedwith no nearby tolerance signal. Inspect the cited line; only when you CONFIRM the Approach genuinely assumes a single uniform corpus shape the corpus does not have is it a gap. If the corpus is uniform or the Approach already names the strictness split, it is a false positive. (Capture stdout into a variable if you need to trim it — do not pipe throughtail/headwhen gating.)
For each requirement that fails or disqualifier that triggers, record an entry with:
- the section or field involved,
- the nature of the gap (missing / thin / wrong-value / disqualified-by),
- what an acceptable resolution looks like.
If the gap list is empty:
--set-ready trueandstatus:is notopen/ready→ skip to Step 7 for a status-flip-only commit (nothing was synthesized, so noAUTO-DEFINED:note).- otherwise → report
TASK-AUTO-DEFINE-NO-CHANGES: <basename>and move to the next task. The caller can run/sdlc:task-ensure-readyto formally stamp the verification.
5. Synthesize gap fills (best-effort)
Section titled “5. Synthesize gap fills (best-effort)”For each gap, synthesize content from two sources, in priority order:
- The task’s own prose. The Goal, Discovery context, any existing Approach/Today rows, and the headline usually carry enough intent to draft the missing sections. Stay faithful to what the author wrote — do not invent scope the prose doesn’t support.
- Codebase context. Use Grep / Glob / Read to anchor synthesized
content in real paths. This is what makes a synthesized
## Todayand## Files to touchtable resolve against the live codebase (the readiness verifier checks every cited Location):- For
## Todayand## Files to touch, only cite paths you have actually confirmed exist (formodify/delete/Today rows) via Grep / Glob / Read. Prefer file+symbol (path#name) over file+line. Mark genuinely new filesnew. - For
## Approach, write concrete ordered steps a competent engineer could execute — not “investigate X”. - For
## Acceptance criteria, write objectively verifiable- [ ] AC-N:bullets (assertable / observable / demonstrable), never subjective ones. - For
## Out of scope, enumerate obvious near-misses, or a single- nonebullet if nothing is excluded.
- For
Apply each fill with Edit, preserving section headers; only the body between
headers changes. Match the v3 table shapes (| Location | Role today | for
Today; | Location | Kind | Change | for Files to touch, Kind ∈
{new,modify,delete}) and the five-form Location grammar documented in
the contract.
Do NOT touch the task-state frontmatter fields owned elsewhere:
readiness_verified_at:, touchpoints_verified_at:, definition_gap:,
completion_note:, prs:. This skill edits body content only, plus the
machine-authored note (Step 6) and the --set-ready status flip (Step 7).
Insufficient-context bail-out
Section titled “Insufficient-context bail-out”If a required gap cannot be plausibly synthesized — there is no prose intent
to draw on AND no codebase anchor to infer from, so any fill would be
fabricated rather than best-effort — do NOT write low-quality filler. Revert
any partial edits, report TASK-AUTO-DEFINE-INSUFFICIENT: <basename> naming
the unfillable gap, and move to the next task without committing.
6. Stamp the machine-authored marker
Section titled “6. Stamp the machine-authored marker”Stamp a discoverable “spec auto-defined — review carefully” note in the body so a human reviewer (and later tooling) can tell the spec was machine-synthesized.
Place the note immediately after the # headline and before ## Goal —
outside every required section, so it neither satisfies nor trips the
readiness verifier’s per-section checks. Use this exact shape, substituting
today’s UTC date:
> AUTO-DEFINED: this spec was best-effort machine-authored by> /sdlc:task-auto-define on <YYYY-MM-DD> because the task is> autonomy: autonomous/pr. Review the Goal, Approach, Today,> Files-to-touch, and Acceptance-criteria carefully before trusting it.If a prior AUTO-DEFINED: note already exists (a re-run), refresh its date
rather than stacking a second note.
7. Set status and commit
Section titled “7. Set status and commit”Reached with pending edits (Steps 5–6) or a pending --set-ready flip
(Step 4).
-
If
--set-ready true, set the task’s frontmatterstatus:toopen/readyvia the task noun’s update op (schema-validated, body byte-untouched):${CLAUDE_PLUGIN_ROOT}cli/sdlc task update <path> --set '{"status": "open/ready"}'This flag is the one exception to Step 5’s frontmatter scope rule.
-
With
--make-pr, before the run’s first commit, createchore/auto-define-<stem>from the current HEAD and switch to it —<stem>is the task basename (single task) orbatch-<YYYYMMDD-HHMM>UTC (multiple). Later tasks in the run commit on the same branch. -
Run the validator (no pipe — gate on the bare exit code, per
${CLAUDE_PLUGIN_ROOT}skills/CLAUDE.md“Don’t pipe commands you gate on”):${CLAUDE_PLUGIN_ROOT}cli/sdlc entities validate <path>If it fails, fix and re-run. If it cannot be made to pass, revert the task’s edits, report
ERROR reason="synthesized doc failed frontmatter validation", and move to the next task. -
Stage only the task file:
git add <path>(the commit op commits the staged index — it does NOT narrow scope). -
Commit on the current branch with the model-generated message routed through
sdlc commit create --message -(stdin heredoc; see${CLAUDE_PLUGIN_ROOT}conventions/commit-messages.md):${CLAUDE_PLUGIN_ROOT}cli/sdlc commit create --message - <<'EOF'docs(tasks): auto-define <basename><one-line summary of which sections were synthesized>EOF -
Report:
TASK-AUTO-DEFINE-DEFINED: <basename>sections synthesized: <list, or "none (status flip only)">
8. Open the PR (--make-pr only)
Section titled “8. Open the PR (--make-pr only)”Skip when the flag is absent or the run made no commits (then no branch was created either). Otherwise:
git push -u origin <branch>.gh pr createagainstmain. Title: the single commit’s subject, ordocs(tasks): auto-define <N> tasksfor a multi-task run. Body: the per-task marker lines plus a pointer to review theAUTO-DEFINED:notes before trusting the specs.- Switch the checkout back to the original branch.
- Report
TASK-AUTO-DEFINE-PR: <url>.
In either mode the skill never merges; the human stays at the merge gate.
9. Hand off
Section titled “9. Hand off”Print one pointer line per DEFINED task:
Next: run /sdlc:task-ensure-ready <basename> to verify and stamp.- Best-effort, not authoritative. The
AUTO-DEFINED:note is the human’s signal to review before trusting the spec. This skill leavesreadiness_verified_at:for/sdlc:task-ensure-readyto stamp;--set-readyflipsstatus:only. - One commit per task, touching only that task file.
- Skill-authoring conventions. See
${CLAUDE_PLUGIN_ROOT}skills/CLAUDE.md— slug-namespaced markers, no duplicated prose, gate on bare exit codes. - Committing model-generated messages. Step 7 routes the per-task message
through
sdlc commit create --message -(stdin heredoc). See${CLAUDE_PLUGIN_ROOT}conventions/commit-messages.md. - Commit the body before the gate runs. Step 7 commits the synthesized
body on the current branch as its own commit. This is what lets the
downstream readiness gate stay frontmatter-only:
/sdlc:task-ensure-ready’s Step 3b precondition refuses (exit 4) to stampreadiness_verified_at:while the task file still carries uncommitted body edits, so the gate’s stamp commit and this skill’s body commit must be two separate commits, body first. Never hand the gate an uncommitted synthesized body. See [[T-XBJY-ensure-ready-refuses-with-unstaged-body-edits]] and${CLAUDE_PLUGIN_ROOT}skills/task-ensure-ready/SKILL.mdStep 3b. - Gap detection computes the same gap facts the gate will re-verify. Step 4
collapses the four former separate op calls into one
sdlc task gap-reportcall (the composite that runsparse-touchpoints+scan-placeholders+resolve-touchpoints+check-claims+ required-section presence in one no-LLM call) plus the separate corpus advisory — two calls total. The interpretation layer (greenfield prose-Today accepted, bulleted-legacy a hard fail, severity filtering, placeholders, parse errors, unresolved touchpoints) readsgap-report’s unified output field-for-field, so what this skill flags as a gap matches what the gate that re-verifies right after would reject. command grepfor symbols — now historical / N-A.form: symbolexistence used to be checked here viacommand grep(not baregrep— some shells aliasgreptorg, which fails on BSD flags). That check now runs INSIDEgap-report(inresolve-touchpoints.ts, in TypeScript), so this skill no longer shellscommand grepitself; the unresolved-row facts arrive pre-computed intouchpoints.unresolved[]. The lesson is preserved here so the symbol-resolution contract stays discoverable.- The advisory corpus scanner stays a separate call.
scan_corpus_assumptions.tsis LLM-judged (confirm-before-gap) and is deliberately NOT part ofgap-report’s deterministic composite — it remains its own Step 4 call. - Branch naming. See
${CLAUDE_PLUGIN_ROOT}conventions/branch-naming.md. Default mode commits on whatever branch the caller is on;--make-pruses the bulk-workchore/<skill>-<stem>shape.