@gobing-ai/spur 0.4.11 → 0.4.12

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 (54) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +22 -0
  3. package/config/rules/quality/coverage-gate.yaml +2 -2
  4. package/config/rules/surface/check-cli-surface.yaml +4 -0
  5. package/config/workflows/feature-verification.yaml +14 -5
  6. package/config/workflows/idea-pipeline.yaml +92 -12
  7. package/config/workflows/task-pipeline.yaml +456 -830
  8. package/config/workflows/wayfinder-resolution.yaml +20 -3
  9. package/config/workflows/wrapup-pipeline.yaml +22 -9
  10. package/package.json +1 -1
  11. package/plugins/sp/README.md +2 -2
  12. package/plugins/sp/agents/super-planner.md +2 -2
  13. package/plugins/sp/agents/super-reviewer.md +17 -8
  14. package/plugins/sp/bunfig.toml +3 -3
  15. package/plugins/sp/commands/dev-changelog.md +1 -1
  16. package/plugins/sp/commands/dev-gitmsg.md +2 -2
  17. package/plugins/sp/commands/dev-handover.md +1 -1
  18. package/plugins/sp/commands/dev-idea.md +23 -13
  19. package/plugins/sp/commands/dev-job-dump.md +1 -1
  20. package/plugins/sp/commands/dev-plan.md +17 -6
  21. package/plugins/sp/commands/dev-review.md +1 -1
  22. package/plugins/sp/commands/dev-run.md +7 -6
  23. package/plugins/sp/commands/dev-runall.md +1 -1
  24. package/plugins/sp/plugin.json +1 -1
  25. package/plugins/sp/skills/code-implementation/SKILL.md +7 -7
  26. package/plugins/sp/skills/code-refactoring/SKILL.md +1 -1
  27. package/plugins/sp/skills/code-verification/SKILL.md +1 -1
  28. package/plugins/sp/skills/code-verification/references/secu-review.md +1 -1
  29. package/plugins/sp/skills/code-verification/references/verdict-schema.md +23 -10
  30. package/plugins/sp/skills/doc-evolve/SKILL.md +1 -1
  31. package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
  32. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +7 -7
  33. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +4 -4
  34. package/plugins/sp/skills/spur-check/SKILL.md +9 -8
  35. package/plugins/sp/skills/spur-cli/SKILL.md +2 -2
  36. package/plugins/sp/skills/spur-cli/references/self.md +37 -2
  37. package/plugins/sp/skills/spur-cli/references/tasks/l3-guard-cheatsheet.md +1 -1
  38. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +3 -3
  39. package/plugins/sp/skills/spur-cli/references/tasks.md +1 -1
  40. package/plugins/sp/skills/spur-cli/references/workflows.md +5 -3
  41. package/plugins/sp/skills/spur-dev/SKILL.md +3 -3
  42. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +9 -8
  43. package/plugins/sp/skills/spur-dev/references/dev-operations.md +11 -11
  44. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +4 -3
  45. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +4 -4
  46. package/plugins/sp/skills/spur-dev/references/execution-batch.md +13 -11
  47. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +31 -22
  48. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +5 -5
  49. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +4 -4
  50. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +4 -4
  51. package/schemas/spur-config.schema.json +19 -1
  52. package/spur.js +31541 -31955
  53. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +0 -997
  54. package/plugins/sp/skills/spur-dev/references/structured-trace-emission.md +0 -178
@@ -46,14 +46,15 @@ one thing and yields, so the **pipeline (not the agent) owns the loop**.
46
46
  | Stage | Operation | Defined in |
47
47
  | ------- | ----------- | ------------ |
48
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
- | `test` → (`test-fix` ↔ `test-recheck`) → `review` \| `failed` | **Project quality gate** (not `/sp:dev-unit`). Soft shell probe of `${vars.qualityGateCmd}` (default `bun run spur-check`) — green path pays **one** full gate run. On FAIL: bounded `/sp:dev-fixall` loop (`qualityGateMaxFixAttempts`, default 2) with soft recheck; exhausted attempts route to pipeline `failed`. `/sp:dev-unit` remains **coverage gap-fill** (router C3/C5 / standalone). | [dev-operations.md §10 fixall](dev-operations.md); unit op still §1 |
49
+ | `test` → (`test-fix` ↔ `test-recheck`) → `review` \| `failed` | **Project quality gate** (not `/sp:dev-unit`). Soft shell probe of `${vars.qualityGateCmd}` (default `spur self exec check`) — green path pays **one** full gate run. On FAIL: bounded `/sp:dev-fixall` loop (`qualityGateMaxFixAttempts`, default 2) with soft recheck; exhausted attempts route to pipeline `failed`. `/sp:dev-unit` remains **coverage gap-fill** (router C3/C5 / standalone). | [dev-operations.md §10 fixall](dev-operations.md); unit op still §1 |
50
50
  | `review` | `/sp:dev-review --tasks <wbs>` — SECUA-framework review of the diff. | [dev-operations.md §2 review](dev-operations.md) |
