@gobing-ai/spur 0.3.77 → 0.3.80

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 (32) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/templates/AGENTS.md +26 -23
  3. package/config/templates/docs/00_ADR.md +13 -23
  4. package/config/templates/docs/01_PRD.md +5 -2
  5. package/config/templates/docs/02_ROADMAP.md +9 -13
  6. package/config/templates/docs/03_ARCHITECTURE.md +2 -2
  7. package/config/templates/docs/04_DESIGN.md +12 -31
  8. package/config/templates/docs/05_FEATURES.md +6 -18
  9. package/config/templates/docs/99_PROJECT_CONSTITUTION.md +162 -394
  10. package/package.json +9 -9
  11. package/plugins/sp/README.md +12 -7
  12. package/plugins/sp/agents/super-reviewer.md +43 -8
  13. package/plugins/sp/commands/dev-refineall.md +1 -0
  14. package/plugins/sp/commands/dev-run.md +1 -0
  15. package/plugins/sp/commands/dev-runall.md +1 -0
  16. package/plugins/sp/commands/dev-verifyall.md +1 -0
  17. package/plugins/sp/plugin.json +1 -1
  18. package/plugins/sp/scripts/batch-preflight.mjs +173 -2
  19. package/plugins/sp/scripts/batch-preflight.ts +257 -2
  20. package/plugins/sp/scripts/verify-answer-lint.ts +32 -9
  21. package/plugins/sp/skills/conflict-finding/SKILL.md +6 -0
  22. package/plugins/sp/skills/daily-summary/SKILL.md +1 -1
  23. package/plugins/sp/skills/doc-evolve/SKILL.md +26 -40
  24. package/plugins/sp/skills/doc-evolve/references/operations.md +17 -30
  25. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +17 -1
  26. package/plugins/sp/skills/spur-cli/references/tasks.md +31 -1
  27. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +14 -0
  28. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +36 -3
  29. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +12 -0
  30. package/plugins/sp/skills/spur-dev/references/execution-batch.md +17 -0
  31. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +148 -17
  32. package/spur.js +1389 -615
@@ -157,13 +157,43 @@ spur task update 0040 --section Review --from-file /tmp/review.md
157
157
  first, then point `--from-file` at it.
158
158
 
159
159
  **Frontmatter set** (the only post-create path to scalar fields, allow-listed to
160
- `feature_id`/`parent_wbs`/`priority`):
160
+ `feature_id`/`parent_wbs`/`priority`, plus the two AC controls below):
161
161
 
162
162
  ```bash
163
163
  spur task update 0040 --feature H2
164
164
  spur task update 0040 --priority P1
165
165
  ```
166
166
 
167
+ ### AC altitude — `--ac-altitude` (task 0818 R5)
168
+
169
+ `--ac-altitude` and `--ac-numbering` are **independent** controls that are easy to confuse:
170
+
171
+ | Flag | Controls | Default | `task-local` means |
172
+ | --- | --- | --- | --- |
173
+ | `--ac-altitude <graduating\|task-local>` | DD-09 **feature-AC subset** rule (task scenarios ⊆ linked feature AC) | `graduating` | the task's scenarios are deliberately **not** feature ship criteria — skip the subset rule |
174
+ | `--ac-numbering <task-local>` | **Requirements↔AC coverage** inside the task | off | opt the task into the R-to-AC coverage check |
175
+
176
+ Setting one says nothing about the other: a `task-local`-altitude task can still be under full
177
+ R-to-AC coverage, and usually should be.
178
+
179
+ **The standing pattern for an issue or fix-batch task.** Link it to the feature it substantively
180
+ belongs to — do not leave it orphaned and do not relink unrelated corpus to silence a diagnostic.
181
+ Then, *only* when its regression scenarios intentionally do not represent that feature's ship
182
+ criteria, declare `--ac-altitude task-local` and record the rationale in the task body (Background
183
+ or Design), so the choice is auditable rather than inferred:
184
+
185
+ ```bash
186
+ # source-local CLI (before `bun link`, or when pinning to this checkout).
187
+ # One frontmatter flag per call: `update` applies a single field, so a second
188
+ # frontmatter flag in the same invocation is silently ignored.
189
+ bun run apps/cli/src/index.ts task update 0818 --feature D6 --json
190
+ bun run apps/cli/src/index.ts task update 0818 --ac-altitude task-local --json
191
+ ```
192
+
193
+ `graduating` stays the default, and DD-09 stays enforced for every graduating task — this flag
194
+ expresses a real altitude distinction, not a gate escape hatch. Ordinary orphan warnings are
195
+ unchanged, and no checker policy changes.
196
+
167
197
  The section-write-then-replace pattern is the workflow agents use to fill in `Plan` / `Solution` /
