@gobing-ai/spur 0.4.10 → 0.4.11

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.
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.4.10",
10
+ "version": "0.4.11",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
@@ -3,13 +3,14 @@
3
3
  # (initialState / states[].id / onEnter / top-level transitions), same family as
4
4
  # basic.yaml / task-pipeline.yaml. Seeded into projects by `spur init` (scaffold manifest).
5
5
  #
6
- # Shape: preflight → hygiene → precheck → push → ensure-pr → request → wait → collect → done
6
+ # Shape: check → precheck → open → review → done
7
7
  # (soft probes everywhere: red gates route to `failed`/`pending` via transitions,
8
8
  # never a raw lifecycle abort — same reliability contract as basic.yaml)
9
9
  #
10
- # This YAML is the SSOT for the review spine's state order and guards. Every state shells
11
- # out to `spur builder pr` (the tested deterministic core); no gh/git
12
- # logic lives in this file. All model-bearing work — finding triage, `fix` mode, `rules`
10
+ # This YAML is the SSOT for the review spine's state order and guards. Every state shells out to
11
+ # the four flat `spur builder pr-<verb>` verbs (task 1219); the op sequencing
12
+ # (preflight→hygiene, push→ensure, request→wait→collect) lives in `runPrVerb`, not in this file's
13
+ # shell, and no gh/git logic lives in this file. All model-bearing work — finding triage, `fix`
13
14
  # mode — stays in the sp:pr-reviewing skill and never enters this machine.
14
15
  #
15
16
  # Non-negotiable: the external review goes through the GitHub PR + an `@codex review`
@@ -21,7 +22,7 @@
21
22
  # submit: request and stop at `pending` (no wait)
22
23
  # rerun: request with --force even when HEAD is already reviewed
23
24
  # 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
+ # focus — extra review focus appended to the @codex review request
25
26
  # noWait — "true" returns pending right after the request instead of polling
26
27
  # waitTimeoutSec — poll budget for Codex output (default 600)
27
28
  # waitIntervalSec — poll interval (default 30; do not poll aggressively)
@@ -34,9 +35,9 @@
34
35
  version: "1"
35
36
  name: pr-review
36
37
  kind: state-machine
37
- description: GitHub Codex PR-review spine — preflight → hygiene → precheck → push → ensure-pr → request → wait → collect
38
+ description: GitHub Codex PR-review spine — check → precheck → open → review
38
39
  iterationBound: 16
39
- initialState: preflight
40
+ initialState: check
40
41
  terminalStates:
41
42
  - done
42
43
  - pending
@@ -53,50 +54,27 @@ vars:
53
54
  spurBin: "spur"
54
55
  preReviewCmd: ""
55
56
  __runId: ""
56
- # Runtime-set by file.read.into-var (0771): the request record's requestedAt|head,
57
- # extracted once by `request` and read per state — no repeated JSON parsing in shell.
58
- prSince: ""
59
- prHead: ""
60
57
 
61
58
  states:
62
- - id: preflight
59
+ - id: check
63
60
  description: >
64
- Soft probe: git/gh/repo checks (detached HEAD, dirty tree, gh auth, GitHub remote,
65
- base-branch refusal — preflight refuses when the current branch IS the resolved base,
66
- before any push can publish it).
67
- Writes PASS|FAIL to .spur/run/${vars.__runId}-pr-preflight.status; always exit 0.
61
+ Soft probe: preflight (git/gh/repo checks, detached HEAD, dirty tree, base-branch refusal —
62
+ refused before any push can publish it) followed by the hygiene scan of base...HEAD
63
+ (secrets/.env/conflict markers BLOCK; debug residue WARNs). A preflight failure stops before
64
+ hygiene. Writes PASS|WARN|BLOCK|FAIL to .spur/run/${vars.__runId}-pr-check.status; always
65
+ exit 0, so a red gate routes through the transitions below.
68
66
  onEnter:
69
- # script-root retired for this workflow: actions call `$spurBin builder pr` directly (PR-7).
67
+ # script-root retired for this workflow: actions call `$spurBin builder pr-<verb>` directly.
70
68
  - kind: shell
71
69
  options:
