@gobing-ai/spur 0.3.48 → 0.3.50

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 (85) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +52 -4
  3. package/config/corpus-baseline.json +12144 -3
  4. package/config/workflows/pr-review.yaml +338 -0
  5. package/package.json +9 -9
  6. package/plugins/sp/README.md +9 -6
  7. package/plugins/sp/commands/{dev-featurechange.md → dev-feature-change.md} +7 -10
  8. package/plugins/sp/commands/dev-find-issue.md +24 -19
  9. package/plugins/sp/commands/dev-find-next.md +3 -3
  10. package/plugins/sp/commands/dev-gtd.md +11 -12
  11. package/plugins/sp/commands/dev-history-load.md +63 -0
  12. package/plugins/sp/commands/dev-pr-review.md +39 -0
  13. package/plugins/sp/plugin.json +1 -1
  14. package/plugins/sp/references/roles.md +25 -12
  15. package/plugins/sp/scripts/history-load.ts +400 -0
  16. package/plugins/sp/scripts/pr-reviewing.ts +867 -0
  17. package/plugins/sp/scripts/validate-commands.ts +33 -2
  18. package/plugins/sp/skills/code-implementation/SKILL.md +9 -1
  19. package/plugins/sp/skills/code-verification/SKILL.md +41 -28
  20. package/plugins/sp/skills/issue-finding/SKILL.md +6 -5
  21. package/plugins/sp/skills/issue-finding/references/session-formats.md +4 -2
  22. package/plugins/sp/skills/next-feature/SKILL.md +6 -6
  23. package/plugins/sp/skills/next-feature/references/handoff-routing.md +5 -5
  24. package/plugins/sp/skills/next-feature/references/signal-derivation.md +7 -2
  25. package/plugins/sp/skills/pr-reviewing/SKILL.md +285 -0
  26. package/plugins/sp/skills/spur-cli/references/features/hierarchy-mece.md +5 -5
  27. package/plugins/sp/skills/spur-cli/references/features.md +1 -1
  28. package/plugins/sp/skills/spur-cli/references/tasks.md +1 -0
  29. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +18 -2
  30. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +14 -6
  31. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +14 -4
  32. package/schemas/spur-config.schema.json +20 -0
  33. package/spur.js +5336 -5714
  34. package/web/_astro/BoardApp.pdtYu-yW.js +1 -0
  35. package/web/_astro/{BoardApp.BjQUNhuj.js → BoardApp.plVXYkKo.js} +11 -11
  36. package/web/_astro/{TaskDetail.CVBuD6dF.js → TaskDetail.5DIyVQ_N.js} +1 -1
  37. package/web/_astro/{arc.BMMjdODi.js → arc.BnUgL7ho.js} +1 -1
  38. package/web/_astro/{architectureDiagram-3BPJPVTR.BU5ShzXf.js → architectureDiagram-3BPJPVTR.B9YMJau-.js} +1 -1
  39. package/web/_astro/{blockDiagram-GPEHLZMM.Bj1iEqPD.js → blockDiagram-GPEHLZMM.Dw2qgvWJ.js} +1 -1
  40. package/web/_astro/{c4Diagram-AAUBKEIU.vX8wepCL.js → c4Diagram-AAUBKEIU.jTbU0-Nk.js} +1 -1
  41. package/web/_astro/channel.DEqvaz-I.js +1 -0
  42. package/web/_astro/{chunk-2J33WTMH.BKAipTym.js → chunk-2J33WTMH.Di46EtkU.js} +1 -1
  43. package/web/_astro/{chunk-4BX2VUAB.B68XkPG7.js → chunk-4BX2VUAB.DweHBwqQ.js} +1 -1
  44. package/web/_astro/{chunk-55IACEB6.BmeDLcrc.js → chunk-55IACEB6.rRjTKaa7.js} +1 -1
  45. package/web/_astro/{chunk-727SXJPM.PDuBA3Kw.js → chunk-727SXJPM.BkEQIkSV.js} +1 -1
  46. package/web/_astro/{chunk-AQP2D5EJ.C7A044za.js → chunk-AQP2D5EJ.Cfe9IvAd.js} +1 -1
  47. package/web/_astro/{chunk-FMBD7UC4.BtzKKFqR.js → chunk-FMBD7UC4.fI6tLbeN.js} +1 -1
  48. package/web/_astro/{chunk-ND2GUHAM.BJuDeeOy.js → chunk-ND2GUHAM.BIjgpq0O.js} +1 -1
  49. package/web/_astro/{chunk-QZHKN3VN.DSeMDgcQ.js → chunk-QZHKN3VN.ZwLnVxyz.js} +1 -1
  50. package/web/_astro/{classDiagram-4FO5ZUOK.D53Q4tCw.js → classDiagram-4FO5ZUOK.BJAGYidE.js} +1 -1
  51. package/web/_astro/{classDiagram-v2-Q7XG4LA2.D53Q4tCw.js → classDiagram-v2-Q7XG4LA2.BJAGYidE.js} +1 -1
  52. package/web/_astro/{cose-bilkent-S5V4N54A.c712AFRH.js → cose-bilkent-S5V4N54A.B5y3nz26.js} +1 -1
  53. package/web/_astro/{dagre-BM42HDAG.D-idisph.js → dagre-BM42HDAG.DHmw0ZBC.js} +1 -1
  54. package/web/_astro/{diagram-2AECGRRQ.DLgnsJCU.js → diagram-2AECGRRQ.10gapJfY.js} +1 -1
  55. package/web/_astro/{diagram-5GNKFQAL.BiaxBVqx.js → diagram-5GNKFQAL.Gh33_drM.js} +1 -1
  56. package/web/_astro/{diagram-KO2AKTUF.C8HX1vd8.js → diagram-KO2AKTUF.8ROWlfcX.js} +1 -1
  57. package/web/_astro/{diagram-LMA3HP47.CfqDLLes.js → diagram-LMA3HP47.BsP3tKmg.js} +1 -1
  58. package/web/_astro/{diagram-OG6HWLK6.15SDiEed.js → diagram-OG6HWLK6.DM2WFDhU.js} +1 -1
  59. package/web/_astro/{erDiagram-TEJ5UH35.DksYtOYM.js → erDiagram-TEJ5UH35.royaC_lH.js} +1 -1
  60. package/web/_astro/{flowDiagram-I6XJVG4X.DR_Au-HV.js → flowDiagram-I6XJVG4X.C9GEvIie.js} +1 -1
  61. package/web/_astro/{ganttDiagram-6RSMTGT7.CHhHrffI.js → ganttDiagram-6RSMTGT7.CXO4T2U0.js} +1 -1
  62. package/web/_astro/{gitGraphDiagram-PVQCEYII.B2Xehvam.js → gitGraphDiagram-PVQCEYII.Q02KzYH7.js} +1 -1
  63. package/web/_astro/{infoDiagram-5YYISTIA.C9c3CNNN.js → infoDiagram-5YYISTIA.DNfSDKJt.js} +1 -1
  64. package/web/_astro/{ishikawaDiagram-YF4QCWOH.BibUHkh8.js → ishikawaDiagram-YF4QCWOH.BFttvtgJ.js} +1 -1
  65. package/web/_astro/{journeyDiagram-JHISSGLW.BYoVHiyO.js → journeyDiagram-JHISSGLW.Cfm-2SbG.js} +1 -1
  66. package/web/_astro/{kanban-definition-UN3LZRKU.CM1K5wHE.js → kanban-definition-UN3LZRKU.BWGNW6fV.js} +1 -1
  67. package/web/_astro/{linear.SPpjJUb-.js → linear.BprdUk2Y.js} +1 -1
  68. package/web/_astro/{mermaid.core.BAgx3nnb.js → mermaid.core.B2zRNxtX.js} +4 -4
  69. package/web/_astro/{mindmap-definition-RKZ34NQL.D35oPG1R.js → mindmap-definition-RKZ34NQL.g9jij8sw.js} +1 -1
  70. package/web/_astro/{pieDiagram-4H26LBE5.DiWuRwk7.js → pieDiagram-4H26LBE5.CbzR4n5b.js} +1 -1
  71. package/web/_astro/{quadrantDiagram-W4KKPZXB.B9PBzTWn.js → quadrantDiagram-W4KKPZXB.DxV3viWt.js} +1 -1
  72. package/web/_astro/{requirementDiagram-4Y6WPE33.CYuuamFN.js → requirementDiagram-4Y6WPE33.DvAb90JS.js} +1 -1
  73. package/web/_astro/{sankeyDiagram-5OEKKPKP.W24UhhtD.js → sankeyDiagram-5OEKKPKP.CIFz5t4D.js} +1 -1
  74. package/web/_astro/{sequenceDiagram-3UESZ5HK.BpbNjA51.js → sequenceDiagram-3UESZ5HK.DzlEQynd.js} +1 -1
  75. package/web/_astro/{stateDiagram-AJRCARHV.DqVsHudf.js → stateDiagram-AJRCARHV.Dph2V-ts.js} +1 -1
  76. package/web/_astro/{stateDiagram-v2-BHNVJYJU.CzwHYX81.js → stateDiagram-v2-BHNVJYJU.wJhfrLAy.js} +1 -1
  77. package/web/_astro/{timeline-definition-PNZ67QCA.Bc3B6djw.js → timeline-definition-PNZ67QCA.BrSiyubX.js} +1 -1
  78. package/web/_astro/{vennDiagram-CIIHVFJN.C-D5rh8O.js → vennDiagram-CIIHVFJN.COobPrUX.js} +1 -1
  79. package/web/_astro/{wardley-L42UT6IY.D7PdYCqn.js → wardley-L42UT6IY.CrjeTx8A.js} +1 -1
  80. package/web/_astro/{wardleyDiagram-YWT4CUSO.CwmJKXF3.js → wardleyDiagram-YWT4CUSO.B8_fTQ8E.js} +1 -1
  81. package/web/_astro/{xychartDiagram-2RQKCTM6.avDYnLsb.js → xychartDiagram-2RQKCTM6.BPpokgVv.js} +1 -1
  82. package/web/favicon.svg +1 -0
  83. package/web/index.html +1 -1
  84. package/web/_astro/BoardApp.8hiqShQn.js +0 -1
  85. package/web/_astro/channel.EwdSemIC.js +0 -1
