@gobing-ai/spur 0.3.40 → 0.3.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/.claude-plugin/marketplace.json +15 -0
  2. package/README.md +15 -1
  3. package/config/templates/AGENTS.md +5 -3
  4. package/config/workflows/task-pipeline.yaml +103 -12
  5. package/package.json +15 -12
  6. package/plugins/README.md +655 -0
  7. package/plugins/sp/README.md +621 -0
  8. package/plugins/sp/agents/expert-spur.md +109 -0
  9. package/plugins/sp/agents/super-coder.md +126 -0
  10. package/plugins/sp/agents/super-planner.md +283 -0
  11. package/plugins/sp/agents/super-reviewer.md +154 -0
  12. package/plugins/sp/commands/dev-arch.md +30 -0
  13. package/plugins/sp/commands/dev-brainstorm.md +40 -0
  14. package/plugins/sp/commands/dev-changelog.md +28 -0
  15. package/plugins/sp/commands/dev-daily.md +29 -0
  16. package/plugins/sp/commands/dev-debug.md +29 -0
  17. package/plugins/sp/commands/dev-dogfood.md +33 -0
  18. package/plugins/sp/commands/dev-featurechange.md +130 -0
  19. package/plugins/sp/commands/dev-find-conflict.md +51 -0
  20. package/plugins/sp/commands/dev-find-issue.md +76 -0
  21. package/plugins/sp/commands/dev-find-next.md +60 -0
  22. package/plugins/sp/commands/dev-fixall.md +33 -0
  23. package/plugins/sp/commands/dev-gitmsg.md +28 -0
  24. package/plugins/sp/commands/dev-gtd.md +97 -0
  25. package/plugins/sp/commands/dev-handover.md +26 -0
  26. package/plugins/sp/commands/dev-idea.md +50 -0
  27. package/plugins/sp/commands/dev-next.md +31 -0
  28. package/plugins/sp/commands/dev-parallel.md +30 -0
  29. package/plugins/sp/commands/dev-plan.md +46 -0
  30. package/plugins/sp/commands/dev-refine.md +48 -0
  31. package/plugins/sp/commands/dev-refineall.md +65 -0
  32. package/plugins/sp/commands/dev-refresh.md +32 -0
  33. package/plugins/sp/commands/dev-reverse.md +32 -0
  34. package/plugins/sp/commands/dev-review.md +31 -0
  35. package/plugins/sp/commands/dev-run.md +63 -0
  36. package/plugins/sp/commands/dev-runall.md +80 -0
  37. package/plugins/sp/commands/dev-simplify.md +39 -0
  38. package/plugins/sp/commands/dev-unit.md +29 -0
  39. package/plugins/sp/commands/dev-verify.md +48 -0
  40. package/plugins/sp/commands/dev-verifyall.md +72 -0
  41. package/plugins/sp/commands/dev-wrap.md +30 -0
  42. package/plugins/sp/commands/dev-wrapall.md +33 -0
  43. package/plugins/sp/commands/rule-add.md +18 -0
  44. package/plugins/sp/commands/rule-refine.md +18 -0
  45. package/plugins/sp/commands/rule-scan.md +18 -0
  46. package/plugins/sp/commands/spur-init.md +22 -0
  47. package/plugins/sp/commands/workflow-add.md +18 -0
  48. package/plugins/sp/commands/workflow-refine.md +18 -0
  49. package/plugins/sp/hooks/agent-hint.ts +60 -0
  50. package/plugins/sp/hooks/careful-guard.ts +147 -0
  51. package/plugins/sp/hooks/context-post-tool.ts +325 -0
  52. package/plugins/sp/hooks/context-session-start.ts +182 -0
  53. package/plugins/sp/hooks/context-session-stop.ts +95 -0
  54. package/plugins/sp/hooks/hooks.json +51 -0
  55. package/plugins/sp/hooks/pi/guard-extension.ts +341 -0
  56. package/plugins/sp/hooks/task-write-guard.ts +84 -0
  57. package/plugins/sp/plugin.json +8 -0
  58. package/plugins/sp/scripts/batch-preflight.ts +204 -0
  59. package/plugins/sp/scripts/daily-summary/daily-summary.ts +606 -0
  60. package/plugins/sp/scripts/daily-summary/logger.ts +28 -0
  61. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +363 -0
  62. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +168 -0
  63. package/plugins/sp/scripts/feature-sync-bounded.ts +451 -0
  64. package/plugins/sp/scripts/stage-registry-adapter.ts +1341 -0
  65. package/plugins/sp/scripts/task-size-precheck.ts +202 -0
  66. package/plugins/sp/scripts/validate-commands.ts +651 -0
  67. package/plugins/sp/scripts/validate-flag-contracts.ts +875 -0
  68. package/plugins/sp/skills/brainstorm/SKILL.md +361 -0
  69. package/plugins/sp/skills/brainstorm/agents/openai.yaml +14 -0
  70. package/plugins/sp/skills/brainstorm/examples/ideation-example.md +209 -0
  71. package/plugins/sp/skills/brainstorm/metadata.openclaw +7 -0
  72. package/plugins/sp/skills/brainstorm/references/grilling-interview.md +68 -0
  73. package/plugins/sp/skills/brainstorm/references/workflows.md +255 -0
  74. package/plugins/sp/skills/branch-workflow/SKILL.md +109 -0
  75. package/plugins/sp/skills/branch-workflow/references/branch-lifecycle.md +69 -0
  76. package/plugins/sp/skills/branch-workflow/references/worktree-patterns.md +100 -0
  77. package/plugins/sp/skills/code-implementation/SKILL.md +176 -0
  78. package/plugins/sp/skills/code-implementation/references/debugging.md +64 -0
  79. package/plugins/sp/skills/code-implementation/references/implementation-patterns.md +113 -0
  80. package/plugins/sp/skills/code-improvement/SKILL.md +231 -0
  81. package/plugins/sp/skills/code-improvement/references/deepening-signals.md +205 -0
  82. package/plugins/sp/skills/code-review/SKILL.md +112 -0
  83. package/plugins/sp/skills/code-review/references/receiving-code-review.md +70 -0
  84. package/plugins/sp/skills/code-review/references/review-lenses.md +117 -0
  85. package/plugins/sp/skills/code-review/references/self-review-checklist.md +53 -0
  86. package/plugins/sp/skills/code-review/references/verification-before-completion.md +68 -0
  87. package/plugins/sp/skills/code-simplification/SKILL.md +225 -0
  88. package/plugins/sp/skills/code-testing/SKILL.md +108 -0
  89. package/plugins/sp/skills/code-testing/references/stacks/bun-ts.md +165 -0
  90. package/plugins/sp/skills/code-testing/references/stacks/go.md +88 -0
  91. package/plugins/sp/skills/code-testing/references/stacks/python.md +117 -0
  92. package/plugins/sp/skills/code-testing/references/test-loop-breaker.md +37 -0
  93. package/plugins/sp/skills/code-testing/references/test-output-discipline.md +52 -0
  94. package/plugins/sp/skills/code-testing/references/unit-testing.md +212 -0
  95. package/plugins/sp/skills/code-verification/SKILL.md +535 -0
  96. package/plugins/sp/skills/code-verification/references/code-improvement.md +39 -0
  97. package/plugins/sp/skills/code-verification/references/secu-review.md +94 -0
  98. package/plugins/sp/skills/code-verification/references/verdict-schema.md +141 -0
  99. package/plugins/sp/skills/conflict-finding/SKILL.md +254 -0
  100. package/plugins/sp/skills/conflict-finding/references/authority-resolution.md +258 -0
  101. package/plugins/sp/skills/conflict-finding/references/comparison-protocol.md +277 -0
  102. package/plugins/sp/skills/conflict-finding/references/finding-contract.md +346 -0
  103. package/plugins/sp/skills/conflict-finding/references/remediation-routing.md +276 -0
  104. package/plugins/sp/skills/daily-summary/SKILL.md +171 -0
  105. package/plugins/sp/skills/daily-summary/agents/openai.yaml +13 -0
  106. package/plugins/sp/skills/doc-evolve/SKILL.md +175 -0
  107. package/plugins/sp/skills/doc-evolve/references/operations.md +93 -0
  108. package/plugins/sp/skills/dogfood-testing/SKILL.md +608 -0
  109. package/plugins/sp/skills/dogfood-testing/references/monitor-ledger.md +211 -0
  110. package/plugins/sp/skills/dogfood-testing/references/report-template.md +351 -0
  111. package/plugins/sp/skills/doubt-driven-development/SKILL.md +136 -0
  112. package/plugins/sp/skills/functional-review/SKILL.md +364 -0
  113. package/plugins/sp/skills/functional-review/references/verdict-schema.md +133 -0
  114. package/plugins/sp/skills/indexed-context/SKILL.md +164 -0
  115. package/plugins/sp/skills/issue-finding/SKILL.md +424 -0
  116. package/plugins/sp/skills/issue-finding/agents/openai.yaml +15 -0
  117. package/plugins/sp/skills/issue-finding/examples/expected-findings.json +27 -0
  118. package/plugins/sp/skills/issue-finding/examples/session-test-loop.jsonl +23 -0
  119. package/plugins/sp/skills/issue-finding/references/session-formats.md +121 -0
  120. package/plugins/sp/skills/next-feature/SKILL.md +125 -0
  121. package/plugins/sp/skills/next-feature/references/handoff-routing.md +92 -0
  122. package/plugins/sp/skills/next-feature/references/proposal-contract.md +49 -0
  123. package/plugins/sp/skills/next-feature/references/ranking-rubric.md +52 -0
  124. package/plugins/sp/skills/next-feature/references/signal-derivation.md +67 -0
  125. package/plugins/sp/skills/next-router/SKILL.md +181 -0
  126. package/plugins/sp/skills/next-router/references/messages.md +90 -0
  127. package/plugins/sp/skills/next-router/references/routing-table.md +216 -0
  128. package/plugins/sp/skills/parallel-execution/SKILL.md +148 -0
  129. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +100 -0
  130. package/plugins/sp/skills/parallel-execution/references/fan-out-patterns.md +101 -0
  131. package/plugins/sp/skills/parallel-execution/references/result-synthesis.md +94 -0
  132. package/plugins/sp/skills/reverse-engineering/SKILL.md +375 -0
  133. package/plugins/sp/skills/reverse-engineering/agents/openai.yaml +18 -0
  134. package/plugins/sp/skills/source-driven-development/SKILL.md +124 -0
  135. package/plugins/sp/skills/spec-decomposition/SKILL.md +117 -0
  136. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +539 -0
  137. package/plugins/sp/skills/spur-cli/SKILL.md +133 -0
  138. package/plugins/sp/skills/spur-cli/references/agent.md +179 -0
  139. package/plugins/sp/skills/spur-cli/references/features/acceptance-criteria.md +82 -0
  140. package/plugins/sp/skills/spur-cli/references/features/hierarchy-mece.md +177 -0
  141. package/plugins/sp/skills/spur-cli/references/features/roadmap-priority.md +84 -0
  142. package/plugins/sp/skills/spur-cli/references/features/verbs.md +122 -0
  143. package/plugins/sp/skills/spur-cli/references/features.md +234 -0
  144. package/plugins/sp/skills/spur-cli/references/init.md +119 -0
  145. package/plugins/sp/skills/spur-cli/references/message.md +98 -0
  146. package/plugins/sp/skills/spur-cli/references/rules/authoring-rules.md +212 -0
  147. package/plugins/sp/skills/spur-cli/references/rules/fine-tuning.md +148 -0
  148. package/plugins/sp/skills/spur-cli/references/rules/operations.md +228 -0
  149. package/plugins/sp/skills/spur-cli/references/rules/validation-and-extension.md +129 -0
  150. package/plugins/sp/skills/spur-cli/references/rules.md +209 -0
  151. package/plugins/sp/skills/spur-cli/references/serve.md +58 -0
  152. package/plugins/sp/skills/spur-cli/references/tasks/l3-guard-cheatsheet.md +98 -0
  153. package/plugins/sp/skills/spur-cli/references/tasks/section-editing.md +95 -0
  154. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +361 -0
  155. package/plugins/sp/skills/spur-cli/references/tasks.md +278 -0
  156. package/plugins/sp/skills/spur-cli/references/team.md +133 -0
  157. package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +226 -0
  158. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +211 -0
  159. package/plugins/sp/skills/spur-cli/references/workflows/validation-and-extension.md +129 -0
  160. package/plugins/sp/skills/spur-cli/references/workflows.md +355 -0
  161. package/plugins/sp/skills/spur-dev/SKILL.md +224 -0
  162. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +196 -0
  163. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +664 -0
  164. package/plugins/sp/skills/spur-dev/references/decision-brief.md +80 -0
  165. package/plugins/sp/skills/spur-dev/references/dev-operations.md +546 -0
  166. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +164 -0
  167. package/plugins/sp/skills/spur-dev/references/execution-batch.md +727 -0
  168. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +350 -0
  169. package/plugins/sp/skills/spur-dev/references/feature-link-helper.md +191 -0
  170. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +417 -0
  171. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +171 -0
  172. package/plugins/sp/skills/spur-dev/references/glossary.md +95 -0
  173. package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +80 -0
  174. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +88 -0
  175. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +302 -0
  176. package/plugins/sp/skills/spur-dev/references/product-planning.md +206 -0
  177. package/plugins/sp/skills/spur-dev/references/section-batching.md +24 -0
  178. package/plugins/sp/skills/sys-architecture/SKILL.md +155 -0
  179. package/plugins/sp/skills/sys-architecture/references/decision-method.md +137 -0
  180. package/plugins/sp/skills/sys-architecture/references/upkeep-survey.md +75 -0
  181. package/plugins/sp/skills/sys-debugging/SKILL.md +228 -0
  182. package/plugins/sp/skills/sys-debugging/references/debugging-protocol.md +62 -0
  183. package/plugins/sp/skills/test-driven-development/SKILL.md +248 -0
  184. package/plugins/sp/skills/wayfinder/SKILL.md +292 -0
  185. package/spur.js +6093 -5180