72
- # (e) 0825: 10 lines — detached-HEAD/dirty/gh-auth/base-refusal probes must record
73
- # before any push can publish; split would let a half-probed run continue.
70
+ # (e) 0825: 7 lines — preflight+hygiene and their status fallback must land together
71
+ # (one verb now owns the whole probe; a split would half-probe the submission gate).
74
72
  command: >-
75
-
76
- STATUS_FILE=".spur/run/$__runId-pr-preflight.status" &&
77
- set +e &&
78
- $spurBin builder pr preflight --base "$baseBranch" --json > ".spur/run/$__runId-pr-context.json";
79
- rc=$?; set -e &&
80
- if [ "$rc" -eq 0 ]; then printf 'PASS\n' > "$STATUS_FILE"; else printf 'FAIL\n' > "$STATUS_FILE"; fi &&
81
- exit 0
82
-
83
- - id: hygiene
84
- description: >
85
- Submission sanity scan of base...HEAD: secrets/.env/conflict markers BLOCK the run;
86
- debug residue only WARNs. Not a replacement for the independent Codex review.
87
- onEnter:
88
- - kind: shell
89
- options:
90
- # (e) 0825: 9 lines — hygiene verdict + json capture land together; the status-file
91
- # fallback keeps a silent driver from passing the gate.
92
- command: >-
93
-
94
- STATUS_FILE=".spur/run/$__runId-pr-hygiene.status" &&
95
- set +e &&
96
- $spurBin builder pr hygiene --base "$baseBranch" --json
97
- --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-hygiene.json";
98
- rc=$?; set -e &&
99
- if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
73
+ STATUS_FILE=".spur/run/$__runId-pr-check.status";
74
+ mkdir -p .spur/run;
75
+ $spurBin builder pr-check --base "$baseBranch" --json --status-file "$STATUS_FILE"
76
+ > ".spur/run/$__runId-pr-check.json";
77
+ if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi;
100
78
  exit 0
101
79
 
102
80
  - id: precheck
@@ -111,141 +89,78 @@ states:
111
89
  command: >-
112
90
  mkdir -p .spur/run; if [ -z "$preReviewCmd" ]; then R=SKIP; elif sh -c "$preReviewCmd"; then R=PASS; else R=FAIL; fi; printf '%s\n' "$R" > ".spur/run/$__runId-pr-precheck.status"
113
91
 
114
- - id: push
92
+ - id: open
115
93
  description: >
116
- Publish the branch (normal push only, never force; sets upstream when missing).
117
- A PR reviews pushed commits only.
94
+ Publish the branch (normal push only, never force; sets upstream when missing) and reuse or
95
+ create its PR — a rejected push stops before any PR work. Writes FOUND|CREATED|FAIL to
96
+ .spur/run/${vars.__runId}-pr-open.status and the composed record (push + pr) to
97
+ .spur/run/${vars.__runId}-pr-open.json.
118
98
  onEnter:
119
99
  - kind: shell
120
100
  options:
121
- # (e) 0825: 9 lines — push result and status fallback are atomic; a split could
122
- # publish commits without recording the outcome.
101
+ # (e) 0825: 7 lines — publish + PR dedupe are one verb now; the status fallback keeps a
102
+ # silent driver from passing the gate.
123
103
  command: >-
124
- mkdir -p .spur/run &&
125
- STATUS_FILE=".spur/run/$__runId-pr-push.status" &&
126
- set +e &&
127
- $spurBin builder pr push --json --status-file "$STATUS_FILE"
128
- > ".spur/run/$__runId-pr-push.json";
129
- rc=$?; set -e &&
130
- if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
104
+ STATUS_FILE=".spur/run/$__runId-pr-open.status";
105
+ mkdir -p .spur/run;
106
+ $spurBin builder pr-open --base "$baseBranch" --json --status-file "$STATUS_FILE"
107
+ > ".spur/run/$__runId-pr-open.json";
108
+ if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi;
131
109
  exit 0
132
110
 