@@ -0,0 +1,338 @@
1
+ # PR-review workflow: deterministic spine for /sp:dev-pr-review (skill sp:pr-reviewing).
2
+ # Authored for the @gobing-ai/ts-dual-workflow-engine state-machine schema
3
+ # (initialState / states[].id / onEnter / top-level transitions), same family as
4
+ # basic.yaml / task-pipeline.yaml. Seeded into projects by `spur init` (scaffold manifest).
5
+ #
6
+ # Shape: preflight → hygiene → precheck → push → ensure-pr → request → wait → collect → done
7
+ # (soft probes everywhere: red gates route to `failed`/`pending` via transitions,
8
+ # never a raw lifecycle abort — same reliability contract as basic.yaml)
9
+ #
10
+ # This YAML is the SSOT for the review spine's state order and guards. Every state shells
11
+ # out to the staged pr-reviewing.ts entrypoint (the tested deterministic core); no gh/git
12
+ # logic lives in this file. All model-bearing work — finding triage, `fix` mode, `rules`
13
+ # mode — stays in the sp:pr-reviewing skill and never enters this machine.
14
+ #
15
+ # Non-negotiable: the external review goes through the GitHub PR + an `@codex review`
16
+ # comment. Never substitute a local Codex review mechanism.
17
+ #
18
+ # Vars (override per run: --vars '{"mode":"submit","focus":"migration safety"}'):
19
+ # mode — full (default) | submit | rerun
20
+ # full: dedupe an up-to-date Codex review, else request + wait + collect
21
+ # submit: request and stop at `pending` (no wait)
22
+ # rerun: request with --force even when HEAD is already reviewed
23
+ # baseBranch — base for a newly created PR (default: existing PR base, else repo default)
24
+ # focus — extra review focus appended to the @codex request
25
+ # noWait — "true" returns pending right after the request instead of polling
26
+ # waitTimeoutSec — poll budget for Codex output (default 600)
27
+ # waitIntervalSec — poll interval (default 30; do not poll aggressively)
28
+ # preReviewCmd — project fast check run before requesting (empty = skipped).
29
+ # TRUSTED CONFIG ONLY — executed via `sh -c` (task 0436 SECUA residual).
30
+ # Never interpolate untrusted operator/LLM input into it.
31
+ # __runId — injected by WorkflowAppService.run(); scopes .spur/run artifacts.
32
+
33
+ "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
34
+ name: pr-review
35
+ kind: state-machine
36
+ description: GitHub Codex PR-review spine — preflight → hygiene → precheck → push → ensure-pr → request → wait → collect
37
+ iterationBound: 16
38
+ initialState: preflight
39
+ terminalStates:
40
+ - done
41
+ - pending
42
+ - failed
43
+ failureStates:
44
+ - failed
45
+ vars:
46
+ mode: 'full'
47
+ baseBranch: ''
48
+ focus: ''
49
+ noWait: 'false'
50
+ waitTimeoutSec: '600'
51
+ waitIntervalSec: '30'
52
+ preReviewCmd: ''
53
+ __runId: ''
54
+
55
+ states:
56
+ - id: preflight
57
+ description: >
58
+ Soft probe: git/gh/repo checks (detached HEAD, dirty tree, gh auth, GitHub remote).
59
+ Writes PASS|FAIL to .spur/run/${vars.__runId}-pr-preflight.status; always exit 0.
60
+ onEnter:
61
+ - kind: shell
62
+ options:
63
+ command: >-
64
+ mkdir -p .spur/run &&
65
+ STATUS_FILE=".spur/run/$__runId-pr-preflight.status" &&
66
+ set +e &&
67
+ bun "$(superskill script path sp pr-reviewing.ts)" preflight --json > ".spur/run/$__runId-pr-context.json";
68
+ rc=$?; set -e &&
69
+ if [ "$rc" -eq 0 ]; then printf 'PASS\n' > "$STATUS_FILE"; else printf 'FAIL\n' > "$STATUS_FILE"; fi &&
70
+ exit 0
71
+
72
+ - id: hygiene
73
+ description: >
74
+ Submission sanity scan of base...HEAD: secrets/.env/conflict markers BLOCK the run;
75
+ debug residue only WARNs. Not a replacement for the independent Codex review.
76
+ onEnter:
77
+ - kind: shell
78
+ options:
79
+ command: >-
80
+ mkdir -p .spur/run &&
81
+ STATUS_FILE=".spur/run/$__runId-pr-hygiene.status" &&
82
+ set +e &&
83
+ bun "$(superskill script path sp pr-reviewing.ts)" hygiene --base "$baseBranch" --json
84
+ --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-hygiene.json";
85
+ rc=$?; set -e &&
86
+ if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
87
+ exit 0
88
+
89
+ - id: precheck
90
+ description: >
91
+ Optional project fast check (vars.preReviewCmd) before spending a review request.
92
+ Empty command records SKIP; a red check stops the run before request (fail loud).
93
+ onEnter:
94
+ - kind: shell
95
+ options:
96
+ command: >-
97
+ mkdir -p .spur/run &&
98
+ STATUS_FILE=".spur/run/$__runId-pr-precheck.status" &&
99
+ if [ -z "$preReviewCmd" ]; then
100
+ printf 'SKIP\n' > "$STATUS_FILE";
101
+ else
102
+ set +e; sh -c "$preReviewCmd"; rc=$?; set -e;
103
+ if [ "$rc" -eq 0 ]; then printf 'PASS\n' > "$STATUS_FILE"; else printf 'FAIL\n' > "$STATUS_FILE"; fi;
104
+ fi &&
105
+ exit 0
106
+
107
+ - id: push
108
+ description: >
109
+ Publish the branch (normal push only, never force; sets upstream when missing).
110
+ A PR reviews pushed commits only.
111
+ onEnter:
112
+ - kind: shell
113
+ options:
114
+ command: >-
115
+ mkdir -p .spur/run &&
116
+ STATUS_FILE=".spur/run/$__runId-pr-push.status" &&
117
+ set +e &&
118
+ bun "$(superskill script path sp pr-reviewing.ts)" push --json --status-file "$STATUS_FILE"
119
+ > ".spur/run/$__runId-pr-push.json";
120
+ rc=$?; set -e &&
121
+ if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
122
+ exit 0
123
+
124
+ - id: ensure-pr
125
+ description: Find or create the GitHub PR for the current branch — never a duplicate.
126
+ onEnter:
127
+ - kind: shell
128
+ options:
129
+ command: >-
130
+ mkdir -p .spur/run &&
131
+ STATUS_FILE=".spur/run/$__runId-pr-ensure.status" &&
132
+ set +e &&
133
+ bun "$(superskill script path sp pr-reviewing.ts)" ensure-pr --base "$baseBranch" --json
134
+ --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr.json";
135
+ rc=$?; set -e &&
136
+ if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
137
+ exit 0
138
+
139
+ - id: request
140
+ description: >
141
+ Post the `@codex review` request (per-HEAD dedupe unless mode=rerun forces).
142
+ Records the request under .spur/run/${vars.__runId}-pr-request.json.
143
+ onEnter:
144
+ - kind: shell
145
+ options:
146
+ command: >-
147
+ mkdir -p .spur/run &&
148
+ STATUS_FILE=".spur/run/$__runId-pr-request.status" &&
149
+ FORCE_FLAG="" &&
150
+ if [ "$mode" = "rerun" ]; then FORCE_FLAG="--force"; fi &&
151
+ set +e &&
152
+ bun "$(superskill script path sp pr-reviewing.ts)" request --focus "$focus" $FORCE_FLAG --json
153
+ --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-request.json";
154
+ rc=$?; set -e &&
155
+ if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
156
+ exit 0
157
+
158
+ - id: wait
159
+ description: >
160
+ Bounded poll for Codex output on the current pushed HEAD. Timeout records TIMEOUT
161
+ and routes to `pending` — never a failure (collect later with /sp:dev-pr-review collect).
162
+ onEnter:
163
+ - kind: shell
164
+ options:
165
+ command: >-
166
+ mkdir -p .spur/run &&
167
+ STATUS_FILE=".spur/run/$__runId-pr-wait.status" &&
168
+ set +e &&
169
+ SINCE="$(bun -e 'const fs=require("node:fs");const value=JSON.parse(fs.readFileSync(process.argv[1],"utf8")).requestedAt;process.stdout.write(value ?? "")' ".spur/run/$__runId-pr-request.json")" &&
170
+ REQUEST_HEAD="$(bun -e 'const fs=require("node:fs");const value=JSON.parse(fs.readFileSync(process.argv[1],"utf8")).head;process.stdout.write(value ?? "")' ".spur/run/$__runId-pr-request.json")" &&
171
+ bun "$(superskill script path sp pr-reviewing.ts)" wait --since "$SINCE" --head "$REQUEST_HEAD" --timeout "$waitTimeoutSec" --interval "$waitIntervalSec"
172
+ --json --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-wait.json";
173
+ rc=$?; set -e &&
174
+ if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
175
+ exit 0
176
+
177
+ - id: collect
178
+ description: Normalize the latest current-HEAD Codex result and record composite PR/CI status.
179
+ onEnter:
180
+ - kind: shell
181
+ options:
182
+ command: >-
183
+ mkdir -p .spur/run &&
184
+ STATUS_FILE=".spur/run/$__runId-pr-collect.status" &&
185
+ set +e &&
186
+ SINCE="$(bun -e 'const fs=require("node:fs");const value=JSON.parse(fs.readFileSync(process.argv[1],"utf8")).requestedAt;process.stdout.write(value ?? "")' ".spur/run/$__runId-pr-request.json")" &&
187
+ REQUEST_HEAD="$(bun -e 'const fs=require("node:fs");const value=JSON.parse(fs.readFileSync(process.argv[1],"utf8")).head;process.stdout.write(value ?? "")' ".spur/run/$__runId-pr-request.json")" &&
188
+ bun "$(superskill script path sp pr-reviewing.ts)" collect --since "$SINCE" --head "$REQUEST_HEAD" --json
189
+ --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-findings.json";
190
+ collect_rc=$?;
191
+ bun "$(superskill script path sp pr-reviewing.ts)" status --since "$SINCE" --head "$REQUEST_HEAD" --json > ".spur/run/$__runId-pr-status.json";
192
+ status_rc=$?; set -e &&
193
+ if [ "$collect_rc" -ne 0 ] || [ "$status_rc" -ne 0 ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
194
+ if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
195
+ { cat ".spur/run/$__runId-pr-findings.json" 2>/dev/null || true; } &&
196
+ exit 0
197
+
198
+ - id: done
199
+ description: Terminal — review collected; findings artifact at .spur/run/${vars.__runId}-pr-findings.json
200
+ - id: pending
201
+ description: Terminal — review requested (or timed out) but not yet collected; run /sp:dev-pr-review collect later
202
+ - id: failed
203
+ description: Terminal — a gate went red; the stage .status/.json artifacts under .spur/run name the blocker
204
+
205
+ transitions:
206
+ - from: preflight
207
+ to: hygiene
208
+ description: Repo, gh auth, and clean tree verified
209
+ guard:
210
+ kind: shell
211
+ options:
212
+ command: 'test "$(cat .spur/run/$__runId-pr-preflight.status 2>/dev/null)" = PASS'
213
+ - from: preflight
214
+ to: failed
215
+ description: Preflight red (detached HEAD, dirty tree, gh auth, no GitHub remote) — stop before any publishing
216
+ guard:
217
+ kind: always
218
+
219
+ - from: hygiene
220
+ to: precheck
221
+ description: Clean or warn-only — warnings ride along to the report
222
+ guard:
223
+ kind: shell
224
+ options:
225
+ command: 'grep -qE "^(PASS|WARN)$" .spur/run/$__runId-pr-hygiene.status 2>/dev/null'
226
+ - from: hygiene
227
+ to: failed
228
+ description: BLOCK (secrets/.env/conflict markers) or probe failure — never submit a tainted diff
229
+ guard:
230
+ kind: always
231
+
232
+ - from: precheck
233
+ to: push
234
+ description: Project fast check passed or was skipped
235
+ guard:
236
+ kind: shell
237
+ options:
238
+ command: 'grep -qE "^(PASS|SKIP)$" .spur/run/$__runId-pr-precheck.status 2>/dev/null'
239
+ - from: precheck
240
+ to: failed
241
+ description: Project checks red — do not spend a review request on code that fails its own gate
242
+ guard:
243
+ kind: always
244
+
245
+ - from: push
246
+ to: ensure-pr
247
+ description: Branch published (or already up to date)
248
+ guard:
249
+ kind: shell
250
+ options:
251
+ command: 'grep -qE "^(PUSHED|UP_TO_DATE)$" .spur/run/$__runId-pr-push.status 2>/dev/null'
252
+ - from: push
253
+ to: failed
254
+ description: Push rejected (e.g. non-fast-forward) — report; never force-push as a workaround
255
+ guard:
256
+ kind: always
257
+
258
+ - from: ensure-pr
259
+ to: request
260
+ description: PR found or created
261
+ guard:
262
+ kind: shell
263
+ options:
264
+ command: 'grep -qE "^(FOUND|CREATED)$" .spur/run/$__runId-pr-ensure.status 2>/dev/null'
265
+ - from: ensure-pr
266
+ to: failed
267
+ description: No reviewable delta or PR creation failed — report the actual git/GitHub state
268
+ guard:
269
+ kind: always
270
+
271
+ # Declaration order matters: ALREADY_REVIEWED routes straight to collect (full mode dedupe);
272
+ # submit/noWait stop at pending; everything else waits.
273
+ - from: request
274
+ to: collect
275
+ description: Current HEAD already carries a Codex review — collect instead of duplicating
276
+ guard:
277
+ kind: shell
278
+ options:
279
+ command: 'test "$(cat .spur/run/$__runId-pr-request.status 2>/dev/null)" = ALREADY_REVIEWED'
280
+ - from: request
281
+ to: pending
282
+ description: Request already in flight, or mode=submit/--no-wait after posting — return pending
283
+ guard:
284
+ kind: shell
285
+ options:
286
+ command: 'test "$(cat .spur/run/$__runId-pr-request.status 2>/dev/null)" = ALREADY_REQUESTED || { test "$(cat .spur/run/$__runId-pr-request.status 2>/dev/null)" = REQUESTED && { test "$mode" = "submit" || test "$noWait" = "true"; }; }'
287
+ - from: request
288
+ to: wait
289
+ description: Request posted — poll for the result
290
+ guard:
291
+ kind: shell
292
+ options:
293
+ command: 'test "$(cat .spur/run/$__runId-pr-request.status 2>/dev/null)" = REQUESTED'
294
+ - from: request
295
+ to: failed
296
+ description: Request failed (no PR, gh error) — report the preserved error
297
+ guard:
298
+ kind: always
299
+
300
+ - from: wait
301
+ to: collect
302
+ description: Codex findings or an explicit clean result on the current HEAD found
303
+ guard:
304
+ kind: shell
305
+ options:
306
+ command: 'grep -qE "^(FOUND|CLEAN)$" .spur/run/$__runId-pr-wait.status 2>/dev/null'
307
+ - from: wait
308
+ to: pending
309
+ description: Poll budget exhausted — pending, not failed
310
+ guard:
311
+ kind: shell
312
+ options:
313
+ command: 'test "$(cat .spur/run/$__runId-pr-wait.status 2>/dev/null)" = TIMEOUT'
314
+ - from: wait
315
+ to: failed
316
+ description: Poll probe itself failed
317
+ guard:
318
+ kind: always
319
+
320
+ - from: collect
321
+ to: done
322
+ description: Current-HEAD review collected (CLEAN/FINDINGS)
323
+ guard:
324
+ kind: shell
325
+ options:
326
+ command: 'grep -qE "^(FINDINGS|CLEAN)$" .spur/run/$__runId-pr-collect.status 2>/dev/null'
327
+ - from: collect
328
+ to: pending
329
+ description: No current-HEAD result yet — pending, never clean
330
+ guard:
331
+ kind: shell
332
+ options:
333
+ command: 'test "$(cat .spur/run/$__runId-pr-collect.status 2>/dev/null)" = PENDING'
334
+ - from: collect
335
+ to: failed
336
+ description: Collect probe failed
337
+ guard:
338
+ kind: always
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.48",
3
+ "version": "0.3.50",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -53,14 +53,14 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@commander-js/extra-typings": "^14.0.0",
56
- "@gobing-ai/ts-db": "^0.4.31",
57
- "@gobing-ai/ts-ai-runner": "^0.4.32",
58
- "@gobing-ai/ts-dual-workflow-engine": "^0.4.31",
59
- "@gobing-ai/ts-infra": "^0.4.31",
60
- "@gobing-ai/ts-llm-jsonl-importer": "^0.4.31",
61
- "@gobing-ai/ts-rule-engine": "^0.4.31",
62
- "@gobing-ai/ts-runtime": "^0.4.31",
63
- "@gobing-ai/ts-utils": "^0.4.31",
56
+ "@gobing-ai/ts-db": "^0.4.38",
57
+ "@gobing-ai/ts-ai-runner": "^0.4.38",
58
+ "@gobing-ai/ts-dual-workflow-engine": "^0.4.38",
59
+ "@gobing-ai/ts-infra": "^0.4.38",
60
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.4.38",
61
+ "@gobing-ai/ts-rule-engine": "^0.4.38",
62
+ "@gobing-ai/ts-runtime": "^0.4.38",
63
+ "@gobing-ai/ts-utils": "^0.4.38",
64
64
  "@types/bun": "1.3.14",
65
65
  "@types/figlet": "^1.7.0",
66
66
  "@types/node-notifier": "8.0.5",
@@ -103,11 +103,12 @@ list this README is checked against.
103
103
  | `dev-next` | Status-aware router — inspect a task (or next frontier under a feature), dispatch the best existing `/sp:dev-*` command, chain on clean success |
104
104
  | `dev-run` | Run a task — full pipeline (precheck→implement→test→review→approve→verify→record→done) or single-step (implement) |
105
105
  | `dev-review` | Multi-dimensional review for a task or path — functional requirements traceability, SECUA framework, and architectural depth |
106
+ | `dev-pr-review` | GitHub Codex PR review — prepare/reuse a PR, request `@codex review`, collect findings, validate/fix/re-review (fix mode); workflow-backed spine |
106
107
  | `dev-verify` | Verify a task against its requirements and Acceptance Criteria — traceability check producing a PASS/PARTIAL/FAIL verdict with evidence |
107
108
  | `dev-unit` | Generate or extend tests until the unit target is met |
108
109
  | `dev-wrap` | Wrap up a single completed task — learnings, metrics, doc-sync, optional feature transition and branch cleanup |
109
110
  | `dev-refresh` | Refresh feature status by feature ID, task WBS, or batch sweep via spur feature sync |
110
- | `dev-featurechange` | Restructure feature tree from a mapping file — dry-run/apply via `spur feature move`, task edges, root `docs/*.md` only |
111
+ | `dev-feature-change` | Restructure feature tree from a mapping file — dry-run/apply via `spur feature move`, task edges, root `docs/*.md` only |
111
112
 
112
113
  #### Lifecycle — batch and parallel
113
114
 
@@ -126,6 +127,7 @@ list this README is checked against.
126
127
  | `dev-handover` | Generate a structured handover document when blocked — captures goal, progress, blocker, rejected approaches, and next steps |
127
128
  | `dev-debug` | Systematic debugging protocol — reproduce, isolate, diagnose root cause, apply minimal fix, and verify with regression tests |
128
129
  | `dev-daily` | Generate a daily summary report from agent usage data, git history, and notes |
130
+ | `dev-history-load` | On-demand cumulative history load + narrowed analyze — import (checkpoint-resume) then analyze, optionally by session/task/window, with optional forensics render |
129
131
  | `dev-dogfood` | Dogfood an agent skill/command/CLI — drive it end-to-end with bounded auto-fix, self-monitor, and emit a comprehensive report |
130
132
  | `dev-find-issue` | Review agent session logs, identify performance bottlenecks and behavioral anti-patterns, and generate a structured task file with proposed fixes |
131
133
  | `dev-find-conflict` | Authority-aware semantic audit across source, task, feature, and project authority files — detect conflicts, resolve claim-specific authority, and route confirmed repairs through owner surfaces |
@@ -135,7 +137,7 @@ list this README is checked against.
135
137
  | `dev-arch` | Survey a codebase (or module tree) for shallow modules and deepening opportunities — emit a ranked MARKDOWN candidate report that feeds the planning half; never auto-refactors |
136
138
  | `dev-reverse` | Reverse-engineer a codebase — analyze unfamiliar repos, generate HLD/architecture docs, audit quality/security, and produce onboarding documentation |
137
139
  | `dev-gitmsg` | Generate conventional commit message(s) from staged changes via per-file summarization, optionally commit |
138
- | `dev-gtd` | Get things done — quality gate (auto-fix) → act CI simulation → conventional commit → push → gh verify in one flow |
140
+ | `dev-gtd` | Get things done — quality gate (auto-fix) → conventional commit → push → gh verify in one flow; optional act CI simulation via `--act` |
139
141
  | `dev-changelog` | Generate changelog from git commits |
140
142
 
141
143
  #### Rule authoring
@@ -313,6 +315,7 @@ surface or run one workflow. All skills target the same five core platforms: `cl
313
315
  | `issue-finding` | 1.1 | Session-log forensics — multi-source discovery, bottleneck ranking, optional topic focus, CLI-gated fix task generation; backs `/sp:dev-find-issue` |
314
316
  | `conflict-finding` | 1.0 | Authority-aware semantic audit — four-pillar (source/task/feature/authority) conflict discovery, claim-specific authority resolution, reproducible evidence, confirmed owner-routed remediation; backs `/sp:dev-find-conflict` |
315
317
  | `next-feature` | 1.0 | Prompt-first feature frontier prioritizer — sync-first precondition, B3 actionability gate (cited, never restated), tiered rubric over measured signals, D1–D4 defect proposals conforming to the restructure map schema; backs `/sp:dev-find-next` |
318
+ | `pr-reviewing` | 1.0 | GitHub Codex PR review — PR prepare/reuse, `@codex review` request with per-HEAD dedupe, bounded polling, findings normalization, validated fix + re-review; spine SSOT `pr-review.yaml` + `scripts/pr-reviewing.ts`; backs `/sp:dev-pr-review` |
316
319
  | `indexed-context` | 1.0 | Cross-agent project context — anatomy/learnings/pitfalls/buglog/memory in `.spur/context/`; hook-tracked token-ledger; graceful degradation on agents without hooks |
317
320
 
318
321
  Each skill directory contains:
@@ -335,11 +338,11 @@ Skills contain zero validation logic — the CLI is the gate.
335
338
 
336
339
  Thin slash-command wrappers that parse user arguments and delegate to the corresponding skill. Each
337
340
  command is a user-facing entry point that bridges natural language to skill invocation. There are
338
- **37 commands** (see the Command index above for the full list), organized by the surface they wrap:
341
+ **39 commands** (see the Command index above for the full list), organized by the surface they wrap:
339
342
 
340
343
  | Prefix | Count | Delegates to | Purpose |
341
344
  | ------------ | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
342
- | `dev-*` | 31 | `sp:spur-dev`, `sp:code-implementation`, `sp:code-testing`, `sp:code-verification`, `sp:code-simplification`, `sp:next-router`, `sp:brainstorm`, `sp:dogfood-testing`, `sp:parallel-execution`, `sp:sys-debugging`, `sp:daily-summary`, `sp:issue-finding`, `sp:conflict-finding`, `sp:reverse-engineering`, inline | The dev-workflow surface — planning, execution, batch, wrap-up, review/verify, hygiene |
345
+ | `dev-*` | 33 | `sp:spur-dev`, `sp:code-implementation`, `sp:code-testing`, `sp:code-verification`, `sp:code-simplification`, `sp:next-router`, `sp:brainstorm`, `sp:dogfood-testing`, `sp:parallel-execution`, `sp:sys-debugging`, `sp:daily-summary`, `sp:issue-finding`, `sp:conflict-finding`, `sp:reverse-engineering`, `sp:pr-reviewing`, inline | The dev-workflow surface — planning, execution, batch, wrap-up, review/verify, hygiene |
343
346
  | `rule-*` | 3 | `sp:spur-cli` | The rule surface — `rule-add`, `rule-refine`, `rule-scan` |
344
347
  | `workflow-*` | 2 | `sp:spur-cli` | The workflow surface — `workflow-add`, `workflow-refine` |
345
348
  | `spur-init` | 1 | `sp:doc-evolve` | Project bootstrap (`spur init`) with doc-evolve integration |
@@ -349,7 +352,7 @@ Each command file contains:
349
352
  - YAML frontmatter (`description`, `argument-hint`, `allowed-tools`).
350
353
  - A delegation block: `Skill(skill="sp:<skill-name>", args="<operation> $ARGUMENTS")`.
351
354
 
352
- **Commands as SSOT (ADR-032).** The 37 `.md` files in `commands/` are the authoritative,
355
+ **Commands as SSOT (ADR-032).** The 39 `.md` files in `commands/` are the authoritative,
353
356
  hand-editable source for the operator command surface. Per-platform adapters are **install-time
354
357
  output** owned by `superskill` (`superskill install sp`) and never committed here. Plugin `sp` ships
355
358
  no per-platform artifacts — only the platform-independent thin wrappers.
@@ -357,7 +360,7 @@ no per-platform artifacts — only the platform-independent thin wrappers.
357
360
  **Thin-wrapper contract** is enforced by `scripts/validate-commands.ts`:
358
361
 
359
362
  ```bash
360
- bun plugins/sp/scripts/validate-commands.ts # validate all 37 commands
363
+ bun plugins/sp/scripts/validate-commands.ts # validate all 39 commands
361
364
  bun plugins/sp/scripts/validate-commands.ts --json # machine-readable output
362
365
  ```
363
366
 
@@ -1,14 +1,11 @@
1
1
  ---
2
- description: >-
2
+ description: "Restructure the feature tree from a mapping file — dry-run then apply via spur feature move / task feature_id edges / root docs/*.md reference rewrites (CLI-gated; no raw Write on docs/features or docs/tasks). Triggers: feature restructure, feature tree move, reparent features, apply mapping file"
3
3
  role: planner
4
- Restructure the feature tree from a mapping file — dry-run then apply via
5
- spur feature move / task feature_id edges / root docs/*.md reference rewrites
6
- (CLI-gated; no raw Write on docs/features or docs/tasks)
7
4
  argument-hint: "[--map <path>] [--dry-run] [--apply] [--limit <old-id>] [--wave <1|2|3|all>] [--yes]"
8
5
  allowed-tools: ["Bash", "Read", "AskUserQuestion", "Skill"]
9
6
  ---
10
7
 
11
- # Dev Featurechange
8
+ # Dev Feature Change
12
9
 
13
10
  CLI-gated feature-tree restructure orchestrator. Executes dispositions from a mapping file; does not invent hierarchy.
14
11
 
@@ -28,7 +25,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
28
25
  ## Usage
29
26
 
30
27
  ```
31
- /sp:dev-featurechange [--map <path>] [--dry-run] [--apply] [--limit <old-id>] [--wave <1|2|3|all>] [--yes]
28
+ /sp:dev-feature-change [--map <path>] [--dry-run] [--apply] [--limit <old-id>] [--wave <1|2|3|all>] [--yes]
32
29
  ```
33
30
 
34
31
  ## Implementation
@@ -43,7 +40,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
43
40
 
44
41
  - Read `--map`. Collect rows where disposition is not `keep` (typically `reparent-under:<parent>`).
45
42
  - Filter by `--limit` / `--wave` if set.
46
- - Wave defaults from map: **1** = K→J, L→J · **2** = N→H, O→H · **3** = P→D, Q→F, R→F8.
43
+ - Wave membership comes from the map itself (its wave column/section is the SSOT). Never hard-code letter sets here the tree moves under the command and literals go stale.
47
44
 
48
45
  **Free-digit preflight (mandatory before dry-run report)**
49
46
 
@@ -53,7 +50,7 @@ Group selected reparent rows by `new_parent`. For each parent:
53
50
  spur feature list --json
54
51
  ```
55
52
 
56
- Count current children (ids where `id` starts with parent and length = parent.length+1, digit 1–9).
53
+ Count current children (ids where `id` starts with parent and length = parent.length+1, digit 1–9).
57
54
  `free = 9 - childCount`. If `rowsUnderParent.length > free`, **abort the plan** with a clear error naming the parent, free slots, and competing old_ids. Do not apply a partial wave.
58
55
 
59
56
  **Dry-run plan (always) — sequential prediction**
@@ -102,10 +99,10 @@ spur feature refresh --json
102
99
  spur feature check --json
103
100
  ```
104
101
 
105
- Task edges: `feature move` rewrites `feature_id` across **all** configured task folders (via `foldersConfig`). Safety check:
102
+ Task edges: `feature move` rewrites `feature_id` across **all** configured task folders (via `foldersConfig`). Safety check (the glob covers every tasks folder, present and future):
106
103
 
107
104
  ```bash
108
- rg -n '^feature_id: <old_id>$' docs/tasks docs/tasks2 docs/tasks3
105
+ rg -n '^feature_id: <old_id>$' docs/tasks*/
109
106
  ```
110
107
 
111
108
  If any stale edges remain, fix with:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: "Render the session-forensics report from imported history data (8 CLI-derivable sections plus 6 model-authored), identify bottlenecks and behavioral anti-patterns, and optionally create a structured fix task behind --create-task. Triggers: post-mortem, performance analysis, session review, find issues, identify bottlenecks"
3
3
  role: reviewer
4
- argument-hint: "[<topic>] [--sessions <glob>] [--source <auto|omp|claude|codex|gemini|opencode|antigravity|openclaw|pi>] [--feature <id>] [--template <meta|issue|standard>] [--priority <P0|P1|P2|P3>] [--severity <S0|S1|S2>] [--category <list>] [--since <iso>] [--until <iso>] [--top <n>] [--min-cost <duration>] [--strict-topic] [--create-task] [--agent <inline|auto|name>] [--json]"
4
+ argument-hint: "[<topic>] [--sessions <glob>] [--source <auto|pi|claude|codex|gemini|opencode|antigravity|openclaw|omp|grok|agy|all>] [--feature <id>] [--template <meta|issue|standard>] [--priority <P0|P1|P2|P3>] [--severity <S0|S1|S2>] [--category <list>] [--since <iso>] [--until <iso>] [--top <n>] [--min-cost <duration>] [--strict-topic] [--create-task] [--agent <inline|auto|name>] [--json]"
5
5
  allowed-tools: ["Bash", "Read", "Write", "Grep", "Glob", "Skill"]
6
6
  ---
7
7
 
@@ -14,24 +14,24 @@ task file via `spur task create`.
14
14
 
15
15
  ## Argument Flags
16
16
 
17
- | Flag | Description | Default |
18
- | ------------------------------------------------------------------------------------ | ------------------------------------ | ---------- |
19
- | `[<topic>]` | Narrow the analysis to a topic. | omitted |
20
- | `--sessions` `<glob>` | Session log glob (fallback input). | recent |
21
- | `--source` `<auto\|omp\|claude\|codex\|gemini\|opencode\|antigravity\|openclaw\|pi>` | Agent source to scan. | auto |
22
- | `--feature` `<id>` | Attach the generated task to a feature. | omitted |
23
- | `--template` `<meta\|issue\|standard>` | Task template shape (`--create-task` only). | standard |
24
- | `--priority` `<P0\|P1\|P2\|P3>` | Filter / assign task priority. | P2 |
25
- | `--severity` `<S0\|S1\|S2>` | Filter / assign severity. | all |
26
- | `--category` `<list>` | Comma list of categories to keep. | all |
27
- | `--since` `<iso>` | Start of the scan window. | configured |
28
- | `--until` `<iso>` | End of the scan window. | now |
29
- | `--top` `<n>` | Limit to top N findings. | omitted |
30
- | `--min-cost` `<duration>` | Minimum wasted duration to report. | omitted |
31
- | `--strict-topic` | Drop findings off-topic. | off |
32
- | `--create-task` | Generate a fix task for findings. | off |
33
- | `--agent` `<inline\|auto\|name>` | Who runs the model-bearing analysis. | omit |
34
- | `--json` | Emit structured JSON. | off |
17
+ | Flag | Description | Default |
18
+ | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------- |
19
+ | `[<topic>]` | Narrow the analysis to a topic. | omitted |
20
+ | `--sessions` `<glob>` | Session log glob (fallback input). | recent |
21
+ | `--source` `<auto\|pi\|claude\|codex\|gemini\|opencode\|antigravity\|openclaw\|omp\|grok\|agy\|all>` | Agent source to scan (CLI vocabulary; `all` fans out, `auto` resolves at runtime). | auto |
22
+ | `--feature` `<id>` | Attach the generated task to a feature. | omitted |
23
+ | `--template` `<meta\|issue\|standard>` | Task template shape (`--create-task` only); `issue` is the explicit single-finding override, `standard` the generic override. | meta |
24
+ | `--priority` `<P0\|P1\|P2\|P3>` | Filter / assign task priority. | P2 |
25
+ | `--severity` `<S0\|S1\|S2>` | Filter / assign severity. | all |
26
+ | `--category` `<list>` | Comma list of categories to keep. | all |
27
+ | `--since` `<iso>` | Start of the scan window. | configured |
28
+ | `--until` `<iso>` | End of the scan window. | now |
29
+ | `--top` `<n>` | Limit to top N findings. | omitted |
30
+ | `--min-cost` `<duration>` | Minimum wasted duration to report. | omitted |
31
+ | `--strict-topic` | Drop findings off-topic. | off |
32
+ | `--create-task` | Generate a fix task for findings. | off |
33
+ | `--agent` `<inline\|auto\|name>` | Who runs the model-bearing analysis. | omit |
34
+ | `--json` | Emit structured JSON. | off |
35
35
 
36
36
  For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
37
37
 
@@ -52,6 +52,11 @@ the history data plane is now the primary source (no flag needed), and the old r
52
52
  is the new default. Raw JSONL remains a fallback under the three conditions documented in
53
53
  `sp:issue-finding`.
54
54
 
55
+ **Data-plane preflight.** Forensics read the imported history plane as-is. If findings come back
56
+ empty or stale, run `/sp:dev-history-load` (on-demand cumulative `spur history import` + analyze,
57
+ checkpoint resume — task 0567) before re-running forensics; it owns the interactive preflight, while
58
+ `spur history daily` owns the periodic cadence.
59
+
55
60
  **See also:** skill `sp:issue-finding` (SSOT), `/sp:dev-runall`, `/sp:dev-dogfood`,
56
61
  `sp:daily-summary`, `sp:reverse-engineering`.
57
62
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Prompt-first feature frontier prioritizer — answers 'which feature should we work on now?' with a ranked, evidence-carrying frontier, and emits rank-distorting tree defects as proposals /sp:dev-featurechange consumes. Triggers: find next, which feature, feature ranking, frontier priority, what should I work on."
2
+ description: "Prompt-first feature frontier prioritizer — answers 'which feature should we work on now?' with a ranked, evidence-carrying frontier, and emits rank-distorting tree defects as proposals /sp:dev-feature-change consumes. Triggers: find next, which feature, feature ranking, frontier priority, what should I work on."
3
3
  role: planner
4
4
  argument-hint: "[--task [<feature-id>]] [--agent <inline|auto|name>] [--auto] [--json]"
5
5
  allowed-tools: ["Bash", "Read", "Write", "Grep", "Glob", "Skill"]
@@ -13,7 +13,7 @@ instead of ranking them, and emits tree structure defects as proposals only.
13
13
 
14
14
  Answers *"which X"* — the question `/sp:dev-next` deliberately does not (next-router routing-table
15
15
  §0 step 1c). Advancing a chosen target remains `/sp:dev-next`'s job; applying tree changes remains
16
- `/sp:dev-featurechange`'s job.
16
+ `/sp:dev-feature-change`'s job.
17
17
 
18
18
  ## Argument Flags
19
19
 
@@ -55,7 +55,7 @@ Without `--task` the command is read-only with respect to the corpus and docs. U
55
55
  only mutation is the one the dispatched commands perform on `docs/tasks*/` after confirm (or
56
56
  auto-accept) — the command still performs no `spur feature move`, no sync apply, and no write under
57
57
  `docs/features/**`. Defect proposals conform to the `docs/plans/feature-tree-restructure-map.md`
58
- schema and are applied only through `/sp:dev-featurechange` (dry-run → confirm → apply).
58
+ schema and are applied only through `/sp:dev-feature-change` (dry-run → confirm → apply).
59
59
 
60
60
  **See also:** skill `sp:next-feature` (SSOT), `sp:next-router` (`/sp:dev-next`),
61
61
  `sp:conflict-finding` (the prompt-first template), `sp:spur-cli`.