@gobing-ai/spur 0.3.96 → 0.3.97

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 (87) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/rules/strict/runtime-boundaries.yaml +1 -0
  3. package/config/templates/AGENTS.md +3 -3
  4. package/config/workflows/wrapup-pipeline.yaml +2 -1
  5. package/package.json +2 -2
  6. package/plugins/sp/README.md +6 -0
  7. package/plugins/sp/commands/dev-job-dump.md +29 -0
  8. package/plugins/sp/commands/dev-job-resume.md +29 -0
  9. package/plugins/sp/lib/inline-run.generated.mjs +25 -16
  10. package/plugins/sp/lib/quality-gate.generated.mjs +12 -5
  11. package/plugins/sp/lib/residual-scan.generated.d.mts +1 -0
  12. package/plugins/sp/lib/residual-scan.generated.mjs +16 -0
  13. package/plugins/sp/plugin.json +1 -1
  14. package/plugins/sp/references/roles.md +2 -2
  15. package/plugins/sp/scripts/feature-verification-steps.mjs +14 -1
  16. package/plugins/sp/scripts/feature-verification-steps.ts +14 -1
  17. package/plugins/sp/scripts/quality-gate.mjs +13 -6
  18. package/plugins/sp/scripts/quality-gate.ts +1 -1
  19. package/plugins/sp/scripts/residual-scan.mjs +64 -38
  20. package/plugins/sp/scripts/residual-scan.ts +39 -34
  21. package/plugins/sp/scripts/wrapup-steps.mjs +64 -3
  22. package/plugins/sp/scripts/wrapup-steps.ts +122 -3
  23. package/plugins/sp/skills/source-driven-development/SKILL.md +11 -0
  24. package/plugins/sp/skills/spur-cli/references/tasks/section-editing.md +9 -5
  25. package/plugins/sp/skills/spur-cli/references/workflows.md +17 -14
  26. package/plugins/sp/skills/spur-dev/SKILL.md +2 -0
  27. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +3 -1
  28. package/plugins/sp/skills/spur-dev/references/dev-operations.md +79 -5
  29. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +4 -2
  30. package/plugins/sp/skills/spur-dev/references/execution-batch.md +8 -6
  31. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +3 -3
  32. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +9 -0
  33. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +43 -12
  34. package/spur.js +4246 -2996
  35. package/web/_astro/{BoardApp.BIjMatT1.js → BoardApp.Bmv5WkJ9.js} +1 -1
  36. package/web/_astro/BoardApp.vveLOdDq.js +322 -0
  37. package/web/_astro/{TaskDetail.BZM3EAFx.js → TaskDetail.IKc3uDYV.js} +1 -1
  38. package/web/_astro/{arc.HkRiZnoI.js → arc.C63Ufg35.js} +1 -1
  39. package/web/_astro/{architectureDiagram-3BPJPVTR.BDdK-tgZ.js → architectureDiagram-3BPJPVTR.CP8Hyldk.js} +1 -1
  40. package/web/_astro/{blockDiagram-GPEHLZMM.CZ9kOBxx.js → blockDiagram-GPEHLZMM.Bo_48MRA.js} +1 -1
  41. package/web/_astro/{c4Diagram-AAUBKEIU.DXK9qeRD.js → c4Diagram-AAUBKEIU.Ch61sw-O.js} +1 -1
  42. package/web/_astro/channel.BKCmJpWM.js +1 -0
  43. package/web/_astro/{chunk-2J33WTMH.BTD2WeX5.js → chunk-2J33WTMH.CHpzS7xf.js} +1 -1
  44. package/web/_astro/{chunk-4BX2VUAB.Ci6Qbcvk.js → chunk-4BX2VUAB.DzMNNWIw.js} +1 -1
  45. package/web/_astro/{chunk-55IACEB6.yl3zsj7p.js → chunk-55IACEB6.BqPrDw_Q.js} +1 -1
  46. package/web/_astro/{chunk-727SXJPM.ClXZsfyR.js → chunk-727SXJPM.ZzBHhNw-.js} +1 -1
  47. package/web/_astro/{chunk-AQP2D5EJ.BmKWZBcP.js → chunk-AQP2D5EJ.1_O_LLkx.js} +1 -1
  48. package/web/_astro/{chunk-FMBD7UC4.By30fcb7.js → chunk-FMBD7UC4.GS4UHg7_.js} +1 -1
  49. package/web/_astro/{chunk-ND2GUHAM.24NmrD-k.js → chunk-ND2GUHAM.BnqotN4g.js} +1 -1
  50. package/web/_astro/{chunk-QZHKN3VN.BN4sKdcS.js → chunk-QZHKN3VN.Ghuh8zoJ.js} +1 -1
  51. package/web/_astro/{classDiagram-4FO5ZUOK.CJpoMPb5.js → classDiagram-4FO5ZUOK.BW9vC3zg.js} +1 -1
  52. package/web/_astro/{classDiagram-v2-Q7XG4LA2.CJpoMPb5.js → classDiagram-v2-Q7XG4LA2.BW9vC3zg.js} +1 -1
  53. package/web/_astro/{cose-bilkent-S5V4N54A.BraxQ2Nt.js → cose-bilkent-S5V4N54A.D6jNC0ti.js} +1 -1
  54. package/web/_astro/{cynefin-OW5HDTMX.gzoU73oL.js → cynefin-OW5HDTMX.BOGoCs4L.js} +1 -1
  55. package/web/_astro/{dagre-BM42HDAG.wyDfWySU.js → dagre-BM42HDAG.8iU5VcWi.js} +1 -1
  56. package/web/_astro/{diagram-2AECGRRQ.h2_EbMxV.js → diagram-2AECGRRQ.CVt88HwH.js} +1 -1
  57. package/web/_astro/{diagram-5GNKFQAL.Db6dcs89.js → diagram-5GNKFQAL.C9HxUUMl.js} +1 -1
  58. package/web/_astro/{diagram-KO2AKTUF.NVwzxu_U.js → diagram-KO2AKTUF.4ywkQN3t.js} +1 -1
  59. package/web/_astro/{diagram-LMA3HP47.B-eNgDQk.js → diagram-LMA3HP47.C48A6gpz.js} +1 -1
  60. package/web/_astro/{diagram-OG6HWLK6.Bsa8ZRbJ.js → diagram-OG6HWLK6.DxFieQW4.js} +1 -1
  61. package/web/_astro/{erDiagram-TEJ5UH35.BospRE5Q.js → erDiagram-TEJ5UH35.CtjtQqYs.js} +1 -1
  62. package/web/_astro/{flowDiagram-I6XJVG4X.DMzvHwAA.js → flowDiagram-I6XJVG4X.C5zAiahU.js} +1 -1
  63. package/web/_astro/{ganttDiagram-6RSMTGT7.Dmdxgd-M.js → ganttDiagram-6RSMTGT7.D_L6zsny.js} +1 -1
  64. package/web/_astro/{gitGraphDiagram-PVQCEYII.CaqdO0rL.js → gitGraphDiagram-PVQCEYII.Ignnrk3V.js} +1 -1
  65. package/web/_astro/index.CbNz17Sx.css +1 -0
  66. package/web/_astro/{infoDiagram-5YYISTIA.DDVD9Wn7.js → infoDiagram-5YYISTIA.DLv8-P5u.js} +1 -1
  67. package/web/_astro/{ishikawaDiagram-YF4QCWOH.EKyCUFsL.js → ishikawaDiagram-YF4QCWOH.p0OTpwFO.js} +1 -1
  68. package/web/_astro/{journeyDiagram-JHISSGLW.By2-RkYB.js → journeyDiagram-JHISSGLW.CIaBt-DD.js} +1 -1
  69. package/web/_astro/{kanban-definition-UN3LZRKU.ar-WmlyR.js → kanban-definition-UN3LZRKU.DGySIntq.js} +1 -1
  70. package/web/_astro/{linear.BnzMBgo_.js → linear.BATV4RXu.js} +1 -1
  71. package/web/_astro/{mermaid.core.DSqeFu2Y.js → mermaid.core.DzkwM3VX.js} +4 -4
  72. package/web/_astro/{mindmap-definition-RKZ34NQL.1XcF8Wh2.js → mindmap-definition-RKZ34NQL.3piBRRzA.js} +1 -1
  73. package/web/_astro/{pieDiagram-4H26LBE5.DnItHOdK.js → pieDiagram-4H26LBE5.DUNueLub.js} +1 -1
  74. package/web/_astro/{quadrantDiagram-W4KKPZXB.BQQyrnBt.js → quadrantDiagram-W4KKPZXB.9bihVbrt.js} +1 -1
  75. package/web/_astro/{requirementDiagram-4Y6WPE33.Dmzxun82.js → requirementDiagram-4Y6WPE33.CkjsC-YT.js} +1 -1
  76. package/web/_astro/{sankeyDiagram-5OEKKPKP.BBIeRKYB.js → sankeyDiagram-5OEKKPKP.Dbq4vaoQ.js} +1 -1
  77. package/web/_astro/{sequenceDiagram-3UESZ5HK.CUNVdBBf.js → sequenceDiagram-3UESZ5HK.BivrH99P.js} +1 -1
  78. package/web/_astro/{stateDiagram-AJRCARHV.DlFf2sJm.js → stateDiagram-AJRCARHV.CqLQ1Vzz.js} +1 -1
  79. package/web/_astro/{stateDiagram-v2-BHNVJYJU.DXR7I1H5.js → stateDiagram-v2-BHNVJYJU.DvvoLD3b.js} +1 -1
  80. package/web/_astro/{timeline-definition-PNZ67QCA.BcO-GyX2.js → timeline-definition-PNZ67QCA.B-KR78gv.js} +1 -1
  81. package/web/_astro/{vennDiagram-CIIHVFJN.ChCECmmW.js → vennDiagram-CIIHVFJN.Ck0Eieb5.js} +1 -1
  82. package/web/_astro/{wardleyDiagram-YWT4CUSO.CRaT12mD.js → wardleyDiagram-YWT4CUSO.CRfdd_do.js} +1 -1
  83. package/web/_astro/{xychartDiagram-2RQKCTM6.B3lsHVpj.js → xychartDiagram-2RQKCTM6.Ck_Jxk9C.js} +1 -1
  84. package/web/index.html +2 -2
  85. package/web/_astro/BoardApp.GvjIe9Z6.js +0 -191
  86. package/web/_astro/channel.DlhX2MEt.js +0 -1
  87. package/web/_astro/index.EoZlzLK-.css +0 -1