168
198
  `Testing` / `Review` during a run. See
169
199
  [tasks/section-editing.md](tasks/section-editing.md) for the full recipe. For pipeline
@@ -113,6 +113,20 @@ Any of the four may additionally carry a **bracket tag** in any position — `[d
113
113
  `Scenario: [advisory] Foo`. Tags are stripped before matching (0398 R7), so tagging never breaks
114
114
  the linkage.
115
115
 
116
+ Task-side, `verify-answer-lint` additionally accepts a fifth declared id source — a **bold-trajectory
117
+ paragraph**: a whole-line `**AC id…**` paragraph inside the task's `### Acceptance Criteria`
118
+ block (task 0817 R3). The id up to its first `:` and the paragraph's full spelling are both
119
+ declared; two bold spans on one line are not a declaration (an interpolated bold id stays
120
+ unmatchable):
121
+
122
+ ```markdown
123
+ ### Acceptance Criteria
124
+
125
+ **AC-0817-HERM-SKIP: unpinned project-config resolution is suppressed.**
126
+
127
+ | AC-0817-HERM-SKIP | MET | test | `tests/loader.test.ts:962` | ← declared
128
+ ```
129
+
116
130
  ### The id is exactly the scenario title — no Gherkin body appended
117
131
 
118
132
  An AC row id must be **exactly** the scenario title (plus any of the four forms above), with the
@@ -209,6 +209,39 @@ executor is the current coding agent. Interactive pipelines retain a run log and
209
209
  through the inline driver; task pipelines additionally record a task run-link. If process isolation or an independently killable
210
210
  stage is required, select the subprocess path (`--agent auto` or `--agent <name>`).
211
211
 
212
+ ## Shared startup contract (task 0814 R1/R3/R4/R6/R7/R8)
213
+
214
+ The workflow-backed dev commands (`dev-run`, `dev-runall`, `dev-refineall`, `dev-verifyall`) share one
215
+ startup order. The order is load-bearing and applies on both the inline driver and the subprocess
216
+ path; skill-only operations (refine/verify batches with no nested workflow) display their owned
217
+ procedure and do not fabricate a workflow YAML.
218
+
219
+ 1. **Publish a compact bootstrap checklist immediately** (host-preparation rows, never copied
220
+ workflow states): `A, Quick readiness` · `B, Prepare Git` · `C, Publish workflow plan` ·
221
+ `D, Comprehensive checking`.
222
+ 2. **Quick deterministic readiness (R2), before isolation.** Evaluate `quickReadiness`
223
+ (`plugins/sp/scripts/batch-preflight.ts`) with the operation, status, filtered-set size, and the
224
+ selected matrix required/present sections + content-policy findings. This is an admission decision
225
+ (runnable / needs-refinement / blocked / skipped / invalid), never an implementation certificate.
226
+ 3. **Isolation (R3), only when `--worktree` is valid.** After quick readiness and the required Git
227
+ safety checks, create/adopt and switch to the execution tree; confirm absolute cwd, branch, base
228
+ SHA, and ownership. An invalid/empty target, unsupported mode, ambiguous ownership, or stale target
229
+ stops without creating a tree or discarding work. All subsequent tools, agents, corpus writes, and
230
+ run artifacts use the confirmed execution tree.
231
+ 4. **Publish the workflow inventory (R4), before reading the YAML.** `spur workflow show
232
+ <resolved-file> --no-logo --format todo --json`; validate with `parseWorkflowInventory` and bind to
233
+ the run's `__definitionDigest` with `assertInventoryIdentity`. Drift or projection failure stops the
234
+ run before any comprehensive/model work — never execute with a misleading plan.
235
+ 5. **Load execution detail and run comprehensive checks (R7).** Only after the plan is visible (and
236
+ after isolation when requested) load the full YAML for the active stage and run the owning
237
+ comprehensive gates at their boundaries. Prefer deterministic checks; invoke semantic model work
238
+ only for an identified unresolved requirement/design/evidence question and record its reason.
239
+
240
+ Quick readiness and plan projection dispatch zero models and execute zero workflow actions. Record a
241
+ timestamped event trace under `.spur/run/<run-id>-event-trace.md` (R8) — event ordering,
242
+ time-to-first-visible-checklist, time-to-workflow-inventory, confirmed cwd, invocation counts — and
243
+ record unavailable measurements as `unknown`, never as invented savings.
244
+
212
245
  ## Every write is CLI-gated
