@gobing-ai/spur 0.3.97 → 0.3.98
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/package.json +1 -1
- package/plugins/sp/README.md +9 -9
- package/plugins/sp/lib/inline-run.generated.mjs +16 -9
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/references/roles.md +3 -3
- package/plugins/sp/scripts/inline-run-setup.mjs +4 -2
- package/plugins/sp/scripts/inline-run-setup.ts +12 -12
- package/plugins/sp/skills/code-implementation/SKILL.md +1 -1
- package/plugins/sp/skills/conflict-finding/SKILL.md +1 -1
- package/plugins/sp/skills/conflict-finding/references/authority-resolution.md +5 -3
- package/plugins/sp/skills/conflict-finding/references/remediation-routing.md +9 -8
- package/plugins/sp/skills/doc-evolve/SKILL.md +4 -3
- package/plugins/sp/skills/spur-cli/references/tasks/section-editing.md +7 -4
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +7 -4
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +16 -13
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +1 -1
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +7 -8
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +3 -0
- package/spur.js +483 -254
- package/web/_astro/{BoardApp.vveLOdDq.js → BoardApp.CYbe-OTb.js} +5 -5
- package/web/_astro/{BoardApp.Bmv5WkJ9.js → BoardApp.Dflq5a8x.js} +1 -1
- package/web/_astro/{TaskDetail.IKc3uDYV.js → TaskDetail.CK7oXddP.js} +1 -1
- package/web/_astro/{arc.C63Ufg35.js → arc.BIqkDATc.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.CP8Hyldk.js → architectureDiagram-3BPJPVTR.D0B3SvWv.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.Bo_48MRA.js → blockDiagram-GPEHLZMM.C2YyKQmL.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.Ch61sw-O.js → c4Diagram-AAUBKEIU.DmtTYrt_.js} +1 -1
- package/web/_astro/channel.JuKVyuhZ.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.CHpzS7xf.js → chunk-2J33WTMH.HsRXbh7l.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.DzMNNWIw.js → chunk-4BX2VUAB.obE_P-R3.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.BqPrDw_Q.js → chunk-55IACEB6.CjWTF5mz.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.ZzBHhNw-.js → chunk-727SXJPM.DMo799Ax.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.1_O_LLkx.js → chunk-AQP2D5EJ.-cE6JOKZ.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.GS4UHg7_.js → chunk-FMBD7UC4.D6Rw6HIk.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.BnqotN4g.js → chunk-ND2GUHAM.d5rBD73Z.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.Ghuh8zoJ.js → chunk-QZHKN3VN.r3ox40Q3.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.BW9vC3zg.js → classDiagram-4FO5ZUOK.CGGbvjjJ.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.BW9vC3zg.js → classDiagram-v2-Q7XG4LA2.CGGbvjjJ.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.D6jNC0ti.js → cose-bilkent-S5V4N54A.CmKtPd4l.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.BOGoCs4L.js → cynefin-OW5HDTMX.QNg5GXs8.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.8iU5VcWi.js → dagre-BM42HDAG.B1SabsjC.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.CVt88HwH.js → diagram-2AECGRRQ.RtDbNj89.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.C9HxUUMl.js → diagram-5GNKFQAL.IzZpuM-Y.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.4ywkQN3t.js → diagram-KO2AKTUF.DPTF_fgv.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.C48A6gpz.js → diagram-LMA3HP47.CCyza39P.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.DxFieQW4.js → diagram-OG6HWLK6.BXAi8zcZ.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.CtjtQqYs.js → erDiagram-TEJ5UH35.DUDX7_MR.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.C5zAiahU.js → flowDiagram-I6XJVG4X.C63QTh3N.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.D_L6zsny.js → ganttDiagram-6RSMTGT7.CnlZJSwG.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.Ignnrk3V.js → gitGraphDiagram-PVQCEYII.CTqIrOPC.js} +1 -1
- package/web/_astro/{infoDiagram-5YYISTIA.DLv8-P5u.js → infoDiagram-5YYISTIA.BYMiDFh9.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.p0OTpwFO.js → ishikawaDiagram-YF4QCWOH.CRiQmI-z.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.CIaBt-DD.js → journeyDiagram-JHISSGLW.YQgWBsEU.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.DGySIntq.js → kanban-definition-UN3LZRKU.1ECnrrK1.js} +1 -1
- package/web/_astro/{linear.BATV4RXu.js → linear.DzVA71yT.js} +1 -1
- package/web/_astro/{mermaid.core.DzkwM3VX.js → mermaid.core.BK7P2Sr_.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.3piBRRzA.js → mindmap-definition-RKZ34NQL.BvXyWZK7.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.DUNueLub.js → pieDiagram-4H26LBE5.BiXk1TW3.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.9bihVbrt.js → quadrantDiagram-W4KKPZXB.krvBH8lh.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.CkjsC-YT.js → requirementDiagram-4Y6WPE33.ih1gL25c.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.Dbq4vaoQ.js → sankeyDiagram-5OEKKPKP.CpUxkv4u.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.BivrH99P.js → sequenceDiagram-3UESZ5HK.clAfeN7y.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.CqLQ1Vzz.js → stateDiagram-AJRCARHV.DpXWb8-m.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.DvvoLD3b.js → stateDiagram-v2-BHNVJYJU.ClZb9GIH.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.B-KR78gv.js → timeline-definition-PNZ67QCA.BLcX5dh7.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.Ck0Eieb5.js → vennDiagram-CIIHVFJN.oGgpKMpx.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.CRfdd_do.js → wardleyDiagram-YWT4CUSO.BPHtMtt-.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.Ck_Jxk9C.js → xychartDiagram-2RQKCTM6.BNZOPYSk.js} +1 -1
- package/web/index.html +1 -1
- package/web/_astro/channel.BKCmJpWM.js +0 -1
package/plugins/sp/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.98",
|
|
4
4
|
"description": "Spur — a local-first harness engineering toolkit that wraps mainstream coding agents with constraint checking, workflow orchestration, and history analytics.",
|
|
5
5
|
"extensions": {
|
|
6
6
|
"pi": ["./hooks/pi/guard-extension.ts"]
|
|
@@ -91,9 +91,9 @@ must not sit below the highest `min_tier` among its folded stages.
|
|
|
91
91
|
architecture survey, feature-frontier prioritization, and feature-tree restructure. Folds `plan`,
|
|
92
92
|
`refine`, `brainstorm`.
|
|
93
93
|
|
|
94
|
-
**Placement notes (directory closure, task 0535).** The decided four-row table listed 31 commands
|
|
95
|
-
|
|
96
|
-
was removed in HA-S1 0661
|
|
94
|
+
**Placement notes (directory closure, task 0535).** The decided four-row table listed 31 commands.
|
|
95
|
+
The current command inventory comes from `plugins/sp/commands/`; `dev-history-load`
|
|
96
|
+
was removed in HA-S1 0661. The six additions to the original mapping were placed by the
|
|
97
97
|
same stage logic: `dev-refineall` folds `refine` → planner; `dev-find-next` is planning-side
|
|
98
98
|
frontier work → planner; `dev-feature-change` is planning-half corpus surgery on the feature tree →
|
|
99
99
|
planner; `dev-gtd` is the execution/delivery flow → coder; `dev-find-conflict` and `dev-find-issue`
|
|
@@ -15,7 +15,7 @@ function getEnvVar(name, fallback) {
|
|
|
15
15
|
|
|
16
16
|
// plugins/sp/scripts/inline-run-setup.ts
|
|
17
17
|
function usage() {
|
|
18
|
-
|
|
18
|
+
const text = [
|
|
19
19
|
"Usage: bun plugins/sp/scripts/inline-run-setup.ts --run-id <id> --file <definition> [--spur-bin <path>]",
|
|
20
20
|
" bun plugins/sp/scripts/inline-run-setup.ts --fingerprint --task-file <path> [--feature-file <path>] [--spur-bin <path>]",
|
|
21
21
|
" bun plugins/sp/scripts/inline-run-setup.ts --action --run-id <id> --node <state> --kind <kind> --status <done|failed> --ok <true|false> --duration-ms <n> [--spur-bin <path>]",
|
|
@@ -23,9 +23,11 @@ function usage() {
|
|
|
23
23
|
" bun plugins/sp/scripts/inline-run-setup.ts --close --run-id <id> --status <done|failed|paused> [--reason <terminal-reason>] [--spur-bin <path>]",
|
|
24
24
|
" bun plugins/sp/scripts/inline-run-setup.ts --persist-out --from <worktree-path> [--task-file <path>]... [--spur-bin <path>]",
|
|
25
25
|
" terminal-reason is a closed enum (0937 R2): done, paused-operator, failed-check, failed-agent, failed-timeout, failed-guard, cancelled, interrupted, retry-exhausted",
|
|
26
|
+
" close defaults (1051 AC1): --status done \u2192 reason done, --status paused \u2192 reason paused-operator; --status failed requires an explicit --reason",
|
|
26
27
|
" bun plugins/sp/scripts/inline-run-setup.ts --decide --run-id <id> --node <state> --options-json <file> [--spur-bin <path>]"
|
|
27
28
|
].join(`
|
|
28
|
-
`)
|
|
29
|
+
`);
|
|
30
|
+
console.error(text);
|
|
29
31
|
process.exit(2);
|
|
30
32
|
}
|
|
31
33
|
var SAFE_RUN_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
@@ -15,18 +15,18 @@ import { getEnvVar } from '../lib/env';
|
|
|
15
15
|
type InlineApp = typeof spurApp & { EMBEDDED_SPUR_SCHEMAS?: ReadonlyMap<string, string> };
|
|
16
16
|
|
|
17
17
|
function usage(): never {
|
|
18
|
-
|
|
19
|
-
[
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
);
|
|
18
|
+
const text = [
|
|
19
|
+
'Usage: bun plugins/sp/scripts/inline-run-setup.ts --run-id <id> --file <definition> [--spur-bin <path>]',
|
|
20
|
+
' bun plugins/sp/scripts/inline-run-setup.ts --fingerprint --task-file <path> [--feature-file <path>] [--spur-bin <path>]',
|
|
21
|
+
' bun plugins/sp/scripts/inline-run-setup.ts --action --run-id <id> --node <state> --kind <kind> --status <done|failed> --ok <true|false> --duration-ms <n> [--spur-bin <path>]',
|
|
22
|
+
' bun plugins/sp/scripts/inline-run-setup.ts --actions-file <json-file> --run-id <id> [--spur-bin <path>] (1007 R5 batch trace emission)',
|
|
23
|
+
' bun plugins/sp/scripts/inline-run-setup.ts --close --run-id <id> --status <done|failed|paused> [--reason <terminal-reason>] [--spur-bin <path>]',
|
|
24
|
+
' bun plugins/sp/scripts/inline-run-setup.ts --persist-out --from <worktree-path> [--task-file <path>]... [--spur-bin <path>]',
|
|
25
|
+
' terminal-reason is a closed enum (0937 R2): done, paused-operator, failed-check, failed-agent, failed-timeout, failed-guard, cancelled, interrupted, retry-exhausted',
|
|
26
|
+
' close defaults (1051 AC1): --status done → reason done, --status paused → reason paused-operator; --status failed requires an explicit --reason',
|
|
27
|
+
' bun plugins/sp/scripts/inline-run-setup.ts --decide --run-id <id> --node <state> --options-json <file> [--spur-bin <path>]',
|
|
28
|
+
].join('\n');
|
|
29
|
+
console.error(text);
|
|
30
30
|
process.exit(2);
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -184,7 +184,7 @@ reproduce → isolate → minimal fix → regression guard.
|
|
|
184
184
|
|
|
185
185
|
- Writing code without having read the immediate callers of what you're changing.
|
|
186
186
|
- A `## Solution` section that lists files but not what changed or why.
|
|
187
|
-
- A `## Solution` section with file references that are not in backtick `` `path:line` `` form (L3 requirement: `` `packages/app/src/foo.ts:123` `` or `` `packages/app/src/bar.ts:10-20` ``; paths from repo root).
|
|
187
|
+
- A `## Solution` section with file references that are not in backtick `` `path:line` `` form (L3 requirement: `` `packages/app/src/foo.ts:123` `` or `` `packages/app/src/bar.ts:10-20` ``; paths from repo root). Non-repo paths (external packages, `@scope/...`) can never resolve repo-relative — cite them in the frozen external-evidence form instead: `Evidence: @gobing-ai/ts-x \`src/persistence.ts\` line 108` (origin and line number OUTSIDE the backticks). Wrong: `` `@gobing-ai/ts-x/src/persistence.ts:108` `` — the L4 gate fails it as an unresolvable anchor (task 1055).
|
|
188
188
|
- A new abstraction with exactly one caller and no second use in sight.
|
|
189
189
|
- The diff touches files unrelated to the task's scope.
|
|
190
190
|
- The diff touches another WBS's surfaces, or the pass reads sibling `todo` / `wip` task files.
|
|
@@ -249,7 +249,7 @@ Thin wrapper: `Skill(skill="sp:conflict-finding", args="$ARGUMENTS")`.
|
|
|
249
249
|
- Silently omitting a selected pillar or a tool failure (no coverage accounting).
|
|
250
250
|
- Claiming "comprehensive" when `coverage.complete` is false.
|
|
251
251
|
- Any mutation in audit mode, or automatic mutation merely because `--resolve` is present.
|
|
252
|
-
- Editing a derived projection before its
|
|
252
|
+
- Editing a derived projection before correcting a defective authority, or changing a correct authority merely to repair its stale projection.
|
|
253
253
|
- Adding a production analyzer, index/cache/database, dependency, or dedicated subagent in v1.
|
|
254
254
|
|
|
255
255
|
## Reference files
|
|
@@ -206,13 +206,15 @@ authority it governs:
|
|
|
206
206
|
| Owner | Repair route | Governs (claim types) |
|
|
207
207
|
|-------|--------------|----------------------|
|
|
208
208
|
| Task/feature corpus | `sp:spur-cli` / `spur task` / `spur feature`; never direct file writes | Task obligation/status, feature goal and AC |
|
|
209
|
-
| Numbered docs and AGENTS projections | `sp:doc-evolve`; authority first,
|
|
209
|
+
| Numbered docs and AGENTS projections | `sp:doc-evolve`; inspect authority first, correct it only if defective, then repair affected projections | Process rules, structural decision, product scope, architecture, command surface |
|
|
210
210
|
| Source/tests | create/use a Spur task and route through `sp:spur-dev` / build competencies | Implementation behavior, architecture mechanism |
|
|
211
211
|
| Command/skill capability source | Superskill command/skill lifecycle in the owning plugin source | Command/API/schema surface |
|
|
212
212
|
| Ambiguous authority | **stop** for an operator decision; do not mutate either side | (all, when unresolved) |
|
|
213
213
|
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
Inspect the governing authority before repairing a derived projection. Correct the authority first
|
|
215
|
+
only when it is defective and the correction is authorized; otherwise leave it unchanged and repair
|
|
216
|
+
the projection. The authority column of §2 remains the owner surface's source of truth; a projection
|
|
217
|
+
is brought into line with it, not the reverse.
|
|
216
218
|
|
|
217
219
|
## 7. Worked examples
|
|
218
220
|
|
|
@@ -113,13 +113,13 @@ between "the audit said X" and "the file now says Y."
|
|
|
113
113
|
Each approved repair is dispatched through the artifact's **owner surface** — the harness path that
|
|
114
114
|
owns writes to that artifact — not a direct file write. Authority for a repair is the same
|
|
115
115
|
authority model as the audit ([./authority-resolution.md](./authority-resolution.md)): for a given
|
|
116
|
-
subject + claim type, one artifact is normative
|
|
117
|
-
authority.
|
|
116
|
+
subject + claim type, one artifact is normative. Inspect it first; correct it only if defective and
|
|
117
|
+
authorized, then update affected projections. A correct authority needs no edit for a stale projection.
|
|
118
118
|
|
|
119
119
|
| Owner | Repair route | Never |
|
|
120
120
|
|-------|--------------|-------|
|
|
121
121
|
| Task/feature corpus | `sp:spur-cli` — `spur task` / `spur feature` (with `--section`, `--from-file`, `--json` as needed) | Direct file writes to task/feature files. |
|
|
122
|
-
| Numbered docs and AGENTS projections | `sp:doc-evolve` —
|
|
122
|
+
| Numbered docs and AGENTS projections | `sp:doc-evolve` — inspect authority first; correct it only if defective, then repair affected projections (see below) | Changing correct authority to repair a stale projection, or projecting a defective authority before its authorized correction. |
|
|
123
123
|
| Source / tests | Create or use a **Spur task** and route through `sp:spur-dev` / build competencies (`sp:code-implementation`, `sp:code-testing`), **unless** the active session already has explicit implementation authority for the change. | Bare in-place edits to source/tests without a task or explicit authority. |
|
|
124
124
|
| Command/skill capability source | Superskill command/skill **lifecycle** (`superskill command …` / `superskill skill …` scaffold/validate/evaluate/refine) in the owning plugin source. | Hand-editing capability source outside the Superskill lifecycle. |
|
|
125
125
|
| Ambiguous authority | **Stop for an operator decision.** Do not mutate either side. | Choosing a winner, editing both sides, or forcing a global ranking. |
|
|
@@ -148,12 +148,13 @@ item; never route around it with a direct write.
|
|
|
148
148
|
|
|
149
149
|
### 3.2 Numbered docs and AGENTS projections
|
|
150
150
|
|
|
151
|
-
Documentation repairs
|
|
151
|
+
Documentation repairs **inspect authority first**. If a derived
|
|
152
152
|
projection (`docs/04_DESIGN.md`, `docs/05_FEATURES.md`, `AGENTS.md`, templates) has drifted from its
|
|
153
153
|
authority (`docs/00_ADR.md`, `docs/01_PRD.md`, `docs/03_ARCHITECTURE.md`,
|
|
154
|
-
`docs/99_PROJECT_CONSTITUTION.md`),
|
|
155
|
-
projection via `sp:doc-evolve`.
|
|
156
|
-
|
|
154
|
+
`docs/99_PROJECT_CONSTITUTION.md`), leave a correct authority unchanged and repair the stale
|
|
155
|
+
projection via `sp:doc-evolve`. If the authority itself is defective, correct it first within the
|
|
156
|
+
approved scope, then update affected projections. Incomparable authority still requires an operator
|
|
157
|
+
decision; projection drift alone never authorizes changing the governing contract (see §6).
|
|
157
158
|
|
|
158
159
|
`sp:doc-evolve` owns the numbered-doc/projection lifecycle: sync checks, contract verification,
|
|
159
160
|
frontmatter checks, and derived-doc refresh. A doc repair is dispatched to it; it is not hand-applied.
|
|
@@ -244,7 +245,7 @@ These are the explicit boundaries for remediation. Each is a hard violation, not
|
|
|
244
245
|
| Anti-pattern | Why it is prohibited |
|
|
245
246
|
|--------------|----------------------|
|
|
246
247
|
| **Automatic mutation merely because `--resolve` is present** | `--resolve` only opens the workflow; it never authorizes automatic repair. Confirmation + freshness + owner surface are all required. |
|
|
247
|
-
| **
|
|
248
|
+
| **Changing correct authority for projection drift** | A stale projection is repaired against its governing contract. Correct authority only when defective and authorized; then update affected projections. |
|
|
248
249
|
| **Broad cleanup outside confirmed findings** | Only the artifacts named by confirmed, freshness-checked findings are touched. No opportunistic refactors or doc "improvements" while repairing. |
|
|
249
250
|
| **Ambiguity silently resolved** | Ambiguous/missing authority stops for an operator decision; it is never forced through a global ranking or a guessed owner. |
|
|
250
251
|
| **Partial failure silently continued** | A failed repair is reported, not papered over; siblings are not marked successful and the run does not roll forward silently. |
|
|
@@ -100,9 +100,10 @@ rg --files apps packages # real modules
|
|
|
100
100
|
git log -1 --format='%ci' -- docs/04_DESIGN.md # last touch vs. recent surface changes
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
**Repair protocol (§7):**
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
**Repair protocol (§7):** inspect the governing statement first. Correct it only if defective and
|
|
104
|
+
authorized, then update affected detail/index/entry files; otherwise leave the authority unchanged
|
|
105
|
+
and repair its stale projections. Preserve ADR numbers, original titles/dates and decision history;
|
|
106
|
+
editorial condensation follows §6.1, while actual reversals need a superseding decision. Record findings in a task/report.
|
|
106
107
|
Routine lessons go to existing learning/context storage (§8); no automatic constitution edits.
|
|
107
108
|
|
|
108
109
|
Output a **drift report**: per finding, `{ doc, what code says, what the doc says, authority, repair
|
|
@@ -42,13 +42,16 @@ for `Plan`, `Acceptance Criteria`, hand-authored `Solution`, and any narrative s
|
|
|
42
42
|
spur task update 0040 --section Review --from-file /tmp/review.md
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
3. The whole `### Review` body is now that file's contents. To amend rather than overwrite,
|
|
46
|
-
the current body (`spur task show 0040`), edit the temp file to the full desired state, and
|
|
47
|
-
replace again —
|
|
45
|
+
3. The whole `### Review` body is now that file's contents. To amend rather than overwrite, either
|
|
46
|
+
read the current body (`spur task show 0040`), edit the temp file to the full desired state, and
|
|
47
|
+
replace again — or pass `--append` (task 1057) to write the file's body after the existing
|
|
48
|
+
section content (existing content + one blank line + new body; surrounding whitespace trimmed; an empty/missing section is
|
|
49
|
+
created). `--append` requires `--section` and never replaces on its own.
|
|
48
50
|
|
|
49
51
|
**`Q&A` is the exception.** `--section "Q&A"` APPENDS a timestamped `#### Q&A entry — <ISO>`
|
|
50
52
|
block rather than replacing the section. Start the body with `<!-- qa:replace -->` to replace it
|
|
51
|
-
wholesale.
|
|
53
|
+
wholesale. Explicit `--append` on `Q&A` uses the generic append (no timestamped wrapper); the
|
|
54
|
+
`<!-- qa:replace -->` marker still wins and forces wholesale replace.
|
|
52
55
|
|
|
53
56
|
`--section` **requires** `--from-file` (exit `2` otherwise). Section names match the DD-08 headings
|
|
54
57
|
exactly: `Background`, `Requirements`, `Acceptance Criteria`, `Q&A`, `Design`, `Plan`, `Solution`, `Root Cause`, `Testing`, `Review`, `References`, `History`, `Notes` (universal sections are `History`, `References`, `Notes`; `Root Cause` is carried by the `issue` template variant).
|
|
@@ -70,9 +70,12 @@ frontmatter scalar.
|
|
|
70
70
|
`testing→done` `check` gates above still run; the CLI evaluates them inline when the FSM guard
|
|
71
71
|
does not. `--force-done` waives the verify **verdict** only, never the section matrix.
|
|
72
72
|
- **Section** (`--section` **requires** `--from-file`): writes the named section body from the file.
|
|
73
|
-
Most sections replace wholesale.
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
Most sections replace wholesale. `--append` extends instead: existing body + one blank line + the
|
|
74
|
+
file's body (task 1057; empty/missing section is created; still requires `--section`). Exception:
|
|
75
|
+
`--section "Q&A"` APPENDS a timestamped `#### Q&A entry — <ISO>` block; start the body with
|
|
76
|
+
`<!-- qa:replace -->` to replace the section wholesale (explicit `--append` on `Q&A` uses the
|
|
77
|
+
generic append, marker still wins). No inline-body flag. Section names (case-sensitive):
|
|
78
|
+
`Background`, `Requirements`, `Acceptance Criteria`, `Q&A`, `Design`, `Plan`, `Solution`, `Testing`, `Review`, `References`, `History`, `Notes`.
|
|
76
79
|
- **Frontmatter** (`--feature <id>`, `--priority <p>`): sets the scalar frontmatter field on an
|
|
77
80
|
existing task — the only post-create path, allow-listed to `feature_id` / `parent_wbs` / `priority`.
|
|
78
81
|
- **Estimate** (`--estimate-hours <n>`): sets the `estimate_hours` frontmatter field (positive number) —
|
|
@@ -113,7 +116,7 @@ Flags: `--folder <path>`, `--json`. Exit codes: `0` success, `1` error, `2` usag
|
|
|
113
116
|
|
|
114
117
|
## `sections <wbs> <op> [name]`
|
|
115
118
|
|
|
116
|
-
CLI-safe, matrix-enforced task section mutation. Section names are validated against canonical sections (`Background`, `Requirements`, `Acceptance Criteria`, `Q&A`, `Design`, `Plan`, `Solution`, `Root Cause`, `Testing`, `Review`, `References`, `History`, `Notes`). Universal sections (`History`, `References`, `Notes`) are always allowed; `Root Cause` is carried by the `issue` template variant. `Q&A` on `update --section` appends rather than replacing (see the Section bullet above); `<!-- qa:replace -->` forces a wholesale replace.
|
|
119
|
+
CLI-safe, matrix-enforced task section mutation. Section names are validated against canonical sections (`Background`, `Requirements`, `Acceptance Criteria`, `Q&A`, `Design`, `Plan`, `Solution`, `Root Cause`, `Testing`, `Review`, `References`, `History`, `Notes`). Universal sections (`History`, `References`, `Notes`) are always allowed; `Root Cause` is carried by the `issue` template variant. `Q&A` on `update --section` appends rather than replacing (see the Section bullet above); `<!-- qa:replace -->` forces a wholesale replace. `--append` is the generic extend-after-existing path (task 1057).
|
|
117
120
|
|
|
118
121
|
| Op | Usage | Description |
|
|
119
122
|
| --- | --- | --- |
|
|
@@ -534,7 +534,8 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
|
|
|
534
534
|
- **Coverage** — bullet count equals the commit count in `<since>..<until>`, and every short hash appears exactly once.
|
|
535
535
|
- **Mapping** — per-category bullet counts match the conventional-type counts (`feat`→`Added`, `fix`→`Fixed`, other recognized types→`Changed`, unrecognized→`Other`).
|
|
536
536
|
- **Header** — `[<version>] - <date>` matches the resolved `--version` (or detected tag) and the header date.
|
|
537
|
-
- **
|
|
537
|
+
- **Citations** — a bullet that asserts API/library behavior or a version/dependency claim beyond its commit summary carries a source citation: an official docs URL, or a local `path:line` verified against the installed manifest/lockfile (`package.json`, lockfile, or the cited file). A commit hash is provenance for what shipped, not a citation for what the API/library does; an uncited claim is flagged inline on the bullet (`(uncited: <claim>)`) rather than silently dropped.
|
|
538
|
+
- **HIGH** — all checks pass with every API/library claim cited. **MEDIUM** — coverage intact but mapping or header deviates, or at least one API/library claim lacks a source citation. **LOW** — coverage broken (missing/duplicate hashes), the range cannot be reconciled against git, or a citation fails verification (dead URL, or a `path:line` that does not support the claim).
|
|
538
539
|
- **Invariants:** Never mutates `CHANGELOG.md` directly — the command surface is stdout-only; writing it to a file (e.g. appending to `CHANGELOG.md`) is the operator's redirect choice, never the command's.
|
|
539
540
|
|
|
540
541
|
### 9. gitmsg
|
|
@@ -624,25 +625,27 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
|
|
|
624
625
|
- **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 `test` hop; when present these ARE the failing set, so fix them in order and do not run the gate to discover what broke.
|
|
625
626
|
- **Backing:** `inline` — lint + test fix loop.
|
|
626
627
|
- **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).
|
|
627
|
-
1.
|
|
628
|
-
2. Run `bun run lint`
|
|
629
|
-
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.
|
|
628
|
+
1. Inspect the project's formatter command, then settle formatter-only diffs. Without `--scope`, use the project formatter (here `bun run 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 `bun run lint` checks formatting without rewriting it and also runs typecheck; formatting errors fail that check.
|
|
629
|
+
2. Run the project's read-only lint/type check (here `bun run lint`). Collect all errors. A repository-wide check may report outside-scope errors; report them without widening the authorized fix scope.
|
|
630
|
+
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 in-scope pinned test/docs file in that sweep; report outside-scope matches without editing them. 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.
|
|
630
631
|
4. If lint is clean, skip to step 6.
|
|
631
|
-
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, `
|
|
632
|
-
6.
|
|
633
|
-
7. If tests are green,
|
|
634
|
-
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).
|
|
635
|
-
9. **Confirming run — standalone invocation only (at most once).** After all fixes,
|
|
632
|
+
5. **Lint fix loop:** for each in-scope error, diagnose the root cause and apply the smallest fix. **Use targeted probes to verify each fix** (`bunx tsc --noEmit` on the affected package, `bunx biome check <file>`) — do NOT re-run the full gate after every batch. Loop until lint is green, or report outside-scope blockers without editing them.
|
|
633
|
+
6. For standalone execution, run `bun run test` and collect all failures. With `--gate-log`, use its failing set and targeted tests instead of running the full suite here.
|
|
634
|
+
7. If tests are green, proceed to the applicable standalone confirmation or pipeline handoff below.
|
|
635
|
+
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).
|
|
636
|
+
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 `bun run spur-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.
|
|
636
637
|
10. **Pipeline-awareness (R4, task 0483; confirming run dropped 2026-08-31).** `--gate-log` is set only by the pipeline's `test-fix` hop, so treat it as the pipeline signal. There, `test-recheck` 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 `test-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 `bun run lint`** (~7 s: Biome + typecheck) to catch type or lint breakage your fixes introduced. Then return and let `test-recheck` judge. `test-recheck` 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 `test-recheck` then ran it a 5th time.
|
|
637
638
|
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.
|
|
638
|
-
- **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.
|
|
639
|
-
- **MANDATORY Exit Condition.**
|
|
639
|
+
- **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 `test-recheck` state be the deciding run.
|
|
640
|
+
- **MANDATORY Exit Condition — standalone only.** At step 9, execute the following once; do not add another confirming run:
|
|
640
641
|
1. Run validation command: `eval "$VALIDATION_CMD"`
|
|
641
642
|
2. Capture exit code: `EXIT_CODE=$?`
|
|
642
643
|
3. Output: `echo "EXIT_CODE=$EXIT_CODE"`
|
|
643
644
|
4. **EXIT_CODE must equal 0**
|
|
644
645
|
|
|
645
|
-
If EXIT_CODE != 0: NOT completed.
|
|
646
|
+
If EXIT_CODE != 0: NOT completed. Continue the bounded fix loop for in-scope failures; report outside-scope blockers.
|
|
647
|
+
|
|
648
|
+
**Pipeline exit condition (`--gate-log` set):** return the fixes and the targeted-test/lint evidence from step 10 to `test-recheck`. Do not run the standalone validation command or claim a full-gate PASS; `test-recheck` owns that verdict.
|
|
646
649
|
|
|
647
650
|
**Hallucination Red Flags — STOP if you think:**
|
|
648
651
|
- "The errors look fixed" — check exit code, not appearance
|
|
@@ -671,7 +674,7 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
|
|
|
671
674
|
└─────────────────────────────────────────────────┘
|
|
672
675
|
```
|
|
673
676
|
|
|
674
|
-
The 7 phases
|
|
677
|
+
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 `test-recheck` instead of running Phase 7's full validation.
|
|
675
678
|
|
|
676
679
|
- **Fix Priority:**
|
|
677
680
|
|
|
@@ -530,7 +530,7 @@ pass before the invoking tree is written → WT-5. Without `--task-file` nothing
|
|
|
530
530
|
The shapes are pinned (task 0975 R1; `record-missing` and citation behavior per 0984): idempotent on re-persist;
|
|
531
531
|
success exits 0 printing
|
|
532
532
|
`{"ok":true,"persisted":<n>,"skipped":[{"id":<run-id>,"reason":"id-exists"|"external-key-conflict"|"record-conflict:<file>"|"record-missing:<file>"|"cited-directory:<name>"|"cited-symlink:<name>"|"cited-non-file:<name>"}]}`
|
|
533
|
-
— an `external-key-conflict` skip leaves the target run unchanged
|
|
533
|
+
— an `external-key-conflict` skip leaves the target run unchanged **and fails the pass (1049)**: the delegate exits 1 printing `{"ok":false,"error":…}` naming the skipped source run ids, because that (workflow, external key) identity already belongs to a different receiving run — the batch was not persisted, so reconcile the source worktree by hand (it stays the provenance owner of record) before any teardown: auditable reconciliation names the original archived DB snapshot and the skipped source run identities, verifies the archive by file hash and by merged-commit ancestry of the source branch, and treats any residual deletion as explicit operator-authorized cleanup under the strict canonical evidence rules above. An `id-exists` replay repairs missing owned artifacts and task links without duplicating them. A
|
|
534
534
|
`record-conflict:<file>` never overwrites a divergent invoking-tree record and causes the delegate to exit 1, retaining the worktree. A
|
|
535
535
|
`record-missing:<file>` skip is a known `task-lifecycle`/`feature-lifecycle` row with no record file
|
|
536
536
|
at all (its inserted DB row still counts in `persisted` — 0984 R5). Any failure
|
|
@@ -17,17 +17,16 @@ patterns, skill-backed, inline) remains in `dev-operations.md`.
|
|
|
17
17
|
|
|
18
18
|
Every flag shared by two or more commands has exactly one entry here. This is the single place a
|
|
19
19
|
shared flag's meaning is stated; command argument-hints and table rows cite it and must not
|
|
20
|
-
re-define it. The shared-flag set is derived mechanically from
|
|
20
|
+
re-define it. The shared-flag set is derived mechanically from all live `dev-*` command argument-hints (a flag
|
|
21
21
|
counts as shared when it appears in two or more); flags appearing on a single command stay documented
|
|
22
22
|
in that command's body and are not listed here.
|
|
23
23
|
|
|
24
|
-
**Reference form (mechanically detectable).**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
in the link form) do not count; the reference must be the link.
|
|
24
|
+
**Reference form (mechanically detectable).** Each `dev-*` command carries exactly one canonical
|
|
25
|
+
footer link to `../skills/spur-dev/references/flag-glossary.md`, enforced by
|
|
26
|
+
`scripts/commands/validate-commands.ts` (task 0412). Per-flag deep links are not required.
|
|
27
|
+
`command-flag-parity.test.ts` derives shared flags from all live hints and requires exactly one
|
|
28
|
+
canonical glossary entry per shared flag. Each entry retains its `#flag-<name>` anchor, where
|
|
29
|
+
`<name>` is the flag minus its leading `--` (so `--keep-going` → `#flag-keep-going`), for navigation.
|
|
31
30
|
|
|
32
31
|
**Availability rule.** Two flags are only declared where the underlying capability already exists:
|
|
33
32
|
`--json` where the command already produces a structured result a script could consume; `--auto`
|
|
@@ -75,6 +75,9 @@ the human/native presentation layer — labels are display addresses only, never
|
|
|
75
75
|
2. Allocate a collision-resistant inline run id (`uuidgen`, with a timestamp/pid fallback), create
|
|
76
76
|
`.spur/run/` for attempt staging and `.spur/memory/runs/` for retained records, and use the two-file run record (task 0927) — append lines to
|
|
77
77
|
`.spur/memory/runs/<run-id>.md` and read machine state from `.spur/memory/runs/<run-id>.state.json`.
|
|
78
|
+
The run id lives in those two files and the persisted run row — never stage it in an ad-hoc
|
|
79
|
+
`*.env` file: the `no-env-files` gate rule flags any `.env` name, so run-scoped staging files
|
|
80
|
+
use `<run-id>-*` names with `.md`/`.json`/`.txt`/`.status` extensions only.
|
|
78
81
|
3. **Authoritative run identity (task 0804 R1, fail-closed).** Persist the run row through the
|
|
79
82
|
internal delegate before any stage executes — this is what makes bound `run.artifact` record
|
|
80
83
|
accept the inline run (0785 R3):
|