@@ -15,7 +15,7 @@ table is the index; the per-operation sections below are the detail.
15
15
 
16
16
  | Pattern | Meaning | Commands |
17
17
  | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
18
- | `Skill()` | Delegates to a backing skill via `Skill(skill="<skill>", args="<op> $ARGUMENTS")`. The skill owns the procedure; the command is a thin entry point. | implement, unit, review, verify, verifyall, run, refine, refineall, plan, brainstorm, runall, parallel, wrap, wrapall, idea |
18
+ | `Skill()` | Delegates to a backing skill via `Skill(skill="<skill>", args="<op> $ARGUMENTS")`. The skill owns the procedure; the command is a thin entry point. | implement, unit, review, verify, verifyall, run, refine, refineall, plan, brainstorm, runall, parallel, wrap, wrapall, idea, job-dump, job-resume |
19
19
  | `inline` | The procedure is defined directly in the command file. No `Skill()` delegation — the command carries its own steps. | changelog, gitmsg, fixall, handover |
20
20
 
21
21
  The `Skill()` commands back onto six skills: `sp:spur-dev` (planning + execution workflow + batch),
@@ -39,10 +39,11 @@ each would be scope creep for one-liner procedures.
39
39
  > `plugins/sp/skills/history-anatomy/SKILL.md`.