213
246
 
214
247
  Never edit a task or feature file directly. Every mutation goes through:
@@ -601,9 +634,9 @@ CLI-gated corpus artifact. The `wrapup-pipeline.yaml` `learning-capture` step wr
601
634
 
602
635
  - **Not CLI-gated.** The file is written directly by the wrap-up pipeline's `learning-capture`
603
636
  agent.run step. It does not go through `spur task update` or `spur feature update`.
604
- - **Not a validated corpus.** The file is a working scratchpad. High-value learnings are promoted
605
- to `docs/99_PROJECT_CONSTITUTION.md §8` (lessons) by the `doc-sync` step (via `sp:doc-evolve`),
606
- not by the learning-capture step itself.
637
+ - **Not a validated corpus.** The file is a working scratchpad. Deduplicate reusable lessons in
638
+ existing project learning/context storage. Constitution §8 routes lessons outside that file;
639
+ doc-sync does not promote lessons into governance without operator-authorized §6.8 scope.
607
640
  - **Append-only within a session.** New entries are appended; existing entries are not rewritten.
608
641
  - **Grouped by date and task.** Each entry has a date and task WBS header so the operator can
609
642
  trace a learning back to its source task.
@@ -128,6 +128,18 @@ silently incomplete (H6 shipped at 23/48 that way, with one verdict carrying an
128
128
  `acceptanceCriteria` array and still reading PASS). See `ac-style-guide.md` §
129
129
  "Verdict AC ↔ feature scenario linkage" for the id forms and evidence vocabulary.
130
130
 
131
+ **Parser contract (verify-answer-lint + `task verdict`, 0817 re-verify findings):**
132
+
133
+ 1. The requirement id cell must be the **bare** id — `| R1 | MET | … |`. Suffixes (`R1 (AC1)`) or
134
+ decoration (`**R1**`) fail the exact-match completeness check (`missing requirement row`).
135
+ 2. The AC table only opens when the header's **third** cell contains the word "evidence" — use
136
+ `| AC | Status | Evidence Type | Evidence |`. `| AC | Status | Type | Evidence |` silently
137
+ parses zero AC rows while lint still reports PASS.
138
+ 3. A behavioral AC marked `MET` with a non-executable evidence type (`static-ref`,
139
+ `manual-review`, `llm-judge`) is **downgraded to PARTIAL** by `task verdict`, making the whole
140
+ verdict PARTIAL. Use `test`/`command` (grep-based verification counts as `command`), or tag the
141
+ AC id `[non-behavior]`/`[advisory]` when executable evidence genuinely doesn't apply.
142
+
131
143
  **Invariant:** a force-done task has a non-empty `done_reason` naming the timeout, a verdict
132
144
  artifact whose AC rows cover every declared scenario, and a green lint/test run recorded in
133
145
  `## Testing`.
@@ -446,6 +446,23 @@ isolated git worktree instead of the operator's working directory. This section
446
446
  lifecycle for the sequential batch loop. Per-task worktrees and `--mode parallel` isolation stay out
447
447
  of scope (task 0142 Slice A); `--worktree --mode parallel` is rejected.
448
448
 
449
+ **Startup ordering (task 0814 R3).** Resolve the selector/status filter and run the quick
450
+ command-aware readiness (the `quickReadiness` contract in `batch-preflight.ts`) **before** creating
451
+ or adopting the tree. The admission decision is what determines whether a tree should be cut at all;
452
+ all subsequent tools, agents, task/feature writes, and run artifacts use the confirmed execution
453
+ tree's cwd. A stale or empty selector, an unsupported mode, or an invalid target creates no tree and
454
+ no marker (WT-2/WT-7), and the required Git safety checks (WT-1) still precede creation.
455
+
456
+ > **Command wiring (task 0814 R3).** The four worktree-capable commands (`dev-run`, `dev-runall`,
457
+ > `dev-refineall`, `dev-verifyall`) each call `quickReadiness` with their operation (`run`/`refine`/
458
+ > `verify`), the resolved selector/status, and the filtered-set size **before** WT-1/WT-2. The
459
+ > admission outcome gates the tree: an invalid/empty selector, unsupported mode, or a target that
460
+ > quickReadiness marks `blocked`/`invalid` creates no tree and no marker (WT-2/WT-7); a
461
+ > `needs-refinement` refine batch is still work to do (the tree is created, the gaps are the work).
462
+ > The required Git safety checks (WT-1) still precede creation, and ownership/identity is confirmed
463
+ > before any tool, agent, corpus write, or run artifact. A later failure retains the tree with
464
+ > recovery information (WT-5).
465
+
449
466
  **Single-task `dev-run` (batch of one).** `/sp:dev-run <wbs> --worktree [<name>]` runs this same
