|
| 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 | +--- |
| 4 | + |
| 5 | +## User Input |
| 6 | + |
| 7 | +```text |
| 8 | +$ARGUMENTS |
| 9 | +``` |
| 10 | + |
| 11 | +You **MUST** consider the user input before proceeding (if not empty). |
| 12 | + |
| 13 | +## Pre-Execution Checks |
| 14 | + |
| 15 | +**Check for extension hooks (before convergence)**: |
| 16 | + |
| 17 | +- Check if `.specify/extensions.yml` exists in the project root. |
| 18 | +- If it exists, read it and look for entries under the `hooks.before_converge` key |
| 19 | +- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally |
| 20 | +- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default. |
| 21 | +- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions: |
| 22 | + |
| 23 | + - If the hook has no `condition` field, or it is null/empty, treat the hook as executable |
| 24 | + - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation |
| 25 | + |
| 26 | +- For each executable hook, output the following based on its `optional` flag: |
| 27 | + |
| 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.implement` can complete it. This command MUST run only after |
| 64 | +`/speckit.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.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 (`.specify/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 `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` 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 = `.specify/memory/constitution.md` (if present) |
| 98 | +
|
| 99 | +If `plan.md` or `tasks.md` is missing, STOP with a clear, actionable message naming the |
| 100 | +prerequisite command to run (`/speckit.plan` for a missing plan, |
| 101 | +`/speckit.tasks` for missing tasks). Do not produce partial output. |
| 102 | +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"). |
| 103 | +
|
| 104 | +### 2. Load Artifacts (Progressive Disclosure) |
| 105 | +
|
| 106 | +Load only the minimal necessary context from each artifact: |
| 107 | +
|
| 108 | +**From spec.md:** |
| 109 | +
|
| 110 | +- Functional Requirements (FR-###) |
| 111 | +- Success Criteria (SC-###) — include only items requiring buildable work; exclude |
| 112 | + post-launch outcome metrics and business KPIs |
| 113 | +- User Stories and their Acceptance Scenarios |
| 114 | +- Edge Cases (if present) |
| 115 | +
|
| 116 | +**From plan.md:** |
| 117 | +
|
| 118 | +- Architecture/stack choices and technical decisions |
| 119 | +- Data Model references |
| 120 | +- Phases and named touch-points (files/components the plan says will be created or edited) |
| 121 | +- Technical constraints |
| 122 | +
|
| 123 | +**From tasks.md:** |
| 124 | +
|
| 125 | +- Task IDs (to compute the next ID and next phase number) |
| 126 | +- Descriptions, phase grouping, and referenced file paths |
| 127 | +
|
| 128 | +**From constitution (if not an unfilled template):** |
| 129 | +
|
| 130 | +- Principle names and MUST/SHOULD normative statements |
| 131 | +
|
| 132 | +### 3. Build the Intent Inventory |
| 133 | +
|
| 134 | +Create an internal model (do not echo raw artifacts): |
| 135 | +
|
| 136 | +- **Requirements inventory**: one stable key per FR-### / SC-### / user-story acceptance |
| 137 | + scenario (e.g. `US1/AC2`), plus the plan decisions and constitution principles that |
| 138 | + impose buildable obligations. |
| 139 | +- **Code-scope map**: from the file paths named in `plan.md` and `tasks.md`, plus a keyword |
| 140 | + search for the concepts each requirement describes, derive the set of source files and |
| 141 | + components in scope for assessment. Bound the assessment to these — do **not** infer |
| 142 | + scope beyond what the artifacts define (FR-001). |
| 143 | +
|
| 144 | +### 4. Assess the Codebase and Classify Findings |
| 145 | +
|
| 146 | +For each item in the intent inventory, inspect the current code in scope and produce a |
| 147 | +`Finding` only where there is a gap. Classify every finding by **gap type**: |
| 148 | +
|
| 149 | +- **`missing`**: the required work is absent from the code entirely. |
| 150 | +- **`partial`**: the work exists but does not yet fully satisfy the requirement / |
| 151 | + acceptance criterion / plan decision. |
| 152 | +- **`contradicts`**: the code does something that conflicts with stated intent or a |
| 153 | + constitution MUST principle. |
| 154 | +- **`unrequested`**: the code contains work not called for by the spec, plan, or tasks |
| 155 | + (surfaced for awareness — converge does **not** delete code, it only appends a task to |
| 156 | + review/justify or remove it). |
| 157 | +
|
| 158 | +Each `Finding` records: a stable id, the `source-ref` it traces to, the `gap-type`, a |
| 159 | +severity, and a short human-readable description with the evidence (the file/area observed). |
| 160 | +
|
| 161 | +**Edge cases:** |
| 162 | +
|
| 163 | +- **Little or no code yet**: treat the entire specified scope as `missing` remaining work |
| 164 | + rather than failing. |
| 165 | +- **Nothing remains**: produce zero findings and follow the converged branch in Step 7. |
| 166 | +
|
| 167 | +### 5. Assign Severity |
| 168 | +
|
| 169 | +- **CRITICAL**: violates a constitution MUST principle, or a `missing`/`contradicts` gap |
| 170 | + that blocks baseline functionality of a P1 user story. |
| 171 | +- **HIGH**: a `missing` or `partial` gap on a core functional requirement or acceptance |
| 172 | + criterion. |
| 173 | +- **MEDIUM**: a `partial` gap on a secondary requirement, or an `unrequested` addition with |
| 174 | + unclear justification. |
| 175 | +- **LOW**: minor partial gaps, polish, or low-risk `unrequested` additions. |
| 176 | +
|
| 177 | +### 6. Present the In-Session Findings Summary |
| 178 | +
|
| 179 | +Before appending anything, output a compact, severity-graded summary (no file writes yet): |
| 180 | +
|
| 181 | +## Convergence Findings |
| 182 | +
|
| 183 | +| ID | Gap Type | Severity | Source | Evidence | Remaining Work | |
| 184 | +|----|----------|----------|--------|----------|----------------| |
| 185 | +| F1 | missing | HIGH | FR-008 | converge template has no guardrail text | Add append-only enforcement | |
| 186 | +
|
| 187 | +**Summary metrics:** |
| 188 | +
|
| 189 | +- Requirements / acceptance criteria checked |
| 190 | +- Plan decisions checked |
| 191 | +- Constitution principles checked (or "skipped — template") |
| 192 | +- Findings by gap type (missing / partial / contradicts / unrequested) |
| 193 | +- Findings by severity |
| 194 | +
|
| 195 | +### 7. Append Convergence Tasks (or report converged) |
| 196 | +
|
| 197 | +**If there are one or more actionable findings** (`tasks_appended` outcome): |
| 198 | +
|
| 199 | +Append to the **end** of `tasks.md`, per the append contract: |
| 200 | +
|
| 201 | +1. Scan all existing task IDs; let `M` be the maximum. Determine the next phase number `N` |
| 202 | + (highest existing phase + 1). |
| 203 | +2. Write a single new section header `## Phase N — Convergence`. |
| 204 | +3. Emit one checklist item per actionable finding, ordered CRITICAL/HIGH first, assigning |
| 205 | + IDs `M+1, M+2, …`: |
| 206 | +
|
| 207 | + ```markdown |
| 208 | + - [ ] T<NNN>: <imperative description> per <source-ref> (<gap-type>) |
| 209 | + ``` |
| 210 | + |
| 211 | + - `<source-ref>` traces the task to its origin: e.g. `FR-003`, `SC-002`, `US1/AC2`, |
| 212 | + `plan: storage decision`, `Constitution II`. |
| 213 | + - `<gap-type>` is one of `missing`, `partial`, `contradicts`, `unrequested`. |
| 214 | + - Constitution-violation tasks MUST be emitted first and described as `CRITICAL`. |
| 215 | +4. Never reuse or renumber existing IDs. If a prior Convergence phase exists, add a new, |
| 216 | + separately-numbered one below it — do not touch the old one. |
| 217 | + |
| 218 | +**If there are no actionable findings** (`converged` outcome): |
| 219 | + |
| 220 | +- Do **not** modify `tasks.md` at all — no empty phase header. |
| 221 | +- Report: **"✅ Converged — the implementation satisfies the spec, plan, and tasks."** |
| 222 | +- Include the summary counts of what was checked. |
| 223 | + |
| 224 | +### 8. Provide Next Actions (Handoff) |
| 225 | + |
| 226 | +- On `tasks_appended`: state how many tasks were appended under which phase, and recommend |
| 227 | + running `/speckit.implement` to complete them; note that a follow-up converge |
| 228 | + run will find fewer or no remaining items. |
| 229 | +- On `converged`: recommend proceeding to review / opening a PR. No further implement pass |
| 230 | + is needed for this feature's specified scope. |
| 231 | + |
| 232 | +### 9. Check for extension hooks |
| 233 | + |
| 234 | +After producing the result, check if `.specify/extensions.yml` exists in the project root. |
| 235 | + |
| 236 | +- If it exists, read it and look for entries under the `hooks.after_converge` key |
| 237 | +- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally |
| 238 | +- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default. |
| 239 | +- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions: |
| 240 | + |
| 241 | + - If the hook has no `condition` field, or it is null/empty, treat the hook as executable |
| 242 | + - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation |
| 243 | + |
| 244 | +- Pass the convergence outcome (`converged` or `tasks_appended`) to the hook context so an |
| 245 | + extension can branch on it. |
| 246 | +- For each executable hook, output the following based on its `optional` flag: |
| 247 | + |
| 248 | + - **Optional hook** (`optional: true`): |
| 249 | + |
| 250 | + ```text |
| 251 | + ## Extension Hooks |
| 252 | +
|
| 253 | + **Optional Hook**: {extension} |
| 254 | + Command: `/{command}` |
| 255 | + Description: {description} |
| 256 | +
|
| 257 | + Prompt: {prompt} |
| 258 | + To execute: `/{command}` |
| 259 | + ``` |
| 260 | +
|
| 261 | + - **Mandatory hook** (`optional: false`): |
| 262 | +
|
| 263 | + ```text |
| 264 | + ## Extension Hooks |
| 265 | +
|
| 266 | + **Automatic Hook**: {extension} |
| 267 | + Executing: `/{command}` |
| 268 | + EXECUTE_COMMAND: {command} |
| 269 | + ``` |
| 270 | +
|
| 271 | +- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently |
0 commit comments