speckit-companion-tasks
Companion tasks — user-story phased task list
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Companion tasks — user-story phased task list
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
Perform a non-destructive cross-artifact consistency and quality analysis
Identify underspecified areas in the current feature spec by asking up
Companion implement — execute tasks.md in dependency order, then mark complete
Mark the active spec completed — the Companion workflow's terminal step (writes status: completed)
Companion plan — implementation plan with research & design artifacts
Companion specify — spec.md with prioritized user stories
| name | speckit-companion-tasks |
| description | Companion tasks — user-story phased task list |
| compatibility | Requires spec-kit project structure with .specify/ directory |
| metadata | {"author":"github-spec-kit","source":"companion:commands/speckit.companion.tasks.md"} |
$ARGUMENTS
Companion runs on top of stock spec-kit, so a project's installed spec-kit extensions (git, and any others registered in .specify/extensions.yml) must still fire on a Companion run exactly as they do on a stock /speckit.* run. This is separate from Companion's own node-hooks (.specify/companion.yml): both fire. Like the rest of the pipeline, checking these hooks must never fail the host command — if anything is missing or malformed, skip silently and continue.
Let <step> be this command's phase: specify, plan, tasks, or implement.
Before-hooks — run these now, before any of the work below.
.specify/extensions.yml exists in the project root. If it does not, skip silently — there are no hooks.hooks.before_<step>. If the YAML cannot be parsed, skip hook checking silently and continue normally.enabled is explicitly false. A hook with no enabled field is enabled by default.condition expression yourself: a hook with no condition (or a null/empty one) is executable; a hook with a non-empty condition is left to the HookExecutor — skip it here.optional flag:
optional: true):
## Extension Hooks
**Optional Pre-Hook**: {extension}
Command: `/{command}`
Description: {description}
Prompt: {prompt}
To execute: `/{command}`
optional: false):
## Extension Hooks
**Automatic Pre-Hook**: {extension}
Executing: `/{command}`
EXECUTE_COMMAND: {command}
Wait for the result of the hook command before proceeding to the Outline.
After-hooks — run these once this command's work is fully reported, before handing off.
.specify/extensions.yml; if absent or unparseable, skip silently. Look under hooks.after_<step>, applying the same enabled / condition filtering as above.optional: true):
## Extension Hooks
**Optional Hook**: {extension}
Command: `/{command}`
Description: {description}
Prompt: {prompt}
To execute: `/{command}`
optional: false):
## Extension Hooks
**Automatic Hook**: {extension}
Executing: `/{command}`
EXECUTE_COMMAND: {command}
For specify, branch creation is normally one of these before_specify hooks (the git extension); spec directory and file creation are always handled by the command body itself.
Produce a dependency-ordered task list organized by user story into phases (Setup → Foundational → one phase per story → Polish), so each story is an independently testable increment.
Right-size this task list to the change. Before drafting, read the recorded size from the spec's context — .spec-context.json → the size field (treat a missing value as normal). Apply the budget to the step below, omitting anything it says to skip.
normal or oversized — produce the full phased task list exactly as the step describes. No trimming.simple — a small change needs the tasks, not the ceremony around them. Produce a lean list:
Goal / Independent Test / Checkpoint blocks — a small change ships in one pass, not as separate demoable slices.T###, the exact file, the requirement) — trim the framing, never the tasks themselves.This budget governs the step that follows. Where it would produce something the budget skips, omit it.
Read .specify/feature.json for the feature directory; load plan.md and spec.md (required), plus data-model.md, contracts/, and research.md if present.
Create <feature_directory>/tasks.md organized by user story, so each story can be implemented, tested, and delivered as an independent increment. Use the line format - [ ] **T###** [P?] [US#] Description · exact/file/path:
[P] marks a task that is independent of the others in its wave — a different file with no incomplete dependency, so it can be built in any order (or in parallel on a host that wants to).[US#] maps the task to a user story from the spec for traceability.Make the dependency structure explicit — group each phase's work into ordered waves, never a flat list. A reader (human or agent) must see at a glance which tasks are independent and where work has to wait:
**Wave 1 — independent (different files):** and tag each of its tasks [P].**⟶ Wait for Wave 1 to finish, then:** — before the tasks that depend on the previous wave. Those form the next wave (or run singly).[P]. Same-file or dependent tasks are never in the same wave. Group every genuinely-independent task of the phase into one wave, so the dependency boundaries are honest.
This wave layout is the execution map implement reads — it replaces the old scattered-[P] list. (Implement builds the tasks inline by default; the wave grouping documents the dependency order and tells a subagent-capable host which tasks could run together.)Group the waves into phases, in this order:
### Tests block (include only when the spec or constitution asks for tests — write them to fail first), then ### Implementation laid out as waves (foundation/models first, then the independent components/UI wave, then the integration wave), then a Checkpoint line stating the story is now independently functional and testable.End with a Dependencies & Execution Order section: the phase dependencies (Setup → Foundational → stories → Polish) and a one-line restatement of each phase's waves (which wave blocks which). Each task names the concrete file it creates or edits.
Output: <feature_directory>/tasks.md organized by user story into dependency-ordered phases, each phase laid out as explicit waves with join points.
.spec-context.json honestThese rules apply to every Companion profile command. The extension records lifecycle timing with its own scripts wherever it can; these rules keep anything you append consistent with that and accurate for any dispatcher (terminal, IDE chat, or the GUI). The model is finish-only: each task and each substep records a single finish event, and its duration is the gap to the previous finish (or the step's start). Never a start+complete pair for a task or substep — a pair stamped at one instant is what produces 0s ticks and bursts.
Never hand-edit .spec-context.json. Record every finish by running the writer script, never by editing the JSON file yourself — a hand-authored edit is what corrupts the file (a duplicated status key). The script stamps the real clock, writes atomically, and is idempotent. The commands below are the only way you touch timing.
Self-close — but not specify or implement. When your own work for plan, tasks, clarify, or analyze ends, record the step finish (feature dir from .specify/feature.json):
python3 .specify/extensions/companion/scripts/write-context.py --feature-dir <feature_dir> --step <this step> --finish --by ai
--finish appends a single step-level complete and touches nothing else (it leaves status/currentStep to the lifecycle hooks). Do NOT self-close specify or implement: the extension closes those itself (specify from its own command, implement from the end-of-step hook), so an ai complete there would duplicate it.
Substeps — one finish each, via the script. For each substep boundary (plan: research, design; tasks: generate), the moment that substep ends, run:
python3 .specify/extensions/companion/scripts/write-context.py --feature-dir <feature_dir> --step <step> --substep <name> --finish --by ai
One call per substep, each stamped with its own real clock at the moment it finishes — never two substeps in one batch, never a separate start. The delta between consecutive finishes is each substep's duration.
Implement — finishing a task is logging it (finish-only). Recording a task's finish is the closing action of that task, done the instant its work is complete and before you start the next one — not a bookkeeping pass you batch at the end of a phase. The closing action is a single append (feature dir from .specify/feature.json):
python3 .specify/extensions/companion/scripts/write-context.py --feature-dir <feature_dir> --task <TaskID> --kind complete --by ai --did "<one-line summary of what this task did>" --files "<comma,separated,files,touched>" --append
--append writes one line to .spec-context.events.jsonl and does not read or rewrite the shared .spec-context.json, so it never hits the "read the file first" retry and parallel workers can each append their own finish at the same time without contending — the line carries its own real timestamp (date -u is stamped by the script). The --did/--files flags ride along so the Activity panel's Tasks card is populated from the script. Do NOT hand-edit the - [ ] checkbox in tasks.md — the script owns it: materialize flips it to - [x] from your appended finish, so a fanned-out subagent only appends and never touches the shared tasks.md. Do NOT hand-author per-task JSON and do NOT write a per-task start.
Then fold the appended lines into .spec-context.json — run this once per wave (after the wave reconciles) and again when the step ends:
python3 .specify/extensions/companion/scripts/write-context.py --feature-dir <feature_dir> --materialize
--materialize is the one read-modify-write: it folds the finishes into the panel and checks off the matching tasks.md boxes for every journaled task, idempotently (re-folding never double-counts), so running it per wave keeps the GUI current without re-serializing the work. The end-of-step hook is a backstop that materializes anything you didn't fold and fills any task you didn't journal. What's trustworthy here is the per-task summary (did/files) and the order tasks completed, plus the step-level start→complete span, which the scripts stamp exactly. The per-task timestamps are best-effort — a single agent logs a task right after building it, so they reflect when you recorded it, not a precisely measured duration; that's fine, the summaries are the point. Still, record each finish as you go, wave by wave rather than dumping every task at the very end — a per-wave cadence keeps the panel live and the ordering true.
Never write the next step's start. Only the next command appends the next step's start entry; writing it here makes the viewer render a phantom "Generating …".
This is one step in the Companion pipeline. How the run continues depends on the environment you are running in; do not invoke a separate headless/deterministic run command for the everyday flow.
speckit-extension/workflows/speckit-companion.workflow.yml) to learn which step comes next, then continue into it on your own — dispatch the next step's /speckit.companion.* command and keep going through the pipeline.gate (e.g. review-spec, review-plan), stop and wait for approval rather than running past it. Only continue once the gate is approved.mark-complete. Run it so the spec lands at status: completed. That step writes completed only through write-context.py --mark-complete, which refuses unless the spec is already implemented — never introduce a second completed-writer.before/after insertsThis command is assembled from ordered nodes. A project can attach its own work at the boundary before or after any node by declaring it in .specify/companion.yml. You are the runtime: read that file (if present) and run those hooks at the right moments. Like the rest of the pipeline, this must never fail the host command — degrade and continue.
Find the hooks for this command. Look up commands.<this-command>.hooks in .specify/companion.yml. It has two anchors, before and after, each keyed by a node id from this command's order. Run a node's before hooks immediately before that node's work, and its after hooks immediately after. When several hooks sit at one anchor, run them top to bottom, in declared order.
Hook types:
{ type: command, run: "<shell>" } — run the shell command with your terminal/Bash tool, then continue. If you have no terminal tool (some chat-only providers), do not pretend to: report the command you would have run and continue.{ type: prompt, text: "<instruction>" } — treat the text as an inline instruction and act on it before moving on.{ type: node, ref: <id> } — read .specify/companion/nodes/<id>.md and carry out its body as if it were part of this command.Background hooks. Any hook may add background: true. Kick it off and continue the pipeline immediately without waiting for it to finish — it must not hold the spec prisoner. Use it for slow, independent side-effects (a test run, a build, a notification): for a command, launch it detached (e.g. append & or use nohup … &); for a node/prompt, do its work without blocking the next step. Report its result whenever it lands, but never block on it. Do not mark a background hook on anything that writes .spec-context.json (the timing/capture calls): those are fast already and run a read-modify-write on the shared file, so two of them racing in the background can lose an update. Background is for side-effects, not bookkeeping.
Failure handling (never abort the host command):
.specify/companion.yml → there are no hooks; run the command exactly as written. Do not warn.type: node hook's ref file is missing → this is a real misconfiguration: report it clearly and stop before doing damage, rather than silently skipping.If a hook's own work fails (a command exits non-zero, a node can't complete), report it and — unless the failure clearly makes the rest unsafe — continue the pipeline. The host command's own output is never blocked by a hook.