450
467
  lifecycle with a one-task loop: WT-1…WT-6 apply unchanged, the marker's `command` is `dev-run` and
451
468
  its `selector` is the `<wbs>` (so WT-6's command+selector fallback resolves the resume), and the
@@ -43,9 +43,19 @@ command, skill, script, or second workflow.
43
43
 
44
44
  ## Run setup
45
45
 
46
- 1. Resolve the command inputs, `--auto`, and any explicit `--vars`; read the selected YAML and overlay
47
- its `vars` defaults with those invocation values. An explicit non-inline executor selection
48
- chooses the subprocess workflow path.
46
+ **Shared startup contract (task 0814 R1/R3/R4/R6/R7).** The order is load-bearing: publish a compact
47
+ **bootstrap checklist** immediately (host-preparation rows, never copied workflow states); run quick
48
+ deterministic readiness (admission, not an implementation certificate) before any isolation; when
49
+ `--worktree` is valid, create/adopt and switch to the execution tree; then publish the **workflow
50
+ inventory** (the CLI todo projection) — and only then read the full YAML for comprehensive/model work.
51
+ Comprehensive checks stay at their owning boundaries and run after the plan is visible and after
52
+ isolation when requested (R7); quick readiness and plan projection dispatch zero models and execute
53
+ zero workflow actions (R8). Use the stable label helpers
54
+ (`columnLabel` / `buildStepLabels` / `labelChild` in `packages/app/src/workflow/step-reporter.ts`) for
55
+ the human/native presentation layer — labels are display addresses only, never an execution key.
56
+
57
+ 1. Resolve the command inputs, `--auto`, and any explicit `--vars` — **without reading the selected
58
+ YAML yet**. An explicit non-inline executor selection chooses the subprocess workflow path.
49
59
  2. Allocate a collision-resistant inline run id (`uuidgen`, with a timestamp/pid fallback), create
50
60
  `.spur/run/`, and use `.spur/run/<run-id>.log` as the run log.
51
61
  3. **Authoritative run identity (task 0804 R1, fail-closed).** Persist the run row through the
@@ -64,18 +74,60 @@ command, skill, script, or second workflow.
64
74
  and writes `.spur/run/<run-id>-inline-setup.json`. Seed `__runId` and `__definitionDigest`
65
75
  from that file so proof capture and bound registration verify against the persisted identity.
66
76
  A non-zero exit (missing row identity, changed definition, bundle-only install) stops the run —
67
- never continue unbound and never fabricate a PASS.
77
+ never continue unbound and never fabricate a PASS. (The delegate persists the authoritative
78
+ RUN row only — the 0808 inline record is the registration-equivalent convention below, not a
79
+ setup-time artifact-ledger insert.)
80
+
81
+ **Frozen invocation identity (task 0809 R4).** The definition parsed and hashed at setup is
82
+ the definition for the ENTIRE run: keep one invocation-time parsed definition and never
83
+ re-resolve or reseed `__definitionDigest` at record because a workflow YAML changed. Two
84
+ digests serve different purposes: `proof.digest` is the freshly captured current-input
85
+ fingerprint; `proof.definitionDigest` identifies the workflow actually interpreted (the setup
86
+ identity). A source-only edit of a TRACKED workflow YAML before capture is part of current
87
+ input proof — the Git fingerprint covers tracked working-tree files, and ignored/external
88
+ workflow files are NOT part of it (their executed identity remains the setup digest).
89
+ Post-capture changes to fingerprinted inputs invalidate that proof and take the normal
90
+ certification loop — stale post-capture evidence is refused, never reconciled. If execution
91
+ must switch to a different definition, or the executed identity cannot be established: stop
92
+ before record, preserve the run log and evidence, and start a FRESH inline run with a fresh
93
+ run id and fresh gate/review/verify certification. Never mutate old run/proof identities,
94
+ manufacture a paused engine snapshot, or call `continuePaused` for a running inline row;
95
+ task text, Git attribution and `--auto` are not consent to stamp `resumeDefinitionDigest` —
96
+ explicit consent for actual paused engine runs stays owned by task 0784.
68
97
  4. Resolve the host session id from `.spur/context/.session.json`, accepting the normalized hook key
69
98
  `session` and the Codex key `session_id` (in that order). If neither is available, allocate
70
99
  `host-session-<run-id>` and record that fallback in the log; provenance must never be blank or
71
100
  guessed from an executor subprocess.
72
- 5. Render the two-layer plan into the host todo list (task 0596):
73
- - **Layer 1** = `spur workflow show <pipeline-yaml> --format todo --json` its `steps[]`: the
74
- declared state inventory in declaration order with `initial` / `terminal` / `failure` /
75
- `pause` / `loopBack` / `conditional` markers. Mark the active state. Never re-derive this
76
- list from the YAML.
101
+ 5. **Publish the bootstrap checklist (R1).** Render host-preparation rows into the host todo list
102
+ before any expensive check: `A, Quick readiness`, `B, Prepare Git`, `C, Publish workflow plan`,
103
+ `D, Comprehensive checking`. These are host preparation, never copied workflow states; they are
104
+ not silently reassigned to unrelated workflow states when the workflow view later appears.
105
+ 6. **Quick deterministic readiness (R2), before isolation.** Evaluate `quickReadiness` from
106
+ `plugins/sp/scripts/batch-preflight.ts` with the operation, status, filtered-set size, the
107
+ matrix-selected required/present sections, and content-policy findings. Record the outcome
108
+ (runnable / needs-refinement / blocked / skipped / invalid) in the run log. Admission decision
109
+ only — no model, no full tests/lint, no live-data probe, no feature mutation, no corpus-wide
110
+ relational check.
111
+ 7. **Isolation (R3), only when `--worktree` is valid.** After quick readiness and the required Git
112
+ safety checks succeed, create/adopt and `cd` into the execution tree; confirm absolute cwd,
113
+ branch, base SHA, and ownership. An invalid/empty target, unsupported mode, ambiguous ownership,
114
+ or stale target stops without creating a tree or discarding work. All subsequent tools, agents,
115
+ corpus writes, and run artifacts use the confirmed execution tree.
116
+ 8. **Publish the workflow inventory (R4), BEFORE reading the YAML.** Resolve the selected workflow
117
+ through the same project/bundled resolver as execution and run
118
+ `spur workflow show <resolved-file> --no-logo --format todo --json`. Validate the projection with
119
+ `parseWorkflowInventory` and bind it to the run's persisted `__definitionDigest` with
120
+ `assertInventoryIdentity` — a drift or projection failure stops the run before any
121
+ comprehensive/model work, never executing with a misleading plan.
122
+ - **Layer 1** = that projection's `steps[]`: the declared state inventory in declaration order
123
+ with `initial` / `terminal` / `failure` / `pause` / `loopBack` / `conditional` markers. Mark
124
+ the active state. Never re-derive this list from the YAML.
125
+ 9. **Read the selected YAML and overlay its `vars` defaults** with the invocation values. Compare the
126
+ resolved definition identity against the bound `__definitionDigest`; a mismatch is identity drift
127
+ and fails closed (step 8 already caught projection-side drift; this re-checks the same definition
128
+ the interpreter will execute).
77
129
  - **Layer 2** = the active state's `onEnter` actions (`kind` + resolved `input`/`command`), from
78
- the YAML parsed in step 1, shown only for the active state.
130
+ the YAML read here, shown only for the active state.
79
131
  - **Refresh cadence** = stage boundaries only (when the current state changes after a transition),
80
132
  never per action.
81
133
  - **Transition reconciliation (task 0727)** = at every stage boundary the host must
@@ -84,9 +136,18 @@ command, skill, script, or second workflow.
84
136
  whether the stage ran via native subagent, host-inline execution, or the post-dispatch host
85
137
  fallback, so a run can never terminate with earlier stages stuck `in_progress` (task 0726
86
138
  ended 0/11 with precheck and implement still open).
87
- - **Source of truth** = the CLI projection for layer 1; the YAML parsed in step 1 for layer 2.
139
+ - **Source of truth** = the CLI projection for layer 1; the YAML read here for layer 2.
88
140
  Never hand-copy or hand-derive the state list into the driver, a command, a skill, or a script.
89
- 6. For task execution only, record lifecycle provenance before entering the FSM:
141
+ - **Stable labels (task 0814 R5).** Top-level declaration indexes map to A, B, Z, AA, AB …;
142
+ visible children restart numbering under their parent (A1, A2, B1 …). Labels never replace the
143
+ canonical step id, and are re-derived identically on retry/resume against the same definition.
144
+ - **Truthful progress (task 0814 R6).** Publish pending/active state before the visible item
145
+ starts, then update it immediately after the observed item completes and before the next item
146
+ starts. Keep completed, skipped, failed, blocked, paused, and unattempted outcomes distinct;
147
+ never mark skipped/conditional work completed merely to clear the UI. If the host has no
148
+ suitable native todo tool, or it fails, use an explicit Markdown fallback with the same labels
149
+ and truth — never a fabricated successful tool invocation.
150
+ 10. For task execution only, record lifecycle provenance before entering the FSM:
90
151
 
91
152
  ```bash
92
153
  spur task run-link <wbs> --source inline-full --run-id <run-id> --json
@@ -95,6 +156,28 @@ command, skill, script, or second workflow.
95
156
  This is required for the normal `testing → done` provenance guard. Planning pipelines have no
96
157
  task lifecycle link and skip this task-specific action.
97
158
 
159
+ ## Comprehensive-check retention and evidence (R7/R8)
160
+
161
+ **R7 — comprehensive checks stay at their owning boundaries.** Quick readiness and plan projection are
162
+ admission and visibility, not a substitute for the owning gates. After the plan is visible and after
163
+ isolation when requested, retain the full task/feature integrity, size, evidence-channel,
164
+ provenance, capability, dependency, quality, review, and verification gates exactly where their
165
+ owners declare them. Prefer deterministic checks; invoke semantic model work only for an identified
166
+ unresolved requirement/design/evidence question and record its reason in the run log. Reuse a
167
+ cached observation only while its relevant inputs (task content, effective status, matrix, dependency
168
+ snapshot, cwd) remain unchanged; refresh after branch/tree changes, task writes, dependency
169
+ completion, or resume. Never run a shadow copy of a workflow precheck state in the host — if a
170
+ workflow defines a precheck state, its result updates that state, not a host-side duplicate.
171
+
172
+ **R8 — matched before/after evidence, no invented claims.** Record a timestamped event trace under
173
+ `.spur/run/<run-id>-event-trace.md` (render via `renderEventTrace` in
174
+ `packages/app/src/workflow/workflow-inventory.ts`) naming event ordering, time-to-first-visible
175
+ checklist, time-to-workflow-inventory, confirmed execution cwd, and CLI/process/model invocation
176
+ counts. Quick readiness and plan projection must dispatch zero models and execute zero workflow
177
+ actions — record that as observed. Record unavailable measurements as `unknown`; never present a
178
+ simulated run as a real verified outcome. Event order and provenance are evidence; wall-clock/token
179
+ savings are observations, never fabricated pass conditions.
180
+
98
181
  ## YAML interpreter
99
182
 
100
183
  Start at `initialState`. For each current state, execute its `onEnter` actions in declaration order,
@@ -127,7 +210,13 @@ Action semantics come from the YAML and the workflow action contract:
127
210
  line to `.spur/run/<run-id>.log` naming the equivalence (artifact kind, path, verdict, digest) and
128
211
  proceeds to `spur task record`. A failed validation stops at the state and follows the failure
129
212
  contract; the step is never silently skipped. Artifact-provenance consumers read that run-log
130
- line on the inline path — there is no ledger row.
213
+ line on the inline path — there is no ledger row. The validation also includes **run/definition
214
+ identity agreement from authoritative evidence** (task 0809 R4): the verdict's `proof.runId` and
215
+ `proof.definitionDigest` must agree with the setup artifact `.spur/run/<run-id>-inline-setup.json`
216
+ and the persisted run row; if that identity is absent or conflicts, STOP — recreating a row is
217
+ not a diagnostic operation. The app-service bound-artifact fixture (which writes a real engine
218
+ ledger row) is service-level test evidence for this identity mechanics, not evidence that the
219
+ inline host writes a ledger.
131
220
 
132
221
  **Native-subagent dispatch (R2 eligibility, evaluated before each action):**
133
222
 
@@ -155,10 +244,52 @@ No token estimate, stage-size threshold, model heuristic, or configuration switc
155
244
  resolved absolute path, not the YAML's relative string, is what the dispatched agent is instructed
156
245
  to write and what post-join validation reads. Resolving once at the dispatch boundary fixes every
157
246
  surface at once; a relative path would resolve against whatever cwd the writer process happens to
158
- have. Send only: the stage id, the YAML's exact pure slash command, and
159
- `execution surface already resolved: native subagent; do not dispatch this stage again`. The WBS/path
160
- already carried by the slash command is the handoff do not paste task/session transcripts or embed
161
- machine-specific session paths. Dispatch exactly one native subagent and wait for it; the inline FSM
247
+ have.
248
+
249
+ **Dispatch payload (task 0818 R2).** Send exactly these five fields. The earlier "send only the
250
+ stage id, the slash command, and the no-recursion notice" restriction is **deliberately replaced**:
251
+ the execution-tree cwd, the Spur invocation, and the output path are all already resolved at this
252
+ boundary, and a delegate left to re-derive them re-derives them against its own cwd and PATH.
253
+
254
+ 1. The stage id.
255
+ 2. The YAML's **exact** pure slash command — unchanged, never reformulated.
256
+ 3. `execution surface already resolved: native subagent; do not dispatch this stage again`.
257
+ 4. The **confirmed execution-tree cwd** (absolute) and the **resolved absolute Spur invocation** —
258
+ `vars.spurBin`, i.e. `resolveSpurBin()`'s `<runtime> <mainModule>` form
259
+ (`apps/cli/src/workflow/resolve-spur-bin.ts`). The delegate MUST run every Spur command through
260
+ that invocation and MUST NOT rely on a bare `spur`: a competing `spur` earlier on the delegate's
261
+ PATH otherwise wins. Setting `SPUR_BIN` alone does **not** change bare-command resolution — only
262
+ using the supplied invocation does. Spur-owned scripted calls take it through the existing
263
+ `--spur-bin` flag rather than a new mechanism.
264
+ 5. The **resolved absolute output path** (`answerFile`/`expectFile`, resolved as above) and the
265
+ **owning stage's artifact contract** — for a verify stage, the compact contract below.
266
+
267
+ Nothing else: no task/session transcripts, no machine-specific session paths. The WBS/path already
268
+ carried by the slash command remains the task handoff.
269
+
270
+ **Verify-stage artifact contract.** A verify handoff names
271
+ [`code-verification/references/verdict-schema.md`](../../code-verification/references/verdict-schema.md)
272
+ as the canonical answer schema and carries this compact form verbatim:
273
+
274
+ ```text
275
+ Verdict: PASS|PARTIAL|FAIL top-level, one line
276
+ | Req | Status | Evidence | Status = MET | PARTIAL | UNMET
277
+ (N/A and PASS are NOT valid requirement statuses)
278
+ | AC | Status | Evidence Type | Evidence | Status = MET | PARTIAL | UNMET | N/A (justified)
279
+ Evidence Type = test | command | static-ref | manual-review | llm-judge | n/a
280
+ AC rows use the task's exact AC identities (verbatim `Scenario:` titles / checklist text).
281
+ A behavioral AC marked MET requires executable evidence (test | command);
282
+ static-ref or llm-judge alone cannot carry it.
283
+ ```
284
+
285
+ **Review-stage artifact contract.** A review handoff carries the Review output contract owned by
286
+ `plugins/sp/agents/super-reviewer.md` — native `P1 (blocker)` / `P2 (major)` / `P3 (minor)` /
287
+ `P4 (advisory)` priority cells and section-relative headings — **not** the verify answer schema.
288
+
289
+ This is an invocation and handoff fix, not a runtime PATH-injection subsystem: it makes no guarantee
290
+ about arbitrary bare commands in host shells or agent-generated shells.
291
+
292
+ Dispatch exactly one native subagent and wait for it; the inline FSM
162
293
  must not advance actions or guards concurrently (one writer at a time). After join, validate
163
294
  `answerFile`, `expectFile`, `requireDiff`, task scope, and the action's error policy from the shared
164
295
  filesystem — a subagent success message is not evidence. On success append exactly: