@gobing-ai/spur 0.3.50 → 0.3.52

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 (30) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/corpus-baseline.json +1995 -1939
  3. package/config/rules/quality/coverage-gate.yaml +3 -2
  4. package/config/tasks/section-matrix.yaml +7 -2
  5. package/config/workflows/pr-review.yaml +13 -11
  6. package/config/workflows/task-lifecycle.yaml +7 -6
  7. package/config/workflows/task-pipeline.yaml +37 -16
  8. package/package.json +1 -1
  9. package/plugins/sp/agents/super-planner.md +3 -2
  10. package/plugins/sp/agents/super-reviewer.md +5 -0
  11. package/plugins/sp/commands/dev-review.md +1 -1
  12. package/plugins/sp/plugin.json +1 -1
  13. package/plugins/sp/scripts/pr-reviewing.ts +57 -5
  14. package/plugins/sp/scripts/stage-registry-adapter.ts +40 -25
  15. package/plugins/sp/skills/code-improvement/SKILL.md +5 -3
  16. package/plugins/sp/skills/code-verification/SKILL.md +28 -31
  17. package/plugins/sp/skills/code-verification/references/verdict-schema.md +47 -0
  18. package/plugins/sp/skills/functional-review/SKILL.md +16 -15
  19. package/plugins/sp/skills/pr-reviewing/SKILL.md +6 -3
  20. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +13 -14
  21. package/plugins/sp/skills/spur-cli/references/tasks/l3-guard-cheatsheet.md +7 -3
  22. package/plugins/sp/skills/spur-cli/references/tasks/section-editing.md +22 -13
  23. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +22 -11
  24. package/plugins/sp/skills/spur-cli/references/tasks.md +16 -10
  25. package/plugins/sp/skills/spur-dev/SKILL.md +10 -5
  26. package/plugins/sp/skills/spur-dev/references/dev-operations.md +5 -5
  27. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +11 -4
  28. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +5 -3
  29. package/plugins/sp/skills/spur-dev/references/section-batching.md +29 -13
  30. package/spur.js +382 -231
@@ -27,15 +27,16 @@ metadata:
27
27
 
28
28
  The **verifier** in the Spur execution loop. A coding agent reports "done" with overconfidence;
29
29
  this skill is the deterministic counterweight that proves — or disproves — the claim against the
30
- task's own requirements and Acceptance Criteria, then writes the evidence back to the corpus
31
- through CLI verbs.
30
+ task's own requirements and Acceptance Criteria, then emits the canonical verdict artifact
31
+ through CLI verbs (section writes are owned by the review coordinator and the deterministic
32
+ `record` step — F92 0593 R1).
32
33
 
33
34
  It backs two commands:
34
35
 
35
36
  | Command | Mode | Input | Output |
36
37
  |---------|------|-------|--------|
37
- | `/sp:dev-verify <wbs>` | **verify** | a task WBS | per-requirement verdict → `## Testing`; `.spur/run/<wbs>-verdict.json` |
38
- | `/sp:dev-review <wbs>` | **review** | a task WBS (diff scope) | three-dimensional findings → `## Review` (functional + SECUA + architecture) |
38
+ | `/sp:dev-verify <wbs>` | **verify** | a task WBS | `.spur/run/<wbs>-verdict.json`; `record` transcribes `## Testing` |
39
+ | `/sp:dev-review <wbs>` | **review** (coordinator) | a task WBS (diff scope) | merged three-dimensional findings → `## Review` |
39
40
 
40
41
  The verify mode is the **completion gate's evidence source**: it emits a machine verdict the
41
42
  `task-pipeline.yaml` workflow reads before allowing `record → done`. A `PASS` clears the gate; a
@@ -243,34 +244,32 @@ blocker finding → FAIL; core PARTIAL or an unresolved major finding (no FAIL)
243
244
  MET or justified N/A → PASS. Minor/advisory findings do not block. Only `PASS` clears the pipeline
244
245
  completion gate (`PARTIAL`/`FAIL` route the pipeline to `failed`).
245
246
 
246
- ### Step 10 — Write findings to the task
247
+ ### Step 10 — Emit the verdict artifact (the only verify output)
247
248
 
248
- Assemble the evidence and write via CLI verbs (temp-file `--section`):
249
+ Assemble the evidence and **emit the canonical verdict artifact** verification writes no task
250
+ section (F92 0593 R1). Under the pipeline, the output is captured as
251
+ `.spur/run/<wbs>-verify-answer.txt`; a deterministic shell step derives
252
+ `.spur/run/<wbs>-verdict.json`, and the `record` step transcribes `## Testing` from it.
253
+
254
+ **Standalone** (`/sp:dev-verify` outside the pipeline), write the artifact yourself, then invoke
255
+ the deterministic Testing writer `spur task record` (section authorship never happens here):
249
256
 
250
257
  ```bash
251
- # Testing section: per-requirement and per-AC verdict tables + evidence
252
- printf '...' > /tmp/<wbs>-testing.md
253
- spur task update <wbs> --section Testing --from-file /tmp/<wbs>-testing.md
258
+ # write .spur/run/<wbs>-verdict.json (shape in references/verdict-schema.md), then:
259
+ spur task record <wbs> --verdict-file .spur/run/<wbs>-verdict.json # renders ## Testing
254
260
  ```
255
261
 
256
262
  > **Corrections: the answer file is the source of truth.** `spur task record` re-transcribes
257
- > `## Testing` from the verdict artifact, overwriting `--section Testing` writes direct section
258
- > fixes are futile. Fix `.spur/run/<wbs>-verify-answer.txt` → `spur task verdict <wbs>
259
- > --from-answer <file>` → re-record. `--section` is initial authorship only.
260
-
261
- > **Do not write `## Review` directly in verify mode.** The `## Review` section is owned by the
262
- > `review` step (`/sp:dev-review`), which dispatches `functional-review` + `code-verification`
263
- > review mode + `code-improvement`. The `record` step backfills `## Review` from the verdict
264
- > artifact only if the section is bare (`sectionIsBare` guard, `task-service.ts:485`). Writing
265
- > `## Review` here bypasses that guard and destroys the review step's three-dimensional findings.
266
-
267
- Section bodies passed to `spur task update --section` must be **body-only**. Do not put a same-level
268
- heading inside any section body; the task writer strips same-level headings to prevent phantom
269
- sections. Concretely:
263
+ > `## Testing` from the verdict artifact direct `--section Testing` writes are futile. Fix
264
+ > `.spur/run/<wbs>-verify-answer.txt` → `spur task verdict <wbs> --from-answer <file>` → re-record.
270
265
 
