|
| 1 | +--- |
| 2 | +description: Assess the current codebase against the feature's spec, plan, and tasks, then append any remaining unbuilt work as new tasks to tasks.md so implement can complete it. |
| 3 | +scripts: |
| 4 | + sh: scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks |
| 5 | + ps: scripts/powershell/check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks |
| 6 | +--- |
| 7 | + |
| 8 | +## User Input |
| 9 | + |
| 10 | +```text |
| 11 | +$ARGUMENTS |
| 12 | +``` |
| 13 | + |
| 14 | +You **MUST** consider the user input before proceeding (if not empty). |
| 15 | + |
| 16 | +## Pre-Execution Checks |
| 17 | + |
| 18 | +**Check for extension hooks (before convergence)**: |
| 19 | + |
| 20 | +- Check if `.specify/extensions.yml` exists in the project root. |
| 21 | +- If it exists, read it and look for entries under the `hooks.before_converge` key |
| 22 | +- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally |
| 23 | +- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default. |
| 24 | +- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions: |
| 25 | + - If the hook has no `condition` field, or it is null/empty, treat the hook as executable |
| 26 | + - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation |
| 27 | +- For each executable hook, output the following based on its `optional` flag: |
| 28 | + - **Optional hook** (`optional: true`): |
| 29 | + |
| 30 | + ```text |
| 31 | + ## Extension Hooks |
| 32 | +
|
| 33 | + **Optional Pre-Hook**: {extension} |
| 34 | + Command: `/{command}` |
| 35 | + Description: {description} |
| 36 | +
|
| 37 | + Prompt: {prompt} |
| 38 | + To execute: `/{command}` |
| 39 | + ``` |
| 40 | +
|
| 41 | + - **Mandatory hook** (`optional: false`): |
| 42 | +
|
| 43 | + ```text |
| 44 | + ## Extension Hooks |
| 45 | +
|
| 46 | + **Automatic Pre-Hook**: {extension} |
| 47 | + Executing: `/{command}` |
| 48 | + EXECUTE_COMMAND: {command} |
| 49 | +
|
| 50 | + Wait for the result of the hook command before proceeding to the Goal. |
| 51 | + ``` |
| 52 | +
|
| 53 | +- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently |
| 54 | +
|
| 55 | +## Goal |
| 56 | +
|
| 57 | +Close the gap between what a feature's specification, plan, and tasks call for and what the |
| 58 | +codebase currently implements. Read `spec.md`, `plan.md`, and `tasks.md` as the **sole |
| 59 | +source of intent** (with the constitution as governing constraints), assess the current |
| 60 | +state of the code, determine which requirements, acceptance criteria, plan decisions, and |
| 61 | +existing tasks are unmet, incomplete, or only partially satisfied, and **append each piece |
| 62 | +of remaining work as a new, traceable task** at the bottom of `tasks.md` so that |
| 63 | +`__SPECKIT_COMMAND_IMPLEMENT__` can complete it. This command MUST run only after |
| 64 | +`__SPECKIT_COMMAND_IMPLEMENT__` has run on the current `tasks.md`, and after `__SPECKIT_COMMAND_TASKS__` has produced a complete `tasks.md`. |
| 65 | +
|
| 66 | +This is **not** a diff tool and does **not** track changes. It assesses the present state |
| 67 | +of the code relative to the feature's artifacts — no git, no branch comparison, no history. |
| 68 | +
|
| 69 | +## Operating Constraints |
| 70 | +
|
| 71 | +**APPEND-ONLY, NEVER REWRITE**: The command's **only** write is appending a new |
| 72 | +`## Phase N: Convergence` section to `tasks.md`. It MUST NOT: |
| 73 | +
|
| 74 | +- modify `spec.md` or `plan.md` in any way; |
| 75 | +- rewrite, renumber, reorder, or delete any existing task (including tasks from a prior |
| 76 | + Convergence phase); |
| 77 | +- modify, create, or delete any application code — completing the appended tasks is the |
| 78 | + job of `__SPECKIT_COMMAND_IMPLEMENT__`. |
| 79 | +
|
| 80 | +When the codebase already satisfies everything, the command MUST leave `tasks.md` |
| 81 | +**byte-for-byte unchanged** (no empty Convergence header) and report a clean result. |
| 82 | +
|
| 83 | +**Constitution Authority**: The project constitution (`/memory/constitution.md`) is |
| 84 | +**non-negotiable**. Code that violates a MUST principle is the highest-severity finding and |
| 85 | +produces a corresponding remediation task. If the constitution is an unfilled template, |
| 86 | +skip constitution checks gracefully rather than failing. |
| 87 | +
|
| 88 | +## Execution Steps |
| 89 | +
|
| 90 | +### 1. Initialize Convergence Context |
| 91 | +
|
| 92 | +Run `{SCRIPT}` once from repo root and parse JSON for FEATURE_DIR and AVAILABLE_DOCS. Derive absolute paths: |
| 93 | +
|
| 94 | +- SPEC = FEATURE_DIR/spec.md |
| 95 | +- PLAN = FEATURE_DIR/plan.md |
| 96 | +- TASKS = FEATURE_DIR/tasks.md |
| 97 | +- CONSTITUTION = `/memory/constitution.md` (if present) |
| 98 | +If `spec.md`, `plan.md`, or `tasks.md` is missing, STOP with a clear, actionable message naming the |
| 99 | +prerequisite command to run (`__SPECKIT_COMMAND_SPECIFY__` for a missing spec, `__SPECKIT_COMMAND_PLAN__` for a missing plan, |
| 100 | +`__SPECKIT_COMMAND_TASKS__` for missing tasks). Do not produce partial output. |
| 101 | +For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot"). |
| 102 | +
|
| 103 | +### 2. Load Artifacts (Progressive Disclosure) |
| 104 | +
|
| 105 | +Load only the minimal necessary context from each artifact: |
| 106 | +
|
| 107 | +**From spec.md:** |
| 108 | +
|
| 109 | +- Functional Requirements (FR-###) |
| 110 | +- Success Criteria (SC-###) — include only items requiring buildable work; exclude |
| 111 | + post-launch outcome metrics and business KPIs |
| 112 | +- User Stories and their Acceptance Scenarios |
| 113 | +- Edge Cases (if present) |
| 114 | +
|
| 115 | +**From plan.md:** |
| 116 | +
|
| 117 | +- Architecture/stack choices and technical decisions |
| 118 | +- Data Model references |
| 119 | +- Phases and named touch-points (files/components the plan says will be created or edited) |
| 120 | +- Technical constraints |
| 121 | +
|
| 122 | +**From tasks.md:** |
| 123 | +
|
| 124 | +- Task IDs (to compute the next ID and next phase number) |
| 125 | +- Descriptions, phase grouping, and referenced file paths |
| 126 | +
|
| 127 | +**From constitution (if not an unfilled template):** |
| 128 | +
|
| 129 | +- Principle names and MUST/SHOULD normative statements |
| 130 | +
|
| 131 | +### 3. Build the Intent Inventory |
| 132 | +
|
| 133 | +Create an internal model (do not echo raw artifacts): |
| 134 | +
|
| 135 | +- **Requirements inventory**: one stable key per FR-### / SC-### / user-story acceptance |
| 136 | + scenario (e.g. `US1/AC2`), plus the plan decisions and constitution principles that |
| 137 | + impose buildable obligations. |
| 138 | +- **Code-scope map**: from the file paths named in `plan.md` and `tasks.md`, plus a keyword |
| 139 | + search for the concepts each requirement describes, derive the set of source files and |
| 140 | + components in scope for assessment. Bound the assessment to these — do **not** infer |
| 141 | + scope beyond what the artifacts define. |
| 142 | +
|
| 143 | +### 4. Assess the Codebase and Classify Findings |
| 144 | +
|
| 145 | +For each item in the intent inventory, inspect the current code in scope and produce a |
| 146 | +`Finding` only where there is a gap. Classify every finding by **gap type**: |
| 147 | +
|
| 148 | +- **`missing`**: the required work is absent from the code entirely. |
| 149 | +- **`partial`**: the work exists but does not yet fully satisfy the requirement / |
| 150 | + acceptance criterion / plan decision. |
| 151 | +- **`contradicts`**: the code does something that conflicts with stated intent or a |
| 152 | + constitution MUST principle. |
| 153 | +- **`unrequested`**: the code contains work not called for by the spec, plan, or tasks |
| 154 | + (surfaced for awareness — converge does **not** delete code, it only appends a task to |
| 155 | + review/justify or remove it). |
| 156 | +
|
| 157 | +Each `Finding` records: a stable id, the `source-ref` it traces to, the `gap-type`, a |
| 158 | +severity, and a short human-readable description with the evidence (the file/area observed). |
| 159 | +
|
| 160 | +**Edge cases:** |
| 161 | +
|
| 162 | +- **Little or no code yet**: treat the entire specified scope as `missing` remaining work |
| 163 | + rather than failing. |
| 164 | +- **Nothing remains**: produce zero findings and follow the converged branch in Step 7. |
| 165 | +
|
| 166 | +### 5. Assign Severity |
| 167 | +
|
| 168 | +- **CRITICAL**: violates a constitution MUST principle, or a `missing`/`contradicts` gap |
| 169 | + that blocks baseline functionality of a P1 user story. |
| 170 | +- **HIGH**: a `missing` or `partial` gap on a core functional requirement or acceptance |
| 171 | + criterion. |
| 172 | +- **MEDIUM**: a `partial` gap on a secondary requirement, or an `unrequested` addition with |
| 173 | + unclear justification. |
| 174 | +- **LOW**: minor partial gaps, polish, or low-risk `unrequested` additions. |
| 175 | +
|
| 176 | +### 6. Present the In-Session Findings Summary |
| 177 | +
|
| 178 | +Before appending anything, output a compact, severity-graded summary (no file writes yet): |
| 179 | +
|
| 180 | +## Convergence Findings |
| 181 | +
|
| 182 | +| ID | Gap Type | Severity | Source | Evidence | Remaining Work | |
| 183 | +|----|----------|----------|--------|----------|----------------| |
| 184 | +| F1 | missing | HIGH | FR-008 | Example: no append-only guard detected in path/to/module.py when writing tasks.md | Add append-only enforcement | |
| 185 | +
|
| 186 | +**Summary metrics:** |
| 187 | +
|
| 188 | +- Requirements / acceptance criteria checked |
| 189 | +- Plan decisions checked |
| 190 | +- Constitution principles checked (or "skipped — template") |
| 191 | +- Findings by gap type (missing / partial / contradicts / unrequested) |
| 192 | +- Findings by severity |
| 193 | +
|
| 194 | +### 7. Append Convergence Tasks (or report converged) |
| 195 | +
|
| 196 | +**If there are one or more actionable findings** (`tasks_appended` outcome): |
| 197 | +
|
| 198 | +Append to the **end** of `tasks.md`, per the append contract: |
| 199 | +
|
| 200 | +1. Scan all existing task IDs; let `M` be the maximum. Determine the next phase number `N` |
| 201 | + (highest existing phase + 1). |
| 202 | +2. Write a single new section header `## Phase N: Convergence`. |
| 203 | +3. Emit one checklist item per actionable finding, ordered CRITICAL/HIGH first, assigning |
| 204 | + zero-padded IDs `T{M+1:03d}, T{M+2:03d}, …`: |
| 205 | +
|
| 206 | + ```markdown |
| 207 | + - [ ] T042 <imperative description> per <source-ref> (<gap-type>) |
| 208 | + ``` |
| 209 | + |
| 210 | + `<source-ref>` traces the task to its origin: e.g. `FR-003`, `SC-002`, |
| 211 | + `US1/AC2`, `plan: storage decision`, `Constitution II`. |
| 212 | + |
| 213 | + `<gap-type>` is one of `missing`, `partial`, `contradicts`, `unrequested`. |
| 214 | + |
| 215 | + Constitution-violation tasks MUST be emitted first and described as |
| 216 | + `CRITICAL`. |
| 217 | +4. Never reuse or renumber existing IDs. If a prior Convergence phase exists, add a new, |
| 218 | + separately-numbered one below it — do not touch the old one. |
| 219 | + |
| 220 | +**If there are no actionable findings** (`converged` outcome): |
| 221 | + |
| 222 | +- Do **not** modify `tasks.md` at all — no empty phase header. |
| 223 | +- Report: **"✅ Converged — the implementation satisfies the spec, plan, and tasks."** |
| 224 | +- Include the summary counts of what was checked. |
| 225 | + |
| 226 | +### 8. Provide Next Actions (Handoff) |
| 227 | + |
| 228 | +- On `tasks_appended`: state how many tasks were appended under which phase, and recommend |
| 229 | + running `__SPECKIT_COMMAND_IMPLEMENT__` to complete them; note that a follow-up converge |
| 230 | + run will find fewer or no remaining items. |
| 231 | +- On `converged`: recommend proceeding to review / opening a PR. No further implement pass |
| 232 | + is needed for this feature's specified scope. |
| 233 | + |
| 234 | +### 9. Check for extension hooks |
| 235 | + |
| 236 | +After producing the result, check if `.specify/extensions.yml` exists in the project root. |
| 237 | + |
| 238 | +- If it exists, read it and look for entries under the `hooks.after_converge` key |
| 239 | +- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally |
| 240 | +- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default. |
| 241 | +- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions: |
| 242 | + - If the hook has no `condition` field, or it is null/empty, treat the hook as executable |
| 243 | + - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation |
| 244 | +- Report the convergence outcome (`converged` or `tasks_appended`) in-session before listing |
| 245 | + any hooks, so users can decide whether to run optional follow-up commands. |
| 246 | +- For each executable hook, output the following based on its `optional` flag: |
| 247 | + - **Optional hook** (`optional: true`): |
| 248 | + |
| 249 | + ```text |
| 250 | + ## Extension Hooks |
| 251 | +
|
| 252 | + **Optional Hook**: {extension} |
| 253 | + Command: `/{command}` |
| 254 | + Description: {description} |
| 255 | +
|
| 256 | + Prompt: {prompt} |
| 257 | + To execute: `/{command}` |
| 258 | + ``` |
| 259 | +
|
| 260 | + - **Mandatory hook** (`optional: false`): |
| 261 | +
|
| 262 | + ```text |
| 263 | + ## Extension Hooks |
| 264 | +
|
| 265 | + **Automatic Hook**: {extension} |
| 266 | + Executing: `/{command}` |
| 267 | + EXECUTE_COMMAND: {command} |
| 268 | + ``` |
| 269 | +
|
| 270 | +- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently |
0 commit comments