/sdlc:task-define
Generated from solutions/ontological/plugin/plugins/sdlc/skills/task-define/task-define.md.
Description
Section titled “Description”Interactively drive a single task document toward the implementation-ready contract (solutions/ontological/lib/model/entities/task/implementation-ready.md). Walks the user through filling missing or thin sections via AskUserQuestion, edits the body, and commits. Leaves readiness_verified_at to /sdlc:task-ensure-ready; callers should invoke task-ensure-ready after this skill returns to verify the result.
Allowed tools
Section titled “Allowed tools”ReadEditBashGrepGlobAskUserQuestion
Source
Section titled “Source”Usage:
/sdlc:task-define <slug-or-filename>— flesh out the named task through guided questions until it satisfies the implementation-ready contract./sdlc:task-define <absolute-path-to-task-file>— same, by absolute path. Use this form when invoking from another skill.
This skill IS interactive — it asks the user via AskUserQuestion to
resolve every gap. If the user can’t or won’t answer, the skill exits
gracefully without forcing a state change (the caller decides what to
do next, typically by invoking /sdlc:task-ensure-ready to record the
incomplete state).
References:
${CLAUDE_PLUGIN_ROOT}/lib/model/entities/task/implementation-ready.md— the contract this skill fills gaps against.sdlc task resolve <arg>— resolves the argument to an absolute task path (see${CLAUDE_PLUGIN_ROOT}/lib/model/entities/task/file-resolution.mdfor the resolution contract it implements, orsdlc task resolve --help).
1. Resolve the task file
Section titled “1. Resolve the task file”Run sdlc task resolve <arg> per
${CLAUDE_PLUGIN_ROOT}/lib/model/entities/task/file-resolution.md — the canonical
call + outcome contract. On success capture the absolute path and
basename and continue to Step 2.
This skill uses the interactive ambiguous-policy mode: on
AMBIGUOUS: it prompts the user via AskUserQuestion over the
--output json candidates and uses the pick. If the user bails (or the
op reports NO TASK FOUND), surface NO TASK FOUND for "<arg>" and stop.
2. Read inputs
Section titled “2. Read inputs”- Read the task file end-to-end.
- Read
${CLAUDE_PLUGIN_ROOT}/lib/model/entities/task/implementation-ready.md.
3. Identify gaps
Section titled “3. Identify gaps”Apply the contract from
${CLAUDE_PLUGIN_ROOT}/lib/model/entities/task/implementation-ready.md. For
each requirement that fails or disqualifier that triggers, add an
entry to the gap list with:
- the section or field involved,
- the nature of the gap (missing / thin / wrong-value / disqualified-by),
- what an acceptable resolution looks like (so the user question can be specific).
Run the mechanical disqualifiers through the deterministic task ops
rather than re-deriving them by reading. This skill must surface the
same gaps /sdlc:task-ensure-ready will (it runs immediately after);
mirror that skill’s Step 3 interpretation layer so a gap this skill
fills is a gap the gate agrees on.
The judged requirements stay LLM work: required-section
presence/thinness (a present section whose body is empty, unchanged
<...> template text, or too vague to inform the implementer),
required-frontmatter fields, subjective ACs, and Approach deferring a
design decision to “the implementer”. Read the body for those. The
LLM-judged corpus-assumption disqualifier is also LLM work, but it has
its own advisory scanner — see “Corpus-assumption advisory” below.
The mechanical disqualifiers run through ONE deterministic composite op,
sdlc task gap-report, which runs scan-placeholders + check-claims +
a read of parse-touchpoints (## Areas shape, informational only)
plus required-section presence in a single NO-LLM call and returns
one structured readiness-gap object. Read that one object instead of
fanning out separate calls.
-
Deterministic gap report. Shell out to the composite op:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc task gap-report <path> --output jsonSee
sdlc task gap-report --help. It is read-only and emits one JSON object; the text-mode marker isGAP-REPORT gaps=N sections=N placeholders=N claims=N(exit 0). A missing/unreadable file isINVALID_INPUT(exit 1) — same as the sibling read-only doc ops. Map its fields onto the gap list:- Touchpoint shape — read
touchpoints.areas_kind(∈table/prose/missing/bulleted-legacy) andtouchpoints.parse_errors[]. As of v7,## Areasis advisory and## Todayis fully free-form prose — neither is a resolution gate, and NEITHER of these fields ever becomes a gap. They exist only so you can narrate the shape to the user if it seems worth mentioning. - Placeholder phrases — each entry in
placeholders[](TBD/pick-one/ angle-bracket /empty-table-cell) is a gap; name the section, the matchedphrase, and theline. The op passes these through unfiltered; they need no further filtering. - Missing required sections — each
sections[]entry withpresent == falseis a required-section gap. - Claim resolvers — read
claims[], mapping byseverity: eachseverity: "disqualifier"finding is a gap — relay itsmessage(andline) into the gap description;severity: "warning"is informational only (no-warning-today; the tier exists for a future use). The op’s owngaps[]array already aggregates the disqualifiers, so you can iterategaps[]directly for the disqualifier union and consult the per-category objects (sections,placeholders,touchpoints,claims) for the full detail to phrase each user question.
The
gaps[]array is the flat, caller-iterable union of every deterministic disqualifier (placeholders, missing sections, claims —## Today/## Areasshape is never one of them);has_gapsis true iff it is non-empty. Iterate it for the union and read the per-category objects for detail. - Touchpoint shape — read
Capture the command’s stdout into a variable and parse it; do not pipe
a command you gate on through tail/head (see
${CLAUDE_PLUGIN_ROOT}/skills/CLAUDE.md).
Corpus-assumption advisory (LLM-judged — separate from gap-report)
Section titled “Corpus-assumption advisory (LLM-judged — separate from gap-report)”See ${CLAUDE_PLUGIN_ROOT}/conventions/corpus-assumptions-scanner.md for
what the scanner checks and how to confirm a candidate. Run it as its own
separate call, after reading the deterministic report:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc task scan-corpus-assumptions <path>Only a candidate you CONFIRM against the cited line is a gap.
If the list is empty, report TASK-DEFINE-ALREADY-READY: <basename> on stdout
and exit without editing or committing. The caller can run
/sdlc:task-ensure-ready to formally stamp the verification. Keep the
marker slug-prefixed (see ${CLAUDE_PLUGIN_ROOT}/skills/CLAUDE.md; the
2026-05-28 namespacing pass fixed an outer LLM mistaking this signal for
its own terminal verdict).
4. Resolve gaps one at a time
Section titled “4. Resolve gaps one at a time”For each gap, ask the user via AskUserQuestion. Be specific:
- Quote the section header and current content (or "
"). - Propose 2-3 plausible options where the gap admits them (e.g. state downshift options, impact tier).
- For free-form content gaps (Goal, Approach, ACs), use AskUserQuestion to confirm the user wants to draft now (“Draft now” / “Skip for now” / “Stop”), then if drafting, ask in plain text for the content.
Apply each answer immediately:
- Branch context — where edits land. Invoke
/sdlc:task-defineonly frommain(or from adocs/<basename>spec-only branch). Per [[T-SIHV-task-state-frontmatter-commits-on-main-not-worktree-branch]], task-state frontmatter (state:,readiness_verified_at:,last_reviewed:,definition_gap:,completion_note:,prs:) belongs onmain; body content belongs on whatever branch the user is on. This skill edits both kinds in the same commit, so running it from inside a task worktree would land non-state frontmatter on the task branch — defer those to a separate spec-only PR if the gap matters enough to land outside the implementation diff. - Body content: use Edit to replace the gap region. Preserve the section header; only the body between headers changes.
## Todayis free-form prose — write whatever orients an implementer, no required shape.## Areasis advisory: when it reads best as a table, use| Area | Note |(a package/directory/module and a one-line gloss); prose or a bulleted list is equally fine. Neither section is resolved against the codebase, so there is no existence requirement to satisfy — see${CLAUDE_PLUGIN_ROOT}/lib/model/entities/task/implementation-ready.md.- Frontmatter: use Edit to set the field. Do NOT touch
readiness_verified_at:,touchpoints_verified_at:,definition_gap:,completion_note:, orprs:— those are task-state fields managed elsewhere (/sdlc:task-ensure-readyowns the readiness stamp / gap;/sdlc:task-workStep 10.4 ownsprs:;/sdlc:task-close-outownscompletion_note:).
If at any point the user picks “Stop” (or equivalent), jump to Step 6 without further questions.
After every gap is resolved (or the user stops), proceed.
4b. Authoring-time advisory: surface schema-violating fields for “make X validate” ACs
Section titled “4b. Authoring-time advisory: surface schema-violating fields for “make X validate” ACs”For a task shaped “make file X pass validate_frontmatter.ts,”
surface which fields of X currently fail so the author can
enumerate them in Approach up front. This step is an authoring aid:
it does not gate readiness, does not edit Out-of-scope unless the
user explicitly opts in, and accepts “decline” as a first-class
answer.
Procedure:
-
Shell out to the scanner:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc task scan-validate-ac <absolute path to task file>The scanner inspects the task’s
## Acceptance criteriasection for lines that mention bothvalidate_frontmatter.tsand at least one.mdpath. For each target, it runs the validator and captures the failing fields. Output is a single JSON object on stdout — see the op’s docstring for the exact shape. -
Parse the JSON. If
matchedisfalse(no validate-AC found), ortargetsis empty, skip the rest of this step. -
For each target with at least one
failing_fieldsentry, present the failures to the user via AskUserQuestion. Quote the path and list each failing pointer + message. Offer three options:- Inject into Approach — Edit a bullet under the
## Approachsection listing the failing fields (one bullet per target, in citation order). Format:Known schema-violating fields in <path>: <pointer1> (<message1>), <pointer2> (<message2>), .... Place the new bullet at the end of the existing Approach body so ordering of pre-existing steps is preserved. - Add to Out of scope — Edit a bullet under
## Out of scopenaming the fields that are not in scope for this task (e.g. when the task fixes one field but the file has unrelated violations). - Decline — leave the body untouched. The advisory was seen and considered; no edit lands.
- Inject into Approach — Edit a bullet under the
-
For each target where the file doesn’t exist (
exists: false) OR the validator passed with no failures (failing_fields: []), surface the finding to the user as informational (“X currently validates clean — the AC may be a regression guard rather than a fix”) but do not Edit the body. The user may want to revise the AC; that’s their call. -
Treat user answers as ordinary gap resolutions for the purposes of Step 5 (re-evaluation) and Step 6 (commit). The commit message summary should mention the advisory if it landed an edit (“inject schema-violating fields for
<path>”).
This step runs once per /sdlc:task-define invocation, after the
section-gap pass and before re-evaluation. It is a no-op on tasks
that don’t carry a validate-AC, and a no-op when the user declines
the offer.
5. Re-evaluate
Section titled “5. Re-evaluate”Re-read the task file. Re-apply the contract. If gaps remain that the user did NOT explicitly skip, ask once more. If they remain after that, treat it as a “Stop” and proceed to Step 6.
6. Commit
Section titled “6. Commit”If any edits were made:
-
Run the validator:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc entities validate <path>If it fails, fix and re-run.
-
Stage only the task file:
git add <path>. -
Commit on the current branch:
docs(tasks): flesh out <basename><one-line summary of what was added> -
Report on stdout:
TASK-DEFINE-DEFINED: <basename>sections updated: <list>
If no edits were made (user stopped immediately, or there were no
gaps), report TASK-DEFINE-NO-CHANGES: <basename> and exit without
committing.
7. Hand off
Section titled “7. Hand off”Print a one-line pointer:
Next: run /sdlc:task-ensure-ready <basename> to verify and stamp.- The doc the user lands on is whatever they typed. Don’t paraphrase, reword, or “improve” their content. Apply minimal edits to put their text into the right section.
- If the user wants to rewrite a section that’s already populated (not thin or missing, just wrong), this is the right skill but you should confirm via AskUserQuestion before overwriting non-empty content.
- One commit per run, touching only the task file. Same atomicity
contract as
/sdlc:task-ensure-ready. - Gap detection is two calls —
sdlc task gap-report(deterministic, NO-LLM composite over sections + placeholders + claims, plus an informational-only read of## Areasshape) plus the separate corpus-assumption advisory (see${CLAUDE_PLUGIN_ROOT}/conventions/corpus-assumptions-scanner.md). As of v7,## Todayand## Areasare never resolved against the codebase, so there is no symbol/path existence probe left in this path at all. - Committing model-generated messages. See
${CLAUDE_PLUGIN_ROOT}/conventions/commit-messages.mdfor the canonical pattern (andsdlc commit create --help); this skill authors multi-line commits from model output, so follow that convention rather than dropping back to single-line-m. - Branch naming. See
${CLAUDE_PLUGIN_ROOT}/conventions/branch-naming.md. This skill commits on whatever branch the user is on; if it’s the spec-onlydocs/<basename>branch, that’s expected — body refinements land in the spec PR.