40
40
 
41
41
  > **`dev-review-session`** is not in this table. It is a thin `Skill()` wrapper over
42
- > **`sp:session-review`** for an immediate, inline, report-only review of the active conversation.
43
- > It launches no workflow or agent and performs no import, persistence, or mutation. Use it before
44
- > the active session ends; use history-anatomy for ended sessions, cross-agent windows, trends, or
45
- > quantitative forensics.
42
+ > **`sp:session-review`** for an immediate, inline review of the active conversation. Report-only
43
+ > is the default; `--triage` applies pure-doc / one-to-two-line fixes and files remaining actionable
44
+ > findings as implement-ready tasks through the task CLI. It launches no workflow or agent and
45
+ > imports no history. Use it before the active session ends; use history-anatomy for ended sessions,
46
+ > cross-agent windows, trends, or quantitative forensics.
46
47
 
47
48
  > **`dev-find-conflict`** is not in this table. It is a thin `Skill()` wrapper over
48
49
  > **`sp:conflict-finding`** (authority-aware four-pillar semantic audit → optional confirmed,
@@ -80,6 +81,8 @@ each would be scope creep for one-liner procedures.
80
81
  | 9 | gitmsg | `dev-gitmsg` | `inline` | bounded diff capture → concern grouping → conventional commit | `[--commit] [--squash] [--all] [--scope <path>]` |
81
82
  | 10 | fixall | `dev-fixall` | `inline` | lint + test fix loop | `[<validation-command>] [--max-retry <n>] [--scope <path>] [--gate-log <path>] [--findings <anchors>]` |
82
83
  | 11 | handover | `dev-handover` | `inline` | structured doc generation | `"<blocker description>"` |
84
+ | 11a | job-dump | `dev-job-dump` | `Skill()` | `sp:spur-dev` (`job-dump`) | `--file <path>` |
85
+ | 11b | job-resume | `dev-job-resume` | `Skill()` | `sp:spur-dev` (`job-resume`) | `--file <path>` |
83
86
  | 12 | brainstorm | `dev-brainstorm` | `Skill()` | `sp:brainstorm` (`dev-brainstorm`) | `<topic> [--depth <basic\|detailed\|comprehensive>] [--options <n>] [--agent <inline\|auto\|name>] [--skip-discovery] [--wayfind] [--task [<feature-id>]] [--feature [<parent-id>]] [--next]` |
84
87
  | 13 | runall | `dev-runall` | `Skill()` → agent | `sp:spur-dev` (`runall`) → `sp:super-planner` | `--tasks <selector> [--feature <id>] [--mode <sequential\|parallel>] [--keep-going] [--auto] [--agent <inline\|auto\|name>] [--json] [--wrap] [--next] [--continue] [--worktree [<name>]]` |
85
88
  | 13a | parallel | `dev-parallel` | `Skill()` | `sp:parallel-execution` | `--tasks <selector> [--feature <id>] [--mode <fan-out\|review-panel\|investigation>] [--agent <inline\|auto\|name>] [--json]` |
@@ -337,6 +340,72 @@ must not be changed without updating the backing skill.
337
340
  - **Behavior:** Read the affected doc → apply the constitution's edit rules (single-source-of-truth, cross-reference updates, same-commit sync triggers) → write via the correct tool.
338
341
  - **Delegation:** `Skill(skill="sp:doc-evolve", args="$ARGUMENTS")` (no thin command wrapper)
339
342
 
343
+ ### 11a. job-dump
344
+
345
+ - **Purpose:** Transfer any unfinished job to another session, agent, or operator through a Markdown snapshot; a blocker or task/feature ID is optional.
346
+ - **Inputs:** Required `--file <path>`; shared path semantics live in [flag-glossary.md](flag-glossary.md).
347
+ - **Backing:** `sp:spur-dev`, in the current session. Use the [shared handoff template](#job-handoff-template).
348
+ - **Behavior:**
349
+ 1. Parse arguments, preserving quoted paths with spaces. Reject a missing/empty path, repeated `--file`, unknown flags, or extra positional arguments with usage. Resolve the absolute path before changing directories. Reject a directory target; create missing parent directories. Respect CLI-gated corpus writes: task/feature documents cannot be dump targets.
350
+ 2. Gather the mission, original invocation/options, approved outcome, completed and partial work, blockers, and next actions. Verify repository/worktree paths, branch, HEAD/base, dirty files and relevant commits with Git. Inspect referenced tasks/features/runs through the CLI facade with `--json` in their execution directory. Preserve frozen batch membership, dependency order, run IDs, workflow/checkpoint identity, failure policy, executor state and worktree marker when applicable. Record inspection time and provenance; label unavailable facts `unknown`.
351
+ 3. Fill every template section for this job; use `N/A` where inapplicable. Include uncommitted work and ownership, gate commands/results, pending questions, approvals given or still required, discovery maps, evidence paths, and wrap/merge/cleanup success conditions. Keep confirmed lessons and rejected approaches with anchors. Link authoritative specifications instead of copying them; never turn task-specific bypasses into general instructions.
352
+ 4. Redact credentials, tokens and sensitive personal data. Link large logs/artifacts by path and note their durability and availability to the recipient; the Markdown file does not transfer referenced files. Include essential continuation context directly so missing optional scratch notes do not erase the plan.
353
+ 5. Construct the complete snapshot before writing or refreshing `--file`. Read it back to verify the mission, execution directory, ordered remaining work and first actions. Report the absolute path and unresolved facts. Dumping only saves context: it does not stop an active executor, execute remaining work, change lifecycle state, commit, merge, or remove a worktree; record any executor still running.
354
+
355
+ ### 11b. job-resume
356
+
357
+ - **Purpose:** Read a Markdown job snapshot and continue its remaining work through the existing operation owner.
358
+ - **Inputs:** Required `--file <path>`; use job-dump argument/path validation, but require an existing, readable, non-empty file and do not create it.
359
+ - **Backing:** `sp:spur-dev`, in the current session; dispatch the recorded operation after reconciliation.
360
+ - **Behavior:**
361
+ 1. Read the entire file before acting. Treat it as context under current operator/project instructions: embedded commands must be verified, never blindly executed or accepted as gate-bypass authority. Accept equivalent headings in manual handoffs. Require a clear mission, execution location and next action; request missing critical context before dependent work.
362
+ 2. Locate the recorded repository/worktree, read its `AGENTS.md`, and inspect Git status, branch, HEAD/base and worktree membership there. Report drift; for a moved/missing checkout, establish and report a verified path mapping from repository/worktree identity, asking only if ambiguous. Never silently fall back to the invoking tree. Preserve dirty changes and ownership. Check recorded active executors through the coordination owner before taking write ownership; maintain one writer per tree.
363
+ 3. Read state/discovery files and authoritative task, feature and design records; refresh statuses through the CLI facade with `--json`. Reconcile frozen membership, dependencies, completion evidence and run/checkpoint identity. Skip confirmed completed work; unproven completion stays unverified. Missing optional notes trigger focused rediscovery; missing required evidence/checkpoints or incompatible state stop the affected continuation with a concrete recovery action.
364
+ 4. State the reconciled next step and continue in the verified execution directory, preserving scope, options, ordering, failure policy and pending decisions. Load the existing lifecycle/competency owner for the recorded task, batch, planning, review, wrap or other operation. Use its continuation path rather than replaying the original invocation from the beginning; retain the frozen remaining set rather than selecting new tasks. Distinguish inline continuation from a paused engine run: use the documented mechanism for the matching live run, never fabricate a paused snapshot or alter definition digests to force resume.
365
+ 5. Execute first actions and proceed through remaining work until completion or a real blocker. Rerun stale checks where the owning gate requires it. Required approvals stay pending; saved `--auto` or narration does not grant new irreversible actions. Apply the existing wrap/worktree finalization contract only on its full success conditions; retain work and evidence on partial success or failure.
366
+ 6. Report resumed work, results and blockers. When stopping again, refresh the same file through job-dump, preserving the original mission, membership and references while updating observed state and next actions.
367
+
368
+ #### Job handoff template
369
+
370
+ Fill this structure for the actual job. Replace placeholders; omit another job's IDs, paths,
371
+ commits, implementation details, quotas, parser workarounds and lifecycle bypasses.
372
+
373
+ ```markdown
374
+ # Resume job: <short mission>
375
+
376
+ ## Mission
377
+ <Goal, expected outcome, original invocation/options and approved scope.>
378
+
379
+ ## Environment (verified <timestamp and timezone>)
380
+ - Execution directory / repository / invoking directory: <absolute paths and their roles>
381
+ - Branch / base / HEAD / working-tree changes: <observed state and ownership>
382
+ - Runtime / CLI / executor: <verified invocation and availability>
383
+ - Run / workflow / checkpoint / worktree marker: <identity and state, or N/A>
384
+ - State, discovery maps and evidence: <paths, retention and availability>
385
+
386
+ ## Completed so far
387
+ <Completed items, commits and verification receipts; separate partial/uncommitted work.>
388
+
389
+ ## Remaining work, in order
390
+ 1. <Next item, dependency, current stage, authoritative specification and required gate.>
391
+ 2. <Subsequent items, then wrap/finalization and its success conditions.>
392
+
393
+ ## Execution mode
394
+ <Inline/delegated mode, one-writer ownership, frozen membership/order, failure policy,
395
+ gate commands, pending questions and approval requirements.>
396
+
397
+ ## Lessons and rejected approaches
398
+ <Verified pitfalls, discoveries and approaches ruled out, with evidence.>
399
+
400
+ ## Constraints and authoritative references
401
+ <Frozen decisions, boundaries, required reading and evidence paths; link specifications.>
402
+
403
+ ## First actions for the new session
404
+ 1. <Verify the execution directory and current repository/run state.>
405
+ 2. <Read state/discovery files and relevant authoritative records.>
406
+ 3. <Resume the next unfinished step through its existing owner.>
407
+ ```
408
+
340
409
  ### 12. brainstorm
341
410
 
342
411
  - **Purpose:** Interactive solution design — heuristic discovery interview (grilling) followed by structured ideation with trade-offs and confidence scoring.
@@ -461,6 +530,11 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
461
530
  - `keepachangelog` (default): `## [<version>] - <date>` header, then category headings per the keepachangelog convention — `### Added` / `### Fixed` / `### Changed` / `### Removed` / `### Other` — mapped from conventional-commit types.
462
531
  - `simple`: flat bulleted list grouped by type heading (`### feat`, `### fix`, …).
463
532
  6. Print the changelog to stdout. If the operator wants it in `CHANGELOG.md`, they redirect or paste.
533
+ 7. Verify the emitted section against git and close with one line: `Verification: HIGH|MEDIUM|LOW — <first failing check and deviation, or 'all checks passed'>`.
534
+ - **Coverage** — bullet count equals the commit count in `<since>..<until>`, and every short hash appears exactly once.
535
+ - **Mapping** — per-category bullet counts match the conventional-type counts (`feat`→`Added`, `fix`→`Fixed`, other recognized types→`Changed`, unrecognized→`Other`).
536
+ - **Header** — `[<version>] - <date>` matches the resolved `--version` (or detected tag) and the header date.
537
+ - **HIGH** — all three checks pass. **MEDIUM** — coverage intact but mapping or header deviates. **LOW** — coverage broken (missing/duplicate hashes) or the range cannot be reconciled against git.
464
538
  - **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.
465
539
 
466
540
  ### 9. gitmsg
@@ -77,12 +77,14 @@ timed-out-implement resume runbook in
77
77
  tree, and only then force-done if the pipeline is not worth re-driving. F6 below remains the
78
78
  recovery when the partial work is not worth keeping or the manual path is already complete.
79
79
 
80
- **1. Recognise it.** A timeout leaves `.spur/run/<runId>-<step>-partial.md` and the run reports
80
+ The writer retains the handoff in the run artifact directory and mirrors it into scratch for immediate compatibility. Older runs may have only the scratch copy.
81
+
82
+ **1. Recognise it.** A timeout leaves `.spur/memory/runs/<runId>/artifacts/<runId>-<step>-partial.md` and the run reports
81
83
  `exited with code 3`. That is a killed subprocess, not a failed assertion - do not read the
82
84
  partial file as a verdict.
83
85
 
84
86
  ```bash
85
- ls -la .spur/run/*-partial.md # handoff files, newest last
87
+ ls -la .spur/memory/runs/*/artifacts/*-partial.md # handoff files, newest last
86
88
  spur workflow trace <run-id> # confirm the terminal state
87
89
  ```
88
90
 
@@ -490,12 +490,12 @@ disk-full, missing directory) routes to **WT-5** — the worktree and branch are
490
490
  batch can never destroy its own evidence. Reuse mode retains its operator-owned tree but still
491
491
  persists the Step 5 report under the invoking tree; the reused tree's `.spur/run/` remains the live
492
492
  copy while that tree lives on. The per-run provenance — the worktree DB's run/action rows and the
493
- `.spur/run/<runId>.md` + `.state.json` records — is persisted mechanically by WT-4a's
493
+ `.spur/memory/runs/<runId>.md` + `.state.json` records — is persisted mechanically by WT-4a's
494
494
  `inline-run-setup.ts --persist-out --from <worktree> [--task-file <merged-task>]...` call,
495
495
  not by hand.
496
496
 
497
497
  **Stage records are worktree-local too (0948 R9, E7 Finding 5; persisted by 0975 R1).** Each task's
498
- own per-stage run record (`.spur/run/<runId>.md` + `.state.json`) and the worktree DB's run rows are
498
+ own per-stage run record (`.spur/memory/runs/<runId>.md` + `.state.json`) and the worktree DB's run rows are
499
499
  written inside the worktree and **are removed with it** in create mode — the E7 batch lost exactly
500
500
  this evidence. Copying them out is no longer a manual audit-time duty: WT-4a (create-mode block
501
501
  below) runs `inline-run-setup.ts --persist-out --from "$WT_PATH"` **before** WT-4b holder cleanup,
@@ -512,6 +512,8 @@ obligation; neither do root-qualified paths (`knowledge-kit/.spur/run/…`, `/ab
512
512
  which cite another project's evidence — cite foreign run artifacts that way, never bare. A citation missing in BOTH trees, a divergent cited file (never overwritten — reconcile
513
513
  by hand), an unreadable task file, or more than 64 distinct cited files fails the pass → WT-5.
514
514
 
515
+ **Durable planes ride it too (E71).** Persist-out copies canonical task verdicts, feature run/latest receipts, nested run artifacts and owned sessions before teardown. Artifact and task-run-link rows are exported with run rows, and stored path references are redirected to the invoking tree. Conflicting or unreadable retained evidence refuses teardown.
516
+
515
517
  **Owned evidence rides it too (1012).** With at least one `--task-file`, persist-out also treats as
516
518
  copy obligations the worktree's `.spur/run/` direct children named `<wbs>-…` (the WBS is each
517
519
  forwarded task file's leading four digits before `_`) or `<runId>-…` (every run row in the worktree
@@ -520,7 +522,7 @@ the task file cites them. They join the cited set: same copy / byte-identical no
520
522
  divergent-refuse handling. The 64-file cap bounds citations alone; owned names are bounded per
521
523
  owner (each `<wbs>-` / `<runId>-` prefix gets its own 64-file budget, task 1034), so the bound
522
524
  scales with the batch and one runaway owner refuses by name before any write. `<runId>.md` /
523
- `<runId>.state.json` stay with the record copy (a conflict there is a reported skip). Files
525
+ `<runId>.state.json` stay with the record copy (a conflict is reported and the delegate refuses teardown). Files
524
526
  matching neither a citation nor an ownership prefix are left behind. An absent worktree `.spur/run/`
525
527
  means nothing is owned; any other listing failure (not a directory, permission denied) fails the
526
528
  pass before the invoking tree is written → WT-5. Without `--task-file` nothing is enumerated.
@@ -528,8 +530,8 @@ pass before the invoking tree is written → WT-5. Without `--task-file` nothing
528
530
  The shapes are pinned (task 0975 R1; `record-missing` and citation behavior per 0984): idempotent on re-persist;
529
531
  success exits 0 printing
530
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>"}]}`
531
- — an `id-exists` / `external-key-conflict` skip never modifies the pre-existing target rows, a
532
- `record-conflict:<file>` skip never overwrites a divergent invoking-tree record, and a
533
+ — an `external-key-conflict` skip leaves the target run unchanged; an `id-exists` replay repairs missing owned artifacts and task links without duplicating them. A
534
+ `record-conflict:<file>` never overwrites a divergent invoking-tree record and causes the delegate to exit 1, retaining the worktree. A
533
535
  `record-missing:<file>` skip is a known `task-lifecycle`/`feature-lifecycle` row with no record file
534
536
  at all (its inserted DB row still counts in `persisted` — 0984 R5). Any failure
535
537
  exits 1 printing `{"ok":false,"error":<message>}` (a worktree DB run id that is not a single safe
@@ -867,7 +869,7 @@ git merge --ff-only "$BRANCH" # FF-only: never rebase, merge-commit, or
867
869
  # Any persistence failure routes to WT-5 — the worktree and branch are retained.
868
870
  WT_PATH="$(cd "../<worktree-dir>" && pwd)" # hoisted: needed by WT-4a AND WT-4b below
869
871
  # WT-4a provenance persist-out (task 0975 R1): copy the worktree DB's run rows plus
870
- # the .spur/run/<runId>.md + .state.json records into THIS tree. Run from the main
872
+ # the .spur/memory/runs/<runId>.md + .state.json records into THIS tree. Run from the main
871
873
  # tree (cwd = the invoking tree). --task-file (0984 R2) forwards each merged task
872
874
  # file (post-merge path) so the cited .spur/run/<file> evidence is copied/verified
873
875
  # too. Resolve the merged path(s) BEFORE this block — an empty value exits 2:
@@ -135,7 +135,7 @@ spur workflow trace "$RUN" --follow --output # streams the run; --output shows
135
135
  burned ~110 min in 47 sleeps and 55 trace polls waiting on one run; ADR-047 mandates pipe-free
136
136
  observation). `--follow` is a blocking human-streaming mode (no `--json`); run it in the session
137
137
  background and let its exit report the terminal verdict. Use `spur workflow trace "$RUN" --follow
138
- --output` to stream the non-interactive agent output to `.spur/run/<runId>.md` as it lands.
138
+ --output` to stream the non-interactive agent output to `.spur/memory/runs/<runId>.md` as it lands.
139
139
 
140
140
  Synchronous invocation (`--json` without `--async`) is acceptable **only** for short pipelines
141
141
  (< 2 min, e.g. precheck-only or a dry-run). Do not use it for the full task pipeline.
@@ -302,9 +302,9 @@ rather than raise again without sign-off").
302
302
  **2. Timed-out implement — resume from the partial tree, don't restart.** A timeout kills the
303
303
  implement `agent.run` (exit 3), the pipeline routes to `failed`, and the task stays `todo` with
304
304
  the partial work still in the working tree. The failure output names the partial-work artifact
305
- (`.spur/run/<runId>-implement-partial.md`) and this runbook. Recovery:
305
+ (`.spur/memory/runs/<runId>/artifacts/<runId>-implement-partial.md`) and this runbook. Recovery:
306
306
 
307
- 1. **Recognise.** `.spur/run/<runId>-implement-partial.md` exists, the run reported `exited
307
+ 1. **Recognise.** `.spur/memory/runs/<runId>/artifacts/<runId>-implement-partial.md` exists, the run reported `exited
308
308
  with code 3`, the task is at `todo`. The artifact's `git diff --stat` section is the partial
309
309
  work inventory.
310
310
  2. **Establish green from the partial files.** `bun run format` then `bun run lint` + `bun
@@ -35,6 +35,15 @@ where the command already has at least one HITL gate. The rule forces a declarat
35
35
  capability exists — a command that would benefit from `--json` but produces only prose is recorded
36
36
  as a follow-up, not quietly left inconsistent.
37
37
 
38
+ ### `--file <path>` — specify the operation's input or output file
39
+
40
+ **Anchor:** `#flag-file`.
41
+
42
+ Resolve relative paths against the invocation directory before switching to an execution
43
+ repository/worktree; preserve quoted paths with spaces. The command defines format and direction:
44
+ job-dump writes/refreshes Markdown, job-resume reads Markdown, and feature-change reads its mapping
45
+ file. Required for job-dump and job-resume; neither has a default path.
46
+
38
47
  ### `--agent <inline|auto|name>` — name who does the model-bearing work
39
48
 
40
49
  **Anchor:** `#flag-agent`.
@@ -11,6 +11,10 @@ see_also:
11
11
 
12
12
  # Inline Pipeline Driver
13
13
 
14
+ **Installed-copy drift (1046):** Superskill converts `/sp:dev-*` command spellings to
15
+ `/sp-dev-*` for Codex. After `superskill install sp`, this adapter-only difference remains;
16
+ the interpreter and trace instructions must match. Never hand-edit the installed reference.
17
+
14
18
  **Owner:** `spur-dev-maintainers` (per task 0755 R1). Reach the named owner via the frontmatter; no need to read the originating task.
15
19
 
16
20
  **Retirement criterion (0755 R5, D8 decision D7):** the per-task interpreter retires once the engine covers per-task execution for `/sp:dev-runall` with real terminal runs **and** the parity check (this doc's documented action/guard set ≡ the resolved action/guard set of every `.spur/workflows/*.yaml`) is green. Recording the criterion is part of this task; acting on it is not — that is a separate A3-gate decision.
@@ -69,8 +73,8 @@ the human/native presentation layer — labels are display addresses only, never
69
73
  1. Resolve the command inputs, `--auto`, and any explicit `--vars` — **without reading the selected
70
74
  YAML yet**. An explicit non-inline executor selection chooses the subprocess workflow path.
71
75
  2. Allocate a collision-resistant inline run id (`uuidgen`, with a timestamp/pid fallback), create
72
- `.spur/run/`, and use the two-file run record (task 0927) — append lines to
73
- `.spur/run/<run-id>.md` and read machine state from `.spur/run/<run-id>.state.json`.
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
+ `.spur/memory/runs/<run-id>.md` and read machine state from `.spur/memory/runs/<run-id>.state.json`.
74
78
  3. **Authoritative run identity (task 0804 R1, fail-closed).** Persist the run row through the
75
79
  internal delegate before any stage executes — this is what makes bound `run.artifact` record
76
80
  accept the inline run (0785 R3):
@@ -91,7 +95,7 @@ the human/native presentation layer — labels are display addresses only, never
91
95
  obtains the selected definition from the existing CLI `workflow show --format todo --json`
92
96
  projection and revalidates its schema/name/digest before preserving its source layer.
93
97
  Both paths create-or-attach the row,
94
- and writes the run-record state `.spur/run/<run-id>.state.json` plus the `.md` run-start
98
+ and writes the run-record state `.spur/memory/runs/<run-id>.state.json` plus the `.md` run-start
95
99
  header (task 0927; a legacy pre-0927 run keeps its `<run-id>-inline-setup.json` sidecar).
96
100
  Seed `__runId` and `__definitionDigest`
97
101
  from that state so proof capture and bound registration verify against the persisted identity.
@@ -236,6 +240,19 @@ Start at `initialState`. For each current state, execute its `onEnter` actions i
236
240
  then evaluate outgoing transitions in declaration order and take the first passing guard. Stop only
237
241
  at a declared terminal state or a surfaced HITL pause. The `iterationBound` remains mandatory.
238
242
 
243
+ After each executed action settles, record its boundary before the next action, transition guard,
244
+ or terminal close. Measure its actual duration and preserve its declared failure policy:
245
+
246
+ ```bash
247
+ bun "$SETUP_SCRIPT" --action --run-id "$RUN_ID" --node <state-id> --kind <action-kind> \
248
+ --status <done|failed> --ok <true|false> --duration-ms <measured-ms>
249
+ ```
250
+
251
+ For a multi-action state, `--actions-file` may emit the measured boundaries together before leaving
252
+ that state. Follow [Structured trace emission](#structured-trace-emission-adr-117-task-0868) for the
253
+ payload, delegated `decide` emission and best-effort failure handling. Never retry a failed batch
254
+ or backfill at close; a zero-row done close fails with `NO_ACTION_ROWS`.
255
+
239
256
  Action semantics come from the YAML and the workflow action contract:
240
257
 
241
258
  - `shell` — run the expanded command in the project working tree with resolved vars exported as
@@ -280,12 +297,12 @@ Action semantics come from the YAML and the workflow action contract:
280
297
  and pass the same `--feature-file` the run folded in — omitting it, or running from elsewhere,
281
298
  yields a different digest and the mismatch surfaces later as a refused `run.artifact`
282
299
  registration — and the run-scoped review-completion marker exists — then appends one provenance
283
- line to `.spur/run/<run-id>.md` naming the equivalence (artifact kind, path, verdict, digest) and
300
+ line to `.spur/memory/runs/<run-id>.md` naming the equivalence (artifact kind, path, verdict, digest) and
284
301
  proceeds to `spur task record`. A failed validation stops at the state and follows the failure
285
302
  contract; the step is never silently skipped. Artifact-provenance consumers read that run-log
286
303
  line on the inline path — there is no ledger row. The validation also includes **run/definition
287
304
  identity agreement from authoritative evidence** (task 0809 R4): the verdict's `proof.runId` and
288
- `proof.definitionDigest` must agree with the run-record state `.spur/run/<run-id>.state.json`
305
+ `proof.definitionDigest` must agree with the run-record state `.spur/memory/runs/<run-id>.state.json`
289
306
  (legacy pre-0927 runs: `<run-id>-inline-setup.json`) and the persisted run row; if that identity
290
307
  is absent or conflicts, STOP — recreating a row is
291
308
  not a diagnostic operation. The app-service bound-artifact fixture (which writes a real engine
@@ -314,6 +331,18 @@ Action semantics come from the YAML and the workflow action contract:
314
331
  with no `estimate_hours` passes this condition unchanged. The driver reads the frontmatter value
315
332
  directly — never estimates size itself.
316
333
 
334
+ **Diffstat arm (verify only, 1033 R1).** When the current state id is `verify`, condition 5
335
+ fails when the triage diffstat file `.spur/run/<wbs>-diffstat.json` exists and shows a
336
+ small, non-sensitive diff: `([.files, .insertions, .deletions] | all(type == "number")) and
337
+ .files <= 3 and (.insertions + .deletions) <= 60 and
338
+ .sensitive == false` (literal thresholds; the driver reads the file with `jq` — it never
339
+ estimates size itself). A missing, unparsable or `sensitive: true` diffstat leaves condition 5
340
+ as above, so the failure mode is more isolation, never less. A missing or null count also leaves
341
+ condition 5 as above. Below the floor on this arm, the
342
+ run log carries `stage verify executed inline in session <session-id> (below dispatch floor:
343
+ diffstat files <f> lines <n>)`. Only `verify` eligibility changes: `implement` and `review`
344
+ keep the estimate floor, and the pipeline state graph is unchanged.
345
+
317
346
  All five pass → dispatch. Any pre-dispatch failure → execute the stage **once** in the host session.
318
347
  An `agent.run` whose `input` is free-form prose rather than a pure slash command fails condition 2
319
348
  and is never dispatch-eligible: the driver executes it in the host session and logs it with the
@@ -465,7 +494,7 @@ or an operator decision returns a blocker; the host pauses at the current state
465
494
  subagent cannot approve, infer consent, or recursively invoke the full pipeline.
466
495
 
467
496
  After every successful inline `agent.run` action append exactly one provenance line (inline or
468
- subagent form above) to `.spur/run/<run-id>.md`, where `<id>` is the current YAML state id. Also
497
+ subagent form above) to `.spur/memory/runs/<run-id>.md`, where `<id>` is the current YAML state id. Also
469
498
  log start/failure and the ignored timeout value so an inline run remains auditable without
470
499
  fabricating an `AgentRunTracedResult`.
471
500
 
@@ -477,7 +506,7 @@ in one file and makes the run unauditable (task 0726 mixed both forms).
477
506
 
478
507
  ## Structured trace emission (ADR-117, task 0868)
479
508
 
480
- `.spur/run/<run-id>.md` is the human half of the two-file run record — evidence, **not the record
509
+ `.spur/memory/runs/<run-id>.md` is the human half of the two-file run record — evidence, **not the record
481
510
  of truth**. A run's
482
511
  observability is a property of the run, so the inline driver owes the same structured trace the
483
512
  engine subprocess writes — and it owes it through the **same writer**, never a parallel
@@ -570,7 +599,7 @@ The driver reaches it through the existing run delegate (`$SETUP_SCRIPT`,
570
599
  nothing), and any `done` close with `actionRows ≥ 1` exits `0`.
571
600
 
572
601
  **Best-effort at the action boundary only (ADR-117).** An `--action` persistence failure is
573
- recorded — the delegate appends a `trace-emission-failed` line to `.spur/run/<run-id>.md` and
602
+ recorded — the delegate appends a `trace-emission-failed` line to `.spur/memory/runs/<run-id>.md` and
574
603
  prints `{"ok":false}` on stdout — and the run continues to its declared terminal state; the
575
604
  delegate exits `0` for that outcome and the driver must never treat an emission failure as a run
576
605
  failure, retry it in a loop, or substitute a hand-written row. The run-row closure (`--close`) is
@@ -594,10 +623,12 @@ Order matters for the `testing → done` hop. The A3 batch hit the same clobberi
594
623
  tasks (0617, 0619) because the sections were hand-written **before** the verdict artifact existed:
595
624
 
596
625
  1. **Write the verdict artifact first.** `spur task record --solution-from-diff --transition testing`
597
- reads `.spur/run/<wbs>-verdict.json` (default). With no artifact it emits a **UNKNOWN** verdict and
598
- **overwrites** a hand-authored `## Testing` with an auto-generated "No requirements recorded" table,
599
- plus replaces `## Solution` with a bare auto change-map. Creating the artifact first (PASS, with
600
- requirement rows keyed by scenario title) makes `task record` the compliant path.
626
+ reads `.spur/run/<wbs>-verdict.json` (default attempt output) on every invocation and atomically retains the recorded verdict under `.spur/memory/evidence/`. A missing or malformed artifact
627
+ yields **UNKNOWN**: bare Testing receives a "No requirements recorded" stub, while already-authored
628
+ Testing is preserved. `--solution-from-diff` backfills only a bare Solution. The A3 clobbering above
629
+ describes the historical behavior, corrected by the authored-Testing safeguard. Creating the
630
+ artifact first (PASS, with requirement rows keyed by scenario title) remains the standard order;
631
+ re-running record after a real verdict arrives refreshes Testing from that verdict.
601
632
 
602
633
  ```bash
603
634
  # verdict artifact first (shape: {wbs, verdict, requirements:[{id,status,evidence}], checks:[], source})