133
- - id: ensure-pr
134
- description: Find or create the GitHub PR for the current branch — never a duplicate.
135
- onEnter:
136
- - kind: shell
137
- options:
138
- # (e) 0825: 9 lines — PR dedupe lookup captures its record for the downstream
139
- # review link; ensure + capture must not race.
140
- command: >-
141
- mkdir -p .spur/run &&
142
- STATUS_FILE=".spur/run/$__runId-pr-ensure.status" &&
143
- set +e &&
144
- $spurBin builder pr ensure-pr --base "$baseBranch" --json
145
- --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr.json";
146
- rc=$?; set -e &&
147
- if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
148
- exit 0
149
-
150
- - id: request
151
- description: >
152
- Post the `@codex review` request (per-HEAD dedupe unless mode=rerun forces).
153
- Records the request under .spur/run/${vars.__runId}-pr-request.json.
154
- onEnter:
155
- - kind: shell
156
- options:
157
- # (e) 0825: 10 lines — the write-then-read split is the file-var transport feeding
158
- # wait/collect and must stay one action (same record, same run scope).
159
- command: >-
160
- F="$([ "$mode" = rerun ] && echo --force)"; $spurBin builder pr request --focus "$focus" $F --json --status-file ".spur/run/$__runId-pr-request.status" > ".spur/run/$__runId-pr-request.json"; [ -f ".spur/run/$__runId-pr-request.status" ] || echo FAIL > ".spur/run/$__runId-pr-request.status"; jq -e . ".spur/run/$__runId-pr-request.json" >/dev/null 2>&1 && jq -r '.requestedAt // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-since.txt" && jq -r '.head // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-head.txt"; exit 0
161
-
162
- - id: wait
111
+ - id: review
163
112
  description: >
164
- Bounded poll for Codex output on the current pushed HEAD. Timeout records TIMEOUT
165
- and routes to `pending` — never a failure (collect later with /sp:dev-pr-review collect).
166
- Reads the request record once at `request` (0771): requestedAt/head land in
167
- run-scoped .txt files, projected into prSince/prHead vars via file.read.into-var.
113
+ Request, wait for and collect the `@codex review` result on the current pushed HEAD
114
+ (per-HEAD dedupe unless mode=rerun; mode=submit or noWait=true stop at PENDING). Writes
115
+ CLEAN|FINDINGS|PENDING|FAIL to .spur/run/${vars.__runId}-pr-review.status — a wait timeout
116
+ is PENDING, never a failure — plus the composed findings record and the composite status.
168
117
  onEnter:
169
- - kind: file.read.into-var
170
- options:
171
- path: .spur/run/${vars.__runId}-pr-since.txt
172
- var: prSince
173
- - kind: file.read.into-var
174
- options:
175
- path: .spur/run/${vars.__runId}-pr-head.txt
176
- var: prHead
177
118
  - kind: shell
178
119
  options:
179
- # (e) 0825: 9 lines — bounded wait loop keeps rc bookkeeping so a crashed driver
180
- # fails closed instead of polling forever.
120
+ # (e) 0825: 10 lines — request/wait/collect are one verb now, so their result lands
121
+ # atomically; the status fallback covers a crashed driver. `mode=submit` or `noWait=true`
122
+ # pass --no-wait and `mode=rerun` passes --force, each as its own space-separated word
123
+ # (two substitutions, never concatenated). `/bin/sh -c` carries no `-e`, so a failed
124
+ # substitution is ignored.
181
125
  command: >-
182
- mkdir -p .spur/run &&
183
- STATUS_FILE=".spur/run/$__runId-pr-wait.status" &&
184
- set +e &&
185
- $spurBin builder pr wait --since "$prSince" --head "$prHead" --timeout "$waitTimeoutSec" --interval "$waitIntervalSec"
186
- --json --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-wait.json";
187
- rc=$?; set -e &&
188
- if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
126
+ O="$([ "$mode" = submit ] || [ "$noWait" = "true" ] && echo --no-wait) $([ "$mode" = rerun ] && echo --force)";
127
+ STATUS_FILE=".spur/run/$__runId-pr-review.status";
128
+ mkdir -p .spur/run;
129
+ $spurBin builder pr-review --focus "$focus" $O --timeout "$waitTimeoutSec" --interval "$waitIntervalSec"
130
+ --json --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-findings.json";
131
+ if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi;
189
132
  exit 0
190
-
191
- - id: collect
192
- description: >-
193
- Normalize the latest current-HEAD Codex result and record composite PR/CI status.
194
- Request record read via file.read.into-var vars (0771, see wait).
195
- onEnter:
196
- - kind: file.read.into-var
197
- options:
198
- path: .spur/run/${vars.__runId}-pr-since.txt
199
- var: prSince
200
- - kind: file.read.into-var
201
- options:
202
- path: .spur/run/${vars.__runId}-pr-head.txt
203
- var: prHead
204
133
  - kind: shell
205
134
  options:
206
- # (e) 0825: 9 lines — collect + status must run against the same since/head pair
207
- # before the composite status is decided (same 0771 record contract).
135
+ # The report reads the same composite PR/CI/Codex artifact as before (read-only, so a
136
+ # failed probe records its own error object instead of failing the collected run).
208
137
  command: >-
209
- mkdir -p .spur/run; $spurBin builder pr collect --since "$prSince" --head "$prHead" --json --status-file ".spur/run/$__runId-pr-collect.status" > ".spur/run/$__runId-pr-findings.json"; c=$?; $spurBin builder pr status --since "$prSince" --head "$prHead" --json > ".spur/run/$__runId-pr-status.json" && [ "$c" -eq 0 ] && [ -f ".spur/run/$__runId-pr-collect.status" ] || printf 'FAIL\n' > ".spur/run/$__runId-pr-collect.status"; cat ".spur/run/$__runId-pr-findings.json" 2>/dev/null; exit 0
138
+ $spurBin builder pr-status --json > ".spur/run/$__runId-pr-status.json" || true
210
139
 
211
140
  - id: done
212
141
  description: Terminal — review collected; findings artifact at .spur/run/${vars.__runId}-pr-findings.json
213
142
  - id: pending
214
- description: Terminal — review requested (or timed out) but not yet collected; run /sp:dev-pr-review collect later
143
+ description: Terminal — review requested (or timed out) but not yet collected; run /sp:dev-pr-review status later
215
144
  - id: failed
216
145
  description: Terminal — a gate went red; the stage .status/.json artifacts under .spur/run name the blocker
217
146
 
218
147
  transitions:
219
- - from: preflight
220
- to: hygiene
221
- description: Repo, gh auth, and clean tree verified
222
- guard:
223
- kind: shell
224
- options:
225
- command: 'test "$(cat .spur/run/$__runId-pr-preflight.status 2>/dev/null)" = PASS'
226
- - from: preflight
227
- to: failed
228
- terminalReason: failed-check
229
- description: Preflight red (detached HEAD, dirty tree, gh auth, no GitHub remote, or the current branch being the base branch) — stop before any publishing
230
- guard:
231
- kind: always
232
-
233
- - from: hygiene
148
+ - from: check
234
149
  to: precheck
235
150
  description: Clean or warn-only — warnings ride along to the report
236
151
  guard:
237
152
  kind: shell
238
153
  options:
239
- command: 'grep -qE "^(PASS|WARN)$" .spur/run/$__runId-pr-hygiene.status 2>/dev/null'
240
- - from: hygiene
154
+ command: 'grep -qE "^(PASS|WARN)$" .spur/run/$__runId-pr-check.status 2>/dev/null'
155
+ - from: check
241
156
  to: failed
242
157
  terminalReason: failed-check
243
- description: BLOCK (secrets/.env/conflict markers) or probe failure — never submit a tainted diff
158
+ description: BLOCK (secrets/.env/conflict markers), a preflight failure (detached HEAD, dirty tree, gh auth, no GitHub remote, or the current branch being the base branch), or a probe failure — stop before any publishing
244
159
  guard:
245
160
  kind: always
246
161
 
247
162
  - from: precheck
248
- to: push
163
+ to: open
249
164
  description: Project fast check passed or was skipped
250
165
  guard:
251
166
  kind: shell
@@ -258,104 +173,37 @@ transitions:
258
173
  guard:
259
174
  kind: always
260
175
 
261
- - from: push
262
- to: ensure-pr
263
- description: Branch published (or already up to date)
264
- guard:
265
- kind: shell
266
- options:
267
- command: 'grep -qE "^(PUSHED|UP_TO_DATE)$" .spur/run/$__runId-pr-push.status 2>/dev/null'
268
- - from: push
269
- to: failed
270
- terminalReason: failed-check
271
- description: Push rejected (e.g. non-fast-forward) — report; never force-push as a workaround
272
- guard:
273
- kind: always
274
-
275
- - from: ensure-pr
276
- to: request
277
- description: PR found or created
278
- guard:
279
- kind: shell
280
- options:
281
- command: 'grep -qE "^(FOUND|CREATED)$" .spur/run/$__runId-pr-ensure.status 2>/dev/null'
282
- - from: ensure-pr
283
- to: failed
284
- terminalReason: failed-check
285
- description: No reviewable delta or PR creation failed — report the actual git/GitHub state
286
- guard:
287
- kind: always
288
-
289
- # Declaration order matters: ALREADY_REVIEWED routes straight to collect (full mode dedupe);
290
- # submit/noWait stop at pending; everything else waits.
291
- - from: request
292
- to: collect
293
- description: Current HEAD already carries a Codex review — collect instead of duplicating
294
- guard:
295
- kind: shell
296
- options:
297
- command: 'test "$(cat .spur/run/$__runId-pr-request.status 2>/dev/null)" = ALREADY_REVIEWED'
298
- - from: request
299
- to: pending
300
- description: Request already in flight, or mode=submit/--no-wait after posting — return pending
301
- guard:
302
- kind: shell
303
- options:
304
- # (e) 0825: 4-predicate guard — ALREADY_REQUESTED/REQUESTED pair state is the
305
- # fallback route when the review driver stalls (mode/noWait honored).
306
- 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"; }; }'
307
- - from: request
308
- to: wait
309
- description: Request posted — poll for the result
310
- guard:
311
- kind: shell
312
- options:
313
- command: 'test "$(cat .spur/run/$__runId-pr-request.status 2>/dev/null)" = REQUESTED'
314
- - from: request
315
- to: failed
316
- terminalReason: failed-check
317
- description: Request failed (no PR, gh error) — report the preserved error
318
- guard:
319
- kind: always
320
-
321
- - from: wait
322
- to: collect
323
- description: Codex findings or an explicit clean result on the current HEAD found
324
- guard:
325
- kind: shell
326
- options:
327
- command: 'grep -qE "^(FOUND|CLEAN)$" .spur/run/$__runId-pr-wait.status 2>/dev/null'
328
- - from: wait
329
- to: pending
330
- description: Poll budget exhausted — pending, not failed
176
+ - from: open
177
+ to: review
178
+ description: Branch published and PR found or created
331
179
  guard:
332
180
  kind: shell
333
181
  options:
334
- command: 'test "$(cat .spur/run/$__runId-pr-wait.status 2>/dev/null)" = TIMEOUT'
335
- - from: wait
182
+ command: 'grep -qE "^(FOUND|CREATED)$" .spur/run/$__runId-pr-open.status 2>/dev/null'
183
+ - from: open
336
184
  to: failed
337
185
  terminalReason: failed-check
338
- description: Poll probe itself failed
186
+ description: Push rejected (e.g. non-fast-forward — report; never force-push as a workaround) or no reviewable delta or PR creation failed
339
187
  guard:
340
188
  kind: always
341
189
 
342
- - from: collect
190
+ - from: review
343
191
  to: done
344
192
  description: Current-HEAD review collected (CLEAN/FINDINGS)
345
193
  guard:
346
194
  kind: shell
347
195
  options:
348
- command: 'grep -qE "^(FINDINGS|CLEAN)$" .spur/run/$__runId-pr-collect.status 2>/dev/null'
349
- - from: collect
196
+ command: 'grep -qE "^(FINDINGS|CLEAN)$" .spur/run/$__runId-pr-review.status 2>/dev/null'
197
+ - from: review
350
198
  to: pending
351
- description: No current-HEAD result yet — pending, never clean
199
+ description: Request in flight, mode=submit/noWait, or a wait timeout — pending, not failed (collect later)
352
200
  guard:
353
201
  kind: shell
354
202
  options:
355
- command: 'test "$(cat .spur/run/$__runId-pr-collect.status 2>/dev/null)" = PENDING'
356
- - from: collect
203
+ command: 'test "$(cat .spur/run/$__runId-pr-review.status 2>/dev/null)" = PENDING'
204
+ - from: review
357
205
  to: failed
358
206
  terminalReason: failed-check
359
- description: Collect probe failed
207
+ description: Review probe itself failed (no PR, gh error, moved HEAD)
360
208
  guard:
361
209
  kind: always
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.4.10",
3
+ "version": "0.4.11",
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",
@@ -1,39 +1,49 @@
1
1
  ---
2
- description: "Review GitHub PRs with Codex; collect and fix findings."
2
+ description: "Local-first PR review — status, a local branch-diff review, and validated fixes; --codex opts into the GitHub Codex review spine."
3
3
  role: reviewer
4
- argument-hint: "[full|submit|collect|fix|rerun|status|rules] [--base <branch>] [--no-wait] [--agent <inline|auto|name>] [<focus>]"
4
+ argument-hint: "[status|review|fix] [--codex] [--force] [--no-wait] [--base <branch>] [--agent <inline|auto|name>] [<focus>]"
5
5
  allowed-tools: ["Bash", "Read", "Skill"]
6
6
  ---
7
7
 
8
8
  # Dev PR Review
9
9
 
10
- Wraps the **sp:pr-reviewing** skill. The review itself runs on the GitHub PR through Codex
11
- (`@codex review`) — never through a local Codex review mechanism; the invoking agent orchestrates
12
- and (in `fix` mode) implements.
10
+ Wraps the **sp:pr-reviewing** skill. The default `status` mode is a read-only snapshot of the
11
+ branch, its base and the pull request; `review` runs a **local** review of the branch diff unless
12
+ `--codex` opts into the GitHub `@codex review` spine; `fix` triages findings from either reviewer
13
+ and commits the verified ones. The invoking agent orchestrates.
13
14
 
14
15
  ## Argument Flags
15
16
 
16
17
  | Flag | Description | Default |
17
18
  | --- | --- | --- |
18
- | `<mode>` | `full\|submit\|collect\|fix\|rerun\|status\|rules` — full: request (deduped) + wait + report; submit: request and stop at pending; collect: report the latest review; fix: validate findings, fix legitimate ones, re-review; rerun: force a fresh review of the pushed HEAD; status: read-only composite; rules: author the repo's `AGENTS.md` `## Code Review Rules`. | full |
19
- | `--base` `<branch>` | Base branch when a new PR must be created. | existing PR base, else repo default |
20
- | `--no-wait` | Return pending right after the review request instead of polling. | off |
21
- | `--agent` `<inline\|auto\|name>` | Who performs model-bearing triage/fix. Omit uses the current agent, `inline` forbids dispatch, `auto` resolves the declared role, and a name pins that executor. This does not change the deterministic workflow/direct route. | omit |
22
- | `<focus>` | Remaining free text — extra review focus appended to the Codex request (e.g. `security boundaries and transaction idempotency`). | none |
19
+ | `<mode>` | `status\|review\|fix` — status: read-only branch + PR state; review: local branch-diff review (or the GitHub Codex spine with `--codex`); fix: validate, fix and commit findings from either reviewer. | status |
20
+ | `--codex` | `review` only — route through the GitHub Codex spine (`pr-review.yaml`) instead of the local `/sp:dev-review`. | off |
21
+ | `--force` | `review --codex` only — request a fresh review of the current HEAD even when it was already reviewed (`mode=rerun`). | off |
22
+ | `--no-wait` | `review --codex` only — post the request and return `pending` without polling (`mode=submit`). | off |
23
+ | `--base <branch>` | Base branch for the branch report, the `pr-check` diff and a newly created PR. | existing PR base, else repo default |
24
+ | `--agent <inline\|auto\|name>` | Who performs the model-bearing triage/fix. Omit uses the current agent, `inline` forbids dispatch, `auto` resolves the declared role, and a name pins that executor. This does not change the deterministic route. | omit |
25
+ | `<focus>` | Remaining free text — extra review focus for the local review or the Codex request (e.g. `security boundaries and transaction idempotency`). | none |
23
26
 