271
- - **Testing section:** do not put `### Acceptance Criteria Verification`, `### Per-Requirement
272
- Traceability`, or any `###` heading inside the Testing body. Use bold labels
273
- (`**Acceptance Criteria Verification**`) or tables instead.
266
+ > **Do not write `## Review` directly, ever.** The `## Review` section is owned by the
267
+ > `review` coordinator (`/sp:dev-review` `sp:super-reviewer`), which merges
268
+ > `functional-review` + `code-verification` review mode + `code-improvement` fragments. The
269
+ > `record` step backfills `## Review` from the verdict artifact **only** if the section is bare
270
+ > (`sectionIsBare` guard, `task-service.ts`) — a standalone compatibility fallback, never an
271
+ > overwrite of authored Review. Writing `## Review` here destroys the review step's
272
+ > three-dimensional findings.
274
273
 
275
274
  ### Step 11 — State the verdict and hand off (the gate contract)
276
275
 
@@ -311,10 +310,8 @@ canonical.
311
310
  `.spur/run/<wbs>-verify-answer.txt`. A deterministic shell step then derives
312
311
  `.spur/run/<wbs>-verdict.json` from it plus an independent `spur task check` (R9; the agent
313
312
  reporting PASS in prose is necessary but not sufficient — the artifact is never left to the agent's
314
- discretion). The **record** step transcribes only `## Testing` from the verdict verdict + per-
315
- requirement/AC tables + evidence. `## Review` is owned by the review step (`/sp:dev-review`) and
316
- the record step's `sectionIsBare` guard (`task-service.ts:485`) preserves any non-bare Review
317
- content. Verify mode never writes `## Review`.
313
+ discretion). Section transcription follows the Step 10 contract (record `## Testing`; bare-only
314
+ Review fallback; verify never writes sections).
318
315
 
319
316
  **Standalone** (`/sp:dev-verify` outside the pipeline — no answer-file capture exists), write the
320
317
  artifact yourself; shape and field-by-field contract in