@@ -0,0 +1,539 @@
1
+ ---
2
+ name: decomposition
3
+ description: Task decomposition conventions — the task-batch.schema.json contract, template-variant selection, scenario-to-task mapping.
4
+ see_also:
5
+ - spec-decomposition
6
+ - spur-dev
7
+ # Granularity knobs — tune the decomposition standard here (judgment guidance, not
8
+ # runtime-enforced). The skill cites these; editing them adjusts the agent's sizing.
9
+ granularity:
10
+ min_hours: 2 # never create a subtask smaller than this
11
+ target_min_hours: 2 # healthy task lower bound
12
+ target_max_hours: 8 # reassess (likely two deliverables) above this
13
+ force_decompose_above_hours: 16 # mandatory split regardless of other signals
14
+ ---
15
+
16
+ # Decomposition
17
+
18
+ Turning a feature's acceptance criteria into a validated task batch. The LLM produces JSON;
19
+ the CLI validates it against `task-batch.schema.json`; nothing is written until the gate
20
+ passes.
21
+
22
+ ## Granularity — two dimensions
23
+
24
+ The frontmatter `granularity` knobs (`min_hours`, `target_min_hours`, `target_max_hours`,
25
+ `force_decompose_above_hours`) bound a task's *size in hours*. They are the **second** dimension
26
+ of sizing, not the only one. The **first** dimension is **cohesion**: work that edits the same
27
+ files, or that requires the same review context to judge, is one task — *even when the hour
28
+ estimate would justify splitting*.
29
+
30
+ ### Cohesion decides legitimacy; hours bound size
31
+
32
+ Apply the two in order:
33
+
34
+ 1. **Cohesion first — is the split legitimate at all?** If the candidate children would edit the
35
+ same file surface, or need to be read together to be reviewed, they are one task. Splitting
36
+ cohesive work multiplies the fixed per-task ceremony (precheck, implement, test, review,
37
+ approve, verify, record, done — plus a verdict artifact with full requirement and AC tables,
38
+ plus gate remediation at each transition) without reducing risk: the reviewer still reads one
39
+ diff, just across more files. **Ceremony cost is per-task**, which is why this rule exists and
40
+ why its rationale is written here rather than re-litigated at each decomposition.
41
+ 2. **Hours second — is the resulting cohesive task too large?** Only after cohesion says a split is
42
+ legitimate do the hour knobs bound how large that single cohesive task may get. Above
43
+ `force_decompose_above_hours`, the size guard overrides cohesion: split even if the children
44
+ share a review context, because at that size the review itself becomes the risk.
45
+
46
+ Without the second clause, cohesion reads as "never split" — the opposite failure. The knobs are
47
+ the escape hatch; cohesion is the default.
48
+
49
+ ### Worked example: H8's own first decomposition
50
+
51
+ Feature H8 ("sp command surface coherence") decomposed into five tasks, each 3–8h — fully inside
52
+ `target_min_hours`/`target_max_hours`. The operator rejected it as over-split, correctly: three of
53
+ the five (0399, 0401, 0402) all edited `dev-operations.md` and the `plugins/sp/commands/*.md`
54
+ surface, so the split created contention over one file surface and tripled the pipeline ceremony
55
+ for a diff a reviewer reads once. The merge (5 → 4, with 0402 absorbed into 0401) removed two full
56
+ sets of precheck/implement/test/review/approve/verify/record/done cycles over content the reviewer
57
+ was always going to read as one diff.
58
+
59
+ The hour knobs alone permitted the five-task split; cohesion is what flagged it. A numeric proxy
60
+ (`max_files_shared` or similar) would have been wrong often enough to be ignored — two tasks
61
+ touching one shared config file may be genuinely independent, and two tasks touching disjoint
62
+ files may share a review context entirely. Cohesion is a judgment about coupling, and it is stated
63
+ as prose for that reason.
64
+
65
+ ### Second occurrence: E1's first charting (2026-08-06)
66
+
67
+ The same failure recurred through `sp:wayfinder`, which authors tickets without going through this
68
+ skill. A wayfinder map for feature E1 was charted with 8 investigation tickets where 4 were right —
69
+ four of the six merged pairs would have read the *same transcript files* to answer. Worse, the
70
+ discovery ticket covered only the four secondary agents while claude and codex, the operator's
71
+ primaries, were split into a separate ticket blocked downstream — so the ETL contract would have
72
+ been decided on evidence from the peripheral sources.
73
+
74
+ Two lessons, both now fixed rather than restated:
75
+
76
+ 1. **Cohesion applies to investigation tickets, not just implementation tasks.** Two questions
77
+ answered by one body of evidence are one ticket, exactly as two changes to one file surface are
78
+ one task.
79
+ 2. **The rule was unreachable from the surface that failed.** It lived only here, cited only by this
80
+ skill and the spur-dev planning path — while wayfinder, issue-finding, brainstorm, and
81
+ dogfood-testing all author tasks through other routes. The shared statement now lives in
82
+ [`../../spur-dev/references/cross-cutting.md`](../../spur-dev/references/cross-cutting.md)
83
+ § Task sizing, which every command and skill already cites; this file keeps the full treatment
84
+ and the knobs. **Do not delete the cross-cutting section as duplication** — that reachability is
85
+ the fix.
86
+
87
+ ## The batch schema
88
+
89
+ `apps/cli/schemas/task-batch.schema.json` (runtime SSOT: the Zod `taskBatchSchema` in
90
+ `@gobing-ai/spur-domain`) defines the JSON shape. **The top level is a JSON ARRAY of task items —
91
+ NOT an object with a `tasks` key.** Each item is `.strict()`: any field not in the table below is
92
+ rejected, and a single rejected item fails the whole batch (all-or-nothing).
93
+
94
+ | Field | Required | Notes |
95
+ |-------|----------|-------|
96
+ | `name` | yes | Task title; used in slug generation. |
97
+ | `template` | no | Template variant (`standard`, `feature-impl`, `issue`, `review`, `meta`, `brainstorm`); defaults to `standard` (`feature-impl` when `--feature` is given). |
98
+ | `feature_id` | no | Links the task to a feature — the single traceability edge. |
99
+ | `parent_wbs` | no | For sub-tasks; references the parent's WBS (quoted 4-digit string, e.g. `"0042"`). |
100
+ | `priority` | no | `P0`–`P3`; align with feature priority. |
101
+ | `tags` | no | String tags. |
102
+ | `background` | no | Pre-filled `## Background` body (the scenario→task mapping note goes here). |
103
+ | `requirements` | no | Pre-filled `## Requirements` body. |
104
+ | `design` | **default yes** | Pre-filled `### Design` (WHAT/WHY). **Author by default** on plan/decompose. Omit only under operator `--skip-design` (refine fills later). |
105
+ | `plan` | recommended | Pre-filled `### Plan` checklist when known at create. |
106
+ | `acceptance_criteria` | recommended | Pre-filled `### Acceptance Criteria` when scenarios are known. |
107
+
108
+ > There is **no** generic `sections` field and **no** `dependencies` field in the batch item — the
109
+ > Zod schema is strict and rejects both. Use `background`/`requirements`/`design`/`plan`/
110
+ > `acceptance_criteria` for content, and record ordering in `background` prose (the WBS-level
111
+ > `dependencies` frontmatter is set later, not at batch create).
112
+
113
+ ### Section bodies are markdown — format them as markdown
114
+
115
+ Every body field is written into the task file verbatim and rendered by the Board's markdown
116
+ preview. **A body is not a plain-text blob**: consecutive lines with no list marker collapse into a
117
+ single run-on paragraph on render, even though they look like separate items in the JSON source.
118
+
119
+ **`requirements` — always author R-items as a GitHub task-list checkbox, one per line:**
120
+
121
+ ```json
122
+ "requirements": "- [ ] R1. <text>\n- [ ] R2. <text>\n- [ ] R3. <text>"
123
+ ```
124
+
125
+ `R1. <text>\nR2. <text>` (no marker) is the trap. `spur task check` **accepts** it — the L3
126
+ R-numbering rule matches the bare `Rn.` token — so nothing fails, and the defect only surfaces later
127
+ as an unreadable paragraph in Board preview. Do not rely on `check` to catch this. Keep the `Rn.`
128
+ (period) token inside the marker so R-numbering still resolves; see the canonical rule in
129
+ `sp:spur-dev` → `references/planning-workflow.md`.
130
+
131
+ Applies to the other body fields too: `plan` as an ordered list (`1. …\n2. …`), `acceptance_criteria`
132
+ as a fenced ```` ```gherkin ```` block, and any enumeration inside `background` or `design` as a
133
+ `- ` list.
134
+
135
+ ### Design at create (default) vs `--skip-design`
136
+
137
+ **Default (no `--skip-design` on `/sp:dev-plan` / `/sp:dev-idea`):** every batch item for
138
+ `standard` / `feature-impl` (and any variant that carries Design at `todo`) **must** include a
139
+ non-empty `design` field — chosen approach + one-line reason, rejected alternatives, invariants,
140
+ key signatures (not code dumps). This is the capable-first cost path: lock the box once at create.
141
+
142
+ **`--skip-design`:** leave `design` empty (scaffold only). Refine is the **fallback** that fills
143
+ blank Design before implement (`/sp:dev-refine` / `dev-refineall`).
144
+
145
+ ## Template-variant selection
146
+
147
+ The `template` field is the **single variant axis** (TASK_VARIANTS): it selects the section
148
+ layout (the `section-matrix.yaml` variant), the scaffold body file
149
+ (`.spur/templates/task/<variant>.md`), and is written to the task's `template:` frontmatter.
150
+ Which sections actually appear is **stage-driven** by the matrix (e.g. `Solution` only from `wip`),
151
+ not a fixed list — pick the variant by *purpose*, not by a section checklist.
152
+
153
+ | Variant | When to use |
154
+ |---------|-------------|
155
+ | `standard` | General-purpose implementation work (the workhorse) |
156
+ | `feature-impl` | Implementation tied to a feature; AC pre-seeded, Background from the feature `## Goal` |
157
+ | `issue` | Bug/defect — repro in Background, verified Root Cause, then fix |
158
+ | `review` | Code-review fix-up — logs the findings as **input** (`#### Review Findings` under Background) and fixes them; `### Review` is the **post-fix** reflection + back-issues |
159
+ | `meta` | Process / docs / chore — lightweight Background + Plan |
160
+ | `brainstorm` | Minimal idea capture |
161
+
162
+ Selection on the CLI: `spur task create "<title>" --template <variant>`; in a batch item: the
163
+ `template` field. A `--feature` link defaults the variant to `feature-impl`; otherwise `default`.
164
+
165
+ ## Scenario-to-task mapping
166
+
167
+ **Run "Default to NOT decomposing" (below) first.** If the parent scores 0–2, there is no mapping to
168
+ do — write the steps in the parent's `## Plan` and stop. This section only applies once decomposition
169
+ has already been justified.
170
+
171
+ Scenario count is **not** task count. A feature with 7 scenarios does not imply 7 tasks; scenarios
172
+ describe observable behavior, tasks describe units of work, and one unit of work routinely delivers
173
+ several behaviors. Walk the scenarios and sort them into groups, then emit one task per group:
174
+
175
+ 1. **Merge** scenarios that one task delivers — same file surface, same subsystem, or unreadable
176
+ apart in review. This is the **most common outcome** and the one agents skip. Two scenarios
177
+ describing two behaviors of one change are one task.
178
+ 2. **One task** when a scenario is a unit of work on its own.
179
+ 3. **Split into multiple tasks** only when a single scenario spans subsystems (e.g. auth service +
180
+ UI) and each part clears the rubric independently. Each task names the subsystem it owns.
181
+ 4. **Record the mapping** in each task's `## Background`, listing every scenario it covers:
182
+ `Implements: R2 — …; R3 — Registered user can log in with email and password`.
183
+
184
+ **Merging never costs AC coverage.** `checkAcCoverage` matches by normalized scenario title across
185
+ each linked task's AC block, so one task carrying R2 and R3 in its `### Acceptance Criteria` covers
186
+ both — there is no orphan warning and no reason to split 1:1 to satisfy the gate. Splitting to keep
187
+ the coverage check quiet is the single most common cause of an over-decomposed batch.
188
+
189
+ ### Two R-namespaces — do not mix them in one scenario list
190
+
191
+ A task's `### Requirements` are numbered **task-locally** (R1, R2, … within that task). A feature's AC
192
+ scenarios are numbered in the **feature's** namespace. Both appear in a task's
193
+ `### Acceptance Criteria`, and conflating them is how AC silently drifts from Requirements.
194
+
195
+ The rule:
196
+
197
+ - **Scenarios covering the task's own requirements carry the task-local R-prefix** —
198
+ `Scenario: R3 — <observable outcome>`. Tasks declaring `ac_numbering: task-local` in frontmatter
199
+ get these cross-checked by `spur task check` (`L3.ac-requirement-coverage`): a requirement with no
200
+ scenario, or a scenario citing a requirement that does not exist, is reported.
201
+ - **Scenarios carried verbatim from the feature (for DD-09 traceability) carry NO R-prefix** — copy
202
+ the title text only. `normalizeTitle` (`packages/domain/src/bdd/coverage.ts:58`) strips `R\d+`
203
+ before matching, so the prefix is invisible to feature coverage anyway; dropping it keeps the
204
+ feature's number from being read as a task requirement id. Verified empirically: removing the
205
+ prefix from a carried scenario left the feature's orphan count unchanged.
206
+
207
+ **Legacy tasks are exempt.** Most existing tasks predate this and copied feature AC wholesale,
208
+ carrying the feature's numbers. The coverage check is opt-in precisely so they emit nothing —
209
+ absent `ac_numbering`, only DD-09 applies. Opting an old task in is a pure prefix renumber; it cannot
210
+ break traceability. New tasks get `ac_numbering: task-local` from the templates automatically;
211
+ `spur task update <wbs> --ac-numbering task-local` opts in an existing one.
212
+
213
+ Edge-case scenarios may map to tasks, merge into a sibling, or be deferred. Record deferrals
214
+ explicitly: `Deferred: R7 — Edge case not in this iteration`.
215
+
216
+ ## Default to NOT decomposing
217
+
218
+ **The default outcome of decomposition is "keep it as one task."** Splitting is the exception you
219
+ must justify, not the baseline. This is the single most important rule on this page, and the one
220
+ most often skipped when an agent moves fast: the agent reaches the decomposition step, sees a list
221
+ of requirements or findings, and emits one child per item by reflex — producing many small tasks
222
+ that the rubric would have rejected as Plan steps.
223
+
224
+ **Every subtask has a real cost** — a file to track, a sequential bottleneck, a separate review,
225
+ a context switch, a rollback boundary. Five subtasks at 1h each cost more total overhead than one
226
+ task at 5h, with no parallelism or review benefit gained. So before producing any batch JSON:
227
+
228
+ 1. **Score the parent first.** Run the rubric (below) on the *whole* unit of work. If it lands at
229
+ 0–2, the answer is **keep as one task** — stop, write the implementation steps in the parent's
230
+ `## Plan`, and do not call `batch-create` at all.
231
+ 2. **Only if the parent scores 5+ (or a force-decompose override fires)** does decomposition even
232
+ enter the conversation. Then score each *candidate* child — any candidate that scores 0–2 on
233
+ its own is a Plan step, not a task; merge it into a sibling.
234
+ 3. **"I can describe N pieces" is not a decomposition trigger.** A finding list, a requirement
235
+ list, or a bullet list is a *Plan checklist*, not a task list. Pieces become tasks only when
236
+ they clear the rubric independently (independent streams / distinct review gate / different
237
+ risk / different expert).
238
+
239
+ The failure mode this section exists to prevent: a parent carrying 6 findings becomes 6 child
240
+ tasks, several of which were <2h doc edits that belonged in the parent's Plan. When in doubt,
241
+ **don't decompose** — the operator can always ask for a split after seeing the Plan.
242
+
243
+ ## When to decompose at all
244
+
245
+ **Every subtask has a cost** — a file to track, a sequential bottleneck, a separate review, a
246
+ context switch. The question is never "can I split this?" but "do I *need* to?" Decompose only
247
+ when a benefit outweighs that cost:
248
+
249
+ - The work has genuinely **independent parallel streams** (different agents, simultaneously).
250
+ - A part needs a **distinct review/approval gate** that cannot be combined.
251
+ - A part has a **materially different risk profile** (one safety-critical, one cosmetic).
252
+ - A part needs a **different domain expert** (DB vs UI).
253
+
254
+ Do **not** decompose when the work fits one agent's head, touches related files in one module,
255
+ has a single review gate, or is one deliverable with one rollback boundary. In that case write the
256
+ steps in the parent task's **Plan**, not as separate task files.
257
+
258
+ ### Quick rubric (required artifact — record it before writing any batch JSON)
259
+
260
+ Estimate five signals — **E** effort (hours), **D** independently-reviewable deliverables,
261
+ **L** layers/modules, **C** coordination (0 none / 1 moderate / 2 high), **R** risk (0 low / 1 med
262
+ / 2 high). `score = E + D + L + C + R`, with overrides applied in order:
263
+
264
+ 1. **Force decompose** if `R = high` (2).
265
+ 2. **Force decompose** if `E > force_decompose_above_hours` (frontmatter knob, default 16h).
266
+ 3. **Force single-task** only if none of the above AND it is one file/module, one deliverable,
267
+ one layer, zero coordination, one rollback boundary.
268
+
269
+ | score | decision |
270
+ |-------|----------|
271
+ | 0–2 | keep as one task (write a one-line skip rationale in Plan) |
272
+ | 3–4 | decomposition optional — single-task plan allowed with rationale |
273
+ | 5+ | decompose into deliverable-based tasks |
274
+
275
+ **Record the assessment.** Before `batch-create`, the rubric assessment MUST be written down — for
276
+ the parent (and, if decomposing, each child candidate). This is the enforcement step that stops
277
+ reflexive over-decomposition: if you cannot show the score, you have not justified the split. Two
278
+ acceptable homes for the assessment:
279
+
280
+ - **In the parent's `## Plan`** (for the keep-as-one decision): a one-line skip rationale naming
281
+ the score, e.g. *"Rubric: E1 D1 L1 C0 R0 = 3 → kept whole; steps below."*
282
+ - **In each child's `background`** (when decomposing): a trailing line naming the score and the
283
+ trigger that cleared it, e.g. *"Rubric: E2 D1 L1 C1 R2 = 7 → decompose (force: R=high)."*
284
+
285
+ A batch produced without a recorded assessment is incomplete — re-score before submitting to
286
+ `batch-create`.
287
+
288
+ ## Parent (umbrella) tasks
289
+
290
+ When a task decomposes into sub-task **files** (each carrying `parent_wbs`), the original becomes a
291
+ **parent/umbrella task**: it owns the requirements and the cross-cutting design, but it implements
292
+ **nothing itself** — the work lives in its children.
293
+
294
+ A parent is **not a skeleton task.** The "skeleton task" anti-pattern below targets *sub-tasks* that
295
+ punt their content to the parent ("see parent"). A parent that holds the requirements and a roster
296
+ of children is the *correct* shape — the inverse direction is fine.
297
+
298
+ Two rules make a parent verifiable:
299
+
300
+ 1. **The parent's `## Plan` must carry the sub-task roster** — a table mapping each child to the
301
+ parent requirement(s) it covers, with its current status AND its blast radius. Write it
302
+ **immediately after `batch-create`** (the same step that lands the children); a parent without a
303
+ roster cannot be checked for completeness by a human. Roster row template:
304
+
305
+ | Sub-task | Covers | Surface | Title | Status |
306
+ |----------|--------|---------|-------|--------|
307
+ | `0110_<slug>.md` | R1, R2 | docs | <child title> | done / todo / wip |
308
+
309
+ The **Surface** column is the blast-radius signal for sequencing: `docs` (skill/command markdown,
310
+ no executable), `code` (app/package TS, has tests), or `infra` (DB schema/migration, workflow
311
+ YAML, CI/CD, `.github/`). When deciding execution order across children of the same priority,
312
+ **run `infra` first** (highest risk, load-bearing, hardest to revert), then `code`, then `docs`
313
+ — riskiest-first surfaces the hard problems while context is fresh and lets the cheap fixes
314
+ absorb any rework. A roster with only a Status column hides this and leads to priority-only
315
+ ordering that buries the infra change among doc edits.
316
+
317
+ The status column is generated by `spur task refresh-roster` (task 0123) — invoked
318
+ automatically by `spur task batch-create` for each distinct `parent_wbs` after the
319
+ atomic create lands (task 0178 F1). Re-run `spur task refresh-roster <parent-wbs>`
320
+ manually to re-emit the block after a child status change outside `batch-create`.
321
+
322
+ 2. **A parent is complete only when every sub-task is `done` (or `cancelled`).** Cross-cutting
323
+ requirements satisfied across multiple children (e.g. "validate + doc-sync") are met *inside*
324
+ each child, not as separate tasks. Do not mark a parent `done` while a child is open, and do not
325
+ leave a parent open once all children are closed.
326
+
327
+ > **Gate note.** `spur task check` validates *structure*; parent/child roll-up is
328
+ > enforced by the L4 roll-up gate (`packages/app/src/services/task-check.ts:426`
329
+ > `runL4Rollup`, task 0121) which warns on parent/child status drift and missing
330
+ > roster. The roster itself is auto-generated by `spur task batch-create` (task
331
+ > 0178 F1) — the operator never hand-writes it.
332
+
333
+ ## Decomposition heuristics
334
+
335
+ - **Deliverable, not phase.** A subtask must be describable in one sentence a non-technical
336
+ person understands ("Add the task-creation endpoint"), never an activity ("investigate X",
337
+ "design Y", "write tests for Z"). If a subtask name contains *investigate / research / design /
338
+ implement (standalone) / testing (standalone)* or a pipeline phase, you are decomposing by
339
+ phase — stop. Design lives in the parent's **Design** section; testing is part of each task.
340
+ - **Full lifecycle per task.** Each task owns the *complete* circle for its requirement(s):
341
+ define the issue, give the solution + acceptance criteria, draw the plan, record the review.
342
+ Never carve a single requirement into "design task / build task / test task".
343
+ - **Size floor / target (frontmatter knobs).** Never create a subtask smaller than `min_hours`
344
+ (default 2h) — merge it into the adjacent deliverable or make it a Plan step. Aim for
345
+ `target_min_hours`–`target_max_hours` (default 2–8h). If a subtask exceeds `target_max_hours`
346
+ after decomposition, reassess (it is probably two deliverables).
347
+ - **Self-contained.** Every task's Background + Requirements must stand alone (a reviewer should
348
+ not need to open the parent). If you cannot write a meaningful Background without referring to
349
+ the parent, it is a Plan step, not a task.
350
+ - **Ordering:** tasks with no dependencies come first. Note ordering in each task's `background`
351
+ prose at batch time; set the WBS-level `dependencies` frontmatter after creation if needed.
352
+ - **Parallelism:** mark independent tasks with the same priority — the pipeline can fan out.
353
+ - **Testing:** every `feature-impl` task produces its own tests. Do **not** create separate
354
+ "write tests" tasks — testing is part of implementation.
355
+ - **Review:** complex or cross-cutting tasks get a `review` companion task (template `review`).
356
+ Simple tasks skip it — the pipeline's review step suffices.
357
+ - **Record rejected split-alternatives (scope-creep guard).** When a requirement is split across
358
+ tasks (e.g. an R1/R2 split, or a finding that *could* have been its own task but was merged into
359
+ a sibling), record the alternative you rejected and why — in the parent's `## Plan` (for the
360
+ merge decision) or the child's `## Design` (for an R1/R2 split). This is what stops a 4h task
361
+ becoming a 2-day task: the moment you write "rejected: pidfile approach — another file artifact
362
+ to manage, stale on crash; the DB column is the natural home," the scope is bounded and the next
363
+ agent (or you, later) won't re-litigate it. A split without a recorded rejected-alternative is
364
+ incomplete — you have not shown the split was necessary, only that it was possible.
365
+
366
+ ## Vertical slices (the slicing-direction axis)
367
+
368
+ The rubric above decides **whether** to split; this section decides **which direction** to cut once
369
+ you do. Every task in a batch must be a thin **vertical slice** through all the layers a scenario
370
+ touches (schema / API / UI / tests, as applicable) — independently demoable or verifiable on its
371
+ own. A vertical slice proves the feature works end-to-end at a small scale; a horizontal layer-task
372
+ proves nothing until every sibling layer-task also lands.
373
+
374
+ **Horizontal layer-tasks are a named anti-pattern** — see the table below (`all-schema` /
375
+ `all-API` / `all-UI` task split). The tell: task names read like layer inventories ("Add the users
376
+ table", "Build the users API", "Build the users UI") instead of capability inventories ("User can
377
+ register with email").
378
+
379
+ **Wrong vs right, worked:**
380
+
381
+ - **Wrong (horizontal):** Task 1 — add `users`/`sessions` tables. Task 2 — add
382
+ `POST /login`/`POST /register` endpoints. Task 3 — build the login/register UI. Nothing is
383
+ demoable until all three land; task 2 blocks on task 1, task 3 blocks on task 2 — a strict
384
+ chain with no parallelism, and a reviewer can't verify task 1 in isolation (a schema with no
385
+ caller proves nothing).
386
+ - **Right (vertical):** Task 1 — user can register with email (schema column + endpoint + form,
387
+ thin but complete). Task 2 — user can log in with email (same three layers, reusing task 1's
388
+ schema). Each task is independently demoable (`curl` the endpoint, or click through the form)
389
+ and independently reviewable; task 2 only depends on task 1's schema, not its UI.
390
+
391
+ **Prefactoring comes first.** "Make the change easy, then make the easy change" — when a vertical
392
+ slice is blocked by an awkward existing shape (a function that needs splitting, a type that needs
393
+ widening, a module boundary that needs to move), that refactor is its own task, ordered **before**
394
+ the slices that depend on it, and it changes no behavior. Do not fold prefactoring into the first
395
+ feature slice — a task that both reshapes existing code and adds a new capability is fighting two
396
+ review lenses at once (§Anti-patterns: this is a variant of under-decomposition when the refactor
397
+ is large enough to warrant its own review).
398
+
399
+ ## Pre-batch-create HITL checkpoint (quiz gate)
400
+
401
+ Before calling `spur task batch-create`, present the proposed breakdown to the operator as a
402
+ numbered list and get it reviewed — a batch is atomic and hard to unwind piecemeal once children
403
+ exist, so this is the cheapest point to catch a granularity or ordering mistake.
404
+
405
+ **Present:**
406
+
407
+ ```
408
+ 1. <title> — blocked by: none — covers: R1 (user can register with email)
409
+ 2. <title> — blocked by: #1 — covers: R2 (user can log in with email)
410
+ 3. <title> — blocked by: none — covers: R3 (user can reset password)
411
+ ```
412
+
413
+ Present the quiz as a decision brief — recommended breakdown + the trade-off of each alternative
414
+ slicing, with an explicit recommendation — per the SSOT
415
+ [spur-dev/references/decision-brief.md](../../spur-dev/references/decision-brief.md).
416
+
417
+ **Quiz the operator on:**
418
+ - **Granularity** — does any task look like a horizontal layer-task, a phase-split, or a
419
+ <2h fragment that belongs in a Plan step instead?
420
+ - **Dependency correctness** — is the `blocked-by` chain minimal (no task waits on a sibling it
421
+ doesn't actually need), and does it match the vertical-slice ordering (schema-owning slice
422
+ before the slices that reuse it)?
423
+
424
+ Proceed to `batch-create` only after the operator confirms, or after they request adjustments and
425
+ you re-present the revised list. **Skip this checkpoint under `--auto`** (the profile that already
426
+ waives interactive HITL gates elsewhere in the pipeline) — record in the batch's parent Plan that
427
+ the quiz was auto-skipped, same as any other `--auto`-waived gate.
428
+
429
+ ## Anti-patterns (do not do these)
430
+
431
+ | Anti-pattern | Why it's wrong | Instead |
432
+ |--------------|----------------|---------|
433
+ | **Phase split** (investigate → design → implement → test as 4 tasks) | Fragments one deliverable; the "design" task finishes while the feature isn't built | One task; phases become Plan steps |
434
+ | **Skeleton tasks** (empty Background/Requirements, "see parent") | Task files must be self-contained for review | Merge back, or write it as a Plan step |
435
+ | **Over-decomposition** (5 tasks each <30 min for one PR) | 5× tracking overhead for no parallelism or review benefit | One task with a Plan checklist |
436
+ | **Under-decomposition** (one task spanning 3 subsystems + 20h) | Unreviewable, one giant PR, no fan-out | Split by subsystem/deliverable |
437
+ | **Horizontal layer-task** (all-schema task, all-API task, all-UI task) | Nothing is demoable until every sibling layer lands; blocks in a strict chain with no parallelism | Cut vertical slices — one capability through all its layers, thin but complete |
438
+
439
+ ### Worked example — the "list reflex" (the most common over-decomposition)
440
+
441
+ A review/findings task arrives carrying 6 findings. The reflex move is to emit one child task per
442
+ finding → 6 tasks. But several findings are typically <2h doc edits or one-line fixes that the
443
+ rubric scores at 0–2 on their own. Those are **Plan steps**, not tasks.
444
+
445
+ **Bad (reflex):** parent + 6 children, three of which were 30-min edits → 6 files, 6 reviews, 6
446
+ rollback boundaries, for work that fit one focused session.
447
+
448
+ **Better:** score each finding. Merge the <2h ones into the parent's `## Plan` as a checklist;
449
+ spawn children only for the findings that clear the rubric independently (distinct module + real
450
+ effort + own review boundary). A 6-finding parent often becomes parent + 2–3 children, not 6.
451
+
452
+ The tell that you're reflex-decomposing: your child names are *"F1 — …", "F2 — …", "F3 — …"* —
453
+ one per list item, sized by the list, not by the work. Re-score before submitting the batch.
454
+
455
+ ### Worked example — the phase split
456
+
457
+ *"Add an Antigravity adapter"* decomposed as: 1) investigate the CLI, 2) design the abstraction,
458
+ 3) implement the adapter, 4) integrate config switching, 5) add tests. Five tasks — but #1 is an
459
+ activity (not a deliverable), #2 belongs in the task's `## Design` section, #4 and #5 are part of
460
+ #3, and the whole thing is one deliverable one agent completes in a session. Correct: **one task**,
461
+ with research/design/implement/integrate/test as `## Plan` steps.
462
+
463
+ ## Stage → sections, and the Design vs Solution split
464
+
465
+ A task created with a spec (a `--feature` link, or a batch item carrying `background`/
466
+ `requirements`) lands at **`todo`** — "ready to execute" (§2.3). A bare capture lands at
467
+ **`backlog`** — "still preparing". The Section-Status-Matrix
468
+ (`.spur/tasks/section-matrix.yaml`) decides which sections a task carries at each stage; the
469
+ producer renders them with invisible HTML guidance comments. You do **not** hand-build the section
470
+ list — `spur task create` / `batch-create` does it from the matrix.
471
+
472
+ | Stage | Means | Sections present |
473
+ |-------|-------|------------------|
474
+ | `backlog` | still preparing | Background |
475
+ | `todo` | ready to execute — the **HITL review gate** | Background, Acceptance Criteria, Design, Plan (+ Q&A/Requirements optional) |
476
+ | `wip` | implementing | + Solution (the change-map starts here) |
477
+ | `testing` | verifying | Solution, Testing |
478
+ | `done` | shipped | Solution, Testing, Review (gated) |
479
+
480
+ **Design (written at `todo`, for HITL review) = the decision record — WHAT/WHY:**
481
+ the chosen approach + a one-line reason, rejected alternatives, key interface/type **signatures**
482
+ (not bodies), and invariants. **Code budget: ≤2 illustrative snippets.** This is what a reviewer
483
+ reads to approve the task *before* any code is written.
484
+
485
+ > **Task `### Design` ≠ the feature design satellite.** This per-task section is code-level and narrow.
486
+ > The feature's cross-cutting design record is the **satellite** `docs/design/<slug>.md`, authored once
487
+ > per feature in the planning half (planning-workflow §Step 5.5), indexed from `04_DESIGN.md §0`. The
488
+ > two coexist: the satellite frames the area; each task's `### Design` records that task's local decision.
489
+
490
+ **Solution (written at `wip`/`testing`) = the change-map — HOW/WHERE:**
491
+ a `file:line` table of every touched site, one sentence each; **≤8-line snippets only for
492
+ non-obvious logic, never full-function dumps.** `spur task check` requires ≥1 `file:line` citation
493
+ once Solution has real content.
494
+
495
+ > **Avoid the legacy "too much code" failure.** Design shows *shape and decision*, not
496
+ > implementation; Solution *points at* the code (file:line), it does not reproduce it. If you find
497
+ > yourself pasting whole functions into either section, you are documenting the diff — stop and
498
+ > cite the location instead.
499
+
500
+ ## Batch JSON example
501
+
502
+ The payload is a top-level JSON **array** (no `tasks` wrapper):
503
+
504
+ ```json
505
+ [
506
+ {
507
+ "name": "Implement task creation endpoint",
508
+ "template": "feature-impl",
509
+ "feature_id": "A1",
510
+ "priority": "P0",
511
+ "background": "Implements: R1 — User can create a task with required fields",
512
+ "requirements": "- [ ] R1. Accept a title and an optional description on POST /tasks.\n- [ ] R2. Reject an empty title with a 400 and a reason.\n- [ ] R3. Allocate the task file through the CLI-gated write path.",
513
+ "design": "Approach: POST /tasks via existing TaskService.create.\nRejected: ad-hoc SQL in handler.\nInvariants: CLI-gated corpus writes only.",
514
+ "plan": "1. Contract\n2. Handler\n3. Tests",
515
+ "acceptance_criteria": "Scenario: create succeeds\n Given a valid title\n When POST /tasks\n Then a task file is allocated"
516
+ },
517
+ {
518
+ "name": "Implement task listing endpoint",
519
+ "template": "feature-impl",
520
+ "feature_id": "A1",
521
+ "priority": "P1",
522
+ "background": "Implements: R2 — User can list tasks filtered by status (runs after the create endpoint)",
523
+ "design": "Approach: GET /tasks with status filter on TaskService.list.\nRejected: client-side full scan only.\nInvariants: reuses list DTO from contracts.",
524
+ "plan": "1. Filter param\n2. Handler\n3. Tests"
525
+ }
526
+ ]
527
+ ```
528
+
529
+ ## Common schema violations
530
+
531
+ | Violation | Fix |
532
+ |-----------|-----|
533
+ | `name` is empty or missing | Every task must have a name. |
534
+ | `template` value not in the enum | Use one of: `default`, `feature-impl`, `issue`, `review`, `meta`. |
535
+ | `feature_id` references a non-existent feature | Run `spur feature list --json` to confirm the ID exists. |
536
+ | `priority` not `P0`–`P3` | Use the canonical priority scale. |
537
+ | Unknown field (e.g. `sections`, `dependencies`, `tasks` wrapper) | The item schema is strict — use only the documented fields; the payload is a bare array. |
538
+ | `parent_wbs` as a number (`0042`) | Quote it: `"0042"` — leading-zero numerics fail the 4-digit string schema. |
539
+ | `requirements` items written as bare `R1.` lines | Prefix each with `- [ ] ` — bare lines pass `check` but render as one paragraph in Board preview. See "Section bodies are markdown" above. |