24
27
  For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
25
28
 
26
29
  ## Usage
27
30
 
28
- /sp:dev-pr-review [full|submit|collect|fix|rerun|status|rules] [--base <branch>] [--no-wait] [--agent <inline|auto|name>] [review focus]
31
+ ```
32
+ /sp:dev-pr-review [status|review|fix] [--codex] [--force] [--no-wait] [--base <branch>] [--agent <inline|auto|name>] [review focus]
33
+ ```
29
34
 
30
35
  ## Implementation
31
36
 
32
37
  - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
33
38
  - Delegate everything: `Skill(skill="sp:pr-reviewing", args="$ARGUMENTS")`. The skill owns mode
34
- routing, finding triage, fix, and rules authoring; `pr-review.yaml` is the SSOT
35
- for the review spine's state order and guards; `spur builder pr` is the
36
- deterministic git/gh core every spine step shells out to.
37
- - The external review goes through the GitHub PR and an `@codex review` comment only — never local
38
- Codex review commands. Never force-push, rewrite history, merge the PR, or discard unrelated
39
- changes; outside `fix` mode, ask before creating any commit.
39
+ routing, the local `/sp:dev-review` dispatch, the Codex spine and finding triage/fix. On the
40
+ Codex path `pr-review.yaml` is the SSOT for state order and guards, and the four flat
41
+ `spur builder pr-<verb>` verbs are the deterministic git/gh core every spine step shells out to.
42
+ - Retired modes print one notice line and run their replacement: `full` → `review --codex`;
43
+ `submit` → `review --codex --no-wait`; `rerun` → `review --codex --force`; `collect` → `status`.
44
+ `rules` prints that `AGENTS.md` review-rule authoring belongs to `cc:cc-magents` (the `cc` plugin)
45
+ and exits without running a review.
46
+ - Never force-push, rewrite history, close or integrate the PR, or discard unrelated changes.
47
+ `review` without `--codex` makes no GitHub writes. `fix` pre-authorizes one focused commit for the
48
+ verified findings — stop if unrelated uncommitted changes make safe separation or committing
49
+ ambiguous.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "sp",
3
- "version": "0.4.10",
3
+ "version": "0.4.11",
4
4
  "description": "Spur — a local-first harness engineering toolkit that wraps mainstream coding agents with constraint checking, workflow orchestration, and history analytics."
5
5
  }
@@ -90,9 +90,13 @@ Before declaring a task `done`, run this lightweight checklist. It catches the m
90
90
  - [ ] No `console.log` / `console.error` in production code (use the project logger).
91
91
  - [ ] No `--no-verify`, `--force`, or new suppression comments added to bypass gates.
92
92
  - [ ] Solution section contains `file:line` citations for every changed file.
93
- - [ ] API/library claims in changed docs carry a source citation (URL or `path:line`) per
94
- source-driven-development; no confidence label is required (ADR-138). The deterministic
95
- advisory backstop is the `cited-version-strings` / `cited-api-claims` rules
93
+ - [ ] Every API/library claim in changed docs carries BOTH a source citation (URL or `path:line`) and
94
+ an EARNED level `HIGH|MEDIUM|LOW` — `HIGH` cites (a URL, `path:line`, or a path with a
95
+ code/doc extension), `MEDIUM`/`LOW` cite or name what is unverified. That is the
96
+ `| Claim | Source | Local verification | Confidence |` contract of
97
+ `.spur/rules/structure/api-library-claim-citation.yaml`; ADR-138 still forbids a confidence
98
+ label on the VERDICT or verify answer. The deterministic advisory backstop for the citation
99
+ half is the `cited-version-strings` / `cited-api-claims` rules
96
100
  (`.spur/rules/docs/sourced-api-claims.yaml`, run ad hoc — not wired into a preset).
97
101
  - [ ] Review section has P1–P4 findings table (even if all rows are empty — the table itself proves review happened).
98
102