@gobing-ai/spur 0.3.54 → 0.3.57
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 +2 -3
- package/config/corpus-baseline.json +2521 -49
- package/config/rules/strict/runtime-boundaries.yaml +3 -0
- package/config/rules/surface/check-cli-surface.yaml +1 -0
- package/config/workflow-composition-baseline.json +241 -22
- package/package.json +1 -1
- package/plugins/sp/agents/expert-spur.md +3 -0
- package/plugins/sp/commands/dev-idea.md +10 -14
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/task-size-precheck.ts +11 -6
- package/plugins/sp/skills/dogfood-testing/references/monitor-ledger.md +4 -4
- package/plugins/sp/skills/dogfood-testing/references/report-template.md +4 -2
- package/plugins/sp/skills/issue-finding/SKILL.md +23 -11
- package/plugins/sp/skills/spur-cli/SKILL.md +23 -15
- package/plugins/sp/skills/spur-cli/references/agent.md +5 -0
- package/plugins/sp/skills/spur-cli/references/builder.md +49 -0
- package/plugins/sp/skills/spur-cli/references/features.md +6 -1
- package/plugins/sp/skills/spur-cli/references/message.md +5 -0
- package/plugins/sp/skills/spur-cli/references/rules.md +5 -0
- package/plugins/sp/skills/spur-cli/references/self.md +101 -0
- package/plugins/sp/skills/spur-cli/references/tasks.md +6 -1
- package/plugins/sp/skills/spur-cli/references/team.md +5 -0
- package/plugins/sp/skills/spur-cli/references/workflows.md +40 -0
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +10 -9
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +19 -0
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +27 -5
- package/spur.js +1548 -316
|
@@ -25,7 +25,7 @@ colon form — the dash form `sp-dogfood-testing@…` is rejected in new runs.
|
|
|
25
25
|
Every dogfood run **always** writes **two** files — with or without `--save`:
|
|
26
26
|
|
|
27
27
|
| Artifact | Path | Role |
|
|
28
|
-
|
|
28
|
+
| ---------- | ------ | ------ |
|
|
29
29
|
| **Live** | `.spur/run/dogfood/<run_id>.md` | Mid-run SSOT; opened in Phase 1; ledger rows appended on every step resolve |
|
|
30
30
|
| **Report** | `docs/dogfood/YYYY-MM-DD-<testee-slug>-dogfood.md` | Operator artifact; same content promoted on open + every step + finalize |
|
|
31
31
|
|
|
@@ -59,7 +59,7 @@ workspace_fingerprint: ← optional — recorded in Phase 1 for fix-mode and
|
|
|
59
59
|
### Status model (partial-OK)
|
|
60
60
|
|
|
61
61
|
| `status` | When |
|
|
62
|
-
|
|
62
|
+
| ---------- | ------ |
|
|
63
63
|
| `running` | Phase 1 opened; steps still in progress |
|
|
64
64
|
| `aborted` | Finalize-or-abort after mid-run stop / incomplete narrative |
|
|
65
65
|
| `complete` | Phase 4 finished a normal end-of-run report |
|
|
@@ -238,6 +238,7 @@ downstream task creation does not inherit an unactionable acceptance criterion:
|
|
|
238
238
|
The tag is a prompt to whoever turns findings into tasks: `[stale]` → drop, `[unverifiable]` →
|
|
239
239
|
reframe or defer, `[feasible]` → proceed. A finding without a tag is treated as `[feasible]`.
|
|
240
240
|
Severity scale:
|
|
241
|
+
|
|
241
242
|
- **P1** — blocks correct use or causes drift/wrong output; fix before shipping the testee.
|
|
242
243
|
- **P2** — real friction or a latent correctness gap; fix soon. **Includes mandatory workspace-drift
|
|
243
244
|
finding:** when a drift row (`drift:external`) is present in the ledger, a P2 finding naming the
|
|
@@ -310,6 +311,7 @@ Findings (P1+P2):
|
|
|
310
311
|
```
|
|
311
312
|
|
|
312
313
|
Rules:
|
|
314
|
+
|
|
313
315
|
- **Result** and **Tokens** lines are mandatory; always tag token numbers `[~estimate]`.
|
|
314
316
|
- List Fixed / Unresolved / Findings; print `(none)` when empty — never omit a sub-list.
|
|
315
317
|
- With `--full`, Findings include P3+P4.
|
|
@@ -139,14 +139,23 @@ sessions (typed ETL via `spur history` — or raw JSONL under the three fallback
|
|
|
139
139
|
**Primary path (typed sources):** `spur history report --mode forensics` (task 0555).
|
|
140
140
|
|
|
141
141
|
```bash
|
|
142
|
-
# 0568 R4: SPUR_BIN env > local CLI
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
$SPUR_BIN
|
|
146
|
-
$SPUR_BIN
|
|
147
|
-
|
|
142
|
+
# 0568 R4 / 0504 R4: SPUR_BIN env > local CLI. NEVER a bare PATH `spur` for history validation —
|
|
143
|
+
# a stale global binary silently runs old code. If SPUR_BIN is unset and apps/cli/src/index.ts
|
|
144
|
+
# is absent, FAIL LOUDLY instead of falling back to PATH.
|
|
145
|
+
SPUR_BIN="${SPUR_BIN:-$([ -f apps/cli/src/index.ts ] && echo 'bun apps/cli/src/index.ts' || echo '')}"
|
|
146
|
+
[ -n "$SPUR_BIN" ] || { echo 'REFUSING: no source-local spur and SPUR_BIN unset (0504 R4)'; exit 1; }
|
|
147
|
+
|
|
148
|
+
$SPUR_BIN history import --source <source> --json # checkpoint resume; record provenance header
|
|
149
|
+
$SPUR_BIN history analyze --sessions <ids> --source <src> --json # narrow the artifact (T2: full run → 2.7 MB trap)
|
|
150
|
+
$SPUR_BIN history report --mode forensics # pure renderer; reads the LATEST artifact — verify it is the one you just wrote
|
|
148
151
|
```
|
|
149
152
|
|
|
153
|
+
**Artifact-size discipline:** `history analyze` without narrowing writes an artifact covering every
|
|
154
|
+
session in the DB — multi-MB blobs that drown the context. Narrow with `--sessions` / `--source` to
|
|
155
|
+
the corpus this investigation actually needs. `history report` renders whatever artifact the latest
|
|
156
|
+
pointer references; if you ran analyze for another purpose in between, re-run analyze (narrowed)
|
|
157
|
+
before reporting.
|
|
158
|
+
|
|
150
159
|
The forensics renderer emits **8 CLI-derivable sections**: Session Data Summary, Tool Breakdown,
|
|
151
160
|
Token Profile (tokens + cache-hit ratio — never prices), Time Decomposition, Per-Phase, Per-Tool
|
|
152
161
|
Execution Time, Bottleneck Ranking, and the Raw Data appendix. The CLI does not write the
|
|
@@ -271,7 +280,9 @@ EOF
|
|
|
271
280
|
spur task update <wbs> --section Background --from-file /tmp/issue-bg.md --json
|
|
272
281
|
```
|
|
273
282
|
|
|
274
|
-
**
|
|
283
|
+
**Recommended sections for a meta issue-finding task** (live matrix `.spur/tasks/section-matrix.yaml`
|
|
284
|
+
meta variant — `Root Cause` is allowed at every status; `Notes` and `References` are **not** defined
|
|
285
|
+
sections and must not be authored):
|
|
275
286
|
|
|
276
287
|
| Section | Content |
|
|
277
288
|
| ------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
@@ -281,17 +292,18 @@ spur task update <wbs> --section Background --from-file /tmp/issue-bg.md --json
|
|
|
281
292
|
| Q&A | 4–6 Q&A pairs: rationale, approach, hook vs guidance, savings, decomposition |
|
|
282
293
|
| Design | Per-fix evidence (counts, timestamps), fix content, target location |
|
|
283
294
|
| Plan | Ordered checkboxes referencing requirements |
|
|
284
|
-
|
|
|
285
|
-
|
|
295
|
+
| Root Cause | RC1–RC*n* analyses with forensic evidence — allowed at every status for meta tasks |
|
|
296
|
+
|
|
286
297
|
|
|
287
298
|
**Section format rules** (from task 0379):
|
|
288
299
|
|
|
289
300
|
1. **Solution `file:line` citations**: repo-relative `file:line` (e.g. `apps/web/src/components/SupervisorTab.tsx:17-20`), never bare `:line` or bare filename without path.
|
|
290
301
|
2. **Review P1–P4 table**: if a Review section exists, include a table with a cell matching
|
|
291
302
|
`/^\s*P[1-4]\s*$/` and a non-placeholder content cell.
|
|
292
|
-
3. **Meta template**:
|
|
303
|
+
3. **Meta template**: `Root Cause` is allowed at every status for meta tasks (live matrix) —
|
|
304
|
+
put RC analyses there, never in `Notes` or `References` (undefined sections).
|
|
293
305
|
4. **Canonical sections only**: `Background`, `Requirements`, `Acceptance Criteria`, `Q&A`,
|
|
294
|
-
`Design`, `Plan`, `Solution`, `Root Cause`, `Testing`, `Review`, `
|
|
306
|
+
`Design`, `Plan`, `Solution`, `Root Cause`, `Testing`, `Review`, `History`.
|
|
295
307
|
5. **Section body**: body-only for `--section` (no duplicate heading).
|
|
296
308
|
6. **Batch writes**: write all section temps → apply all `spur task update --section` calls →
|
|
297
309
|
**one** `spur task check`. Never write-check-rewrite-check per section.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spur-cli
|
|
3
|
-
description: "The CLI facade for the `spur` command surface - one reference per noun (task/feature/rule/workflow/agent/message/team/
|
|
3
|
+
description: "The CLI facade for the `spur` command surface - one reference per noun (task/feature/rule/workflow/builder/agent/message/team/self): verbs, flags, `--json` shapes, exit codes, the CLI-gated write contract. NOT for driving the lifecycle (that is the spine, sp:spur-dev). Triggers: \"spur task\", \"spur feature\", \"spur rule\", \"spur workflow\", \"spur agent\", \"spur message\", \"spur team\", \"spur self\", \"spur self init\", \"spur self status\", \"create a task\", \"task check\", \"batch-create\", or looking up any spur CLI verb or convention."
|
|
4
4
|
license: Apache-2.0
|
|
5
5
|
metadata:
|
|
6
6
|
author: spur
|
|
@@ -14,12 +14,11 @@ metadata:
|
|
|
14
14
|
- feature
|
|
15
15
|
- rule
|
|
16
16
|
- workflow
|
|
17
|
+
- builder
|
|
17
18
|
- agent
|
|
18
19
|
- message
|
|
19
20
|
- team
|
|
20
|
-
-
|
|
21
|
-
- init
|
|
22
|
-
- serve
|
|
21
|
+
- self
|
|
23
22
|
openclaw:
|
|
24
23
|
emoji: "🧰"
|
|
25
24
|
---
|
|
@@ -27,7 +26,7 @@ metadata:
|
|
|
27
26
|
# spur-cli — the CLI facade for the Spur command surface
|
|
28
27
|
|
|
29
28
|
`spur-cli` is the single reference for operating the **`spur` command-line surface**. Each `spur`
|
|
30
|
-
noun (`task`, `feature`, `rule`, `workflow`, `agent`, `message`, `team`, `
|
|
29
|
+
noun (`task`, `feature`, `rule`, `workflow`, `builder`, `agent`, `message`, `team`, `self`) has one reference file that documents *what each verb
|
|
31
30
|
is, how to use it well, its flags, `--json` shapes, and exit codes*. This skill is a **facade /
|
|
32
31
|
dispatch reference** — it tells you which verb does what and routes you to the noun's detail. It is
|
|
33
32
|
**not** an orchestrator and contains **no competency logic**: the skill knows *how to invoke*; the
|
|
@@ -38,17 +37,17 @@ CLI knows *what is valid*; the **spine** (`sp:spur-dev`) knows *how to drive the
|
|
|
38
37
|
Pick the noun, read its reference. Each Tier A and Tier B reference owns that noun's full verb catalog and conventions.
|
|
39
38
|
|
|
40
39
|
| Tier | Noun | Operate | Reference |
|
|
41
|
-
|
|
40
|
+
| ------ | ------ | --------- | ----------- |
|
|
42
41
|
| **Tier A** | **task** | Task corpus: create (variants), `deps` mutation, canonical `sections` (`init`/`add`/`list`), status lifecycle, `record`/`verdict` artifacts, `run-link`, `check --json` matrix | [references/tasks.md](references/tasks.md) |
|
|
43
42
|
| **Tier A** | **feature** | Feature tree: author with hierarchical IDs (DD-14), acceptance criteria (Gherkin), status lifecycle, move subtrees, `check --json` | [references/features.md](references/features.md) |
|
|
44
43
|
| **Tier A** | **rule** | Constraint quality gate: run presets, author rules, fine-tune, validate rule files/presets, extend engine | [references/rules.md](references/rules.md) |
|
|
45
44
|
| **Tier A** | **workflow** | Dual-mode workflow runtime: author state-machine / transition-flow workflows, validate, run, read traces | [references/workflows.md](references/workflows.md) |
|
|
45
|
+
| **Tier A** | **builder** | Release plumbing: bump a package (or the `workspace:`-pinned set) with `bump-ver`, delete release tags with `drop-tags`, commit + tag + optional push | [references/builder.md](references/builder.md) |
|
|
46
46
|
| **Tier B** | **agent** | Coding-agent execution surface: run prompts via detected/named agents, manage team agent specs, persistent self-draining loop, readiness check | [references/agent.md](references/agent.md) |
|
|
47
47
|
| **Tier B** | **message** | Durable inter-agent messaging: send, inbox, reply, watch | [references/message.md](references/message.md) |
|
|
48
48
|
| **Tier B** | **team** | Team coordination and supervision: assign, status, up/down rosters, start/stop supervised processes | [references/team.md](references/team.md) |
|
|
49
|
-
| **Tier B** | **
|
|
50
|
-
| **Tier
|
|
51
|
-
| **Tier C** | **history** / **migrate** / **projects** / **help** | Excluded while immature (see exclusion reasons below). Read `spur <noun> --help` as last resort | Last-resort `--help` |
|
|
49
|
+
| **Tier B** | **self** | Self-management verbs: scaffold (`init`), schema migrations (`migrate`), local web server (`serve`), status overview (`status`); `self init` runs post-scaffold validation probes & layout classification | [references/self.md](references/self.md) |
|
|
50
|
+
| **Tier C** | **history** / **projects** / **help** | Excluded while immature (see exclusion reasons below). Read `spur <noun> --help` as last resort | Last-resort `--help` |
|
|
52
51
|
|
|
53
52
|
**Execute-First Contract:** Load `sp:spur-cli` references first to execute Tier A and Tier B commands directly without calling `spur --help`. Use `spur <noun> --help` only as a last resort for Tier C nouns, version skew, unlisted long-tail flags, or parity assertion failures.
|
|
54
53
|
|
|
@@ -57,9 +56,8 @@ Pick the noun, read its reference. Each Tier A and Tier B reference owns that no
|
|
|
57
56
|
These nouns are intentionally undocumented - each has a concrete immaturity reason, not an oversight:
|
|
58
57
|
|
|
59
58
|
| Noun | Reason |
|
|
60
|
-
|
|
59
|
+
| ------ | -------- |
|
|
61
60
|
| `history` | `report` verb is a TODO stub (`spur history report` prints a marker); surface is still converging. |
|
|
62
|
-
| `migrate` | Zero verbs - bare `spur migrate --json` runs schema migrations. No verb catalog to document. |
|
|
63
61
|
| `projects` | Multi-project management surface (`add`/`remove`/`list`/`start`/`stop`); still evolving and not yet stable enough for a reference. |
|
|
64
62
|
| `help` | Auto-generated by Commander.js; not a real noun. |
|
|
65
63
|
|
|
@@ -105,6 +103,17 @@ the whole point of this facade is that the CLI surface has a single, scalable ho
|
|
|
105
103
|
semantics — including task and feature status-transition verbs — while multi-step lifecycle
|
|
106
104
|
orchestration belongs to `sp:spur-dev`.
|
|
107
105
|
|
|
106
|
+
## Shared option registry (0618)
|
|
107
|
+
|
|
108
|
+
Options shared by two or more command modules are declared once in
|
|
109
|
+
`apps/cli/src/commands/shared-options.ts` and spread at every call site
|
|
110
|
+
(`.option(...SHARED_OPTIONS.<key>)` — parser/default/collector args append after the spread). One
|
|
111
|
+
registry entry per **(flag, description) pair**: semantic homonyms (`--json`,
|
|
112
|
+
`--cwd`) keep separate keys with their distinct texts. When editing a command module, never
|
|
113
|
+
re-declare a shared flag inline — `apps/cli/tests/shared-option-parity.test.ts` fails on any literal
|
|
114
|
+
declaration of a flag string in `SHARED_OPTION_FLAGS`. Add a new shared option by adding the entry
|
|
115
|
+
and spreading it; full contract in `docs/04_DESIGN.md` §1.0.1.
|
|
116
|
+
|
|
108
117
|
## See also
|
|
109
118
|
|
|
110
119
|
- **[references/agent.md](references/agent.md)** - coding-agent execution surface (`run`, `loop`,
|
|
@@ -114,10 +123,9 @@ the whole point of this facade is that the CLI surface has a single, scalable ho
|
|
|
114
123
|
`inbox`, `reply`, `watch`).
|
|
115
124
|
- **[references/team.md](references/team.md)** - team coordination and supervision (`assign`,
|
|
116
125
|
`status`, `up`/`down`, `start`/`stop`).
|
|
117
|
-
- **[references/
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
post-scaffold init validation (Phase 1.5/1.6 probes).
|
|
126
|
+
- **[references/self.md](references/self.md)** - `spur self init|migrate|serve|status` CLI verbs
|
|
127
|
+
(the four legacy top-level nouns remain hidden aliases). `self init` runs post-scaffold init
|
|
128
|
+
validation (Phase 1.5/1.6 probes).
|
|
121
129
|
- **`sp:spur-dev`** - the spine that dispatches these verbs into the planning +
|
|
122
130
|
execution lifecycle. Use it to *drive* work; use this facade to *look up or operate a verb*.
|
|
123
131
|
- **`plugins/sp/references/roles.md`** — the Layer-1 role→tier table (`scribe` / `coder` /
|
|
@@ -215,3 +215,8 @@ spur agent delete worker-1 --force
|
|
|
215
215
|
supervision.
|
|
216
216
|
- **`spur message` (see [message.md](message.md))** - the inbox `--drain` reads from.
|
|
217
217
|
- **`sp:spur-cli`** SKILL.md - the facade that routes to this reference.
|
|
218
|
+
|
|
219
|
+
> **Shared option declarations (0618):** options shared across command modules resolve from
|
|
220
|
+
> `apps/cli/src/commands/shared-options.ts` (`SHARED_OPTIONS`). Never re-declare a shared flag
|
|
221
|
+
> inline in a command module — see SKILL.md "Shared option registry" and
|
|
222
|
+
> `docs/04_DESIGN.md` §1.0.1.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spur-cli-builder
|
|
3
|
+
description: "spur-cli noun reference: operate `spur builder` as the release plumbing surface - bump a workspace package (or the `workspace:`-pinned release set) with `bump-ver`, delete release tags with `drop-tags`, with commit + annotated tag + optional push. Promoted from spur-dev (task 0617, ADR-051); frozen at exactly these two verbs."
|
|
4
|
+
see_also:
|
|
5
|
+
- spur-cli
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# spur builder - release plumbing
|
|
9
|
+
|
|
10
|
+
`spur builder` is the CLI for **version bumps and release tags**. It wraps the internal
|
|
11
|
+
`spur-dev release` flow behind a public two-verb surface, promoted verbatim from
|
|
12
|
+
`scripts/commands/release.ts` (now a thin forwarder to the same implementation). Package ids are
|
|
13
|
+
the unscoped short names (`@gobing-ai/spur` → `spur`); the released set and the aggregate tag are
|
|
14
|
+
discovered from the repo's own workspace manifests, so the same code serves any git+semver
|
|
15
|
+
monorepo.
|
|
16
|
+
|
|
17
|
+
This noun is **frozen at exactly two verbs** by operator consent (`docs/design/harness-surface-governance.md`
|
|
18
|
+
§3) — do not invent additional `builder` subcommands.
|
|
19
|
+
|
|
20
|
+
## Verb map
|
|
21
|
+
|
|
22
|
+
| Verb | Purpose | Key flags |
|
|
23
|
+
| ---- | ------- | --------- |
|
|
24
|
+
| `bump-ver [package-id] <version>` | Bump one package (manifest + in-source `binaryVersion` + consumer `workspace:` pins), commit, tag, optionally push | `--all` `--push` `--json` |
|
|
25
|
+
| `drop-tags [package-id] <version>` | Delete a package's release tag (local only by default) | `--all` `--remote` `--json` |
|
|
26
|
+
|
|
27
|
+
A bare `bump-ver <version>` (single positional that parses as semver) or explicit `--all` bumps
|
|
28
|
+
every package pinned via `workspace:` by another workspace package, then adds per-package trace
|
|
29
|
+
tags plus the aggregate `@<scope>/<root>-v<version>` publish tag. `drop-tags --all` mirrors that
|
|
30
|
+
for deletion.
|
|
31
|
+
|
|
32
|
+
**Exit codes:** `0` success, `1` error (invalid semver, unknown package id, dirty tree, detached
|
|
33
|
+
HEAD, or an existing local/origin tag). **Errors abort before any write** — a re-run after fixing
|
|
34
|
+
the cause is safe.
|
|
35
|
+
|
|
36
|
+
## `bump-ver` - bump and tag a release
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
spur builder bump-ver spur 0.1.4 # one package: manifest, pins, commit, tag @gobing-ai/spur-v0.1.4
|
|
40
|
+
spur builder bump-ver --all 0.1.4 # every workspace:-pinned package + aggregate tag
|
|
41
|
+
spur builder bump-ver --all 0.1.4 --push # also push branch + tags to origin
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## `drop-tags` - delete release tags
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
spur builder drop-tags spur 0.1.4 # delete the local tag @gobing-ai/spur-v0.1.4
|
|
48
|
+
spur builder drop-tags --all 0.1.4 --remote # delete per-package + aggregate tags, locally and on origin
|
|
49
|
+
```
|
|
@@ -28,7 +28,7 @@ what* or *how to write a scenario*, this skill.
|
|
|
28
28
|
| `list` | List features, filtered | `--status <s>` `--priority <p>` `--folder` `--json` |
|
|
29
29
|
| `move <id>` | Re-parent a subtree (cascade-rename of descendants) | `--parent <id>` `--dry-run` `--folder` `--json` |
|
|
30
30
|
| `refresh` | Rebuild INDEX + each feature `## Tasks` table from task edges (**docs only**; no status change) | `--feature <id>` `--folder` `--json` |
|
|
31
|
-
| `check [id]` | Validate one feature / the tree; the 4-layer gate | `--strict` `--folder` `--json` |
|
|
31
|
+
| `check [id]` | Validate one feature / the tree; the 4-layer gate; `--fix` repairs structural findings in place | `--strict` `--fix` `--folder` `--json` |
|
|
32
32
|
| `sync [id]` | Align feature **lifecycle status** with linked task states (real transitions + guards) | `--all` `--dry-run` `--force` `--folder` `--json` |
|
|
33
33
|
|
|
34
34
|
**`refresh` vs `sync` (do not conflate):**
|
|
@@ -235,3 +235,8 @@ spur feature sync H2 --folder docs/custom-tasks --json # non-default tasks fol
|
|
|
235
235
|
*drive* planning; use this skill to *look up a verb* or *author AC*.
|
|
236
236
|
- **`spur task` (see [tasks.md](tasks.md))** — the companion for `spur task` (WBS lifecycle, section editing, the
|
|
237
237
|
readiness matrix).
|
|
238
|
+
|
|
239
|
+
> **Shared option declarations (0618):** options shared across command modules resolve from
|
|
240
|
+
> `apps/cli/src/commands/shared-options.ts` (`SHARED_OPTIONS`). Never re-declare a shared flag
|
|
241
|
+
> inline in a command module — see SKILL.md "Shared option registry" and
|
|
242
|
+
> `docs/04_DESIGN.md` §1.0.1.
|
|
@@ -107,3 +107,8 @@ lines.
|
|
|
107
107
|
- **`spur agent` (see [agent.md](agent.md))** - `run --drain` and `loop` consume the inbox.
|
|
108
108
|
- **`spur team` (see [team.md](team.md))** - team lifecycle that assigns agents to tasks.
|
|
109
109
|
- **`sp:spur-cli`** SKILL.md - the facade that routes to this reference.
|
|
110
|
+
|
|
111
|
+
> **Shared option declarations (0618):** options shared across command modules resolve from
|
|
112
|
+
> `apps/cli/src/commands/shared-options.ts` (`SHARED_OPTIONS`). Never re-declare a shared flag
|
|
113
|
+
> inline in a command module — see SKILL.md "Shared option registry" and
|
|
114
|
+
> `docs/04_DESIGN.md` §1.0.1.
|
|
@@ -207,3 +207,8 @@ directly on the command line.
|
|
|
207
207
|
|
|
208
208
|
**Template type**: technique
|
|
209
209
|
**Purpose**: Operate `spur rule` across its full lifecycle as the deterministic constraint gate in LLM code delivery
|
|
210
|
+
|
|
211
|
+
> **Shared option declarations (0618):** options shared across command modules resolve from
|
|
212
|
+
> `apps/cli/src/commands/shared-options.ts` (`SHARED_OPTIONS`). Never re-declare a shared flag
|
|
213
|
+
> inline in a command module — see SKILL.md "Shared option registry" and
|
|
214
|
+
> `docs/04_DESIGN.md` §1.0.1.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spur-cli-self
|
|
3
|
+
description: "spur-cli noun reference for `spur self`: self-management verbs — scaffold (`init`), schema migrations (`migrate`), local web server (`serve`), and status overview (`status`). Each verb mounts the same command builder as its legacy top-level noun, which remains a hidden alias over the identical command."
|
|
4
|
+
see_also:
|
|
5
|
+
- spur-cli
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# spur self - self-management verbs
|
|
9
|
+
|
|
10
|
+
`spur self` hosts the four self-management verbs. Each verb is the canonical path for a command
|
|
11
|
+
that also remains registered as a legacy top-level **hidden alias** (`spur init`, `spur migrate`,
|
|
12
|
+
`spur serve`, `spur status`) so existing scripts, workflow YAML, and habits keep working unchanged.
|
|
13
|
+
Both paths share the same command builder: identical flags, output, and exit codes. The legacy
|
|
14
|
+
top-level forms are omitted from `spur --help`, leaving `self` as the visible surface.
|
|
15
|
+
|
|
16
|
+
## Verb map
|
|
17
|
+
|
|
18
|
+
| Verb | Purpose | Key flags |
|
|
19
|
+
| ---- | ------- | --------- |
|
|
20
|
+
| `init` | Scaffold a new Spur project in the current directory | `--name <name>` `--force` `--minimal` `--json` |
|
|
21
|
+
| `migrate` | Apply CLI-owned schema migrations | `--json` |
|
|
22
|
+
| `serve` | Start the Spur web server (local fallback) | `--port <n>` `--host <addr>` `--no-open` `--cwd <path>` `--json` |
|
|
23
|
+
| `status [path]` | Show project and git status for a Spur project | `--json` |
|
|
24
|
+
|
|
25
|
+
**Deep detail lives in the verb-owner references** — **[init.md](init.md)** owns the `init` and
|
|
26
|
+
`status` verbs (scaffold semantics + the Phase 1.5 / 1.6 post-scaffold validation probes),
|
|
27
|
+
**[serve.md](serve.md)** owns the `serve` verb (server flags and dry-probe semantics). `migrate`
|
|
28
|
+
has no reference of its own and is documented inline below.
|
|
29
|
+
|
|
30
|
+
## `self init` - scaffold a Spur project
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
spur self init # interactive: prompt for project name
|
|
34
|
+
spur self init --name my-project # non-interactive
|
|
35
|
+
spur self init --name my-project --force # overwrite existing .spur/ files
|
|
36
|
+
spur self init --minimal # skip optional scaffolding (rules, workflows)
|
|
37
|
+
spur self init --json # machine-readable
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Materializes the `.spur/` directory tree with config, docs, rules, and workflow templates. Flags:
|
|
41
|
+
`--name <name>` (default: current directory name), `--force` (recreate existing files), `--minimal`
|
|
42
|
+
(skip optional scaffolding), `--json` (machine-readable output). Post-scaffold validation probes
|
|
43
|
+
(Phase 1.5 / 1.6) run immediately after this verb completes — see **[init.md](init.md)** for the
|
|
44
|
+
probe protocol and rule-glob adaptation procedure.
|
|
45
|
+
|
|
46
|
+
## `self migrate` - apply CLI-owned schema migrations
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
spur self migrate # apply pending migrations
|
|
50
|
+
spur self migrate --json # machine-readable { ok, applied }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Temporary helper: applies CLI-owned schema migrations and reports `{ ok, applied }`. Only flag is
|
|
54
|
+
`--json`.
|
|
55
|
+
|
|
56
|
+
## `self serve` - start the local web server
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
spur self serve # default: localhost:3000, opens browser
|
|
60
|
+
spur self serve --port 8080 --host 0.0.0.0
|
|
61
|
+
spur self serve --no-open # skip browser
|
|
62
|
+
spur self serve --json # dry probe: print { port, url, pid, running } and exit
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Starts the Hono/Cloudflare-Worker server that serves the web Task Kanban and exposes the team
|
|
66
|
+
supervisor API (`/api/team/*`). It is the local fallback when no remote server is configured.
|
|
67
|
+
Flags: `--port <n>`, `--host <addr>`, `--no-open`, `--cwd <path>`, `--json` (a dry probe — reports
|
|
68
|
+
the resolved port/url without starting the server). Full flag semantics: **[serve.md](serve.md)**.
|
|
69
|
+
|
|
70
|
+
## `self status [path]` - project and git status
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
spur self status # current directory
|
|
74
|
+
spur self status /path/to/project # specific project
|
|
75
|
+
spur self status --json # machine-readable
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Reports the project's Spur configuration state (init status, feature/task counts, rule preset
|
|
79
|
+
health) and git working-tree status. Optional `[path]` argument targets a different project
|
|
80
|
+
directory. Only flag is `--json`.
|
|
81
|
+
|
|
82
|
+
## What this skill is NOT
|
|
83
|
+
|
|
84
|
+
- **Not the team supervisor.** `self serve` hosts the supervisor API; `spur team start` / `stop` /
|
|
85
|
+
`status` are the verbs that drive it. See **[team.md](team.md)**.
|
|
86
|
+
- **Not a production server.** This is the local fallback. Production deployment uses the Cloudflare
|
|
87
|
+
Worker build (`apps/server/`), not `self serve`.
|
|
88
|
+
|
|
89
|
+
## See also
|
|
90
|
+
|
|
91
|
+
- **[init.md](init.md)** - `init` / `status` verbs: scaffold semantics and the Phase 1.5 / 1.6
|
|
92
|
+
post-scaffold validation probes.
|
|
93
|
+
- **[serve.md](serve.md)** - `serve` verb: server flags and the `--json` dry-probe contract.
|
|
94
|
+
- **`spur team` (see [team.md](team.md))** - `start`/`stop`/`status` require `self serve` for the
|
|
95
|
+
supervisor API.
|
|
96
|
+
- **`sp:spur-cli`** SKILL.md - the facade that routes to this reference.
|
|
97
|
+
|
|
98
|
+
> **Shared option declarations (0618):** options shared across command modules resolve from
|
|
99
|
+
> `apps/cli/src/commands/shared-options.ts` (`SHARED_OPTIONS`). Never re-declare a shared flag
|
|
100
|
+
> inline in a command module — see SKILL.md "Shared option registry" and
|
|
101
|
+
> `docs/04_DESIGN.md` §1.0.1.
|
|
@@ -51,7 +51,7 @@ re-reading or re-tokenizing the task.
|
|
|
51
51
|
| `batch-create` | Create many tasks from a validated JSON array | `--file <path>` `--folder` `--json` |
|
|
52
52
|
| `record <wbs>` | Write `Testing` from a verify verdict (deterministic); bare-`## Review` fallback only; optional Solution + transition | `--verdict-file <path>` `--solution-from-diff` `--transition <status>` `--folder` `--json` |
|
|
53
53
|
| `verdict <wbs>` | Derive PASS/PARTIAL/FAIL/UNKNOWN from verify answer text → verdict JSON; see [answer-file shape](tasks/verbs.md#answer-file-shape-what---from-answer-parses) | `--from-answer <path>` `--folder` `--json` |
|
|
54
|
-
| `check [wbs]` | Four-layer validation; the readiness matrix | `--strict` `--as <status>` `--strict-core` `--folder` `--json` |
|
|
54
|
+
| `check [wbs]` | Four-layer validation; the readiness matrix; `--fix` repairs structural findings in place | `--strict` `--as <status>` `--strict-core` `--fix` `--folder` `--json` |
|
|
55
55
|
| `resolve <file-path>` | Map a file path to its owning task WBS | `--strict` `--folder` `--json` |
|
|
56
56
|
| `path <wbs>` | Map a WBS to its absolute task file path (inverse of `resolve`) | `--folder` `--json` |
|
|
57
57
|
| `run-link <wbs>` | Record pipeline run provenance link for task | `--source <src>` `--run-id <id>` `--json` |
|
|
@@ -310,3 +310,8 @@ spur task path 0040 --json
|
|
|
310
310
|
execution loop. Use it to *drive* work; use this skill to *look up a verb*.
|
|
311
311
|
- **`spur feature` (see [features.md](features.md))** — the companion for `spur feature` (hierarchical IDs, AC conventions,
|
|
312
312
|
traceability).
|
|
313
|
+
|
|
314
|
+
> **Shared option declarations (0618):** options shared across command modules resolve from
|
|
315
|
+
> `apps/cli/src/commands/shared-options.ts` (`SHARED_OPTIONS`). Never re-declare a shared flag
|
|
316
|
+
> inline in a command module — see SKILL.md "Shared option registry" and
|
|
317
|
+
> `docs/04_DESIGN.md` §1.0.1.
|
|
@@ -138,3 +138,8 @@ process spawning. The started process runs `spur agent loop --agent <id>` under
|
|
|
138
138
|
- **`spur message` (see [message.md](message.md))** - the durable inbox team members drain.
|
|
139
139
|
- **`spur serve` (see [serve.md](serve.md))** - the local server `start`/`stop`/`status` require.
|
|
140
140
|
- **`sp:spur-cli`** SKILL.md - the facade that routes to this reference.
|
|
141
|
+
|
|
142
|
+
> **Shared option declarations (0618):** options shared across command modules resolve from
|
|
143
|
+
> `apps/cli/src/commands/shared-options.ts` (`SHARED_OPTIONS`). Never re-declare a shared flag
|
|
144
|
+
> inline in a command module — see SKILL.md "Shared option registry" and
|
|
145
|
+
> `docs/04_DESIGN.md` §1.0.1.
|
|
@@ -199,10 +199,45 @@ spur workflow run ./workflows/approval.yaml --steer # interactive
|
|
|
199
199
|
- **`--steer`** is synchronous and in-process: it cannot combine with `--json` or `--async` (exit `2`).
|
|
200
200
|
It accepts steering commands on stdin at declared action boundaries for interactive control.
|
|
201
201
|
|
|
202
|
+
## Composition measures and the advisory (0615)
|
|
203
|
+
|
|
204
|
+
`workflow validate` (valid path only) also reports a **warn-only composition advisory** covering the
|
|
205
|
+
two detectable measures from ADR-069. It answers "does this workflow lean on ad-hoc shell or raw
|
|
206
|
+
agent prompts where a first-class surface would own it better?" — nothing more.
|
|
207
|
+
|
|
208
|
+
**The two triggers:**
|
|
209
|
+
|
|
210
|
+
- **Shell measure** — a `shell` action (state hooks `onEnter`/`onExit`; guards are exempt) flags when
|
|
211
|
+
its `command` has **≥6** non-comment units (split on newline and `;`, blank/`#` units skipped).
|
|
212
|
+
- **agent.run measure** — an `agent.run` action flags when its `input` is a **non-slash** prompt;
|
|
213
|
+
raw prompt length only sets the reported severity (<200 low / ≤1000 medium / >1000 high).
|
|
214
|
+
|
|
215
|
+
**How to run it:** it is not a separate command — `spur workflow validate <file> --json` returns
|
|
216
|
+
`composition: {findings[], suppressed}` on the valid path; human mode prints the advisory to stderr
|
|
217
|
+
with exit 0. Actions with a recorded disposition in
|
|
218
|
+
`config/workflow-composition-baseline.json` (resolved by walking up from the workflow file) are
|
|
219
|
+
counted in `suppressed`, not `findings`.
|
|
220
|
+
|
|
221
|
+
**How to read it, and the fix path per defect class:**
|
|
222
|
+
|
|
223
|
+
- **Shell finding** → pick one of the five recorded owner options from
|
|
224
|
+
`docs/design/workflow-shell-ownership.md`: (a) public `spur` verb (consent-gated),
|
|
225
|
+
(b) application service, (c) least-privilege built-in action kind, (d) workflow-relative external
|
|
226
|
+
extension, (e) deliberately-stays-shell exception (record the reason in the baseline).
|
|
227
|
+
- **agent.run finding** → move the operation behind a centralized agent skill or slash command and
|
|
228
|
+
make the action's `input` reference it (ADR-043 preference).
|
|
229
|
+
|
|
230
|
+
**Advisory-only posture (binding):** findings never justify blocking a run, failing a gate, or
|
|
231
|
+
editing a pipeline that is currently executing. The advisory never changes `validate`'s exit status,
|
|
232
|
+
never blocks `workflow run`, and is not part of `spur-check` / `spur-check-new`. Treat a finding as
|
|
233
|
+
a to-be-enhanced note for the workflow's owner — surface it in your report, apply the fix only when
|
|
234
|
+
the operator accepts it, and never hot-edit a running workflow's shell in place.
|
|
235
|
+
|
|
202
236
|
## Command surface
|
|
203
237
|
|
|
204
238
|
```
|
|
205
239
|
spur workflow validate <file> [--no-schema] [--json]
|
|
240
|
+
spur workflow show <file>
|
|
206
241
|
spur workflow run <file> [--run-id <id>] [--vars <json>] [--dry-run] [--async] [--no-plan] [--quiet/--silent/--verbose] [--detail <level>] [--trace-file] [--no-log] [--steer] [--json]
|
|
207
242
|
spur workflow continue [run-id] [--yes] [--answer <yes|no|cancel>] [--json]
|
|
208
243
|
spur workflow cancel <run-id> [--json]
|
|
@@ -359,3 +394,8 @@ directly on the command line.
|
|
|
359
394
|
|
|
360
395
|
**Template type**: technique
|
|
361
396
|
**Purpose**: Operate `spur workflow` across its full lifecycle — choose the execution mode, author, validate, run, and refine dual-mode workflows
|
|
397
|
+
|
|
398
|
+
> **Shared option declarations (0618):** options shared across command modules resolve from
|
|
399
|
+
> `apps/cli/src/commands/shared-options.ts` (`SHARED_OPTIONS`). Never re-declare a shared flag
|
|
400
|
+
> inline in a command module — see SKILL.md "Shared option registry" and
|
|
401
|
+
> `docs/04_DESIGN.md` §1.0.1.
|
|
@@ -82,7 +82,7 @@ each would be scope creep for one-liner procedures.
|
|
|
82
82
|
| 13a | parallel | `dev-parallel` | `Skill()` | `sp:parallel-execution` | `--tasks <selector> [--feature <id>] [--mode <fan-out\|review-panel\|investigation>] [--agent <inline\|auto\|name>] [--json]` |
|
|
83
83
|
| 14 | wrap | `dev-wrap` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `<wbs> [--agent <inline\|auto\|name>] [--auto] [--merge] [--dry-run]` |
|
|
84
84
|
| 15 | wrapall | `dev-wrapall` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `[--since <iso>] [--feature <id>] [--status <s>] [--agent <inline\|auto\|name>] [--auto] [--merge] [--dry-run]` |
|
|
85
|
-
| 16 | idea | `dev-idea` | `Skill()` | `spur workflow run` (idea-pipeline) | `"<idea>" [--auto] [--skip-design] [--approve-taste]` |
|
|
85
|
+
| 16 | idea | `dev-idea` | `Skill()` | `spur workflow run` (idea-pipeline) | `"<idea>" [--auto] [--skip-design] [--approve-taste] [--agent <inline\|auto\|name>]` |
|
|
86
86
|
|
|
87
87
|
## Skill-backed operations
|
|
88
88
|
|
|
@@ -412,14 +412,15 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
|
|
|
412
412
|
- **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).
|
|
413
413
|
1. Run `bun run format` (add `-- <path>` if `--scope` is given) to settle formatter-only diffs first — `bun run lint` asserts `--error-on-warnings` + typecheck but does **not** rewrite formatting, so a formatter-only change (e.g. a multi-line import reflow) can pass `lint` locally yet still be unformatted. Formatting before linting removes that class of false-green.
|
|
414
414
|
2. Run `bun run lint` (add `-- <path>` if `--scope` is given). Collect all errors.
|
|
415
|
-
3. If
|
|
416
|
-
4.
|
|
417
|
-
5.
|
|
418
|
-
6.
|
|
419
|
-
7.
|
|
420
|
-
8. **
|
|
421
|
-
9. **
|
|
422
|
-
10.
|
|
415
|
+
3. **Surface-change sweep (before any fix).** If the failing set is a **surface/parity** change — CLI noun/verb/flag surface, reference-file structure, or a renamed/moved symbol — do one upfront `rg` sweep across ALL test dirs + docs for stale references to the changed symbols (e.g. `rg -l "<old-noun>|<old-file>.md|Tier C" apps/*/tests plugins/sp/tests plugins/sp/skills docs`), and fix every pinned test/docs file in that sweep. A surface change is pinned in **multiple independent test files** (each with its own hardcoded noun→reference map); discovering them one-by-one via full-suite probes is the dominant waste — each wave costs a suite run and a fresh edit loop (task 0436 R2 lesson). One sweep produces the complete edit set upfront.
|
|
416
|
+
4. If lint is clean, skip to step 6.
|
|
417
|
+
5. **Lint fix loop:** for each error, diagnose the root cause and apply the smallest fix. **Use targeted probes to verify each fix** (`bunx tsc --noEmit` on the affected package, `bun run lint -- <file>`) — do NOT re-run the full gate after every batch. Loop until lint is green.
|
|
418
|
+
6. Run `bun run test`. Collect all failures.
|
|
419
|
+
7. If tests are green, done.
|
|
420
|
+
8. **Test fix loop:** for each failure, diagnose (test bug vs implementation bug), apply the fix, re-run the **failing test only** (`bun test <file> --test-name-pattern "<test>"`). Do NOT re-run the full suite per fix — it is the dominant loop cost (task 0436 R2).
|
|
421
|
+
9. **Confirming run (at most once).** After all fixes, run `bun run format && bun run lint && bun run test` **at most once** to confirm. If it passes, the hop is done.
|
|
422
|
+
10. **Pipeline-awareness (R4, task 0483).** When `/sp:dev-fixall` is invoked from the pipeline's `test-fix` hop, `test-recheck` runs the full `${vars.qualityGateCmd}` gate immediately after this hop returns — that is the **deciding** run that writes PASS to `.spur/run/<wbs>-test-gate.status`. Do NOT re-run the full gate beyond the single confirming run in step 9; the deciding run belongs to `test-recheck`. If your confirming run already passed, return immediately — a second or third gate run inside this hop is pure redundancy (0482 ran the gate 3× plus a standalone `bun run test`; all four were followed by `test-recheck` running it a 5th time). If your confirming run failed and you fixed more, re-run the full gate once more within `--max-retry` budget, then return — let `test-recheck` judge.
|
|
423
|
+
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.
|
|
423
424
|
- **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. Never claim green on `bun run lint` alone — a formatter-only diff passes `lint` but fails the formatter; run `bun run format` (or assert it produces no diff) before declaring the gate clean. **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 `test-recheck` state be the deciding run.
|
|
424
425
|
- **MANDATORY Exit Condition.** The ONLY way to complete successfully:
|
|
425
426
|
1. Run validation command: `eval "$VALIDATION_CMD"`
|
|
@@ -734,6 +734,25 @@ command doc so it does not read as a bug.
|
|
|
734
734
|
`sp:super-planner` surfaces blockers/HITL only at the **batch boundary** (between task runs), not
|
|
735
735
|
from inside a pipeline step.
|
|
736
736
|
|
|
737
|
+
## Gate preflight (dogfood 2026-08-21, feature A3)
|
|
738
|
+
|
|
739
|
+
The A3 batch burned multiple full `spur-check-new` runs (~2 min each) that failed only at the tail
|
|
740
|
+
gates. The cheap rule gates fail fast when run first — the full-gate run is dominated by the ~65 s
|
|
741
|
+
test suite, so a gate run that dies at `test-post-check` or `corpus-check` wasted most of its wall
|
|
742
|
+
time. Before launching a full `spur-check-new`:
|
|
743
|
+
|
|
744
|
+
1. **Run the two rule gates first** — `bun run test-pre-check` (43 rules: `no-console-output`,
|
|
745
|
+
`no-direct-process-spawn`, `cli-*`, `require-corresponding-test`) and `bun run test-post-check`
|
|
746
|
+
(`every-export-has-tsdoc`, `coverage-gate`). They catch boundary/TSDoc violations in seconds.
|
|
747
|
+
2. **Promoted code must satisfy the boundary rules `scripts/` never enforced.** A command module
|
|
748
|
+
moving from `scripts/` into `apps/cli/src` must route output through the `CommandOutput` seam (no
|
|
749
|
+
`console.*`), spawn processes via `NodeProcessExecutor` (no `Bun.spawnSync`), get a
|
|
750
|
+
`runtime-boundaries` fs-io exemption for sync reads (mirrors `task.ts`), and a non-command helper
|
|
751
|
+
must not live in `apps/cli/src/commands/` (the noun scan treats every file there as a noun).
|
|
752
|
+
3. **Doc/TSDoc edits shift `file:line` anchors** cited by other tasks — `corpus-check` surfaces them
|
|
753
|
+
as `L4.anchor-subject-mismatch`. Repoint the shifted citations (via `spur task update --section`)
|
|
754
|
+
in the same commit, and reconcile new/stale baseline entries before the gate run.
|
|
755
|
+
|
|
737
756
|
## AC traceability
|
|
738
757
|
|
|
739
758
|
| AC | Where satisfied |
|
|
@@ -124,12 +124,34 @@ Transition guards are not advisory. Execute the declared guard exactly, in order
|
|
|
124
124
|
resolved variables and artifacts. `--no-lifecycle` remains bookkeeping only; the YAML's task checks,
|
|
125
125
|
verdict gate, record step, and done guard all remain authoritative.
|
|
126
126
|
|
|
127
|
-
##
|
|
127
|
+
## Record & done sequencing (dogfood 2026-08-21, feature A3)
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
Order matters for the `testing → done` hop. The A3 batch hit the same clobbering spiral on two
|
|
130
|
+
tasks (0617, 0619) because the sections were hand-written **before** the verdict artifact existed:
|
|
131
|
+
|
|
132
|
+
1. **Write the verdict artifact first.** `spur task record --solution-from-diff --transition testing`
|
|
133
|
+
reads `.spur/run/<wbs>-verdict.json` (default). With no artifact it emits a **UNKNOWN** verdict and
|
|
134
|
+
**overwrites** a hand-authored `## Testing` with an auto-generated "No requirements recorded" table,
|
|
135
|
+
plus replaces `## Solution` with a bare auto change-map. Creating the artifact first (PASS, with
|
|
136
|
+
requirement rows keyed by scenario title) makes `task record` the compliant path.
|
|
137
|
+
```bash
|
|
138
|
+
# verdict artifact first (shape: {wbs, verdict, requirements:[{id,status,evidence}], checks:[], source})
|
|
139
|
+
# then the record hop; then re-write Testing/Solution if record's backfill is thinner than intended.
|
|
140
|
+
spur task update <wbs> wip --no-lifecycle
|
|
141
|
+
spur task record <wbs> --solution-from-diff --transition testing
|
|
142
|
+
```
|
|
143
|
+
The engine now preserves an already-authored Testing when the verdict is UNKNOWN (task-service
|
|
144
|
+
`record` fallback-only, mirroring the Review 0593 precedent) — but the order above is still the
|
|
145
|
+
contract for the standard pipeline.
|
|
146
|
+
2. **Done-probe before done.** Run the check projected to `done` (`spur task check <wbs> --as done`
|
|
147
|
+
via the `TaskCheckService` probe pattern) — it surfaces `L3.unchecked-checklist` (flip `- [ ]` → `- [x]`)
|
|
148
|
+
and `L3.required-section-placeholder` before the transition, not after.
|
|
149
|
+
3. **Solution change-map anchor rule (L4.anchor-subject-mismatch).** A Solution change-map table must
|
|
150
|
+
list **one `file:line` per row**. A ·-joined paragraph makes every anchor's "subject" the other
|
|
151
|
+
anchors and trips the L4 subject check. Paths containing `_` (e.g. `docs/help/cmd_*.md`,
|
|
152
|
+
`spur-cli-matrix.md`) can **never** match their cited line — the snake_case filename token is
|
|
153
|
+
extracted as the subject and cannot appear in the line content — so drop those rows from the table
|
|
154
|
+
(prose still covers them).
|
|
133
155
|
|
|
134
156
|
## Failure contract
|
|
135
157
|
|