@gobing-ai/spur 0.3.67 → 0.3.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/config/corpus-baseline.json +2 -50
- package/config/templates/docs/99_PROJECT_CONSTITUTION.md +21 -16
- package/config/workflow-composition-baseline.json +109 -59
- package/config/workflows/docs-pipeline.yaml +98 -22
- package/config/workflows/idea-pipeline.yaml +20 -22
- package/config/workflows/task-pipeline.yaml +207 -108
- package/package.json +9 -9
- package/plugins/sp/README.md +6 -7
- package/plugins/sp/commands/dev-idea.md +5 -3
- package/plugins/sp/commands/dev-plan.md +3 -1
- package/plugins/sp/commands/dev-review-session.md +2 -1
- package/plugins/sp/hooks/context-post-tool.ts +101 -2
- package/plugins/sp/hooks/context-session-start.ts +22 -1
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/stage-registry-adapter.ts +144 -2
- package/plugins/sp/skills/session-review/SKILL.md +16 -0
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +40 -16
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +6 -6
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +80 -11
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +18 -13
- package/spur.js +2069 -597
- package/web/_astro/{BoardApp.BEtcJqde.js → BoardApp.BQFbkeqq.js} +15 -15
- package/web/_astro/BoardApp.CTkqrhWd.js +1 -0
- package/web/_astro/{TaskDetail.ClAbCXom.js → TaskDetail.Dl2Eaj1w.js} +1 -1
- package/web/_astro/{arc.CCvf51_y.js → arc.uG14rp8A.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.C0cb0J5M.js → architectureDiagram-3BPJPVTR.Dye6uD_x.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.CIyjqoCE.js → blockDiagram-GPEHLZMM.B9Pkh7Hb.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.fs14IuFs.js → c4Diagram-AAUBKEIU.C2x7SC_X.js} +1 -1
- package/web/_astro/channel.Dsvulp7W.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.CaBKv4ZO.js → chunk-2J33WTMH.D2p4-nWk.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.BOllTPto.js → chunk-4BX2VUAB.S-6jf33o.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.ChEof0O4.js → chunk-55IACEB6.DVXj4Fdh.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.Co2kdjD8.js → chunk-727SXJPM.Dz689FMN.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.SWmfcnog.js → chunk-AQP2D5EJ.KxYj5TnI.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.rDAFifF3.js → chunk-FMBD7UC4.itTQyHQB.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.BCnoXKCw.js → chunk-ND2GUHAM.euSrbJf5.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.RSmy2hDO.js → chunk-QZHKN3VN.OWASJRQy.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.Be7PEfrX.js → classDiagram-4FO5ZUOK.BLvrlpNO.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.Be7PEfrX.js → classDiagram-v2-Q7XG4LA2.BLvrlpNO.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.BkUp2aSK.js → cose-bilkent-S5V4N54A.XBF-rmyD.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.BegGGlUV.js → cynefin-OW5HDTMX.DlCx762Z.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.BkUdjsaC.js → dagre-BM42HDAG.D17Rshxv.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.E9vugt3-.js → diagram-2AECGRRQ.AhBIVJC8.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.Dj4yeHXB.js → diagram-5GNKFQAL.C9ximjyC.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.Buaquwli.js → diagram-KO2AKTUF.CZb7Ru_9.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.BV3dgGgm.js → diagram-LMA3HP47.BW7LwqoS.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.Cnx3s-tc.js → diagram-OG6HWLK6.XC025W0V.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.DKK_abu4.js → erDiagram-TEJ5UH35.CpMXmBDP.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.BNuu9fbm.js → flowDiagram-I6XJVG4X.D2ednJWg.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.b16KUMjy.js → ganttDiagram-6RSMTGT7.BjL9FGKO.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.Kh41lbG5.js → gitGraphDiagram-PVQCEYII.B90g1VGk.js} +1 -1
- package/web/_astro/{infoDiagram-5YYISTIA.DEWBXkp-.js → infoDiagram-5YYISTIA.RqgycKtQ.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.DiAdmcL6.js → ishikawaDiagram-YF4QCWOH.Ctn-zt6a.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.D1Ki7IRm.js → journeyDiagram-JHISSGLW.DJhT8Ctp.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.CWUhrQpc.js → kanban-definition-UN3LZRKU.BY1QdejI.js} +1 -1
- package/web/_astro/{linear.BaFsgcCe.js → linear.Di7YObSt.js} +1 -1
- package/web/_astro/{mermaid.core.CHw_AsGy.js → mermaid.core.CbxtJS3Q.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.UIhghgmN.js → mindmap-definition-RKZ34NQL.CxvR4g_J.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.D05l3JUA.js → pieDiagram-4H26LBE5.jNWqnBHH.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.BcWIhIcE.js → quadrantDiagram-W4KKPZXB.BCp12MbA.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.B1rYvKGn.js → requirementDiagram-4Y6WPE33.Dxhm4TyR.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.CKylVRC4.js → sankeyDiagram-5OEKKPKP.BtQXp4J9.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.Dm3uA_s4.js → sequenceDiagram-3UESZ5HK.BWEM1R_Q.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.Bgca_BLe.js → stateDiagram-AJRCARHV.BG3wUkWB.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.C1T7YFrG.js → stateDiagram-v2-BHNVJYJU.BLtMeFVP.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.ZOHJn3Sn.js → timeline-definition-PNZ67QCA.D5fHo0az.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.DegZitjD.js → vennDiagram-CIIHVFJN.0DcuMluU.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.BDsC115d.js → wardleyDiagram-YWT4CUSO.BZ-dxgHm.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.D0MO70ea.js → xychartDiagram-2RQKCTM6.Bg-XWF7z.js} +1 -1
- package/web/index.html +1 -1
- package/web/_astro/BoardApp.DBEin4N5.js +0 -1
- package/web/_astro/channel.BGn_DUCD.js +0 -1
|
@@ -421,6 +421,23 @@ written for a batch with nothing to run. The early-exit report carries zero per-
|
|
|
421
421
|
terminal action runs. A contract test pins this
|
|
422
422
|
(`plugins/sp/tests/dogfood-testing/execution-batch-contract.test.ts`).
|
|
423
423
|
|
|
424
|
+
**Evidence persistence (worktree batches — task 0720 R3).** A worktree batch's Step 5 report and
|
|
425
|
+
verdict artifacts live in the worktree's own `.spur/run/` while the batch runs — exactly the tree
|
|
426
|
+
create-mode WT-4 deletes. Before any WT-4 removal, persist them into the **invoking** tree, which
|
|
427
|
+
survives removal:
|
|
428
|
+
|
|
429
|
+
- Write the emitted batch report to `.spur/run/worktree-<marker-id>-batch-report.md`.
|
|
430
|
+
- Copy each attempted task's `.spur/run/<wbs>-verdict.json` from the worktree to
|
|
431
|
+
`.spur/run/worktree-<marker-id>-verdicts/<wbs>-verdict.json`.
|
|
432
|
+
- Make the report's per-task verdict references use those persisted invoking-tree paths, not the
|
|
433
|
+
worktree-local paths that removal deletes.
|
|
434
|
+
|
|
435
|
+
Evidence persistence precedes destructive cleanup: a persistence failure (unreadable verdict file,
|
|
436
|
+
disk-full, missing directory) routes to **WT-5** — the worktree and branch are retained so a green
|
|
437
|
+
batch can never destroy its own evidence. Reuse mode retains its operator-owned tree but still
|
|
438
|
+
persists the Step 5 report under the invoking tree; the reused tree's `.spur/run/` remains the live
|
|
439
|
+
copy while that tree lives on.
|
|
440
|
+
|
|
424
441
|
## Worktree isolation (`--worktree [<name>]`)
|
|
425
442
|
|
|
426
443
|
When a batch command (`dev-runall`, `dev-refineall`, `dev-verifyall`) is invoked with
|
|
@@ -671,14 +688,52 @@ git checkout "$BASE_REF"
|
|
|
671
688
|
[ "$(git rev-list --count "$BASE_SHA..$BRANCH")" -gt 0 ] \
|
|
672
689
|
|| { echo "halt: branch carries no commits - nothing to merge" >&2; false; } # -> WT-5
|
|
673
690
|
git merge --ff-only "$BRANCH" # FF-only: never rebase, merge-commit, or resolve conflicts
|
|
674
|
-
# if FF succeeded:
|
|
691
|
+
# if FF succeeded — WT-4a evidence persistence (Step 5, task 0720 R3) runs FIRST:
|
|
692
|
+
# persist the batch report + verdict artifacts into the invoking tree's .spur/run/
|
|
693
|
+
# before anything below touches the worktree. Persistence failure routes to WT-5.
|
|
694
|
+
#
|
|
695
|
+
# WT-4b — bounded CWD-holder cleanup (task 0720 R1). Resolve the EXACT absolute
|
|
696
|
+
# worktree path; a relative path or a stale entry matches the wrong processes.
|
|
697
|
+
WT_PATH="$(cd "../<worktree-dir>" && pwd)"
|
|
698
|
+
# Holders = processes with any open fd under the worktree tree (lsof +D walks the
|
|
699
|
+
# tree; CWD holders are the common case but +D also catches open-file holders —
|
|
700
|
+
# over-match errs toward removal success; a plain -t <dir> matches only the
|
|
701
|
+
# directory itself). Orphaned `serve` proof daemons (PPID 1) are exactly this
|
|
702
|
+
# class: they defeat `git worktree remove` (ENOTEMPTY), defeat rm -rf, while
|
|
703
|
+
# `git worktree prune` still deregisters the tree. Note +D is a full-tree walk,
|
|
704
|
+
# so the wait loop below bounds ITERATIONS (6 × 1s ticks + walk cost), not
|
|
705
|
+
# wall-clock.
|
|
706
|
+
HOLDERS="$(lsof -t +D "$WT_PATH" 2>/dev/null | sort -u)"
|
|
707
|
+
if [ -n "$HOLDERS" ]; then
|
|
708
|
+
kill -TERM $HOLDERS 2>/dev/null # 1) TERM first, all holders (unquoted — word-split PID list)
|
|
709
|
+
for _ in 1 2 3 4 5 6; do # 2) bounded wait: 6 × 1s ticks
|
|
710
|
+
sleep 1
|
|
711
|
+
[ -z "$(lsof -t +D "$WT_PATH" 2>/dev/null)" ] && break
|
|
712
|
+
done
|
|
713
|
+
SURVIVORS="$(lsof -t +D "$WT_PATH" 2>/dev/null | sort -u)"
|
|
714
|
+
if [ -n "$SURVIVORS" ]; then
|
|
715
|
+
kill -KILL $SURVIVORS 2>/dev/null # 3) KILL only the survivors (unquoted — one arg per PID)
|
|
716
|
+
sleep 1
|
|
717
|
+
fi
|
|
718
|
+
fi
|
|
719
|
+
# 4) Re-query: only an EMPTY holder set may proceed to remove/prune/branch delete.
|
|
720
|
+
FINAL="$(lsof -t +D "$WT_PATH" 2>/dev/null | sort -u)"
|
|
721
|
+
if [ -n "$FINAL" ]; then
|
|
722
|
+
PORTS="$(lsof -nP -a -p "$(echo "$FINAL" | paste -sd, -)" -iTCP -sTCP:LISTEN 2>/dev/null \
|
|
723
|
+
| awk 'NR>1 {print $9}' | sort -u | paste -sd' ' -)"
|
|
724
|
+
echo "halt: worktree still held by PID(s): $FINAL ${PORTS:+listening: $PORTS}" >&2
|
|
725
|
+
exit 1 # -> WT-5: retain worktree + branch,
|
|
726
|
+
fi # NO prune/remove/branch delete
|
|
675
727
|
git worktree remove "../<worktree-dir>"
|
|
676
728
|
git branch -d "$BRANCH"
|
|
677
729
|
# update marker: status = "merged"
|
|
678
730
|
```
|
|
679
731
|
|
|
680
|
-
On
|
|
681
|
-
|
|
732
|
+
On either guard firing — zero-commit branch (task 0701 R1), or surviving CWD holders (task 0720 R1)
|
|
733
|
+
— fall through to **WT-5**: the worktree and branch are retained, never removed. While any holder
|
|
734
|
+
remains, do **not** run `git worktree prune`, `git worktree remove`, or branch deletion. The holder
|
|
735
|
+
halt report names every surviving PID; the listening port is best-effort — a CWD holder may own no
|
|
736
|
+
socket, and `lsof` port discovery failing must not hide the PIDs.
|
|
682
737
|
|
|
683
738
|
#### Reuse mode — merge, retain
|
|
684
739
|
|
|
@@ -711,14 +766,28 @@ risk losing work); WT-5 retains the worktree and branch whenever FF is impossibl
|
|
|
711
766
|
Reuse mode is **narrower** than the carve-out (it merges but does not delete the branch), so the
|
|
712
767
|
carve-out text needs no widening.
|
|
713
768
|
|
|
714
|
-
**Lifecycle-DB disposition (task 0701 R2d).** The worktree has its own `.spur`
|
|
715
|
-
WT-4/WT-5 remove or retain that tree — the DB state does **not** travel with the
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
769
|
+
**Lifecycle-DB disposition (task 0701 R2d, amended by 0720).** The worktree has its own `.spur`
|
|
770
|
+
lifecycle DB, and WT-4/WT-5 remove or retain that tree — the DB state does **not** travel with the
|
|
771
|
+
merge. One contract, no alternatives:
|
|
772
|
+
|
|
773
|
+
- **Committed task files own lifecycle state.** The **committed task file is authoritative**: after
|
|
774
|
+
a green merge the branch's task files already read `done`/`testing` in the invoking tree; no
|
|
775
|
+
`spur task update` or `spur task record` replay runs post-merge. Replay is not "one of two
|
|
776
|
+
options" — it is removed: it writes `updated_at`-only churn and can never restore worktree-only
|
|
777
|
+
DB rows.
|
|
778
|
+
- **The persisted invoking-tree artifacts own evidence.** The Step 5 batch report at
|
|
779
|
+
`.spur/run/worktree-<marker-id>-batch-report.md` and the copied verdict JSONs under
|
|
780
|
+
`.spur/run/worktree-<marker-id>-verdicts/` (written before WT-4 removal) are the batch/verdict
|
|
781
|
+
record.
|
|
782
|
+
- **Per-worktree lifecycle DB rows intentionally do not travel.** No `task_run_links` import, no
|
|
783
|
+
cross-database provenance synthesis — the DB is per-tree by design.
|
|
784
|
+
- **No timestamp-only corpus churn.** Post-merge the invoking tree's DB statuses may read stale
|
|
785
|
+
relative to the committed files; that divergence is accepted, not repaired. Do not run
|
|
786
|
+
`task update`/`task record` to "catch up" the DB, and do not repair churn with
|
|
787
|
+
`git checkout -- docs/tasks*/`.
|
|
788
|
+
|
|
789
|
+
This is a deliberate choice over auto-migrating DB state: the committed corpus files are the durable
|
|
790
|
+
record and the persisted run artifacts are the evidence record.
|
|
722
791
|
|
|
723
792
|
### WT-5 — Failure path: retain and report (R5)
|
|
724
793
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: inline-pipeline-driver
|
|
3
|
-
description: "Interactive host-session interpreter for
|
|
3
|
+
description: "Interactive host-session interpreter for Spur state-machine pipelines: execute the existing FSM without a workflow agent subprocess while preserving actions, guards, artifacts, and provenance."
|
|
4
4
|
see_also:
|
|
5
5
|
- spur-dev
|
|
6
6
|
- execution-workflow
|
|
@@ -9,12 +9,13 @@ see_also:
|
|
|
9
9
|
|
|
10
10
|
# Inline Pipeline Driver
|
|
11
11
|
|
|
12
|
-
This driver is the interactive control-inversion path granted by ADR-047. It applies
|
|
13
|
-
interactive `/sp:dev-run --mode full
|
|
14
|
-
|
|
15
|
-
batch mode, `spur workflow run`, and `spur agent run` keep the existing
|
|
12
|
+
This driver is the interactive control-inversion path granted by ADR-047. It applies when an
|
|
13
|
+
interactive `/sp:dev-run --mode full`, sequential `/sp:dev-runall`, `/sp:dev-idea`, or
|
|
14
|
+
`/sp:dev-plan` invocation omits `--agent` or passes `--agent inline`. A named executor,
|
|
15
|
+
`--agent auto`, parallel batch mode, `spur workflow run`, and `spur agent run` keep the existing
|
|
16
|
+
subprocess path.
|
|
16
17
|
|
|
17
|
-
The project runtime definition — `task-pipeline.yaml`, resolved through the two-tier
|
|
18
|
+
The selected project runtime definition — `task-pipeline.yaml` or `idea-pipeline.yaml`, resolved through the two-tier
|
|
18
19
|
project→bundled model (task 0648/0650, never an unbundled runtime path) — remains the sole
|
|
19
20
|
FSM definition. The driver MUST read that file
|
|
20
21
|
at invocation time. It must not copy the state list, actions, guards, or transition order into a
|
|
@@ -22,9 +23,9 @@ command, skill, script, or second workflow.
|
|
|
22
23
|
|
|
23
24
|
## Run setup
|
|
24
25
|
|
|
25
|
-
1. Resolve
|
|
26
|
-
with those invocation values. An explicit
|
|
27
|
-
|
|
26
|
+
1. Resolve the command inputs, `--auto`, and any explicit `--vars`; read the selected YAML and overlay
|
|
27
|
+
its `vars` defaults with those invocation values. An explicit non-inline executor selection
|
|
28
|
+
chooses the subprocess workflow path.
|
|
28
29
|
2. Allocate a collision-resistant inline run id (`uuidgen`, with a timestamp/pid fallback), create
|
|
29
30
|
`.spur/run/`, and use `.spur/run/<run-id>.log` as the run log.
|
|
30
31
|
3. Resolve the host session id from `.spur/context/.session.json`, accepting the normalized hook key
|
|
@@ -42,13 +43,14 @@ command, skill, script, or second workflow.
|
|
|
42
43
|
never per action.
|
|
43
44
|
- **Source of truth** = the CLI projection for layer 1; the YAML parsed in step 1 for layer 2.
|
|
44
45
|
Never hand-copy or hand-derive the state list into the driver, a command, a skill, or a script.
|
|
45
|
-
5.
|
|
46
|
+
5. For task execution only, record lifecycle provenance before entering the FSM:
|
|
46
47
|
|
|
47
48
|
```bash
|
|
48
49
|
spur task run-link <wbs> --source inline-full --run-id <run-id> --json
|
|
49
50
|
```
|
|
50
51
|
|
|
51
|
-
This is required for the normal `testing → done` provenance guard.
|
|
52
|
+
This is required for the normal `testing → done` provenance guard. Planning pipelines have no
|
|
53
|
+
task lifecycle link and skip this task-specific action.
|
|
52
54
|
|
|
53
55
|
## YAML interpreter
|
|
54
56
|
|
|
@@ -61,12 +63,15 @@ Action semantics come from the YAML and the workflow action contract:
|
|
|
61
63
|
- `shell` — run the expanded command in the project working tree with resolved vars exported as
|
|
62
64
|
environment variables. A non-zero result follows the action's existing failure policy.
|
|
63
65
|
- `note` — append the expanded message to the inline run log.
|
|
66
|
+
- `doctor.probe` — run the declared Spur doctor once, persist its status file, and apply any
|
|
67
|
+
`setVars` result (including a resolved executor) before the next action or state.
|
|
64
68
|
- `file.read.into-var` — read the declared file into the declared run variable before subsequent
|
|
65
69
|
actions/guards.
|
|
66
70
|
- `hitl.confirm` — under `profile=auto`, follow the YAML's auto-skip transition. Otherwise pause,
|
|
67
71
|
surface the prompt, and resume from the same state with the operator's answer.
|
|
68
|
-
- `agent.run` — execute the action's
|
|
69
|
-
|
|
72
|
+
- `agent.run` — execute the action's input in the host session. Task execution may use the native
|
|
73
|
+
subagent eligibility below; idea/plan never dispatch a native subagent unless the operator
|
|
74
|
+
explicitly requested delegation. Do not call `spur agent run` or re-enter a full pipeline. Preserve the YAML options: capture
|
|
70
75
|
`answerFile`; assert `expectFile`; enforce `requireDiff` against a pre-action git snapshot,
|
|
71
76
|
including the task-scope guard; honor declared error policy. `timeoutMs` is recorded as not
|
|
72
77
|
applicable because the host session has no independent kill boundary.
|