51
51
  | `verify` | `sp:code-verification` — requirements traceability + verdict. | [dev-operations.md §3 verify](dev-operations.md) |
52
52
 
53
- Interactive omit/`inline` executes these model stages through the
54
- [inline pipeline driver](inline-pipeline-driver.md) in the host session and records stage/session
55
- provenance. The host is the controller; eligible `agent.run` stages may dispatch once to a native
56
- subagent (task 0508), with host fallback and no post-dispatch replay — see the driver reference.
53
+ Interactive omit/`inline` executes these model stages in the host session through the engine loop:
54
+ the engine owns every guard and transition, the host performs each returned work item and records
55
+ its receipt. Eligible `agent.run` stages may dispatch once to a native subagent (task 0508), with
56
+ host fallback and no post-dispatch replay — see
57
+ [cross-cutting.md](cross-cutting.md#inline-default-execution-surface).
57
58
  `--agent <name|auto>`, parallel batches, and headless workflow invocation select
58
59
  the existing subprocess actions. Direct invocations of the same dev operations remain inline by
59
60
  default. See the [inline-default execution-surface contract](cross-cutting.md#inline-default-execution-surface).
@@ -106,9 +107,9 @@ and merge-or-retain after the run reports. The lifecycle is
106
107
  applied to a batch of one. Rejected with `--mode implement`.
107
108
 
108
109
  **Choose the surface before execution.** In an interactive `/sp:dev-run --mode full` invocation,
109
- omit/`--agent inline` selects the [inline pipeline driver](inline-pipeline-driver.md). Read the YAML
110
- at invocation time, allocate the inline run id/session provenance, record `task run-link`, and walk
111
- its actions/guards in declaration order. Do not call `spur workflow run` on this path. `--agent auto`,
110
+ omit/`--agent inline` selects the host executor. Start the run with `spur workflow run <file>
111
+ --vars '{"executor":"host",…}'` and advance it with `spur workflow continue <run-id> --answer-text
112
+ <receipt>`; the engine walks the YAML's actions/guards, this session never re-executes them. `--agent auto`,
112
113
  a named executor, an explicit `vars.agent`/`vars.implementAgent`, or a headless caller selects the
113
114
  workflow subprocess path below. Never fall back silently from inline to `agent.default`.
114
115
 
@@ -171,13 +172,7 @@ Two branches reach the bounded repair hop, not one (session finding after 1088):
171
172
  an on-graph, bounded path to remediation instead of dead-ending the run, and the fix re-enters
172
173
  quality → review → verify on a freshly captured proof digest.
173
174
 
174
- The completion gate reads deterministic evidence only (F511, task 1207): both `verify → record` and
175
- `record → done` check the proof digests in `.spur/run/<wbs>-verdict.json` — verdict PASS, matching
176
- run/definition digests, review stage completed. No confidence is read, stated or acknowledged; the
177
- asserted `Confidence:` line and the `ackLowConfidence` operator var were retired because a model
178
- that can write a PASS can write `HIGH` — the grade verified nothing. What protects a hand-driven
179
- `task update <wbs> done` is unchanged: the digests must match the run's captured proof, and the
180
- review stage must actually be completed in the artifact.
175
+ 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.
181
176
 
182
177
  Agentic steps use the pure slash inputs declared by each YAML `agent.run` action (ADR-043). The
183
178
  workflow engine dispatches them; the interactive driver invokes their backing skills in-session.
@@ -325,8 +320,8 @@ the partial work still in the working tree. The failure output names the partial
325
320
  1. **Recognise.** `.spur/memory/runs/<runId>/artifacts/<runId>-implement-partial.md` exists, the run reported `exited
326
321
  with code 3`, the task is at `todo`. The artifact's `git diff --stat` section is the partial
327
322
  work inventory.
328
- 2. **Establish green from the partial files.** `bun run format` then `bun run lint` + `bun
329
- test` (or the affected packages). Fix mechanical formatting/type fallout first; the partial
323
+ 2. **Establish green from the partial files.** `spur self exec format` then `spur self exec lint` + `spur
324
+ self exec test` (or the affected packages). Fix mechanical formatting/type fallout first; the partial
330
325
  tree is the baseline, not a code review target.
331
326
  3. **Resume the remaining requirements against that tree.** Re-run the implement step with the
332
327
  partial diff as explicit context — hand the continuation agent `git diff` (the partial
@@ -338,11 +333,25 @@ the partial work still in the working tree. The failure output names the partial
338
333
  [`done-housekeeping.md`](done-housekeeping.md) F6 — it carries the provenance obligations
339
334
  (honest `done_reason`, verdict regeneration).
340
335
 
341
- **Inline path (task 0727).** There is no `<runId>-implement-partial.md` artifact on the inline
342
- driver path — it is written only by the subprocess `agent.run` action. The inline equivalent is
343
- the dispatch-timeout contract in [`inline-pipeline-driver.md`](inline-pipeline-driver.md):
344
- resume from the partial tree, never restart the stage inline; the partial working tree is the
345
- recovery input.
336
+ **Host-executor path (task 0727).** There is no `<runId>-implement-partial.md` artifact on the
337
+ host path — it is written only by the subprocess `agent.run` action. A host-stage timeout is a
338
+ recorded stage failure: resume from the partial tree, never restart the stage inline; the partial
339
+ working tree is the recovery input.
340
+
341
+ **3a. Verify dispatch floor (task 1039).** A small, clean diff does not need a separate verify
342
+ session: when the diff is below the floor, `verify` runs host-inline in the current session and
343
+ records exactly one log line —
344
+
345
+ stage verify executed inline in session <session-id> (below dispatch floor: diffstat files <f> lines <n>)
346
+
347
+ The floor is read from the recorded diffstat artifact under `.spur/run/`; the filter that decides
348
+ it is
349
+
350
+ ([.files, .insertions, .deletions] | all(type == "number")) and .files <= 3 and (.insertions + .deletions) <= 60 and .sensitive == false
351
+
352
+ A diffstat that is missing, malformed, or names a sensitive path is never below the floor: the
353
+ floor is an optimisation, so an unreadable artifact dispatches the normal verify executor. (This
354
+ contract moved here from the retired inline driver reference, D65 1242.)
346
355
 
347
356
  **3. Match the executor to the size (task 0487 R3).** Size and executor capability are one
348
357
  decision, not two. **≥ 6 requirements or ≥ 9 Plan items → a `reviewer`-role executor (the
@@ -116,7 +116,7 @@ WT_PATH="$(cd "../<worktree-dir>" && pwd)" # hoisted: needed by WT-4a AND WT-4
116
116
  # automatically reconciles each forwarded terminal task's receiving lifecycle row in
117
117
  # the invoking tree (finalizing any stale in-flight or interrupted row left from the
118
118
  # task's creation), so a manual DB edit is never required:
119
- spur workflow inline persist-out --from "$WT_PATH" "${TASK_FILE_ARGS[@]}" \
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
121
  #
122
122
  # WT-4b — bounded CWD-holder cleanup (task 0720 R1). $WT_PATH above is the EXACT
@@ -155,9 +155,9 @@ fi # NO prune/remove/branch delete
155
155
  # worktree while it still owns evidence absent from (or divergent from) the invoking tree —
156
156
  # the D63 landing skipped persist-out and silently lost verdicts + receipts. WBSes ride the
157
157
  # same TASK_FILE_ARGS resolved for WT-4a; run ids are a separate `--run-id <id>` per run and
158
- # belong to THIS check only — `spur workflow inline persist-out` accepts `--from` and
158
+ # belong to THIS check only — `spur workflow persist-out` accepts `--from` and
159
159
  # `--task-file` alone and exits 2 on `--run-id` (1089 driver note).
160
- spur workflow inline persist-check --from "$WT_PATH" "${TASK_FILE_ARGS[@]}" \
160
+ spur workflow persist-check --from "$WT_PATH" "${TASK_FILE_ARGS[@]}" \
161
161
  || { echo "WT-4 halt: worktree evidence would be abandoned - persist-out missing or stale (WT-5)" >&2; write_marker retained; exit 1; }
162
162
  git worktree remove "../<worktree-dir>" \
163
163
  || { echo "WT-4 halt: worktree remove failed after landed merge $BATCH_TIP" >&2; write_marker retained; exit 1; }
@@ -408,7 +408,7 @@ conflicts itself. Other halt causes (task failure, HITL pause) keep the hint as
408
408
  # (a test, a hook, a tool invocation) discards MERGE_HEAD silently. The failure is invisible
409
409
  # until the history is read — it produced a single-parent commit in run ada5a36c (task 1090),
410
410
  # which then needed an extra empty ancestry merge to repair. A cheap probe could not
411
- # reproduce it (MERGE_HEAD survived `bun run lint`, the rule preset and a test-file subset),
411
+ # reproduce it (MERGE_HEAD survived `spur self exec lint` (recorded then as the raw lint script), the rule preset and a test-file subset),
412
412
  # so the cross-command dependency is removed rather than diagnosed.
413
413
  git checkout <base-ref> && git merge --no-ff -m "<prepared message>" <branch>
414
414
 
@@ -443,7 +443,7 @@ git checkout <base-ref> && git merge --no-ff -m "<prepared message>" <branch>
443
443
  # ancestry).
444
444
 
445
445
  # 6. persist evidence out (WT-4a), then WT-4b/4c cleanup, and set the marker to merged
446
- spur workflow inline persist-out --from <worktree> --task-file …
446
+ spur workflow persist-out --from <worktree> --task-file …
447
447
  ```
448
448
 
449
449
  The report reuses the [`--next` chain contract](flag-glossary.md#--next-chain-contract) halt-report
@@ -79,8 +79,8 @@ inherits no cwd from the previous call, so "the loop runs with the worktree as p
79
79
  bootstrap convenience, never a carried guarantee. Every host command boundary in this lifecycle —
80
80
  corpus reads/writes, the WT-3b commit, WT-4's merge and evidence persistence, the WT-4a
81
81
  persist-out — re-selects its intended tree within the same call via the canonical per-call pin
82
- protocol ([inline-pipeline-driver.md](inline-pipeline-driver.md) § "Per-call execution-tree
83
- pin"): `cd --` to the quoted absolute tree, verify `pwd -P` against the recorded physical tree,
82
+ protocol ([execution-batch.md](execution-batch.md) § "Per-call execution-tree pin"):
83
+ `cd --` to the quoted absolute tree, verify `pwd -P` against the recorded physical tree,
84
84
  verify Git top-level and expected branch, then execute the already-resolved Spur invocation. The
85
85
  identity is consumed, not re-derived: it is the WT-3 marker's confirmed `path` + `branch` (or the
86
86
  resolved worktree's physical path + checked-out branch in reuse mode). The one deliberate tree
@@ -269,8 +269,8 @@ the tree's own source:
269
269
  cd "<worktree>" && bun apps/cli/src/index.ts task check <wbs> --json
270
270
 
271
271
  Run that as a per-call pin subshell (task 1058) — `cd --` plus the `pwd -P` / git-top-level /
272
- branch identity checks of the canonical protocol (inline-pipeline-driver.md § "Per-call
273
- execution-tree pin") — rather than relying on a persistent `cd` between host tool calls.
272
+ branch identity checks of the canonical protocol (execution-batch.md § "Per-call execution-tree
273
+ pin") — rather than relying on a persistent `cd` between host tool calls.
274
274
 
275
275
  Confirm isolation by making a distinctive change in the worktree and checking that
276
276
  the command reflects it.
@@ -17,7 +17,7 @@ catch it (the CLI catches schema violations, not intent errors).
17
17
  Run each checklist as an actual command sequence, not a mental confirmation:
18
18
 
19
19
  1. Read the checklist for the gate you are about to enter.
20
- 2. Run each verification command (grep, `spur task check`, `bun run lint`, etc.).
20
+ 2. Run each verification command (grep, `spur task check`, `spur self exec lint`, etc.).
21
21
  3. If any checkbox fails: stop, fix, re-run. Do not enter the gate.
22
22
  4. Only when every checkbox passes: enter the gate (run the CLI verb or trigger the workflow state).
23
23
 
@@ -89,7 +89,7 @@ Entered before `task-pipeline.yaml` `review` state dispatches `sp:code-verificat
89
89
  - [ ] The implementation matches the task's `## Plan` checklist (every checked item maps to a code/test/doc change).
90
90
  - [ ] `git status` shows only changes traceable to this task's Plan (no drive-by edits).
91
91
  - [ ] Check receipt current: `spur task gate <wbs> status` reports `reuse: true` for
92
- `.spur/run/<wbs>-check-receipt.json` at the current digest; run `bun run spur-check` only
92
+ `.spur/run/<wbs>-check-receipt.json` at the current digest; run `spur self exec check` only
93
93
  when it reports stale or missing (0940 — never re-run the full chain on a reusable receipt).
94
94
  - [ ] New `biome-ignore` / `eslint-disable` suppressions: none, or each is justified inline.
95
95
  - [ ] No new `console.*` in scripts (use a project logger if one exists).
@@ -176,9 +176,9 @@ transition to `done`.
176
176
 
177
177
  > **Finding-rule discipline (ADR-108).** When checker policy changes, run focused tests and one explicit unsuppressed `bun run corpus-check` audit; record/reconcile essential failures without waivers (T10). Ordinary corpus commit prep checks changed tasks/features and their required linked evidence, not the corpus (T11). The baseline and regenerators remain deleted; tests are not a substitute for the explicit policy-change audit.
178
178
  >
179
- > **Transition-shim discipline (`transition-shim-check`, task 0541 / ADR-058).** Wired as an early step of `spur-check` / `spur-check-new` (second, after `link-check` and before `lint`) so a shim violation fails in ~0.3 s rather than after the test run. Two-sided against `config/transition-shims.json`: an `@transition-shim(<id>)` marker with no manifest entry fails as a **new unregistered shim**, **and** a listed entry whose marker is gone from source fails as a **stale entry**. Emptying the manifest is the definition of the agent-role transition being complete. A removal condition must be objectively checkable against the repository. Shapes: `docs/04_DESIGN.md` §2.5.
179
+ > **Transition-shim discipline (`transition-shim-check`, task 0541 / ADR-058).** Wired as an early step of `spur-check-feature` (second, after `link-check`) so a shim violation fails in ~0.3 s rather than after the test run. Two-sided against `config/transition-shims.json`: an `@transition-shim(<id>)` marker with no manifest entry fails as a **new unregistered shim**, **and** a listed entry whose marker is gone from source fails as a **stale entry**. Emptying the manifest is the definition of the agent-role transition being complete. A removal condition must be objectively checkable against the repository. Shapes: `docs/04_DESIGN.md` §2.5.
180
180
 
181
- > **Sandbox test baseline (`bun run test` / `spur-check`).** In the restricted Bash sandbox
181
+ > **Sandbox test baseline (`bun run test` / `spur-check`).** In spur-new's restricted Bash sandbox
182
182
  > `bun run spur-check` exits **1 regardless of code health**: ~24 tests bind real ports and the
183
183
  > sandbox denies `listen`, so they fail environmentally. They cluster in seven suites — `spur
184
184
  > projects CLI`, `startServer`, `createServerContext`, `healthModule`, `rpc client`,
@@ -343,8 +343,26 @@
343
343
  },
344
344
  "builder": {
345
345
  "type": "object",
346
- "description": "Builder noun configuration. Currently hosts the release plumbing knobs for `spur builder bump-ver` / `drop-tags`; every field defaults to the built-in release convention, so an absent builder section keeps default behavior.",
346
+ "description": "Builder noun configuration. Hosts the release plumbing knobs for `spur builder bump-ver` / `drop-tags` and the SDLC action binding (`preset` + `actions`, ADR-139) that binds the reserved action vocabulary to this project's commands. Every field defaults to the built-in behavior, so an absent builder section keeps default behavior.",
347
347
  "properties": {
348
+ "preset": {
349
+ "type": "string",
350
+ "enum": ["bun", "none"],
351
+ "default": "bun",
352
+ "description": "Stack preset for the SDLC action vocabulary. `bun` (default) binds every reserved action to the legacy bun scripts, so a bun project needs no config change; `none` binds only the stack-neutral `spur rule run` presets (rules-pre, rules-post) and leaves every other undeclared action unbound."
353
+ },
354
+ "actions": {
355
+ "type": "object",
356
+ "default": {},
357
+ "propertyNames": { "pattern": "^[a-z][a-z0-9-]*$" },
358
+ "additionalProperties": {
359
+ "oneOf": [
360
+ { "type": "string", "minLength": 1, "pattern": "\\S" },
361
+ { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } }
362
+ ]
363
+ },
364
+ "description": "Action name -> one shell command, or a list of action names (composite, executed in order, fail-fast). A declared entry replaces the preset binding whole. Reserved names (closed in packages/config): build, dev, clean, format, autofix, lint, typecheck, test, test-full, test-heavy, rules-pre, rules-post, check, check-full, check-feature, lint-changed, typecheck-changed, test-changed; other names are custom (exec-only). Placeholders are allowed only in the scoped actions, each with its own set: lint-changed {files}, typecheck-changed {workspace}, test-changed {workspace} {paths}; and each substituted item is shell-quoted."
365
+ },
348
366
  "bump-ver": {
349
367
  "type": "object",
350
368
  "description": "Release knobs for bump-ver/drop-tags. Defaults: -v separator, publish.yml workflow, chore(release) commit, gh run list limit 5.",