@@ -455,8 +452,8 @@ re-audit is never misread as a successful `testing -> done` (dev-verify.md `--ne
455
452
  ## Mode: review (`/sp:dev-review`)
456
453
 
457
454
  The source-oriented path: SECUA review of a task's diff without the full traceability verdict. Runs
458
- Steps 3 + 7 + 10 (Review section only) — no verdict artifact, no `done` gate. Use for a focused
459
- quality/security audit of changes when the full verify isn't wanted.
455
+ Steps 3 + 7 and returns a **review fragment** — no verdict artifact, no section write, no `done`
456
+ gate (F92 0593 R1); the coordinator (`sp:super-reviewer`) merges fragments into `## Review`.
460
457
 
461
458
  Flags: `--agent <inline|auto|name>` (execution surface — inline default, with named escalation triggers taking precedence), `--auto` (no confirmations), `--fix <none|blockers-first|all>` (post-review repair), and `--focus <all|security|efficiency|correctness|usability|architecture>` (SECUA dimensions). Apply the [central contract](../spur-dev/references/cross-cutting.md#inline-default-execution-surface) before starting the review.
462
459
 
@@ -139,3 +139,50 @@ completion without an explicit PASS artifact.
139
139
  - **Read:** by the workflow gate on the `verify → record` transition.
140
140
  - **Location:** `.spur/run/` (the run-scratch dir the pipeline's `record` step also uses).
141
141
  - **Lifetime:** per execution attempt; overwritten on the next verify of the same WBS.
142
+
143
+ ## Optional check severity (task 0592, feature F92)
144
+
145
+ `checks[]` rows may carry an optional `severity` field so the aggregation policy can distinguish a
146
+ blocking review finding from a non-blocking one:
147
+
148
+ ```typescript
149
+ checks: Array<{
150
+ name: string; // aliases accepted on read: `check`, `id`
151
+ status: 'pass' | 'fail' | 'warn';
152
+ evidence: string;
153
+ severity?: 'blocker' | 'major' | 'minor' | 'advisory';
154
+ }>;
155
+ ```
156
+
157
+ ### Compatibility aliases: check label key
158
+
159
+ Producers SHOULD write the check label as `name`. Consumers ALSO accept `check` and `id` as
160
+ aliases, normalized to `name` in the same single place the `scenario`→`id` coverage alias is
161
+ normalized (`checkSchema` in `verify-verdict.ts`). A row carrying none of the three is
162
+ **structurally invalid** — an unnamed check cannot be matched by the aggregation policy's
163
+ `task-check` detection, so it would silently exempt a failed task-check from the completion rule.
164
+
165
+ The alias resolves for raw rows as well as parsed ones (`checkRowName`), because
166
+ `aggregateVerifyVerdict` and the done guard's task-check lookup both run over unparsed artifacts.
167
+ Precedence is `name` → `check` → `id`, first non-empty string wins.
168
+
169
+ ## Canonical runtime contract + one aggregation policy (task 0592)
170
+
171
+ The prose shape above is executed by a single runtime-validated contract:
172
+ `packages/app/src/services/verify-verdict.ts`. It owns:
173
+
174
+ - **`verifyVerdictSchema`** (Zod) — validates the persisted artifact and distinguishes
175
+ **missing** (file absent / empty), **malformed** (bad JSON), **structurally invalid**
176
+ (`invalid` outcome), and **valid** (with case-normalized `verdict`). The `scenario`→`id` coverage
177
+ alias and the `check`/`id`→`name` check-label alias are both normalized here, in exactly one place.
178
+ - **`aggregateVerifyVerdict`** — the ONE aggregation policy every verdict consumer uses (answer
179
+ derivation, persisted-artifact consistency checks, task/feature validation, record rendering,
180
+ and the done-transition gate). Requirements/AC use `MET`/`PARTIAL`/`UNMET`/`N/A`. Checks:
181
+ non-pass **blocker** → FAIL, non-pass **major** → PARTIAL, **minor**/**advisory** do not block;
182
+ legacy rows without a severity map `fail` → FAIL and `warn` → PARTIAL. An independent task-check
183
+ failure can never yield PASS.
184
+ - A row-less artifact aggregates to UNKNOWN — a stored PASS that does not recompute to PASS
185
+ (including a row-less PASS) is treated as non-PASS at the done gate. The done-transition choke
186
+ point (`done-transition-guard.ts` `evaluateDoneTransition`) is the final authority; workflow JSON
187
+ routing may select `verify → record/failed` but cannot weaken the final transition.
188
+ - `--force-done --reason` on `spur task update <wbs> done` remains the sole auditable override.
@@ -241,16 +241,16 @@ all core requirements MET → PASS
241
241
  `PARTIAL` blocks the gate exactly like `FAIL` — the distinction only tells the operator *how far
242
242
  off* delivery is.
243
243
 
244
- ### Step 7 — Write findings to the task
244
+ ### Step 7 — Return the review fragment (no section write)
245
245
 
246
- Write the review body to the task's `## Review` section via CLI verbs. The body MUST lead with a
247
- `| Priority | Dimension | Location | Finding |` table (the L3 `hasPopulatedPriorityTable` gate at
246
+ Assemble the findings into a **review fragment** the priority-table lead + the per-requirement
247
+ traceability table. The fragment MUST lead with a `| Priority | Dimension | Location | Finding |`
248
+ table (the L3 `hasPopulatedPriorityTable` gate at
248
249
  `task-check.ts:96-106` requires at least one `P[1-4]` row with non-placeholder siblings — any other
249
250
  shape, e.g. `| Req | Status | Evidence |` alone, is structurally rejected and denies the
250
251
  `wip→testing` transition). Use the same canonical shape as `sp:code-verification`:
251
252
 
252
- ```bash
253
- cat > /tmp/<wbs>-functional.md <<'BODY'
253
+ ```markdown
254
254
  | Priority | Dimension | Location | Finding |
255
255
  | --- | --- | --- | --- |
256
256
  | P4 | — | — | No P1–P3 findings; functional verdict PASS |
@@ -260,16 +260,17 @@ cat > /tmp/<wbs>-functional.md <<'BODY'
260
260
  | R1 | MET | `src/api/users.ts:42` — `createUser()` |
261
261
  | R2 | PARTIAL | `src/api/users.ts:42` — basic only; MISSING duplicate-email handling |
262
262
  | R3 | UNMET | no implementation found; searched src/api/, src/services/ |
263
- BODY
264
- spur task update <wbs> --section Review --from-file /tmp/<wbs>-functional.md
265
- rm /tmp/<wbs>-functional.md
266
263
  ```
267
264
 
268
265
  For a PARTIAL/FAIL verdict, replace the P4 row with the actual P1–P3 findings ranked by severity.
269
266
  The priority table leads; the traceability table follows for per-requirement detail.
270
267
 
271
- Section bodies passed to `spur task update --section` must be **body-only** — no same-level (`##`)
272
- headings inside the body. Tables and bold labels are fine.
268
+ **Fragment-only discipline (F92 0593 R1).** In coordinated mode (dispatched by `/sp:dev-review` /
269
+ `sp:super-reviewer`), do **not** write `## Review` return the fragment to the coordinator, which
270
+ merges the functional + SECUA + architecture fragments into the combined `## Review` section. Only
271
+ `sp:super-reviewer` (the review coordinator) writes `## Review`; direct component-skill use is
272
+ advisory output. `spur task record` backfills a **bare** `## Review` from the verdict artifact as a
273
+ standalone compatibility fallback only and never overwrites authored Review (F92 0593 R1).
273
274
 
274
275
  ### Step 8 — Report
275
276
 
@@ -289,11 +290,11 @@ Include the per-requirement traceability table in the report:
289
290
  | R3 | UNMET | no implementation found; searched src/api/, src/services/ |
290
291
  ```
291
292
 
292
- **Under the pipeline**, `sp:functional-review` is the review step dispatched by `/sp:dev-review`,
293
- so it owns `## Review` — its `--section Review` write is the authoritative source. The pipeline's
294
- `record` step transcribes only `## Testing` from the verify verdict (`code-verification/SKILL.md`,
295
- `task-record.ts:226-247`); it does not overwrite a non-bare `## Review` thanks to the
296
- `sectionIsBare` guard (`task-service.ts:485`). Keep the priority-table lead stable so the L3 gate
293
+ **Under the pipeline**, `sp:functional-review` is a component of `/sp:dev-review`: it returns its
294
+ fragment to the coordinator (`sp:super-reviewer`), which writes the combined `## Review`. The
295
+ `record` step transcribes only `## Testing` from the verdict artifact and backfills `## Review`
296
+ only when the section is bare (`sectionIsBare` guard, `task-service.ts`); it never overwrites the
297
+ coordinator's authored Review. Keep the priority-table lead stable in the fragment so the L3 gate
297
298
  stays satisfied through `record` → `done`.
298
299
 
299
300
  ---
@@ -135,9 +135,12 @@ bun "$(superskill script path sp pr-reviewing.ts)" <subcommand> [flags]
135
135
  Installed targets resolve the staged TypeScript source and execute it with Bun, matching the rest
136
136
  of `plugins/sp/scripts`.
137
137
 
138
- 1. **Preflight** — `<script> preflight --json`. Hard-fails on a
139
- detached HEAD, missing `gh` auth, no GitHub remote, or a dirty tree. On a dirty tree, triage
140
- with the user (commit/stash/exclude) before continuing the workflow refuses to guess.
138
+ 1. **Preflight** — `<script> preflight --base "$base" --json`. Hard-fails on a
139
+ detached HEAD, missing `gh` auth, no GitHub remote, a dirty tree, or the current branch
140
+ being the base branch (a PR reviews a feature branch against the base; nothing on the
141
+ base branch is reviewable, and the guard runs before any push can publish it). On a
142
+ dirty tree, triage with the user (commit/stash/exclude) before continuing — the
143
+ workflow refuses to guess.
141
144
  2. **Hygiene** — `<script> hygiene --base "$base" --json`. `BLOCK` (secrets, `.env`, conflict markers,
142
145
  private keys) stops the run — never submit a tainted diff. `WARN` (debug residue) rides along
143
146
  into the report. This is a submission sanity check, not a second local review.
@@ -147,8 +147,9 @@ blank Design before implement (`/sp:dev-refine` / `dev-refineall`).
147
147
  The `template` field is the **single variant axis** (TASK_VARIANTS): it selects the section
148
148
  layout (the `section-matrix.yaml` variant), the scaffold body file
149
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.
150
+ Which sections actually appear is **status-driven** by the runtime matrix query
151
+ `spur task sections <wbs> list --json` rather than assuming a fixed list — pick the variant by
152
+ *purpose*, not by a section checklist.
152
153
 
153
154
  | Variant | When to use |
154
155
  |---------|-------------|
@@ -464,18 +465,16 @@ with research/design/implement/integrate/test as `## Plan` steps.
464
465
 
465
466
  A task created with a spec (a `--feature` link, or a batch item carrying `background`/
466
467
  `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) |
468
+ **`backlog`** — "still preparing". The runtime section matrix decides which sections a task
469
+ carries at each status; the producer renders them with invisible HTML guidance comments. You do
470
+ **not** hand-build the section list `spur task create` / `batch-create` does it from the matrix.
471
+
472
+ **Query the runtime contract — never restate a status-to-section table (F92 0593 R2).**
473
+ `spur task sections <wbs> list --json` returns the matrix required/optional/forbidden sections
474
+ per status; `spur task check <wbs> --json` returns what the gate requires at the current status.
475
+ Both replace any static "sections present at stage X" projection. The section *content* guidance
476
+ below (Design = the decision record, Solution = the change-map) is prose ownership, not a
477
+ section-layout authority.
479
478
 
480
479
  **Design (written at `todo`, for HITL review) = the decision record — WHAT/WHY:**
481
480
  the chosen approach + a one-line reason, rejected alternatives, key interface/type **signatures**
@@ -8,7 +8,10 @@ see_also:
8
8
 
9
9
  # Task L3 guard cheat sheet
10
10
 
11
- Read this before writing `Solution`, `Testing`, or `Review`. The owning implementations are
11
+ Read this before writing `Solution`, `Testing`, or `Review`. Section **writers** are one per
12
+ evidence section (F92 0593 R1): implement owns `Solution`, the review coordinator
13
+ (`/sp:dev-review`) owns `Review`, and `spur task record` owns `Testing` (bare-`## Review`
14
+ backfill is fallback-only). The owning implementations are
12
15
  `.spur/workflows/task-lifecycle.yaml`, `hasPopulatedPriorityTable()` in
13
16
  `packages/app/src/services/task-check.ts`, the verdict normalizers in
14
17
  `packages/app/src/services/task-record.ts`, and `TASK_CANONICAL_SECTIONS` in
@@ -25,8 +28,9 @@ done → wip
25
28
  backlog|todo|wip|testing|blocked → cancelled
26
29
  ```
27
30
 
28
- - `wip → testing` runs `spur task check <wbs>`.
29
- - `testing → done` runs `spur task check <wbs> --strict-core`, followed by the PASS-verdict gate.
31
+ - `wip → testing` runs `spur task check <wbs> --as testing` (F92 R3 — target-aware).
32
+ - `testing → done` runs `spur task check <wbs> --as done` (evaluates the `done` row incl. `gate:true`),
33
+ followed by the PASS-verdict gate. `--strict-core` remains as a compatibility alias only.
30
34
  - Invalid: `todo → testing`, `todo → done`, and `wip → done`.
31
35
  - Normal path: `backlog → todo → wip → testing → done`.
32
36
 
@@ -12,10 +12,12 @@ Task bodies are edited section-by-section through `spur task update --section <n
12
12
  replaced wholesale from the file you point at. There is no inline-body flag — always stage the new
13
13
  body in a file first.
14
14
 
15
- For **pipeline output** (`Testing` / `Review` / safety-net `Solution`), prefer `spur task record`
16
- over hand-assembling files it renders the matrix-compliant tables from a verify verdict for you.
17
- Use the manual recipe below for `Plan`, `Acceptance Criteria`, hand-authored `Solution`, and any
18
- narrative section.
15
+ For **pipeline output**, section authorship is one-writer-per-section (F92 0593 R1):
16
+ `Testing` comes from `spur task record` (deterministic, from a verify verdict artifact — the
17
+ matrix-compliant tables are rendered for you); `Review` is authored by the review coordinator
18
+ (`/sp:dev-review`), with `record` backfilling it only when bare; `Solution` is authored by the
19
+ implement step (record safety-nets a bare `Solution` from the diff). Use the manual recipe below
20
+ for `Plan`, `Acceptance Criteria`, hand-authored `Solution`, and any narrative section.
19
21
 
20
22
  ## The recipe
21
23
 
@@ -47,16 +49,19 @@ exactly: `Background`, `Requirements`, `Acceptance Criteria`, `Q&A`, `Design`, `
47
49
 
48
50
  ## `record` vs. hand-editing
49
51
 
50
- `spur task record 0040 --transition testing` reads `.spur/run/0040-verdict.json` and writes both
51
- `Testing` (per-requirement table) and `Review` (P1–P4 findings table) in the matrix-required shape,
52
- optionally backfilling a bare `Solution` from `git diff -U0`. It never transitions to `done`.
52
+ `spur task record 0040 --transition testing` reads `.spur/run/0040-verdict.json`, writes
53
+ `Testing` (per-requirement table), and backfills `Review` (P1–P4 findings table) **only when the
54
+ section is bare** a standalone compatibility fallback, never an overwrite of the review
55
+ coordinator's authored Review — optionally backfilling a bare `Solution` from `git diff -U0`. It
56
+ never transitions to `done`.
53
57
 
54
- - **Use `record`** when a verify step produced a verdict artifact — it is the pipeline's record step.
58
+ - **Use `record`** when a verify step produced a verdict artifact — it is the pipeline's record step
59
+ and the deterministic `Testing` writer.
55
60
  - **Use `update --section`** when you are authoring a section by hand (planning, design, narrative
56
61
  solution) or amending one `record` already wrote.
57
62
 
58
- The two are interchangeable on the same section: `record` writes `Review`, a later
59
- `update --section Review` overwrites it. Both go through the same file-wins atomic write.
63
+ `record` writes `Testing` unconditionally and `Review` only when bare; a later
64
+ `update --section` overwrites either (file-wins). Both go through the same file-wins atomic write.
60
65
 
61
66
  ## Which section, when
62
67
 
@@ -68,9 +73,13 @@ LLM's job (orchestrated by `sp:spur-dev`); this skill only owns the *mechanism*:
68
73
  | `Background` | at create (derived from feature `Goal` if `--feature`) | why this task exists |
69
74
  | `Acceptance Criteria` | planning (present at `todo` for spec'd tasks) | the scenarios this task satisfies (matched to feature AC by title) |
70
75
  | `Plan` | before `wip` | the step list |
71
- | `Solution` | during impl (first appears at `wip`) | the approach actually taken; L3 `file:line` rule fires once it has real content |
72
- | `Testing` | testing phase (via `record`) | what was verified and how — gated at `wip→testing` by `check` |
73
- | `Review` | review phase (via `record`) | SECU findings + verdict — gated at `testing→done` by `check --strict-core` |
76
+ | `Solution` | during impl (implement step) | the approach actually taken; L3 `file:line` rule fires once it has real content |
77
+ | `Testing` | testing phase (`record` — deterministic writer) | what was verified and how — gated at `wip→testing` by `check` |
78
+ | `Review` | review phase (`/sp:dev-review` coordinator) | merged SECU findings + verdict — gated at `testing→done` by `check --strict-core` |
79
+
80
+ Section presence per status is a **runtime contract**, not a table: query
81
+ `spur task sections <wbs> list --json` (permitted present sections) and `spur task check <wbs> --json`
82
+ (required sections at the current status) before writing.
74
83
 
75
84
  A spec'd task (`--feature` link or batch item with `background`/`requirements`) is created at `todo`
76
85
  with Acceptance Criteria + Plan scaffolding present; a bare capture is created at `backlog` with
@@ -35,8 +35,9 @@ and its scaffold body. **Default:** `feature-impl` when `--feature` is given, el
35
35
  unknown variant is exit `2`.
36
36
 
37
37
  **Creation status** follows the matrix: a spec'd task (a `--feature` link, or a batch item with
38
- `background`/`requirements`) is created at **`todo`** ("ready to execute"); a bare capture is created
39
- at **`backlog`** ("still preparing"). `Solution` first appears at `wip`.
38
+ `background`/`requirements`) is created at **`todo`**; a bare capture is created at
39
+ **`backlog`** ("still preparing"). Which sections a status carries is a runtime contract — query
40
+ `spur task sections <wbs> list --json` or `spur task check <wbs> --json`; do not restate the matrix.
40
41
 
41
42
  ## `show <wbs>` / `list`
42
43
 
@@ -50,8 +51,10 @@ Multi-mode. Status and `--section` are **mutually exclusive**; `--feature`/`--pr
50
51
  frontmatter scalar.
51
52
 
52
53
  - **Status** (positional): legal transition over `backlog → todo → wip → testing → blocked → done →
53
- cancelled`. Two transitions run a `check` guard (§7.5): `wip→testing` → `spur task check <wbs>`;
54
- `testing→done` → `spur task check <wbs> --strict-core`. A failing gate blocks the transition.
54
+ cancelled`. Two transitions run a target-aware `check` guard (§7.5): `wip→testing` →
55
+ `spur task check <wbs> --as testing`; `testing→done` → `spur task check <wbs> --as done`
56
+ (F92 R3 — each evaluates the transition target, so `testing→done` checks the `done` row).
57
+ A failing gate blocks the transition.
55
58
  - **`--no-lifecycle`**: suppress lifecycle workflow *run record* creation (use inside pipeline runs
56
59
  to avoid orphaned nested lifecycle runs). **It is not a guard bypass** — the `wip→testing` and
57
60
  `testing→done` `check` gates above still run; the CLI evaluates them inline when the FSM guard
@@ -127,8 +130,9 @@ in `sp:spur-dev`.
127
130
 
128
131
  ## `record <wbs>`
129
132
 
130
- Write `Testing` + `Review` from a verify verdict, with optional `Solution` backfill and a lifecycle
131
- transition. Collapses the pipeline's record step to one call.
133
+ Write `Testing` from a verify verdict artifact the **deterministic Testing writer** (F92 0593 R1) —
134
+ with a **bare-only `Review` backfill** (never overwrites authored Review), optional `Solution`
135
+ backfill, and a lifecycle transition. Collapses the pipeline's record step to one call.
132
136
 
133
137
  | Flag | Effect |
134
138
  | ---- | ------ |
@@ -149,9 +153,11 @@ transition. Collapses the pipeline's record step to one call.
149
153
 
150
154
  - `verdict`: `PASS` | `PARTIAL` | `FAIL` | `UNKNOWN`. A missing/malformed/empty file degrades to
151
155
  `UNKNOWN` (empty arrays) — `record` never throws.
152
- - `requirements[]` → the `Testing` per-requirement table. `checks[]` → the `Review` P1–P4 findings
153
- table. With no requirements/checks, each renders exactly one "none recorded" row (a clean verify is
154
- a valid outcome; the matrix requires a table, not an empty section).
156
+ - `requirements[]` → the `Testing` per-requirement table (deterministic transcript).
157
+ - `checks[]` the P1–P4 findings table used for the **bare-only `Review` backfill** the done-gate's
158
+ `## Review` L3 layer is satisfied by the `review` coordinator's authored table; `record` writes the
159
+ fallback shape only when the section is bare. With no requirements/checks, each renders exactly one
160
+ "none recorded" row (a clean verify is a valid outcome; the matrix requires a table, not an empty section).
155
161
  - `--solution-from-diff` parses `+++ b/<path>` + `@@ +new @@` hunk headers into sorted, unique
156
162
  `` `file:line` `` rows; falls back to `--name-only` at `:1` when there are no hunk lines.
157
163
 
@@ -162,7 +168,12 @@ traceability. Bare = whole corpus; with a WBS = one task. The matrix is loaded f
162
168
  `.spur/tasks/section-matrix.yaml`.
163
169
 
164
170
  - **`--strict`** elevates *all* warnings to failures.
165
- - **`--strict-core`** is the `testing→done` gate variant: fails only on **hard-core errors**
171
+ - **`--as <status>`** evaluates the task as if it were already in `<status>` (F92 R2 the lifecycle
172
+ guards pass the transition target). Validated against canonical task statuses; mutually exclusive
173
+ with `--corpus`. Omitted `--as` uses current-status diagnostics.
174
+ - **`--strict-core`** is a **temporary compatibility alias** (F92 R2), retained so installed
175
+ plugins/workflows that call it keep working; target-state selection (`--as`) supplies the real
176
+ done semantics. Fails only on **hard-core errors** —
166
177
  Solution `file:line`, Review P1–P4, and `gate:true` required-section misses — *without* the blanket
167
178
  warning elevation.
168
179
 
@@ -354,7 +365,7 @@ spur task refresh-roster <wbs> [--folder] [--json]
354
365
  spur task batch-create --file <path> [--folder] [--json]
355
366
  spur task record <wbs> [--verdict-file <p>] [--solution-from-diff] [--transition <s>] [--folder] [--json]
356
367
  spur task verdict <wbs> [--from-answer <p>] [--folder] [--json]
357
- spur task check [wbs] [--strict] [--strict-core] [--folder] [--json]
368
+ spur task check [wbs] [--strict] [--as <status>] [--strict-core] [--folder] [--json]
358
369
  spur task resolve <file-path> [--strict] [--folder] [--json]
359
370
  spur task path <wbs> [--folder] [--json]
360
371
  spur task run-link <wbs> [--source <src>] [--run-id <id>] [--json]
@@ -49,9 +49,9 @@ re-reading or re-tokenizing the task.
49
49
  | `migrate-anchors` | Qualify in-repo evidence anchors to repo-relative paths (0583 R1–R3) | `--dry-run` `--json` |
50
50
  | `refresh-roster <wbs>` | Regenerate a parent task's sub-task roster block in `## Plan` | `--folder` `--json` |
51
51
  | `batch-create` | Create many tasks from a validated JSON array | `--file <path>` `--folder` `--json` |
52
- | `record <wbs>` | Write Testing/Review from a verify verdict; optional Solution + transition | `--verdict-file <path>` `--solution-from-diff` `--transition <status>` `--folder` `--json` |
52
+ | `record <wbs>` | Write `Testing` from a verify verdict (deterministic); bare-`## Review` fallback only; optional Solution + transition | `--verdict-file <path>` `--solution-from-diff` `--transition <status>` `--folder` `--json` |
53
53
  | `verdict <wbs>` | Derive PASS/PARTIAL/FAIL/UNKNOWN from verify answer text → verdict JSON; see [answer-file shape](tasks/verbs.md#answer-file-shape-what---from-answer-parses) | `--from-answer <path>` `--folder` `--json` |
54
- | `check [wbs]` | Four-layer validation; the readiness matrix | `--strict` `--strict-core` `--folder` `--json` |
54
+ | `check [wbs]` | Four-layer validation; the readiness matrix | `--strict` `--as <status>` `--strict-core` `--folder` `--json` |
55
55
  | `resolve <file-path>` | Map a file path to its owning task WBS | `--strict` `--folder` `--json` |
56
56
  | `path <wbs>` | Map a WBS to its absolute task file path (inverse of `resolve`) | `--folder` `--json` |
57
57
  | `run-link <wbs>` | Record pipeline run provenance link for task | `--source <src>` `--run-id <id>` `--json` |
@@ -120,7 +120,8 @@ spur task update 0040 wip
120
120
 
121
121
  Valid statuses: `backlog · todo · wip · testing · blocked · done · cancelled` (the lifecycle engine
122
122
  enforces legal transitions). Two transitions are **guarded by `check`**: `wip→testing` runs
123
- `spur task check <wbs>`, and `testing→done` runs `spur task check <wbs> --strict-core` — a failing
123
+ `spur task check <wbs> --as testing`, and `testing→done` runs `spur task check <wbs> --as done`
124
+ (F92 R3 — target-aware guards) — a failing
124
125
  gate blocks the transition (§7.5).
125
126
 
126
127
  **`--no-lifecycle`** suppresses lifecycle workflow *run record* creation (use during pipeline-driven
@@ -166,12 +167,14 @@ spur task update 0040 --priority P1
166
167
  The section-write-then-replace pattern is the workflow agents use to fill in `Plan` / `Solution` /
167
168
  `Testing` / `Review` during a run. See
168
169
  [tasks/section-editing.md](tasks/section-editing.md) for the full recipe. For pipeline
169
- output specifically, prefer **`record`** (below) over hand-assembling Testing/Review files.
170
+ output specifically, prefer **`record`** for `Testing` (below) over hand-assembling section files; `Review` is authored by the review coordinator (`/sp:dev-review`), not hand-filled.
170
171
 
171
172
  ## Recording pipeline results — `record`
172
173
 
173
- `spur task record <wbs>` writes the `Testing` and `Review` sections **from a verify verdict**, so the
174
- pipeline's record step is one CLI call instead of awk/sed/jq plumbing:
174
+ `spur task record <wbs>` writes the `Testing` section **from a verify verdict artifact** (the
175
+ deterministic Testing writer F92 0593 R1) and backfills `Review` **only when the section is
176
+ bare** (standalone compatibility fallback; never overwrites authored Review), so the pipeline's
177
+ record step is one CLI call instead of awk/sed/jq plumbing:
175
178
 
176
179
  ```bash
177
180
  spur task record 0040 --transition testing
@@ -179,8 +182,8 @@ spur task record 0040 --verdict-file .spur/run/0040-verdict.json --solution-from
179
182
  ```
180
183
 
181
184
  - Reads the verdict JSON (default `.spur/run/<wbs>-verdict.json`); renders `Testing` as a
182
- per-requirement table and `Review` as a P1–P4 findings table. A missing/malformed verdict degrades
183
- to an `UNKNOWN` verdict — it never throws.
185
+ per-requirement table and, when the `Review` section is bare, backfills a P1–P4 findings table.
186
+ A missing/malformed verdict degrades to an `UNKNOWN` verdict — it never throws.
184
187
  - **`--solution-from-diff`** backfills `Solution` from `git diff -U0` hunk headers **only when the
185
188
  Solution section is still bare** — a safety net, not an overwrite.
186
189
  - **`--transition <status>`** optionally advances the lifecycle after writing (e.g. `testing`).
@@ -235,7 +238,8 @@ corpus, or with a WBS for one task:
235
238
  spur task check --json # whole corpus
236
239
  spur task check 0040 --json # one task
237
240
  spur task check --strict --json # elevate ALL warnings to failures
238
- spur task check 0040 --strict-core # the testing→done gate variant
241
+ spur task check 0040 --as done # evaluate as the done row (lifecycle target, F92 R2)
242
+ spur task check 0040 --strict-core # temporary compatibility alias
239
243
  ```
240
244
 
241
245
  **Folder resolution (task 0522):** a WBS-targeted check (`<wbs>` present, no `--folder`) resolves
@@ -253,7 +257,9 @@ or "are there orphaned scenarios?" rather than reading task files and re-impleme
253
257
  The two flags are distinct gate profiles:
254
258
 
255
259
  - **`--strict`** elevates *all* warnings to failures (the strictest reading).
256
- - **`--strict-core`** fails only on hard-core errors Solution `file:line`, Review P1–P4, and
260
+ - **`--as <status>`** evaluates the task as if it were already in `<status>` (F92 R2); the lifecycle
261
+ guards pass the transition target. Validated against canonical task statuses; excluded with `--corpus`.
262
+ - **`--strict-core`** is a **temporary compatibility alias** (F92 R2). Fails only on hard-core errors — Solution `file:line`, Review P1–P4, and
257
263
  `gate:true` required-section misses — *without* the blanket elevation. This is the variant wired
258
264
  as the `testing→done` lifecycle guard.
259
265
 
@@ -122,7 +122,7 @@ reference for the half you're operating; do not duplicate its content here.
122
122
  | Continue | execution | `spur feature update` / `refresh` | [execution-workflow.md](references/execution-workflow.md) |
123
123
  | Batch run | execution | `sp:super-planner` + `spur workflow run` | [execution-batch.md](references/execution-batch.md) |
124
124
  | Parallel fan-out | execution | `sp:parallel-execution` decision framework | [execution-batch.md](references/execution-batch.md) |
125
- | All writes (both halves) | — | CLI-gated section editing | [cross-cutting.md](references/cross-cutting.md) · [section-batching.md](references/section-batching.md) |
125
+ | All writes (both halves) | — | CLI-gated section editing | [cross-cutting.md](references/cross-cutting.md) · [section-batching.md](references/section-batching.md) (one-writer protocol, F92 0593) |
126
126
 
127
127
  ## When to use
128
128
 
@@ -156,8 +156,11 @@ CLI does.
156
156
  1. **Never skip a gate.** A clean `feature check` is the only proof the AC is valid; a
157
157
  passing `batch-create` is the only proof the decomposition is well-formed. Skip either and
158
158
  you ship corrupted corpus.
159
- 2. **The pipeline, not you, writes results.** `## Testing` and `## Review` sections are
160
- filled by the pipeline's `record` step. Do not edit them directly during execution.
159
+ 2. **One writer per evidence section (F92 0593 R1).** `## Solution` is authored by the
160
+ implement step; `## Review` by the review coordinator (`/sp:dev-review`); `## Testing` by the
161
+ deterministic `record` step from the verdict artifact (`record` backfills `## Review` only when
162
+ bare — fallback-only, never an overwrite). During execution, do not hand-edit another stage's
163
+ section.
161
164
  3. **Resolve task IDs through the CLI.** Read a known WBS with `spur task show <wbs> --json`; it
162
165
  returns metadata, full content, and `filePath` across configured task folders. Use `spur task
163
166
  path <wbs> --json` only when another tool needs the absolute path. Never search `docs/tasks*` or
@@ -189,8 +192,10 @@ for "what's actually in file Y" or for resources that sit outside the step seque
189
192
  - [references/gate-checklists.md](references/gate-checklists.md) — checkbox checklists for the
190
193
  five gates (feature-check, batch-create, precheck, review, verify). Each checklist is a
191
194
  `- [ ]` list of prerequisites an agent verifies before entering the gate.
192
- - [references/section-batching.md](references/section-batching.md) — first-write protocol for
193
- staging Solution, Testing, and Review together before one task check.
195
+ - [references/section-batching.md](references/section-batching.md) — the evidence-section
196
+ **one-writer protocol** (F92 0593 R1/R2): implement owns `Solution`, the review coordinator owns
197
+ `Review`, deterministic `record` owns `Testing`; skills query `spur task sections` /
198
+ `spur task check` instead of static section tables.
194
199
  - [references/ac-style-guide.md](references/ac-style-guide.md) — BDD scenario authoring:
195
200
  R-numbering, the two AC tiers, scenario-title stability, Gherkin template usage.
196
201
  - [references/feature-link-helper.md](references/feature-link-helper.md) — opt-in,
@@ -110,17 +110,17 @@ must not be changed without updating the backing skill.
110
110
 
111
111
  - **Purpose:** Multi-dimensional code review of a task or path — (1) functional requirements traceability (WBS mode only), (2) SECUA framework (Security, Efficiency, Correctness, Usability, Architecture), (3) architecture depth.
112
112
  - **Modes:**
113
- - **WBS mode (`<wbs>`)**: Runs functional requirements traceability (`sp:functional-review`), SECUA framework (`sp:code-verification`), and architectural depth (`sp:code-improvement`). May write findings to the task's `## Review` section.
113
+ - **WBS mode (`<wbs>`)**: Runs functional requirements traceability (`sp:functional-review`), SECUA framework (`sp:code-verification`), and architectural depth (`sp:code-improvement`). The three skills return review fragments; the coordinator writes the combined `## Review` (F92 0593 R1).
114
114
  - **Path mode (`<path>`)**: Runs advisory SECUA framework (`sp:code-verification`) and architectural depth (`sp:code-improvement`). Performs no task mutation.
115
115
  - **Inputs:** `<wbs|path>` (required). Review executes inline (in-session) by default. `--agent <inline|auto|name>` selector accepted (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--focus <lens>` narrows to one SECUA dimension. Note: `--fix` and `--next` are **deprecated** (no-op with warning; route remediation to `/sp:dev-verify --fix` and progression to `/sp:dev-next`).
116
116
  - **Backing:** `sp:functional-review`, `sp:code-verification` (review mode), `sp:code-improvement`.
117
- - **Behavior:** WBS mode runs functional traceability + SECUA + architecture depth, ranking findings P1–P4 and writing findings to the task's `## Review` section. Path mode runs advisory SECUA + architecture depth with no task mutation.
117
+ - **Behavior:** WBS mode runs functional traceability + SECUA + architecture depth, ranking findings P1–P4, and hands the merged report to the review coordinator, which writes `## Review`. Component skills never write `## Review` in coordinated mode. Path mode runs advisory SECUA + architecture depth with no task mutation.
118
118
  - **Delegation:** WBS mode: `sp:functional-review` + `sp:code-verification` (review) + `sp:code-improvement`; Path mode: `sp:code-verification` (review) + `sp:code-improvement`.
119
119
 
120
120
  ### 3. verify
121
121
 
122
122
  - **Purpose:** Requirements traceability — verify a task's implementation against its acceptance criteria, producing a PASS/PARTIAL/FAIL verdict with per-requirement evidence. Optionally (with `--fix all`) evaluate **feature shippable readiness**.
123
- - **Inputs:** `<wbs>` (required). Verify executes inline (in-session) by default. `--agent <inline|auto|name>` selector accepted (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--fix`, `--focus`, `--bdd`, `--auto`, `--force` modulate the verify pass. `--next` (terminal chain link): on the **post-`--fix`** PASS verdict, transition `testing → done` through the FSM (`--strict-core` guard honored). On PARTIAL/FAIL or guard failure, stop as review-pending. **`--skip-shippable`** (alias `--skip-shipable`): disable the shippable gate that otherwise runs under `--fix all` when the task has a `feature_id`.
123
+ - **Inputs:** `<wbs>` (required). Verify executes inline (in-session) by default. `--agent <inline|auto|name>` selector accepted (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--fix`, `--focus`, `--bdd`, `--auto`, `--force` modulate the verify pass. `--next` (terminal chain link): on the **post-`--fix`** PASS verdict, transition `testing → done` through the FSM (target-aware `--as done` guard honored). On PARTIAL/FAIL or guard failure, stop as review-pending. **`--skip-shippable`** (alias `--skip-shipable`): disable the shippable gate that otherwise runs under `--fix all` when the task has a `feature_id`.
124
124
  - **Backing:** `sp:code-verification` skill, `verify` mode.
125
125
  - **Behavior:** Status guard → change-scope detection → requirements traceability → SECUA review → verdict aggregation → findings write-back → verdict-artifact emission → optional `--fix` pass → **shippable readiness** (when active). The per-task verdict gates the pipeline's `done` transition. With `--next`: the (post-`--fix`) PASS verdict → transition to `done` (FSM guard honored); PARTIAL/FAIL → stop and surface verdict. Shippable FAIL does not rewrite the task verdict line but must be printed; feature is not “ready.”
126
126
  - **Shippable readiness (default on with `--fix all`):** After the task verdict, if `--fix all` and the task has `feature_id` and not `--skip-shippable`, run `spur feature check <id> --json` + linked-task completeness. Emit `Shippable: PASS|FAIL|N/A`. FAIL when feature AC scenarios are orphaned/unverified or any linked task is not `done`/`cancelled`. SSOT procedure: `sp:code-verification` Step 13.
@@ -129,9 +129,9 @@ must not be changed without updating the backing skill.
129
129
  ### 3a. verifyall
130
130
 
131
131
  - **Purpose:** Batch verification of a set of tasks (or all tasks under a feature) against their requirements and AC. Produces per-task verdicts + a summary report with aggregate statistics (counts, table, overall batch verdict). With `--fix all`, also evaluates **feature shippable readiness** once for the set.
132
- - **Inputs:** `--tasks <selector>` (required unless `--feature`). `--feature <id>` (convenience for `--tasks feature:<id>`). Shared verify flags from `dev-verify` (`--agent <inline|auto|name>`, `--fix`, `--focus`, `--bdd`, `--auto`, `--force`, **`--skip-shippable`**). `--next` (per-task lifecycle chaining: on a PASS verdict transition `testing → done` through the FSM with `--strict-core` honored; PARTIAL/FAIL does not transition; transitions run **before** the shippable gate so `spur feature check` sees final statuses). `--json` for machine-readable summary report.
132
+ - **Inputs:** `--tasks <selector>` (required unless `--feature`). `--feature <id>` (convenience for `--tasks feature:<id>`). Shared verify flags from `dev-verify` (`--agent <inline|auto|name>`, `--fix`, `--focus`, `--bdd`, `--auto`, `--force`, **`--skip-shippable`**). `--next` (per-task lifecycle chaining: on a PASS verdict transition `testing → done` through the FSM with the target-aware `--as done` guard honored; PARTIAL/FAIL does not transition; transitions run **before** the shippable gate so `spur feature check` sees final statuses). `--json` for machine-readable summary report.
133
133
  - **Backing:** `sp:spur-dev` skill, `verifyall` operation (resolves the set using the shared selector grammar, dispatches per-task verify via `sp:code-verification` verify mode, writes per-task artifacts, aggregates and emits the batch summary report, then optional shippable gate).
134
- - **Behavior:** Resolve + freeze the set (supports `--feature` sugar). For each task: apply status guard, requirements traceability + AC + SECUA review, write `## Testing` + verdict.json (per-task fix pass under `--fix`). After the batch: **shippable gate once** when active (see below). Emit a structured summary report (markdown or `--json`). Per-task behavior matches single `dev-verify` (except shippable is batch-once). **Batch verdict rollup is deterministic** — computed by `spur task verifyall-aggregate --from-file <batch-input.json> --json` (a tested service module, not agent discretion). **Per-task outcome grammar:** `PASS` / `PARTIAL` / `FAIL` for implemented tasks; `NOT-STARTED` for tasks that have not entered implementation (status `backlog`/`todo`/`blocked` — reachable only via `--force`). **Rollup rule:** all-NOT-STARTED → `UNKNOWN`; any `FAIL` → `FAIL`; any `PARTIAL` or `UNKNOWN` → `PARTIAL`; all `PASS` → `PASS`. NOT-STARTED rows are _excluded_ from the FAIL/PARTIAL rollup (they cannot manufacture a batch failure) but are _reported explicitly_ in the summary ("N NOT-STARTED, excluded from rollup"). This closes the 0341 dogfood gap where a healthy feature with 5 PASS + 2 unstarted tasks read as FAIL. **Shippable FAIL:** treat the batch as not clean — force rollup to at least **PARTIAL** and set `"shippable": false` under `--json` even if every task outcome is PASS.
134
+ - **Behavior:** Resolve + freeze the set (supports `--feature` sugar). For each task: apply status guard, requirements traceability + AC + SECUA review, emit the verdict artifact (per-task fix pass under `--fix`). `## Testing` is written by the deterministic `record` step from the artifact (F92 0593 R1). After the batch: **shippable gate once** when active (see below). Emit a structured summary report (markdown or `--json`). Per-task behavior matches single `dev-verify` (except shippable is batch-once). **Batch verdict rollup is deterministic** — computed by `spur task verifyall-aggregate --from-file <batch-input.json> --json` (a tested service module, not agent discretion). **Per-task outcome grammar:** `PASS` / `PARTIAL` / `FAIL` for implemented tasks; `NOT-STARTED` for tasks that have not entered implementation (status `backlog`/`todo`/`blocked` — reachable only via `--force`). **Rollup rule:** all-NOT-STARTED → `UNKNOWN`; any `FAIL` → `FAIL`; any `PARTIAL` or `UNKNOWN` → `PARTIAL`; all `PASS` → `PASS`. NOT-STARTED rows are _excluded_ from the FAIL/PARTIAL rollup (they cannot manufacture a batch failure) but are _reported explicitly_ in the summary ("N NOT-STARTED, excluded from rollup"). This closes the 0341 dogfood gap where a healthy feature with 5 PASS + 2 unstarted tasks read as FAIL. **Shippable FAIL:** treat the batch as not clean — force rollup to at least **PARTIAL** and set `"shippable": false` under `--json` even if every task outcome is PASS.
135
135
  - **Shippable readiness (default on with `--fix all`):** Active when `--fix all` and feature context exists (`--feature` or unique shared `feature_id`) and not `--skip-shippable`. Procedure: `sp:code-verification` Step 13 once after all per-task legs. Without `--fix all`, do not run the hard gate (optional note: use `--fix all` for ship evaluation).
136
136
  - **Cache discipline (batch):** freeze the `spur task list --feature <id> --json` (or selector) capture once at resolve; reuse that snapshot for every per-task verify leg. Do not re-list the set mid-batch. Re-read a task body only when that task's sections changed (e.g. after a `--fix` write). Prefer re-reading only cited `file:line` anchors over re-tokenizing full Solution sections when prior Testing is already present.
137
137
  - **Dogfood / mutation composition:** prefer step-split when dogfooding verifyall with `--fix all` and/or `--next` — first observe-only verifyall, then a separate fix pass, then `--next` only if status transitions are still needed. See `sp:dogfood-testing` §step-splitting.