@gobing-ai/spur 0.4.14 → 0.4.16
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/config/config.global.yaml +21 -8
- package/config/decisions/executor.yaml +53 -0
- package/config/decisions/task-pipeline.yaml +44 -28
- package/config/pipeline-budgets.json +0 -14
- package/config/workflow-candidates.json +18 -0
- package/config/workflows/feature-lifecycle.yaml +9 -16
- package/config/workflows/idea-pipeline.yaml +158 -740
- package/config/workflows/task-pipeline.yaml +66 -54
- package/config/workflows/wrapup-pipeline.yaml +91 -623
- package/package.json +11 -10
- package/plugins/sp/README.md +9 -5
- package/plugins/sp/agents/expert-spur.md +3 -0
- package/plugins/sp/agents/super-planner.md +5 -1
- package/plugins/sp/agents/super-reviewer.md +43 -12
- package/plugins/sp/commands/dev-fixall.md +7 -2
- package/plugins/sp/commands/dev-idea.md +15 -6
- package/plugins/sp/commands/dev-plan.md +1 -1
- package/plugins/sp/commands/dev-pr-review.md +6 -6
- package/plugins/sp/commands/dev-run.md +3 -0
- package/plugins/sp/commands/dev-runall.md +6 -3
- package/plugins/sp/commands/dev-verify.md +1 -1
- package/plugins/sp/commands/dev-wrap.md +1 -1
- package/plugins/sp/commands/dev-wrapall.md +4 -4
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/skills/code-implementation/SKILL.md +8 -8
- package/plugins/sp/skills/code-improvement/SKILL.md +3 -3
- package/plugins/sp/skills/code-review/references/verification-before-completion.md +5 -4
- package/plugins/sp/skills/code-verification/SKILL.md +4 -4
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +27 -11
- package/plugins/sp/skills/functional-review/SKILL.md +1 -1
- package/plugins/sp/skills/functional-review/references/verdict-schema.md +1 -1
- package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
- package/plugins/sp/skills/pr-reviewing/SKILL.md +36 -18
- package/plugins/sp/skills/spec-decomposition/references/decomposition.md +2 -1
- package/plugins/sp/skills/spur-check/SKILL.md +1 -1
- package/plugins/sp/skills/spur-cli/SKILL.md +23 -2
- package/plugins/sp/skills/spur-cli/references/agent.md +12 -0
- package/plugins/sp/skills/spur-cli/references/builder.md +2 -2
- package/plugins/sp/skills/spur-cli/references/decision/lifecycle.md +166 -0
- package/plugins/sp/skills/spur-cli/references/decision.md +146 -16
- package/plugins/sp/skills/spur-cli/references/features.md +19 -0
- package/plugins/sp/skills/spur-cli/references/rules.md +2 -0
- package/plugins/sp/skills/spur-cli/references/tasks.md +14 -1
- package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +1 -1
- package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +3 -2
- package/plugins/sp/skills/spur-cli/references/workflows.md +9 -0
- package/plugins/sp/skills/spur-composer/SKILL.md +20 -1
- package/plugins/sp/skills/spur-dev/SKILL.md +16 -16
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +2 -1
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +2 -2
- package/plugins/sp/skills/spur-dev/references/decision-points.md +97 -0
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +18 -18
- package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +1 -1
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +19 -10
- package/plugins/sp/skills/spur-dev/references/execution-parallel-isolation.md +4 -4
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +41 -29
- package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +34 -2
- package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +4 -4
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +3 -3
- package/plugins/sp/skills/spur-dev/references/gate-checklists.md +3 -2
- package/plugins/sp/skills/spur-dev/references/glossary.md +12 -3
- package/plugins/sp/skills/spur-dev/references/planning-workflow.md +7 -6
- package/plugins/sp/skills/spur-doctor/SKILL.md +23 -0
- package/plugins/sp/skills/wayfinder/SKILL.md +11 -1
- package/spur.js +25617 -24290
- package/web/_astro/{BoardApp.Bjdp3XWV.js → BoardApp.CC7Mwswv.js} +65 -65
- package/web/_astro/{BoardApp.DCDZxLlQ.js → BoardApp.mWyrWCAR.js} +1 -1
- package/web/_astro/{TaskDetail.B3vBxynO.js → TaskDetail.CtAXuiv8.js} +1 -1
- package/web/_astro/{arc.DcuHTB_T.js → arc.Duf4u60i.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.ClOFWBON.js → architectureDiagram-3BPJPVTR.JoymtqxN.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.otYyr7Zb.js → blockDiagram-GPEHLZMM.BvmhcioC.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.BCjpc9LP.js → c4Diagram-AAUBKEIU.CfaWkgoQ.js} +1 -1
- package/web/_astro/channel.DtEPXXcH.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.D5Wpnpt_.js → chunk-2J33WTMH.B7uR02cD.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.DkQGtWNz.js → chunk-4BX2VUAB.SwiEauYR.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.B7dqjAip.js → chunk-55IACEB6.6ZRCK8PO.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.BDQvnKE2.js → chunk-727SXJPM.Cxra_G3N.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.D92doBX5.js → chunk-AQP2D5EJ.Cxd7gZeX.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.C968oI5G.js → chunk-FMBD7UC4.DCLhFkVc.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.AkkYC1bY.js → chunk-ND2GUHAM.B9AmKcv6.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.sCc-rKKo.js → chunk-QZHKN3VN.DOjCvl6S.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.pOQ9u0mY.js → classDiagram-4FO5ZUOK.BMiT_mNf.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.pOQ9u0mY.js → classDiagram-v2-Q7XG4LA2.BMiT_mNf.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.CRaeD6FY.js → cose-bilkent-S5V4N54A.mLBCEGjI.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.BiCPBu54.js → cynefin-OW5HDTMX.CjDAY0qn.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.C1-q3vkT.js → dagre-BM42HDAG._G_sP8fP.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.BSVOv30O.js → diagram-2AECGRRQ.39OcfSuz.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.CHMkjJ-V.js → diagram-5GNKFQAL.D7v_eNC4.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.CKY9M564.js → diagram-KO2AKTUF.Da1x-lhg.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.B9yNJiTP.js → diagram-LMA3HP47.C8EnzbEb.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.Dk8AUGsk.js → diagram-OG6HWLK6.DPnBj69F.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.BQHR89TZ.js → erDiagram-TEJ5UH35.CXMu2TIh.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.oNkWVgoK.js → flowDiagram-I6XJVG4X.ZklePVtQ.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.Kz2U2nu9.js → ganttDiagram-6RSMTGT7.BhYOkdqk.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.DHIZ_wPq.js → gitGraphDiagram-PVQCEYII.CADyX8a1.js} +1 -1
- package/web/_astro/{infoDiagram-5YYISTIA.D0NJLcv9.js → infoDiagram-5YYISTIA.BsdmwjHt.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.CFEfTWRG.js → ishikawaDiagram-YF4QCWOH.CzjZ3Crd.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.Dc7IE7I4.js → journeyDiagram-JHISSGLW.Bxj-ZH_t.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.D5v0xO9k.js → kanban-definition-UN3LZRKU.Cbg3wVvX.js} +1 -1
- package/web/_astro/{linear.wR5KzXnE.js → linear.DJNUrBI9.js} +1 -1
- package/web/_astro/{mermaid.core.BDQ2FoPd.js → mermaid.core.DVHQV3SF.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.W6_INsia.js → mindmap-definition-RKZ34NQL.DyomosRU.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.61ihbgkK.js → pieDiagram-4H26LBE5.DajtFknN.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.B5lEpFLo.js → quadrantDiagram-W4KKPZXB.Bjq6SjGe.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.CmhVBVX0.js → requirementDiagram-4Y6WPE33.ubBVqGLP.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.D7Vvj9Wf.js → sankeyDiagram-5OEKKPKP.I4q46xd-.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.B1vPLixM.js → sequenceDiagram-3UESZ5HK.DsCgZIa8.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.BnACmrGi.js → stateDiagram-AJRCARHV.DcYjYSqT.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.CW4pnmc3.js → stateDiagram-v2-BHNVJYJU.Dt8yPqiS.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.CkzMCPnC.js → timeline-definition-PNZ67QCA.0YTkoa5F.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.CY4aNdAR.js → vennDiagram-CIIHVFJN.BNl0l1hs.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.BtoU9UFk.js → wardleyDiagram-YWT4CUSO.BYSX6cfn.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6._9ijUUAs.js → xychartDiagram-2RQKCTM6.DzxxpixK.js} +1 -1
- package/web/index.html +1 -1
- package/worker/laya_worker.py +219 -0
- package/config/workflows/feature-verification.yaml +0 -98
- package/config/workflows/pr-review.yaml +0 -209
- package/config/workflows/wayfinder-resolution.yaml +0 -302
- package/plugins/sp/skills/wayfinder/references/pipeline-resolution.md +0 -30
- package/web/_astro/channel.qgOLXjI_.js +0 -1
|
@@ -147,7 +147,7 @@ must not be changed without updating the backing skill.
|
|
|
147
147
|
- **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.
|
|
148
148
|
- **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.
|
|
149
149
|
- **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).
|
|
150
|
-
- **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`
|
|
150
|
+
- **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 `spur task record` close 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.
|
|
151
151
|
- **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).
|
|
152
152
|
- **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.
|
|
153
153
|
- **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.
|
|
@@ -159,7 +159,7 @@ must not be changed without updating the backing skill.
|
|
|
159
159
|
- **Inputs:** `<wbs>` (required). `--mode <full|implement>` selects the execution mode. `implement` invokes `sp:code-implementation` inline by default. Interactive `full` resolves the selector uniformly (task 0687): omit ≡ explicit `--agent inline`; full mode reads `task-pipeline.yaml` and drives its actions/guards in the host session — host-controlled and non-subprocess, with 0508 eligibility applying to the resolved-inline selector (eligible `agent.run` stages dispatch once to a native subagent, host fallback)). `--agent auto`, a name, or headless invocation launches the workflow subprocess. `--agent <inline|auto|name>` selects the execution surface (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--auto` skips the HITL approve gate / confirmations and propagates down the `--next` chain. `--next` controls chaining only and never changes the mode; a pipeline implement stage must invoke `/sp:dev-run <wbs> --mode implement`. On implement success with `--next`, transition `todo → wip → testing` through the FSM (guards honored — no `--no-lifecycle`) + chain to `/sp:dev-verify <wbs> --auto --next`. On a guard failure, stop as review-pending. **Partial-deliverable rule:** if the task ships only part of its requirements (e.g. an R1/R2 split with the rest in a follow-up task), the `## Solution` section must state that explicitly and the verify verdict will record the scope. `--worktree [<name>]` runs the full pipeline inside an isolated git worktree (create or reuse; FF-merge on success, retain on failure) — the batch lifecycle in [execution-batch.md § Worktree isolation](execution-batch.md#worktree-isolation---worktree-name) applied to a batch of one; rejected with `--mode implement`. `--no-summary` skips the [execution summary](#execution-summary) printed after a full-mode run. `--wrap` hands off to `/sp:dev-wrap <wbs>` after the main step; the `--agent` selector is preserved into that handoff when supplied (omission remains omission), and the wrap hop reports its own trigger-3 subprocess override per the wrap contract.
|
|
160
160
|
- **Backing:** `sp:spur-dev` skill — `run` operation for the full pipeline (the spine drives it); `sp:code-implementation` competency skill for the implement step (the spine dispatches to it).
|
|
161
161
|
- **Modes:**
|
|
162
|
-
- **`full`** (default): Drive the full pipeline — precheck → implement →
|
|
162
|
+
- **`full`** (default): Drive the full pipeline — precheck → implement → gate ⇄ remediate → review → done, with the repair, stop and approval routes taken from decision rows ([decision-points.md](decision-points.md)). Interactive omit/inline runs `spur workflow run task-pipeline.yaml --vars '{"wbs":"<wbs>","executor":"host"}'` and performs each returned work item (eligible stages may use a native subagent); explicit/headless executor selection runs the same definition without the `executor` var (with `profile: auto` when `--auto`). Both monitor/surface HITL and preserve the YAML gates. `--next` never changes this mode.
|
|
163
163
|
- **`implement`** (explicit `--mode implement` only): Execute only the implement step. Read the task's `## Requirements` / `## Design` / `## Plan`, write the code that satisfies them, author the `## Solution` change-map section (file:line + what/why per changed file) via `spur task update <wbs> --section Solution --from-file`. This is the implement step the pipeline calls — it is NOT the pipeline driver. With `--next`: on success, transition `todo → wip → testing` through the FSM (guards honored — no `--no-lifecycle`) + chain to `/sp:dev-verify <wbs> --auto --next`; on a guard failure, stop as review-pending. **Partial-deliverable rule:** if the task ships only part of its requirements (e.g. an R1/R2 split with the rest in a follow-up task), the `## Solution` and `## Review` sections MUST carry a `⚠️ PARTIAL` marker naming the deferred part and the follow-up WBS — see `plugins/sp/commands/dev-run.md` → "Section ownership".
|
|
164
164
|
- **Delegation:** `Skill(skill="sp:spur-dev", args="run $ARGUMENTS")` for both full-mode paths (the `executor` var picks host session vs child process); `Skill(skill="sp:code-implementation", args="$ARGUMENTS")` for implement mode.
|
|
165
165
|
|
|
@@ -366,13 +366,13 @@ check receipt (`receipt.runId === runId`), otherwise `n/a (<reason>)`. Any value
|
|
|
366
366
|
|
|
367
367
|
### 6. plan
|
|
368
368
|
|
|
369
|
-
- **Purpose:** Plan a feature from a description — intake → feature create → AC generation →
|
|
369
|
+
- **Purpose:** Plan a feature from a description — intake → feature create → AC generation → decomposition → batch-create (with **Design by default**).
|
|
370
370
|
- **Inputs:** `"<description>"` (required). `--feature <id>` links to an existing feature. `--parent <feature-id>` nests under a parent. Omitted/`inline` drives `idea-pipeline.yaml` in the host session; `auto` or a name launches the async workflow worker. **Design package flags (unified with `/sp:dev-idea`):**
|
|
371
371
|
- **Default:** author task `design` on every batch item + feature satellite when the seam heuristic fires (**ties lean design**). There is **no** `--design` force flag.
|
|
372
372
|
- `--skip-design` — skip feature satellite **and** omit task `design` fields (scaffold only; refine fills later). Sole design opt-out.
|
|
373
373
|
- `--auto` — accept the recommendation at every operator gate, taste gates included (same contract as § 16 idea).
|
|
374
374
|
- **Backing:** `sp:spur-dev` skill, `plan` operation. Stage floor: the `planner` role per [`roles.md`](../../../references/roles.md) — this file names roles, never tiers (0538 R4).
|
|
375
|
-
- **Behavior:** Clarify scope → `spur feature create` → author BDD AC →
|
|
375
|
+
- **Behavior:** Clarify scope → `spur feature create` → author BDD AC → decompose into task-batch JSON **including `design` (unless `--skip-design`)**. The pipeline then runs `spur feature check` on the recorded AC (`ac-generate`) and `spur task batch-create` (`batch-create-run`) as deterministic steps that route on their recorded result — neither is an operator gate. Design package details: [planning-workflow.md](planning-workflow.md) Step 5.5.
|
|
376
376
|
- **Delegation:** `Skill(skill="sp:spur-dev", args="plan $ARGUMENTS")`
|
|
377
377
|
|
|
378
378
|
### 7. docs
|
|
@@ -489,10 +489,10 @@ gate commands, pending questions and approval requirements.>
|
|
|
489
489
|
|
|
490
490
|
### 14. wrap
|
|
491
491
|
|
|
492
|
-
- **Purpose:** Wrap up a single completed task — capture learnings, record metrics, sync docs, and optionally
|
|
492
|
+
- **Purpose:** Wrap up a single completed task — capture learnings, record metrics, sync docs, and optionally clean up the branch.
|
|
493
493
|
- **Inputs:** `<wbs>` (required, positional). `--agent <inline|auto|name>` names the wrap's model-bearing executor (default: `inline`, resolving identically when omitted; task 0687); wrap is workflow-backed (headless), so omit ≡ explicit `inline` (task 0687): tier substitution under objective trigger 3 (durable auditable run record required) plus one warning naming the substituted executor. `auto` tier-resolves an executor, and a name pins that executor into `vars.agent` (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--auto` skips objective confirmations (the branch-cleanup HITL gate still pauses — irreversible). `--merge` triggers branch cleanup (irreversible HITL gate).
|
|
494
494
|
- **Backing:** `spur workflow run wrapup-pipeline.yaml` — direct workflow invocation (no backing skill; the pipeline IS the procedure).
|
|
495
|
-
- **Behavior:** Resolves the executor (`agent.default` for omit/`inline`, tier-resolved for `auto`, unchanged for a name), emits a pre-dispatch notice naming the subprocess override — `execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: <selector>`, `executor: <resolved>` — then builds `--vars '{"tasks":"[\"<wbs>\"]","agent":"<resolved>","profile":"interactive|auto","merge":"true|false"}'` and invokes the wrapup pipeline. The pipeline runs: task-resolve → doc-sync → learnings-validate → learnings-append → doc-tripwire → metrics-record → (
|
|
495
|
+
- **Behavior:** Resolves the executor (`agent.default` for omit/`inline`, tier-resolved for `auto`, unchanged for a name), emits a pre-dispatch notice naming the subprocess override — `execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: <selector>`, `executor: <resolved>` — then builds `--vars '{"tasks":"[\"<wbs>\"]","agent":"<resolved>","profile":"interactive|auto","merge":"true|false"}'` and invokes the wrapup pipeline. The pipeline runs: task-resolve → doc-sync → learnings-validate → learnings-append → doc-tripwire → metrics-record → (branch-cleanup) → done. `doc-tripwire` (1037) runs the TRUSTED CONFIG ONLY `docTripwireCmd` over the still-uncommitted wrap diff after the doc-sync exits converge — the default runs `bun run test-repo-wide` only when `package.json` declares the script (a no-op in other projects); override it via `--vars`, and an empty string disables the check while still recording PASS; a FAIL fails the wrap with already-written learnings/docs preserved. Task and feature statuses are NOT mutated. Branch cleanup is an irreversible HITL gate that always pauses, even under `--auto`.
|
|
496
496
|
- **Vars string typing:** `tasks` is a JSON-encoded **string**, not a JSON array — `spur workflow run --vars` accepts only string values (`--vars values must be strings`); the pipeline's guards parse the string with `jq length`. `jq -nc` guarantees the shape:
|
|
497
497
|
|
|
498
498
|
```bash
|
|
@@ -505,15 +505,15 @@ gate commands, pending questions and approval requirements.>
|
|
|
505
505
|
|
|
506
506
|
### 15. wrapall
|
|
507
507
|
|
|
508
|
-
- **Purpose:** Wrap up a batch of completed tasks — capture learnings, record metrics, sync docs,
|
|
509
|
-
- **Inputs:** `--since <iso-date>` filters done tasks by frontmatter `updated_at >= date` (v1 approximation). `--feature <id>` selects all tasks under a feature
|
|
508
|
+
- **Purpose:** Wrap up a batch of completed tasks — capture learnings, record metrics, sync docs, and optionally clean up branches.
|
|
509
|
+
- **Inputs:** `--since <iso-date>` filters done tasks by frontmatter `updated_at >= date` (v1 approximation). `--feature <id>` selects all tasks under a feature; it no longer advances the feature — wrap-up owns post-task knowledge work only (1249 R1/R5), so follow the batch with `spur feature sync <id>` if a transition is wanted. `--status <s>` (default: `done`) filters by task status. `--agent <inline|auto|name>` names the wrap's model-bearing executor (default: `inline`, resolving identically when omitted; task 0687); wrap is workflow-backed (headless), so omit ≡ explicit `inline` (task 0687): tier substitution under objective trigger 3 (durable auditable run record required) plus one warning naming the substituted executor. `auto` tier-resolves an executor, and a name pins that executor into `vars.agent` (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--auto` skips objective confirmations. `--merge` triggers branch cleanup (irreversible HITL gate).
|
|
510
510
|
- **Backing:** `spur workflow run wrapup-pipeline.yaml` — direct workflow invocation.
|
|
511
|
-
- **Behavior:** Resolves the task list via `spur task list --json` (filtered by `--feature`, `--since`, `--status`), resolves the executor (omission and explicit `--agent inline` tier-substitute identically with a warning per task 0687, `auto` tier-resolves, a name pins), emits a pre-dispatch notice naming the subprocess override — `execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: <selector>`, `executor: <resolved>` — then builds `--vars '{"tasks":"[...]","
|
|
511
|
+
- **Behavior:** Resolves the task list via `spur task list --json` (filtered by `--feature`, `--since`, `--status`), resolves the executor (omission and explicit `--agent inline` tier-substitute identically with a warning per task 0687, `auto` tier-resolves, a name pins), emits a pre-dispatch notice naming the subprocess override — `execution surface: subprocess`, `reason: trigger 3 — durable auditable run record required`, `requested agent: <selector>`, `executor: <resolved>` — then builds `--vars '{"tasks":"[...]","agent":"<resolved>","profile":"interactive|auto","merge":"true|false"}'` and invokes the wrapup pipeline. The pipeline runs the same states as `wrap` — including the `doc-tripwire` hop (1037), whose TRUSTED CONFIG ONLY `docTripwireCmd` runs the repo-wide tripwires over the still-uncommitted wrap diff and can be overridden or disabled (empty string) via `--vars` — but with the full task list. Task and feature statuses are NOT mutated. Branch cleanup is an irreversible HITL gate.
|
|
512
512
|
- **Vars string typing:** `tasks` is a JSON-encoded **string**, not a JSON array — `--vars` values must be strings (the CLI rejects raw arrays); `jq -nc` passes the array text through as a string value:
|
|
513
513
|
|
|
514
514
|
```bash
|
|
515
|
-
VARS=$(jq -nc --arg tasks "$TASKS" --arg
|
|
516
|
-
'{tasks:$tasks,
|
|
515
|
+
VARS=$(jq -nc --arg tasks "$TASKS" --arg agent "$AGENT" --arg profile "$PROFILE" --arg merge "$MERGE" \
|
|
516
|
+
'{tasks:$tasks, agent:$agent, profile:$profile, merge:$merge}')
|
|
517
517
|
spur workflow run wrapup-pipeline.yaml --vars "$VARS"
|
|
518
518
|
```
|
|
519
519
|
|
|
@@ -538,7 +538,7 @@ gate commands, pending questions and approval requirements.>
|
|
|
538
538
|
fails the run when that file is empty or missing, and every model-bearing stage prompt treats
|
|
539
539
|
it as the authoritative ask (R2).
|
|
540
540
|
- **Backing:** `idea-pipeline.yaml` on the host executor (`vars.executor: host`, advanced by `spur workflow continue`) for omitted/`inline`, or `spur workflow run idea-pipeline.yaml --async` for `auto`/name.
|
|
541
|
-
- **Behavior:** Builds vars from the table above and drives the idea pipeline. Flow: discovery → **idea-eval** (taste; reject → cancelled) → feature-create → ac-generate →
|
|
541
|
+
- **Behavior:** Builds vars from the table above and drives the idea pipeline. Flow: discovery → **idea-eval** (taste; reject → cancelled) → feature-create → ac-generate → system-design (conditional) → design-approval (taste) → decompose → batch-create-run (`--skip-ready`) → ready-prepare (ready checklist per created task + ready-evidence sidecar, 0788) → handoff-finalize → handoff. STOPS at handoff — no task execution, no pipeline nesting. Headless runs use one `trace --follow`; cancellation is reported stopped only when `workflow cancel --json` returns `killed: true`.
|
|
542
542
|
- **Delegation:** Host executor (this session answers each work item) by default; explicit executor selection uses the async workflow worker.
|
|
543
543
|
- **Idea-evaluation gate:** After discovery, operator reviews `.spur/run/idea-eval-report.md` ([idea-evaluation.md](idea-evaluation.md)). Approve continues; reject/cancel → no feature. Under `--auto`, follows the report's recommendation (`drop` → cancelled; missing recommendation → pauses). Enhanced idea is a sidecar — `vars.idea` is not overwritten.
|
|
544
544
|
- **Design package (`--skip-design` only):**
|
|
@@ -569,7 +569,7 @@ These define their procedure directly in the command file. No `Skill()` delegati
|
|
|
569
569
|
is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent reasoning.
|
|
570
570
|
|
|
571
571
|
**Gate ownership.** A project quality gate (`spur self exec autofix|check|lint`, typecheck, tests,
|
|
572
|
-
rule runs) runs only where an operation's own contract names it: the pipeline `
|
|
572
|
+
rule runs) runs only where an operation's own contract names it: the pipeline `gate` state
|
|
573
573
|
(`run`/`runall`), `fixall`, `gtd`, `fixgha`, `unit`, and the `--check <cmd>` loops. The scribe
|
|
574
574
|
operations — `changelog`, `gitmsg`, `handover`, `job-dump` — produce text or a commit, not code, so
|
|
575
575
|
they run **no gate by default**, and a generic "verify before you finish" rule from `AGENTS.md` or
|
|
@@ -683,7 +683,7 @@ host instructions does not add one. An opt-in gate is explicit: `gitmsg --check
|
|
|
683
683
|
### 10. fixall
|
|
684
684
|
|
|
685
685
|
- **Purpose:** Fix all lint, type, and test errors systematically across the working tree.
|
|
686
|
-
- **Inputs:** `--scope <path>` (default: entire working tree) — limits fixes to a file or directory. `--gate-log <path>` (R3, task 0482) — before fixing, read this captured validation-run log and start at the `file:line` anchors its findings name, rather than re-deriving the failure from a fresh gate run. `--findings <anchors>` (R3, task 0482) — space-separated `file:line` anchors already extracted from that log by the `
|
|
686
|
+
- **Inputs:** `--scope <path>` (default: entire working tree) — limits fixes to a file or directory. `--gate-log <path>` (R3, task 0482) — before fixing, read this captured validation-run log and start at the `file:line` anchors its findings name, rather than re-deriving the failure from a fresh gate run. `--findings <anchors>` (R3, task 0482) — space-separated `file:line` anchors already extracted from that log by the `gate` state; when present these ARE the failing set, so fix them in order and do not run the gate to discover what broke.
|
|
687
687
|
- **Backing:** `inline` — lint + test fix loop.
|
|
688
688
|
- **Behavior:** 0. **Start at the anchors, never at a discovery run.** If `--findings <anchors>` is given, that space-separated `file:line` list IS the failing set — open those locations first, in order, and fix them; do not run the gate to find out what broke. If only `--gate-log <path>` is given, read that log first and identify the failing findings (lint/test errors with their `file:line` anchors) before running the loop — the captured log is the authoritative source. Either way the first action of this hop is a read, not a gate run (R3, task 0482).
|
|
689
689
|
1. Inspect the project's formatter command, then settle formatter-only diffs. Without `--scope`, use the project formatter (here `spur self exec format`). With `--scope`, use a formatter invocation whose only path operands are inside the selected scope — for Biome, `bunx biome check --write "$SCOPE"`. Never append a path to a script already containing `.`: `biome check . --write <path>` still writes across the repository. Preserve quoted paths and apply the same scope to every later formatting pass. If no scoped formatter is available, report that limitation and leave out-of-scope files untouched. Here `spur self exec lint` checks formatting without rewriting it and also runs typecheck; formatting errors fail that check.
|
|
@@ -695,9 +695,9 @@ host instructions does not add one. An opt-in gate is explicit: `gitmsg --check
|
|
|
695
695
|
7. If tests are green, proceed to the applicable standalone confirmation or pipeline handoff below.
|
|
696
696
|
8. **Test fix loop:** for each in-scope failure, diagnose (test bug vs implementation bug), apply the fix, re-run the **failing test only** (`bun test <file> --test-name-pattern "<test>"`). Report outside-scope blockers without editing them. Do NOT re-run the full suite per fix — it is the dominant loop cost (task 0436 R2).
|
|
697
697
|
9. **Confirming run — standalone invocation only (at most once).** After all fixes, repeat the scope-safe formatting invocation from step 1, then run the selected validation command **at most once** to confirm (here the default project gate is `spur self exec check`). If it passes, the hop is done. **Skip this step entirely when `--gate-log` is set** (see step 10) — under the pipeline nothing consumes its verdict.
|
|
698
|
-
10. **Pipeline-awareness (R4, task 0483; confirming run dropped 2026-08-31).** `--gate-log` is set only by the pipeline's `
|
|
698
|
+
10. **Pipeline-awareness (R4, task 0483; confirming run dropped 2026-08-31).** `--gate-log` is set only by the pipeline's `remediate` hop, so treat it as the pipeline signal. There, the `gate` state's recheck visit runs the full `${vars.qualityGateCmd}` gate immediately after this hop returns — that is the **deciding** run, the only one that writes PASS to `.spur/run/<wbs>-test-gate.status`. A confirming run inside this hop decides nothing and costs a second full gate (~105 s here) to answer a question the gate recheck is about to answer anyway. So under `--gate-log`: **run no full gate at all.** Your self-check is what step 8 already gives you — the failing tests you re-ran individually — plus **one `spur self exec lint`** (~7 s: Biome + typecheck) to catch type or lint breakage your fixes introduced. Then return and let the gate recheck judge. It opens with the same cheap `${vars.gateProbeCmd}` probe, so a still-red tree is caught in seconds rather than by a full suite. Historical anti-pattern this replaces: 0482 ran the gate 3× plus a standalone `bun run test`, and the recheck then ran it a 5th time.
|
|
699
699
|
11. Report: list what was fixed (file + one-line summary per fix). If any error could not be resolved, report it explicitly — do not suppress.
|
|
700
|
-
- **Invariants:** Never bypass with `--no-verify`, `--force`, or new `biome-ignore`/`eslint-disable` suppressions. Never skip or `.skip` a test to make the suite green. Fix the root cause, not the symptom. Here lint checks formatting and types; it does not prove that the full test gate passed. Keep every write inside `--scope`. **Never re-run the full gate more than once per confirming pass** (R4) — use targeted probes during the fix loops and let the pipeline's `
|
|
700
|
+
- **Invariants:** Never bypass with `--no-verify`, `--force`, or new `biome-ignore`/`eslint-disable` suppressions. Never skip or `.skip` a test to make the suite green. Fix the root cause, not the symptom. Here lint checks formatting and types; it does not prove that the full test gate passed. Keep every write inside `--scope`. **Never re-run the full gate more than once per confirming pass** (R4) — use targeted probes during the fix loops and let the pipeline's `gate` recheck be the deciding run.
|
|
701
701
|
- **MANDATORY Exit Condition — standalone only.** At step 9, execute the following once; do not add another confirming run:
|
|
702
702
|
1. Run validation command: `eval "$VALIDATION_CMD"`
|
|
703
703
|
2. Capture exit code: `EXIT_CODE=$?`
|
|
@@ -706,7 +706,7 @@ host instructions does not add one. An opt-in gate is explicit: `gitmsg --check
|
|
|
706
706
|
|
|
707
707
|
If EXIT_CODE != 0: NOT completed. Continue the bounded fix loop for in-scope failures; report outside-scope blockers.
|
|
708
708
|
|
|
709
|
-
**Pipeline exit condition (`--gate-log` set):** return the fixes and the targeted-test/lint evidence from step 10 to `
|
|
709
|
+
**Pipeline exit condition (`--gate-log` set):** return the fixes and the targeted-test/lint evidence from step 10 to the `gate` recheck. Do not run the standalone validation command or claim a full-gate PASS; the recheck owns that verdict.
|
|
710
710
|
|
|
711
711
|
**Hallucination Red Flags — STOP if you think:**
|
|
712
712
|
- "The errors look fixed" — check exit code, not appearance
|
|
@@ -735,7 +735,7 @@ host instructions does not add one. An opt-in gate is explicit: `gitmsg --check
|
|
|
735
735
|
└─────────────────────────────────────────────────┘
|
|
736
736
|
```
|
|
737
737
|
|
|
738
|
-
The 7 phases describe standalone execution: Phases 1–2 capture the gate, Phase 3 settles auto-fixable formatting within scope, Phases 4–6 are the per-group root-cause fix loops, Phase 7 is the final verification run. With `--gate-log`, use the supplied evidence instead of capturing the gate again, and hand off to `
|
|
738
|
+
The 7 phases describe standalone execution: Phases 1–2 capture the gate, Phase 3 settles auto-fixable formatting within scope, Phases 4–6 are the per-group root-cause fix loops, Phase 7 is the final verification run. With `--gate-log`, use the supplied evidence instead of capturing the gate again, and hand off to the `gate` recheck instead of running Phase 7's full validation.
|
|
739
739
|
|
|
740
740
|
- **Fix Priority:**
|
|
741
741
|
|
|
@@ -15,7 +15,7 @@ Read at Step 5 and once at batch end (task 1128 R1).
|
|
|
15
15
|
When the batch finishes — clean (all `done`), halted (default failure policy), parked (`paused`:
|
|
16
16
|
one or more tasks sit on an operator question (escalate, 0933) or an approval gate), or aborted
|
|
17
17
|
(cycle / unknown selector) — emit a structured report. The report is the orchestrator's sole
|
|
18
|
-
output; it does not mutate the corpus (the pipeline's `
|
|
18
|
+
output; it does not mutate the corpus (the pipeline's `done` state already recorded per-task
|
|
19
19
|
results). A `paused` task is non-terminal — the report marks it `paused` (never `done`) and names
|
|
20
20
|
the resume command. Unless `--no-summary`, follow it with the measured
|
|
21
21
|
[execution summary](dev-operations.md#execution-summary), one `--progress <wbs>=<file>` per attempted run.
|
|
@@ -112,7 +112,8 @@ bun run apps/cli/src/index.ts feature check <id> --strict --json
|
|
|
112
112
|
live tasks (a warning in `FeatureCheckService` until `done`); `--strict` elevates both to error,
|
|
113
113
|
so they are reported verbatim but do **not** abort the batch; every other error finding (L1–L3
|
|
114
114
|
structural, `L4.malformed-verdict-artifact`, `L4.uncovered-feature-scenario`) still aborts. The
|
|
115
|
-
|
|
115
|
+
feature-lifecycle done-boundary gate (reached via `spur feature sync <id>`, the forward hop from
|
|
116
|
+
task-pipeline's done close) enforces scenario verification after the batch runs, so pre-run
|
|
116
117
|
unverified scenarios and incomplete tasks are transient, not defects (dogfood 2026-08-11,
|
|
117
118
|
feature I2; 2026-10-08, feature H1). Extend the set by editing that constant, never this prose.
|
|
118
119
|
- **Auto-repairs are reported.** Structural repairs applied by `--fix` are listed under
|
|
@@ -461,14 +462,12 @@ in next-router; this only maps status → primary TABLE A hop for recovery.
|
|
|
461
462
|
|
|
462
463
|
### 3.3c Feature-sync retry suppression (task 0411; 1004 R3)
|
|
463
464
|
|
|
464
|
-
During a batch, the per-task `
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
this, not the engine.
|
|
465
|
+
During a batch, the per-task `done` state invokes feature status sync. When a feature is
|
|
466
|
+
L4-gate-blocked (e.g. not all linked tasks are `done`), the identical blocked proposal repeats on
|
|
467
|
+
every call with no intervening input change. The service fixes this, not the engine.
|
|
468
468
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
`FeatureService.syncFeature` implementation:
|
|
469
|
+
`task-pipeline.yaml`'s `done` state invokes `spur feature sync <feature-id> --json` directly —
|
|
470
|
+
retry suppression lives inside the `FeatureService.syncFeature` implementation:
|
|
472
471
|
|
|
473
472
|
1. On a **blocked** result (`gateBlocked` checked first — a partial hop can have `applied: true`
|
|
474
473
|
while still gate-blocked — then an unapplied from≠to deferral), the service persists
|
|
@@ -483,7 +482,7 @@ invoke `spur feature sync <feature-id> --json` directly — retry suppression li
|
|
|
483
482
|
never reads or writes the state.
|
|
484
483
|
|
|
485
484
|
**Batch driver contract:** the orchestrator does **nothing extra** — the suppression lives inside
|
|
486
|
-
the pipeline's `
|
|
485
|
+
the pipeline's `done` state. The driver still
|
|
487
486
|
launches `task-pipeline.yaml` verbatim (R4.1). Suppression is transparent: the sync emits the same
|
|
488
487
|
`FeatureSyncResult` JSON shape (`suppressed: true` added on replay), so downstream report logic is
|
|
489
488
|
unchanged. The only observable difference is fewer redundant `feature sync` derivations.
|
|
@@ -531,6 +530,16 @@ belongs to a subagent or the operator, not to the batch controller's report loop
|
|
|
531
530
|
By default, the **first** pipeline failure halts the batch. Remaining tasks in the plan are reported
|
|
532
531
|
as `not-attempted`. The report lists succeeded, failed, and not-attempted tasks.
|
|
533
532
|
|
|
533
|
+
**Run-failed / task-done (observed 2026-10-19, feature P1).** A run can fail *after* the task is
|
|
534
|
+
already finished: the `done` state's close commands run last, and a lint or anchor rule can refuse
|
|
535
|
+
the transition on an otherwise green task. Resolve it the honest way — fix the finding through the
|
|
536
|
+
owning surface, re-run the same close command, and confirm the task reads `done` with a PASS verdict
|
|
537
|
+
— then record the task as `done (run-failed-recovered)` with the failing command in the report.
|
|
538
|
+
That is **not** a `failed` outcome: the failure policy applies to a task that did not reach its
|
|
539
|
+
contract, not to a run whose last recorded state was superseded. Surface it in the report either
|
|
540
|
+
way (never silently continue), and never re-run the pipeline just to flip a run row from `failed` to
|
|
541
|
+
`done` — a second run re-executes model stages for a task that is already closed.
|
|
542
|
+
|
|
534
543
|
### 4.2 `--keep-going` (R3.2)
|
|
535
544
|
|
|
536
545
|
With `--keep-going`, a failed task does **not** halt the batch. Instead:
|
|
@@ -650,7 +659,7 @@ Before launching a full `spur-check:full`:
|
|
|
650
659
|
| R4.3 (`--agent` merged into per-task vars) | Step 3.2 |
|
|
651
660
|
| R5.1 (orchestrator boundary) | "Zero engine code" preamble + Step 3 |
|
|
652
661
|
| R5.2 (structured batch report) | Step 5 |
|
|
653
|
-
| 0411 (bounded feature-sync retry suppression) | Step 3.3c — wrapper lives in pipeline `record
|
|
662
|
+
| 0411 (bounded feature-sync retry suppression) | Step 3.3c — wrapper lives in pipeline `record`; driver unchanged |
|
|
654
663
|
| 0510 R2 (feature-derived strict preflight) | Step 1 — "Feature-derived strict preflight (R2, task 0510)" |
|
|
655
664
|
| 0510 R5 (metadata-only host controller) | Step 3.4 + projected `task show` / trace snippets in Step 1, 2.3, 3.1 |
|
|
656
665
|
|
|
@@ -29,7 +29,7 @@ while ready or running:
|
|
|
29
29
|
RUN[t] = (cd "$WT" && spur workflow run task-pipeline.yaml \
|
|
30
30
|
--vars '{"wbs":"<wbs>","deferFeatureSync":"true"[,"deferQualityGate":"true"],...}' --async --json)
|
|
31
31
|
# deferQualityGate is added ONLY under the opt-in --defer-gate flag (1111 R3):
|
|
32
|
-
# the task's `
|
|
32
|
+
# the task's `gate` state then runs the light tier and writes DEFERRED.
|
|
33
33
|
wait for any RUN terminal # trace poll --follow --timeout 600000; stale-evidence rule applies
|
|
34
34
|
on done: WT-3b commit on $BRANCH → integrate(t)
|
|
35
35
|
on failed: WT-5 retain (marker retained); failure policy — stop-the-batch default / --keep-going subtree skip
|
|
@@ -92,9 +92,9 @@ per-task with `/sp:dev-run <wbs> --worktree <branch>`.
|
|
|
92
92
|
|
|
93
93
|
### Generated regions — defer the sync, regenerate once (R5)
|
|
94
94
|
|
|
95
|
-
The only per-task writer of feature files is the `
|
|
95
|
+
The only per-task writer of feature files is the `done` state's post-record feature sync
|
|
96
96
|
(`task-pipeline.yaml`). Parallel launches set
|
|
97
|
-
the pipeline var `deferFeatureSync: "true"` (default `"false"`): the
|
|
97
|
+
the pipeline var `deferFeatureSync: "true"` (default `"false"`): the done state appends
|
|
98
98
|
`feature sync deferred to batch integration` to the task report and skips the sync, so task
|
|
99
99
|
branches never touch feature files or `docs/features/INDEX.md`. After the last integration, on the
|
|
100
100
|
base ref, the orchestrator runs `spur feature sync <f> --json` (service-level suppression) plus `spur feature refresh --feature <f>`
|
|
@@ -103,7 +103,7 @@ inline runs keep the default `"false"` and are unchanged. Any rebase conflict
|
|
|
103
103
|
path or any other — is an R4 `integration-conflict`; there is no path-based exception.
|
|
104
104
|
|
|
105
105
|
**Deferred gate (`--defer-gate`, task 1111 R3/R4).** The opt-in flag adds
|
|
106
|
-
`deferQualityGate: "true"` to the same per-task `--vars`, so each task's `
|
|
106
|
+
`deferQualityGate: "true"` to the same per-task `--vars`, so each task's `gate` state runs the light
|
|
107
107
|
tier and writes `DEFERRED` instead of a full-gate `PASS` (see
|
|
108
108
|
[flag-glossary](flag-glossary.md#flag-defer-gate)). The orchestrator then runs the project
|
|
109
109
|
`qualityGateCmd` **once** on the integrated `BASE_REF` **before** the deferred feature sync:
|
|
@@ -10,15 +10,17 @@ see_also:
|
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
pick task (spur task list --json)
|
|
13
|
-
→ interactive omit/inline:
|
|
13
|
+
→ interactive omit/inline: spur workflow run task-pipeline.yaml with executor=host
|
|
14
14
|
→ explicit/headless executor: spur workflow run task-pipeline.yaml
|
|
15
15
|
→ on HITL pause: surface to operator → resume the selected driver
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
The execution half runs a single task through the `task-pipeline.yaml` FSM
|
|
19
|
-
omit/inline invocation
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
The execution half runs a single task through the `task-pipeline.yaml` FSM, always on the workflow
|
|
19
|
+
engine. In an interactive omit/inline invocation the engine runs with `executor=host`: it executes
|
|
20
|
+
every deterministic action (shell, `command.gate`, `decide`) and every guard itself, and hands each
|
|
21
|
+
model stage back to this session as a work item. Explicit executors and headless invocations run the
|
|
22
|
+
model stages as subprocesses. Both surfaces share the same actions, guards, artifacts, decision
|
|
23
|
+
rows, HITL gates and terminal states.
|
|
22
24
|
|
|
23
25
|
> **Single-task vs batch.** This file covers the **single-task** execution half — one task through
|
|
24
26
|
> `task-pipeline.yaml`. For **batch** execution (a set of tasks in dependency-correct order), see
|
|
@@ -32,11 +34,11 @@ This file owns **how operations sequence** in the pipeline. What each operation
|
|
|
32
34
|
|
|
33
35
|
> **`/sp:dev-run` drives the pipeline — it is NEVER a pipeline step.** The command
|
|
34
36
|
> `/sp:dev-run <wbs>` means "run this whole pipeline" (default `--mode full`). The pipeline's
|
|
35
|
-
> internal stages call `/sp:dev-run --mode implement`,
|
|
36
|
-
> `/sp:dev-fixall`, `/sp:dev-review
|
|
37
|
+
> internal stages call `/sp:dev-run --mode implement`, the typed quality gate + optional
|
|
38
|
+
> `/sp:dev-fixall`, and `/sp:dev-review` — never `/sp:dev-run` in full mode.
|
|
37
39
|
> Calling `/sp:dev-run --mode full` from inside the `implement` step would recurse into another
|
|
38
40
|
> full pipeline run. The `implement` step is the **implement operation** (dev-operations.md §4);
|
|
39
|
-
>
|
|
41
|
+
> requirement/AC certification happens inside `review` (D65 merged the former `verify` stage).
|
|
40
42
|
|
|
41
43
|
## The pipeline's internal stages
|
|
42
44
|
|
|
@@ -45,10 +47,11 @@ one thing and yields, so the **pipeline (not the agent) owns the loop**.
|
|
|
45
47
|
|
|
46
48
|
| Stage | Operation | Defined in |
|
|
47
49
|
| ------- | ----------- | ------------ |
|
|
48
|
-
| `implement` | `/sp:dev-run --mode implement <wbs>` — write the code that satisfies the task; author `## Solution`. | [dev-operations.md §4 run](dev-operations.md) → `sp:code-implementation` |
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
50
|
+
| `implement` | `/sp:dev-run --mode implement <wbs>` — write the code that satisfies the task; author `## Solution`. May pause through `escalate` (operator question). | [dev-operations.md §4 run](dev-operations.md) → `sp:code-implementation` |
|
|
51
|
+
| `gate` | **Typed quality gate** (not `/sp:dev-unit`): `spur task gate <wbs> run\|recheck` over `${vars.qualityGateCmd}` (default `spur self exec check`) under the host-wide lock, with tree-hash receipt reuse. The first visit runs `run`; every visit after a remediation runs `recheck`. Also resolves the review lane (`task-triage`) and classifies a red gate (`failure-class`). | `spur task gate` ([tasks reference](../../spur-cli/references/tasks/verbs.md)) |
|
|
52
|
+
| `remediate` | `/sp:dev-fixall "${vars.qualityGateCmd}" --gate-log … --findings …` — the bounded repair hop for a red gate **or** a fixable non-PASS review; re-enters `gate`. One shared counter (`qualityGateMaxFixAttempts`, default 2) bounds both lanes. `/sp:dev-unit` stays coverage gap-fill (router C3/C5 / standalone). | [dev-operations.md §10 fixall](dev-operations.md) |
|
|
53
|
+
| `review` | `/sp:dev-review --tasks <wbs> --auto --focus <functional\|all>` — SECUA + requirement/AC traceability; `spur task verdict --from-answer` certifies the answer, `review-failure-class` classifies a non-PASS, then the approval decision point answers. | [dev-operations.md §2 review](dev-operations.md) |
|
|
54
|
+
| `done` | Deterministic close: `spur task record` writes `## Testing` from the verdict, then `spur task update <wbs> done --no-lifecycle` runs the completion check. | [dev-operations.md §3 verify](dev-operations.md) (standalone re-certification) |
|
|
52
55
|
|
|
53
56
|
Interactive omit/`inline` executes these model stages in the host session through the engine loop:
|
|
54
57
|
the engine owns every guard and transition, the host performs each returned work item and records
|
|
@@ -144,7 +147,7 @@ Synchronous invocation (`--json` without `--async`) is acceptable **only** for s
|
|
|
144
147
|
On the subprocess path, when `--agent <value>` is set (passed through from the thin wrapper), merge it into the vars as
|
|
145
148
|
**both** `agent` and `implementAgent` (task 0483 R2):
|
|
146
149
|
`--vars '{"wbs":"<wbs>","agent":"<value>","implementAgent":"<value>"}'`. The pipeline YAML reads
|
|
147
|
-
`${vars.agent}` for review
|
|
150
|
+
`${vars.agent}` for remediate/review and `${vars.implementAgent}` for implement — setting
|
|
148
151
|
both keys ensures the pinned executor reaches every hop. The full value-semantics contract (one
|
|
149
152
|
rule, value table, objective triggers, and headless `inline` substitution (tier resolution + one warning) per ADR-087)
|
|
150
153
|
lives in [cross-cutting.md](cross-cutting.md#inline-default-execution-surface) — the SSOT.
|
|
@@ -161,34 +164,39 @@ pipeline (bug-742).
|
|
|
161
164
|
The pipeline (`kind: state-machine`) runs the work loop:
|
|
162
165
|
|
|
163
166
|
```
|
|
164
|
-
precheck → implement →
|
|
167
|
+
precheck → implement[⇄ escalate] → gate[⇄ remediate] → review → done | failed
|
|
165
168
|
```
|
|
166
169
|
|
|
167
|
-
Two branches reach the bounded
|
|
170
|
+
Two branches reach the bounded `remediate` hop, and each is routed by a recorded decision row, not
|
|
171
|
+
by this session's judgment:
|
|
168
172
|
|
|
169
|
-
- `
|
|
170
|
-
-
|
|
171
|
-
`
|
|
172
|
-
|
|
173
|
-
|
|
173
|
+
- a red `gate` → `failure-class` (`fix` → `remediate`, `stop` → `failed`);
|
|
174
|
+
- a review that did not certify PASS → `review-failure-class` (`fix` → `remediate`, `stop` →
|
|
175
|
+
`failed`), bounded by the SAME `qualityGateMaxFixAttempts` counter. The repair re-enters
|
|
176
|
+
`gate` (recheck) → `review` on the remediated tree.
|
|
177
|
+
|
|
178
|
+
Every decision point, its fallback and its consumer are listed in
|
|
179
|
+
[decision-points.md](decision-points.md); read the rows it names instead of re-judging them.
|
|
174
180
|
|
|
175
181
|
The completion gate reads deterministic evidence only: the review stage's **verdict artifact** (`.spur/run/<wbs>-verdict.json`, derived by `spur task verdict --from-answer`) and the **tree-hash gate receipt** (`.spur/run/<wbs>-check-receipt.json`, reused while the tree is unchanged). The ADR-071 proof chain this paragraph used to describe — proof digests, `verify → record`, review-inside-the-bracket — was deleted by the D65 pipeline rewrite; `record` now runs inside `done`'s onEnter and `verify` merged into `review`. Two grades are read, and only as cross-checks against the answer's own rows: the review answer states one `Confidence: HIGH|MEDIUM|LOW` line (ADR-141) and the review gate recomputes it from the finding dispositions, rejecting a disagreement. Nothing grades the *verifier's* opinion: an open P1–P3 finding blocks `done` on its own, and what protects a hand-driven `task update <wbs> done` is unchanged — the gate must show a PASS receipt for this tree and a recorded review artifact.
|
|
176
182
|
|
|
177
183
|
Agentic steps use the pure slash inputs declared by each YAML `agent.run` action (ADR-043). The
|
|
178
184
|
workflow engine dispatches them; the interactive driver invokes their backing skills in-session.
|
|
179
|
-
The `
|
|
180
|
-
**deterministic
|
|
185
|
+
The `gate` state is
|
|
186
|
+
**deterministic** (quality gate plus decision points); only the optional `remediate` hop is agentic
|
|
181
187
|
(`/sp:dev-fixall`). The skill monitors the run:
|
|
182
188
|
|
|
183
|
-
- **On HITL pause** (`
|
|
184
|
-
|
|
185
|
-
|
|
189
|
+
- **On HITL pause** (`escalate`, or the approval decision point inside `review`): surface the
|
|
190
|
+
question, or the review answer and verdict, to the operator. Resume with `spur workflow continue
|
|
191
|
+
<run-id> --answer-text <answer>` (or `--yes` for the approval). The approval answer lands in
|
|
192
|
+
`.spur/run/<wbs>-approval.status`; a `no`/`cancel` ends the run `failed` with terminal reason
|
|
193
|
+
`cancelled`, a recorded denial rather than a check failure.
|
|
186
194
|
- **On guard failure** (`precheck`): the task's check findings block progress — fix the
|
|
187
195
|
task first.
|
|
188
|
-
- **On completion** (`done`): the
|
|
196
|
+
- **On completion** (`done`): the `done` state's onEnter has already written the verdict
|
|
189
197
|
transcript into the task's `## Testing` via `spur task record <wbs>` (matrix-compliant tables;
|
|
190
198
|
`## Review` was authored by the review step and is only backfilled bare, never overwritten —
|
|
191
|
-
F92 0593 R1
|
|
199
|
+
F92 0593 R1) and moved the task to `done` through the verb's own completion check.
|
|
192
200
|
|
|
193
201
|
## `--next` chain — advance to the next step
|
|
194
202
|
|
|
@@ -400,6 +408,10 @@ After a completed task, decide next action:
|
|
|
400
408
|
|
|
401
409
|
## Skipping HITL
|
|
402
410
|
|
|
403
|
-
Passing `--vars '{"profile":"auto"}'` to `spur workflow run` (a var choice, not a YAML fork)
|
|
404
|
-
|
|
411
|
+
Passing `--vars '{"profile":"auto"}'` to `spur workflow run` (a var choice, not a YAML fork) makes the
|
|
412
|
+
approval decision point answer itself instead of prompting: its evidence binding answers from the
|
|
413
|
+
recorded review evidence, through the `gate-evidence` decision when `workflows.hitlDecisionMaker`
|
|
414
|
+
is on. It is not a bypass — an auto run still ends `failed`/`cancelled` when the maker answers
|
|
415
|
+
`no`; a deferred answer (switch off, no reachable maker, or insufficient evidence) is not a denial. Use it for low-risk,
|
|
416
|
+
well-understood tasks where operator review adds no value.
|
|
405
417
|
(Combine with `wbs` in one object: `--vars '{"wbs":"0042","profile":"auto"}'`.)
|
|
@@ -118,6 +118,39 @@ WT_PATH="$(cd "../<worktree-dir>" && pwd)" # hoisted: needed by WT-4a AND WT-4
|
|
|
118
118
|
# task's creation), so a manual DB edit is never required:
|
|
119
119
|
spur workflow persist-out --from "$WT_PATH" "${TASK_FILE_ARGS[@]}" \
|
|
120
120
|
|| { echo "halt: worktree run-record persist-out failed - worktree retained (WT-5)" >&2; write_marker retained; exit 1; }
|
|
121
|
+
|
|
122
|
+
**Two refusals this step raises, and how to clear each without touching foreign evidence.**
|
|
123
|
+
|
|
124
|
+
1. **`durable evidence conflicts: <name>`** — the worktree owns a receipt (`*-feature-verification.json`)
|
|
125
|
+
whose canonical target already holds *different* bytes. The conflict policy is fail-closed on
|
|
126
|
+
purpose: overwriting would destroy the invoking tree's copy. When the worktree receipt is the
|
|
127
|
+
newer, authoritative one (e.g. the feature transition this batch performed), archive the
|
|
128
|
+
superseded copy out of the canonical path and re-run — never delete it, and never copy the
|
|
129
|
+
worktree file in with `cp`:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
mkdir -p .spur/memory/evidence/superseded
|
|
133
|
+
mv ".spur/memory/evidence/<name>" ".spur/memory/evidence/superseded/<name>.<iso-timestamp>.json"
|
|
134
|
+
# then re-run the persist-out command above; the newer receipt lands at the canonical path
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
When the *invoking* copy is the newer one, do nothing: `persist-check` reports it as foreign and
|
|
138
|
+
divergent, which is not a blocker.
|
|
139
|
+
2. **`persist-check … BLOCKED n unforwarded durable verdict/receipt`** — the worktree holds
|
|
140
|
+
`*-verdict.json` files for tasks this batch did not run, because **WT-2 stages the invoking tree's
|
|
141
|
+
evidence into the worktree before the first task**. Forwarding them back (`--task-file`) is wrong
|
|
142
|
+
when the invoking tree's copies are newer: persist-out then refuses with `cited run evidence …
|
|
143
|
+
diverges`, and it would write stale bytes over fresh ones. Compare mtimes and delete the staged
|
|
144
|
+
worktree copies, then re-run `persist-check` with only this batch's `--task-file` arguments:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
for w in <staged-wbs>; do
|
|
148
|
+
[ .spur/run/$w-verdict.json -nt "$WT_PATH/.spur/run/$w-verdict.json" ] \
|
|
149
|
+
&& rm -f "$WT_PATH/.spur/run/$w-verdict.json"
|
|
150
|
+
done
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Both steps are reads plus a delete of a *copy* whose source still holds it — no evidence is lost.
|
|
121
154
|
#
|
|
122
155
|
# WT-4b — bounded CWD-holder cleanup (task 0720 R1). $WT_PATH above is the EXACT
|
|
123
156
|
# absolute worktree path; a relative path or a stale entry matches the wrong processes.
|
|
@@ -361,8 +394,7 @@ skipped persist-out (or the pre-removal assertion fired too late), verdicts rema
|
|
|
361
394
|
from the task records — `spur task show <wbs> --json` carries the recorded verdict and its
|
|
362
395
|
proof block, so a lost `<wbs>-verdict.json` is regenerated by re-recording or copying from
|
|
363
396
|
the task store. Feature run/latest receipts are re-runnable, not recovered: rerun the
|
|
364
|
-
feature-verification
|
|
365
|
-
`spur workflow run feature-verification.yaml --vars '{"featureId":"<id>"}'` — which rewrites
|
|
397
|
+
feature-verification pass in the invoking tree — `spur feature verify <id>` — which rewrites
|
|
366
398
|
the receipt files it owns. Divergent files are never auto-overwritten; reconcile by hand.
|
|
367
399
|
|
|
368
400
|
```
|
|
@@ -208,10 +208,10 @@ the worktree directory before launching the loop.
|
|
|
208
208
|
#### Evidence staging before the first task (create and reuse mode)
|
|
209
209
|
|
|
210
210
|
`.spur/memory/evidence/` and `.spur/run/` are **untracked per-tree** planes, so a fresh worktree
|
|
211
|
-
starts with neither while the invoking tree holds every earlier task's verdict.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
starts with neither while the invoking tree holds every earlier task's verdict. Feature completion
|
|
212
|
+
checks (`spur feature check --strict --as done`) and wrap-up metrics resolve verdict artifacts relative
|
|
213
|
+
to the tree they run in; wrap-up task resolution itself checks task identity and terminal status only.
|
|
214
|
+
Without this step an already-`done` linked task reads as missing evidence
|
|
215
215
|
(`L4.evidence-not-recoverable`, `L4.scenario-unverified`) and its metrics row degrades to
|
|
216
216
|
`UNKNOWN`.
|
|
217
217
|
|
|
@@ -151,7 +151,7 @@ halt-on-first-failure. Never silently retried; the failure is still reported.
|
|
|
151
151
|
**Applies to:** `/sp-dev-runall --mode parallel`, and `--mode auto` when it resolves to parallel.
|
|
152
152
|
**Default:** off — every task pipeline runs its own FULL project gate inside its worktree.
|
|
153
153
|
|
|
154
|
-
With `--defer-gate`, each task's `
|
|
154
|
+
With `--defer-gate`, each task's `gate` state (every visit) runs the **light tier** (changed-scope
|
|
155
155
|
format, per-workspace typecheck, related tests) and writes `DEFERRED` — never `PASS` — to
|
|
156
156
|
`.spur/run/<wbs>-test-gate.status`. The orchestrator then owes **one integrated full gate** on the
|
|
157
157
|
base ref over the merged slices, **before** the deferred feature sync; on FAIL the batch verdict is
|
|
@@ -164,8 +164,8 @@ Two properties are load-bearing and are asserted structurally:
|
|
|
164
164
|
fails inside its own worktree instead of at the end of the batch (the reason ADR-124 rejected an
|
|
165
165
|
unconditional single end-of-run gate).
|
|
166
166
|
- **The full tier is still the only `PASS` writer.** Only the integrated run can claim a green
|
|
167
|
-
project gate; the per-task token is `DEFERRED`, and the `
|
|
168
|
-
|
|
167
|
+
project gate; the per-task token is `DEFERRED`, and the deferred `gate → review`
|
|
168
|
+
guard accepts it only while `deferQualityGate = "true"`.
|
|
169
169
|
|
|
170
170
|
`--defer-gate` with `--mode sequential` (or omitted `--mode`) is rejected — the flag exists to move
|
|
171
171
|
one full gate from N worktrees to the one place the integrated tree exists. Under `--mode auto` it
|
|
@@ -98,9 +98,10 @@ Entered before `task-pipeline.yaml` `review` state dispatches `sp:code-verificat
|
|
|
98
98
|
|
|
99
99
|
## verify gate
|
|
100
100
|
|
|
101
|
-
Entered before `task-pipeline.yaml` `
|
|
101
|
+
Entered before the `task-pipeline.yaml` `review` state certifies a task verdict (D65 merged the
|
|
102
|
+
former `verify` state into `review`; standalone `/sp:dev-verify` applies the same list).
|
|
102
103
|
|
|
103
|
-
- [ ] The
|
|
104
|
+
- [ ] The answer file (`.spur/run/<runId>-review-answer.txt` in the pipeline) is lint-clean before
|
|
104
105
|
verdict derivation: `spur task verdict <wbs> --from-answer …` (0726 R3) lints the
|
|
105
106
|
file first and rejects missing/duplicate/unknown R IDs, AC identities that are not an
|
|
106
107
|
exact task checklist label or linked-feature scenario title, invalid status/evidence-type
|
|
@@ -80,9 +80,18 @@ Avoid: *prompt* (reserved for LLM input text), *interrupt* (implies an exception
|
|
|
80
80
|
pause point).
|
|
81
81
|
|
|
82
82
|
**DecisionMaker** — optional provider-backed responder for executed `hitl.confirm`/`hitl.select`
|
|
83
|
-
actions (ADR-123), enabled via `workflows.hitlDecisionMaker: true
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
actions (ADR-123), enabled via `workflows.hitlDecisionMaker: true`. Evidence-mode confirm gates
|
|
84
|
+
answer through the catalog decision `gate-evidence`, so the effective maker (and its credentials)
|
|
85
|
+
comes from `decisions.*` config. Evidence answers clear the answer variable and record
|
|
86
|
+
`statusVar: accepted/deferred`; unresolved cases defer or delegate to the human. Readiness:
|
|
87
|
+
`spur decision status --probe`.
|
|
88
|
+
|
|
89
|
+
**decision point** — a recorded, closed-vocabulary judgment inside a workflow: a `decide` action
|
|
90
|
+
(or an evidence-mode HITL gate) that names a catalog decision id and writes a schemaVersion-1
|
|
91
|
+
`.decision` row whose `value` the next guard reads. It always has a deterministic fallback, so it
|
|
92
|
+
works with no model. Inventory: [decision-points.md](decision-points.md).
|
|
93
|
+
Avoid: *decision brief* (the operator-facing HITL summary format in
|
|
94
|
+
[decision-brief.md](decision-brief.md) — prose for a human, not a catalog answer).
|
|
86
95
|
|
|
87
96
|
**WBS** (work-breakdown-structure ID) — the four-digit task identifier (e.g. `0187`) that
|
|
88
97
|
names a task file and its position in the corpus. WBS IDs are assigned once and never reused.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: planning-workflow
|
|
3
|
-
description: "Extracted section: the planning half — intake → feature create → AC generation →
|
|
3
|
+
description: "Extracted section: the planning half — intake → feature create → AC generation → decomposition → batch-create → refine. The full step-by-step procedure for turning a vague description into a validated, decomposed feature."
|
|
4
4
|
see_also:
|
|
5
5
|
- spur-dev
|
|
6
6
|
- decomposition
|
|
@@ -13,18 +13,19 @@ see_also:
|
|
|
13
13
|
vague description
|
|
14
14
|
→ intake (clarify scope, constraints — prompt work)
|
|
15
15
|
→ spur feature create … ; AC authored/generated (spur agent run, bdd templates)
|
|
16
|
-
→
|
|
16
|
+
→ ac-generate runs `spur feature check` (BDD validator; loop until clean)
|
|
17
17
|
→ decomposition (prompt work) → task-batch JSON
|
|
18
|
-
→
|
|
18
|
+
→ batch-create-run runs `task-batch.schema.json` + `spur task batch-create` (atomic: all-or-nothing)
|
|
19
19
|
→ design doc (conditional: seam heuristic under default; skip with --skip-design) → docs/design/<slug>.md + 04 index
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
The planning half transforms a description into a validated feature file with acceptance
|
|
24
|
-
criteria, then decomposes it into a batch of tasks. Two
|
|
25
|
-
unable to corrupt the corpus: `spur feature check` validates the AC, and
|
|
24
|
+
criteria, then decomposes it into a batch of tasks. Two deterministic validation steps make LLM
|
|
25
|
+
regressions unable to corrupt the corpus: `spur feature check` validates the AC, and
|
|
26
26
|
`task-batch.schema.json` validates the decomposition shape before `spur task batch-create`
|
|
27
|
-
writes anything.
|
|
27
|
+
writes anything. Both run inside the pipeline (`ac-generate`, `batch-create-run`) and route on
|
|
28
|
+
their recorded result — neither is an operator gate.
|
|
28
29
|
|
|
29
30
|
## Step 1: Intake
|
|
30
31
|
|