@gobing-ai/spur 0.4.10 → 0.4.12

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 (60) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +22 -0
  3. package/config/rules/quality/coverage-gate.yaml +2 -2
  4. package/config/rules/surface/check-cli-surface.yaml +4 -0
  5. package/config/workflows/feature-verification.yaml +14 -5
  6. package/config/workflows/idea-pipeline.yaml +92 -12
  7. package/config/workflows/pr-review.yaml +72 -224
  8. package/config/workflows/task-pipeline.yaml +456 -830
  9. package/config/workflows/wayfinder-resolution.yaml +20 -3
  10. package/config/workflows/wrapup-pipeline.yaml +22 -9
  11. package/package.json +1 -1
  12. package/plugins/sp/README.md +2 -2
  13. package/plugins/sp/agents/super-planner.md +2 -2
  14. package/plugins/sp/agents/super-reviewer.md +17 -8
  15. package/plugins/sp/bunfig.toml +3 -3
  16. package/plugins/sp/commands/dev-changelog.md +1 -1
  17. package/plugins/sp/commands/dev-gitmsg.md +2 -2
  18. package/plugins/sp/commands/dev-handover.md +1 -1
  19. package/plugins/sp/commands/dev-idea.md +23 -13
  20. package/plugins/sp/commands/dev-job-dump.md +1 -1
  21. package/plugins/sp/commands/dev-plan.md +17 -6
  22. package/plugins/sp/commands/dev-pr-review.md +27 -17
  23. package/plugins/sp/commands/dev-review.md +1 -1
  24. package/plugins/sp/commands/dev-run.md +7 -6
  25. package/plugins/sp/commands/dev-runall.md +1 -1
  26. package/plugins/sp/plugin.json +1 -1
  27. package/plugins/sp/skills/code-implementation/SKILL.md +7 -7
  28. package/plugins/sp/skills/code-refactoring/SKILL.md +1 -1
  29. package/plugins/sp/skills/code-verification/SKILL.md +1 -1
  30. package/plugins/sp/skills/code-verification/references/secu-review.md +8 -4
  31. package/plugins/sp/skills/code-verification/references/verdict-schema.md +23 -10
  32. package/plugins/sp/skills/doc-evolve/SKILL.md +1 -1
  33. package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
  34. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +7 -7
  35. package/plugins/sp/skills/pr-reviewing/SKILL.md +157 -210
  36. package/plugins/sp/skills/source-driven-development/SKILL.md +14 -6
  37. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +4 -4
  38. package/plugins/sp/skills/spur-check/SKILL.md +9 -8
  39. package/plugins/sp/skills/spur-cli/SKILL.md +3 -3
  40. package/plugins/sp/skills/spur-cli/references/builder.md +86 -13
  41. package/plugins/sp/skills/spur-cli/references/self.md +37 -2
  42. package/plugins/sp/skills/spur-cli/references/tasks/l3-guard-cheatsheet.md +1 -1
  43. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +3 -3
  44. package/plugins/sp/skills/spur-cli/references/tasks.md +1 -1
  45. package/plugins/sp/skills/spur-cli/references/workflows.md +5 -3
  46. package/plugins/sp/skills/spur-dev/SKILL.md +3 -3
  47. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +9 -8
  48. package/plugins/sp/skills/spur-dev/references/dev-operations.md +11 -11
  49. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +4 -3
  50. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +4 -4
  51. package/plugins/sp/skills/spur-dev/references/execution-batch.md +13 -11
  52. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +31 -22
  53. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +5 -5
  54. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +4 -4
  55. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +3 -2
  56. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +4 -4
  57. package/schemas/spur-config.schema.json +19 -1
  58. package/spur.js +32388 -31906
  59. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +0 -997
  60. package/plugins/sp/skills/spur-dev/references/structured-trace-emission.md +0 -178
@@ -83,16 +83,20 @@ verdict artifact so quality failures are not lost behind a requirements-only PAS
83
83
  Before declaring a task `done`, run this lightweight checklist. It catches the most common oversights that survive the formal pipeline gates:
84
84
 
85
85
  - [ ] Check receipt `.spur/run/<wbs>-check-receipt.json` reports `reuse: true` for the current
86
- digest via `spur task gate <wbs> status`; run `bun run spur-check` only when it reports stale or
86
+ digest via `spur task gate <wbs> status`; run `spur self exec check` only when it reports stale or
87
87
  missing (0940).
88
88
  - [ ] No `TODO` or `FIXME` without a linked task WBS.
89
89
  - [ ] `git status` shows only intentional changes (no debug artifacts, no temp files).
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
 
@@ -40,16 +40,29 @@ interface VerifyVerdict {
40
40
  }
41
41
  ```
42
42
 
43
- ## No asserted confidence (F511, task 1207)
44
-
45
- Verdict artifacts carry no `confidence` field and verify answers no `Confidence:` line. The
46
- 1068/1133 machinery that required, linted and coherence-checked a model-asserted
47
- `HIGH | MEDIUM | LOW` was retired: a verifier that can write a PASS can write `HIGH`, so the grade
48
- verifies nothing. What the level compressed belongs in the evidence cells — cite fresh executable
49
- evidence and name residual gaps explicitly. The done gate no longer denies a confidence-less PASS:
50
- it checks the proof digests, which are the part a hand-edited artifact cannot fake. The DERIVED
51
- confidence family is a different thing and stays: feature-verification receipts (ADR-131, 1196),
52
- the decision subsystem threshold, history-anatomy reading.
43
+ ## Answer confidence is derived and cross-checked (ADR-141, superseding F511 for answers)
44
+
45
+ A verify answer carries exactly one top-level `Confidence: HIGH|MEDIUM|LOW` line — conventionally
46
+ right after `Verdict:`, and legal anywhere at top level. The label is **not** a self-assessment: the
47
+ lint recomputes it from the answer's own rows and rejects a disagreement.
48
+
49
+ | Derived | When the answer's rows say so |
50
+ | --- | --- |
51
+ | `LOW` | the verdict is not PASS, or any requirement/AC row is PARTIAL/UNMET |
52
+ | `HIGH` | PASS, and every AC row is MET on executable evidence (`test`/`command`; compounds allowed) |
53
+ | `MEDIUM` | PASS with every AC MET, but at least one row rests on `static-ref`, `manual-review`, `llm-judge` or `N/A` |
54
+
55
+ Rejections (`spur task verdict --from-answer`, exit 1, no artifact): `confidence-missing`,
56
+ `confidence-duplicate`, `confidence-mismatch` — the last names both the stated and the derived level
57
+ plus the clause the rows turn on. Derivation lives once, in
58
+ `packages/app/src/services/answer-confidence.ts`; the review lane uses the same module for its own
59
+ dispositions.
60
+
61
+ Still retired and not revived by this: **verdict artifacts** carry no `confidence` field (the answer
62
+ stays the record of truth, and a test pins the field's absence), feature-verification receipts keep
63
+ no level (ADR-131, 1196), no operator `ackLowConfidence`-style var exists, and history-anatomy
64
+ findings carry no per-finding grade. A verifier that can write a PASS can still write a wrong
65
+ `HIGH` — which is exactly why the gate derives the level instead of trusting it.
53
66
 
54
67
  ## Compatibility alias: `scenario` row key
55
68
 
@@ -77,7 +77,7 @@ project's actual stack and scope. Invoked by `sp:spur-init` after scaffolding.
77
77
  routing Need keys — see `apps/cli/tests/fixtures/agents-md-portable-contract.ts`).
78
78
 
79
79
  **Done when:** no residual `{project-name}` / `{project-description}` in AGENTS.md; stack/build
80
- stubs filled or deliberately documented; `bun run lint` passes where applicable.
80
+ stubs filled or deliberately documented; `spur self exec lint` passes where applicable.
81
81
 
82
82
  ## drift-audit (§7)
83
83
 
@@ -115,7 +115,7 @@ token, deterministic).
115
115
  | Order | When evaluated | Probe | Signal | Redirect dispatch | Else |
116
116
  | --- | --- | --- | --- | --- | --- |
117
117
  | C1 | A1, A3, A5 (pre-implement / refine path) | `spur task check <wbs> --json` | Any **L3** finding on sections ∈ {Background, Requirements, Acceptance Criteria, Design, Plan} | Force `/sp:dev-refine <wbs> --auto` (**without** `--next` if already mid-refine; with `--next` only when status was backlog/todo and operator wants chain — default: keep `--next` for A1/A3) | continue |
118
- | C2 | A3, A5 after C1 clean | Cheap workspace health: `bun run lint` (or project lint) exit ≠ 0 **and** scope inferable from task Solution/Plan paths or default repo | lint/type failures | `/sp:dev-fixall` (optional `--scope` if single package known) | continue |
118
+ | C2 | A3, A5 after C1 clean | Cheap workspace health: `spur self exec lint` exit ≠ 0 **and** scope inferable from task Solution/Plan paths or default repo | lint/type failures | `/sp:dev-fixall` (optional `--scope` if single package known) | continue |
119
119
  | C3 | A5/A6 when Testing empty/N/A **and** verify would fail for missing tests — only if prior implement claims code exists | Coverage/test signal: `bun test` fail attributed to task paths OR explicit "insufficient tests" in prior verify verdict artifact `.spur/run/<wbs>-verdict.json` | test fail / coverage gap | `/sp:dev-unit <wbs> --auto` | continue |
120
120
  | C4 | A3/A5/A6 when operator or task tags mention rules, OR `spur rule run` last report dirty in `.spur/` if present | `spur rule run` (default project preset) non-zero with findings | rule findings | **HITL STOP** — print rule summary; suggest `/sp:rule-scan` or `rule-add`/`rule-refine` (do not auto-author rules) | continue |
121
121
  | C5 | A6 only | Existing `.spur/run/<wbs>-verdict.json` with FAIL and findings pointing at coverage | verdict artifact | `/sp:dev-unit <wbs>` then re-verify on next invocation (`--once` friendly) | `/sp:dev-verify …` |
@@ -102,13 +102,13 @@ non-sandboxed shell, or a workspace that owns the storage path). The upstream fi
102
102
  pi-coding-agent's storage-path resolution; it is out of scope here and recorded as motivating
103
103
  evidence only.
104
104
 
105
- ## Composition with the inline pipeline driver (task 0508)
105
+ ## Composition with the host executor (task 0508)
106
106
 
107
- The interactive inline driver (`cross-cutting.md` § Inline-default execution surface) applies this
107
+ The interactive host executor (`cross-cutting.md` § Inline-default execution surface) applies this
108
108
  reference's default — native subagent first — to sequential `task-pipeline.yaml` `agent.run`
109
109
  stages. Eligibility there is the same observable test (pure-slash action, non-interactive state,
110
- native subagent with shared-worktree capability); the inline driver remains the authority for
111
- provenance, artifact validation, and no-replay guarantees. This reference stays the authority for
110
+ native subagent with shared-worktree capability); the engine remains the authority for provenance,
111
+ artifact validation, and no-replay guarantees. This reference stays the authority for
112
112
  the native-subagent versus `spur agent run` choice everywhere else.
113
113
 
114
114
  ## Fork dispatch on hosts that support it (2026-09-15 subagent-dispatch evaluation)
@@ -131,9 +131,9 @@ Three constraints keep fork honest:
131
131
  adversarial panels — must NOT fork; a worker that inherits the author's reasoning grades its own
132
132
  homework. Fork is for continuity, cold dispatch is for independence.
133
133
 
134
- The inline driver's resume-over-re-dispatch rule
135
- ([inline-pipeline-driver.md](../../spur-dev/references/inline-pipeline-driver.md)) is the same
136
- instinct one level down: reuse a warm worker for continuation, dispatch fresh for judgment.
134
+ The engine's resume-over-re-dispatch rule (a paused run resumes with
135
+ `spur workflow continue` instead of re-dispatching its stage) is the same instinct one level down:
136
+ reuse a warm worker for continuation, dispatch fresh for judgment.
137
137
 
138
138
  ## Role propagation across fan-out (task 0551, feature I4)
139
139
 
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: pr-reviewing
3
- description: "GitHub Codex PR-review workflow — prepare/reuse a PR, request `@codex review`, collect findings, and optionally validate/fix/re-review them. Backs /sp:dev-pr-review. Triggers: PR review, codex review, @codex review, review my PR, codex findings, dev-pr-review."
3
+ description: "Local-first PR review — status, a local /sp:dev-review of the branch diff, and validated fixes; `--codex` opts into the GitHub Codex review spine. Backs /sp:dev-pr-review. Triggers: PR review, codex review, @codex review, review my PR, dev-pr-review."
4
4
  license: Apache-2.0
5
- version: 1.0.0
5
+ version: 2.0.0
6
6
  metadata:
7
7
  author: spur
8
8
  platforms: "claude-code,codex,openclaw,opencode,antigravity,pi"
@@ -11,12 +11,12 @@ metadata:
11
11
  - workflow
12
12
  - review
13
13
  pipeline_steps:
14
- - preflight
15
- - hygiene
16
- - request
17
- - wait
18
- - collect
14
+ - status
15
+ - check
16
+ - review
17
+ - open
19
18
  - triage
19
+ - fix
20
20
  see_also:
21
21
  - sp:code-verification
22
22
  - sp:functional-review
@@ -24,11 +24,12 @@ see_also:
24
24
  - sp:spur-dev
25
25
  ---
26
26
 
27
- # sp:pr-reviewing — GitHub Codex PR Review
27
+ # sp:pr-reviewing — Local-First PR Review
28
28
 
29
- Backend for `/sp:dev-pr-review`. The invoking coding agent is the local orchestrator and
30
- implementer; **GitHub Codex Code Review** is the independent reviewer. The point of the route is
31
- that review effort happens on the PR, through Codex — not in the local session.
29
+ Backend for `/sp:dev-pr-review`. Local-first by default: `status` is a read-only snapshot and
30
+ `review` reviews the branch diff locally with `/sp:dev-review`. `review --codex` opts into the
31
+ GitHub Codex review on the pull request; `fix` triages and fixes findings from either reviewer. The
32
+ invoking coding agent is the local orchestrator and implementer.
32
33
 
33
34
  ## Architecture
34
35
 
@@ -36,193 +37,155 @@ that review effort happens on the PR, through Codex — not in the local session
36
37
  /sp:dev-pr-review (thin command)
37
38
  │ Skill(skill="sp:pr-reviewing", args=...)
38
39
  ▼
39
- sp:pr-reviewing (this skill — mode routing, triage, fix, rules)
40
- │ deterministic spine, state order + guards:
41
- ▼
42
- pr-review.yaml ← workflow SSOT (seeded by spur init; project-tunable)
43
- │ every deterministic action shells out to:
40
+ sp:pr-reviewing (this skill — mode routing, local-review dispatch, triage, fix)
41
+ │ local route: pr-check --scan-only → git diff --name-only → /sp:dev-review
42
+ │ Codex route: pr-review.yaml (check → precheck → open → review)
44
43
  ▼
45
- `spur builder pr` ← Bun entrypoint for the tested git/gh core
44
+ `spur builder pr-<verb>` + `spur builder show-branches` ← tested git/gh core
46
45
  ```
47
46
 
48
- - **State order and guards** are defined once, in the workflow YAML. Do not re-derive them in
49
- prose; when the YAML and this file disagree, the YAML wins and this file gets fixed.
50
- - **Deterministic work** (every git/gh call) goes through the script subcommands — never
51
- hand-rolled `gh` invocations that drift from the tested core.
52
- - **Model-bearing work** (finding triage, `fix` edits, `rules` authoring) is this skill's job and
53
- never enters the workflow machine.
54
- - The workflow YAML exposes only its declared spine modes (`full`, `submit`, and `rerun`). The
55
- direct-mode routes below own `collect`, `fix`, `status`, and `rules`; keep those modes outside
56
- the workflow `mode` variable.
57
-
58
- ## Non-negotiable Codex routing
59
-
60
- The external review MUST go through the GitHub pull request and an `@codex review` request.
61
- Never substitute a local Codex review mechanism — no Codex CLI `/review`, no `codex review`, no
62
- vendor-specific local review commands. If GitHub Codex Code Review is unavailable, stop and report
63
- the setup/access problem; never silently fall back to a local review.
64
-
65
- Never claim a request consumed a specific billing/quota bucket unless the platform exposes that
66
- fact. The guarantee of this workflow is the route: GitHub Codex Code Review on the PR.
47
+ - **State order and guards** for the Codex route are defined once, in `pr-review.yaml`. Do not
48
+ re-derive them in prose; when the YAML and this file disagree, the YAML wins and this file gets
49
+ fixed.
50
+ - **Deterministic work** (every git/gh call) goes through the four flat `spur builder pr-<verb>`
51
+ commands and `spur builder show-branches` — never hand-rolled `gh` invocations that drift from
52
+ the tested core.
53
+ - **Model-bearing work** (the local review dispatch, finding triage, `fix` edits) is this skill's
54
+ job and never enters the workflow machine.
67
55
 
68
56
  ## Modes and routing
69
57
 
70
- Parse the first positional argument as the mode; default `full`.
58
+ Parse the first positional argument as the mode; default `status`.
71
59
 
72
60
  | Mode | Route | Behavior |
73
61
  | --- | --- | --- |
74
- | `full` | Workflow YAML | Preflight → hygiene → precheck → push → ensure-pr → request (reviewed/in-flight HEAD dedupe) → wait → collect → report. No source edits. |
75
- | `submit` | Workflow YAML | Run the spine through `request`; return pending for a new request (`--no-wait` has the same effect). If the exact current HEAD was already reviewed, collect that result instead of requesting a duplicate. |
76
- | `rerun` | Workflow YAML | Run the spine and request a fresh review of the current pushed HEAD with `--force`. No source edits. |
77
- | `collect` | Direct script | Do not start the workflow or request a review. Collect the current PR's result and composite status; a missing current-HEAD result is **pending**, never clean. |
78
- | `fix` | Direct script + model work | Collect first, independently validate current-HEAD findings, fix legitimate issues, verify, make one focused commit, push, then force-request/review/collect the new HEAD. Do not pass `mode=fix` to the workflow. |
79
- | `status` | Direct script | Read-only composite: repository, branch, local HEAD, PR/base, local changes, CI, and Codex state for the current PR HEAD. Do not start the workflow. |
80
- | `rules` | Model work only | Create or improve the repo-root `AGENTS.md` section `## Code Review Rules`; do not invoke the workflow, request a review, commit, or push. |
62
+ | `status` | direct CLI | `spur builder show-branches --base <b> --pr --format markdown`, with the report filtered to the current branch and its base, plus `spur builder pr-status --json` (PR number, CI, local changes, latest current-head review in `.review`). Read-only. |
63
+ | `review` | local stack | `spur builder pr-check --base <b> --scan-only --json`; `BLOCK` stops, `WARN` is reported. Then `git diff --name-only <b>...HEAD` → `/sp:dev-review --scope <comma-joined paths> --focus <focus>`. An empty diff ends with "nothing to review". Posts nothing to GitHub. |
64
+ | `review --codex` | `pr-review.yaml` | Run the spine with `mode=full`; `--force` → `mode=rerun`; `--no-wait` → `mode=submit`; `focus`/`baseBranch` passed as vars. States: check → precheck → open → review. `pending` is reported as pending, never failure. |
65
+ | `fix` | direct verb + model work | Findings from the latest local review verdict, or from `spur builder pr-status --json` `.review` when the last review was Codex. Validate each finding against the code before editing; rejected findings are listed with a reason. Fix the legitimate ones, run the project gate, make one focused commit and push without force (`spur builder pr-open` handles a first push). |
66
+
67
+ Retired modes print one notice line and run their replacement: `full` → `review --codex`;
68
+ `submit` → `review --codex --no-wait`; `rerun` → `review --codex --force`; `collect` → `status`.
69
+ `rules` prints a notice that `AGENTS.md` review-rule authoring belongs to `cc:cc-magents` (in the
70
+ `cc` plugin, not `sp`) and exits.
81
71
 
82
72
  ## Arguments
83
73
 
84
- - `--base <branch>` — base for a newly created PR. Default: existing PR's base, else repo default.
85
- - `--no-wait` — after a successful request, return pending instead of polling.
74
+ - `--codex` — run `review` through the GitHub Codex spine instead of the local stack.
75
+ - `--force` — with `--codex`, request a fresh review of the current HEAD even when it was already
76
+ reviewed.
77
+ - `--no-wait` — with `--codex`, post the request and return pending instead of polling.
78
+ - `--base <branch>` — base for the branch report, the `pr-check` diff and a newly created PR.
79
+ Default: the existing PR's base, else the repo default.
86
80
  - `--agent <inline|auto|name>` — names **who performs model-bearing work**, per the
87
81
  [inline-default execution-surface contract](../spur-dev/references/cross-cutting.md#inline-default-execution-surface).
88
- Omit: the current agent is the default owner (eligible model stages may use one native subagent
89
- under the shared contract). `inline` (also what omission resolves to, task 0687) keeps model work in the host session — native-subagent-first with host fallback where eligible `auto` resolves the command's declared role; a named executor pins that executor.
90
- An alternate executor gets one `spur agent run --agent <value>` dispatch with the selector removed
91
- from child args; that child owns model work. Current-agent selection stays inline.
92
- Headless surfaces substitute tier resolution for `inline` with a warning (task 0687), never refusing.
93
- - `--agent` describes the model owner only; it is independent of the deterministic git/GitHub spine
94
- and the workflow/direct route. Run the selected route in that resolved skill context. A separate
95
- workflow subprocess belongs to the caller's execution surface or an objective trigger (for example,
96
- a required durable run record), not to `--agent auto` or a name by itself.
97
- - Remaining free text — extra review focus, appended to the Codex request without weakening
98
- repository-defined rules (e.g. `security and authorization boundaries`, `migration safety`).
99
-
100
- ## Safety rules
82
+ `--agent` describes the model owner only; it is independent of the deterministic git/GitHub spine.
83
+ - Remaining free text — extra review focus, passed to the local review and appended to the Codex
84
+ request without weakening repository-defined rules (e.g. `security and authorization boundaries`).
101
85
 
102
- **Git history — never:** force-push (`--force`/`--force-with-lease`), destructive `git reset`,
103
- `git clean`, rewriting published history, merging the PR, deleting branches, discarding unrelated
104
- user changes.
86
+ ## Status mode
105
87
 
106
- **Local changes.** A GitHub PR only reviews pushed commits. If relevant changes are uncommitted:
107
- inspect the tree, separate relevant from unrelated, never `git add .` blindly, and ask the user
108
- before creating any commit outside `fix` mode. If safe separation is ambiguous, stop and explain.
109
- In `fix` mode the user pre-authorized one focused fix commit for verified findings — still stop if
110
- unrelated uncommitted changes make safe editing or committing ambiguous.
88
+ Read-only; no source edits, PR creation, pushes, or review requests.
111
89
 
112
- **Current-HEAD invariant.** Treat the PR's pushed `headRefOid` as the review identity. After every
113
- preflight, push, commit, and request, record the returned HEAD and require `wait`, `collect`, and
114
- the report to match that exact HEAD. A result for an older commit is stale; a result absent for the
115
- current HEAD is pending, not clean. `wait` re-asserts this at two points, not one: at the start of
116
- every poll, and again immediately before it emits FOUND/CLEAN/TIMEOUT — a head that moved while the
117
- review was being fetched, or between polls, fails the wait (exit 2) instead of accepting an old-head
118
- result. The pinned identity is the PR number AND the expected head, so a different PR appearing on
119
- the branch is also a failure, never a silent retarget. Reject uncorrelated issue/conversation
120
- comments rather than using them to manufacture a current-HEAD result. In `fix` mode, discard the old
121
- result after the fix commit and judge only the forced re-review for the new pushed HEAD.
90
+ 1. Resolve the base: `--base`, else the existing PR's base, else the repo default.
91
+ 2. `spur builder show-branches --base "$base" --pr --format markdown` — keep only the rows for the
92
+ current branch and its base (the full report is long) plus the current branch's graph line.
93
+ 3. `spur builder pr-status --json` for the composite repository/branch/PR/base/local/CI status and
94
+ `.review` (the current-HEAD Codex record). With no PR, report `PR: none` rather than failing.
122
95
 
123
- **Reviewer authority.** Codex is an independent reviewer, not an authority. For every finding that
124
- may lead to a code change: inspect the referenced code, verify reachability and intended behavior,
125
- inspect callers/callees where needed, check existing tests, classify, reject false positives, fix
126
- root causes rather than wording, prefer the smallest coherent patch, avoid drive-by refactors.
96
+ Report:
127
97
 
128
- ## Workflow-backed spine (`full`, `submit`, `rerun`)
98
+ ```text
99
+ PR: <number + URL | none>
100
+ Branch: <branch>
101
+ HEAD: <short SHA>
102
+ Base: <base>
103
+ Ahead/Behind: <n>/<n> vs <base>
104
+ CI: <status | unavailable>
105
+ Codex: clean | findings | pending | not requested | unavailable
106
+ ```
129
107
 
130
- Run the workflow YAML's declared states in order. Every deterministic state invokes the
131
- `spur builder pr` operation below, supports `--json`, and must be parsed. Stop at the first red gate and
132
- report its artifact. The canonical installed invocation is:
108
+ ## Review mode (local)
109
+
110
+ 1. **Submission scan.** `spur builder pr-check --base "$base" --scan-only --json`. Three outcomes:
111
+ - `PASS`/`WARN` — continue. A `WARN` (debug residue) is reported and rides into the review.
112
+ - `BLOCK` (secrets, `.env`, conflict markers, private keys) — stop; never review a tainted diff,
113
+ and name the blocking files.
114
+ - hard failure (exit 2, e.g. `gh` missing or unauthenticated, no GitHub remote, not a
115
+ repository) — stop and report the tool's message plus the one-line remedy (`gh auth login`
116
+ and a GitHub `origin` remote). A hard failure is **not** a `BLOCK`; hygiene did not run.
117
+ `--scan-only` skips the preflight sub-op so a dirty tree is expected, but hygiene itself still
118
+ resolves the repository through `gh` — the scan needs `gh` authenticated with a GitHub remote.
119
+ 2. **Diff scope.** `git diff --name-only "$base"...HEAD`. An empty list ends the mode with
120
+ "nothing to review". `/sp:dev-review` takes `--scope` paths, not a diff range, so pass the
121
+ comma-joined file list.
122
+ 3. **Local review.** `/sp:dev-review --scope <comma-joined paths> --focus "<focus>"`. It owns the
123
+ review dimensions — do not re-implement them here. Report findings by severity with `file:line`.
124
+ Post nothing to GitHub.
125
+
126
+ ## Review mode (--codex)
127
+
128
+ Run `pr-review.yaml` as the single source of truth for the Codex spine — check → precheck → open →
129
+ review. Never call `spur builder pr-review` in a way that bypasses the workflow's state order and
130
+ guards.
133
131
 
134
132
  ```sh
135
- spur builder pr <subcommand> [flags]
133
+ spur workflow run pr-review.yaml --vars '{"mode":"full","baseBranch":"<base>","focus":"<focus>"}'
136
134
  ```
137
135
 
138
- The installed Spur CLI owns these operations; no staged script, Node twin or plugin resolver is used.
139
-
140
- 1. **Preflight** — `spur builder pr preflight --base "$base" --json`. Hard-fails on a
141
- detached HEAD, missing `gh` auth, no GitHub remote, a dirty tree, or the current branch
142
- being the base branch (a PR reviews a feature branch against the base; nothing on the
143
- base branch is reviewable, and the guard runs before any push can publish it). On a
144
- dirty tree, triage with the user (commit/stash/exclude) before continuing — the
145
- workflow refuses to guess.
146
- 2. **Hygiene** — `spur builder pr hygiene --base "$base" --json`. `BLOCK` (secrets, `.env`, conflict markers,
147
- private keys) stops the run — never submit a tainted diff. `WARN` (debug residue) rides along
148
- into the report. This is a submission sanity check, not a second local review.
149
- 3. **Precheck** — if the workflow YAML's `preReviewCmd` var is set, run it; a red check stops the
150
- run (do not spend a review request on code that fails its own gate). When unset, report that
151
- pre-review verification was not configured rather than inventing project commands.
152
- 4. **Push** — `spur builder pr push --json`. Normal push only; sets upstream when missing.
153
- 5. **Ensure PR** — `spur builder pr ensure-pr --base "$base" --json`. Reuses the branch's PR; creates with
154
- `gh pr create --fill` only when absent. Never a duplicate PR.
155
- 6. **Request** — `spur builder pr request --focus "<focus>" --json` (`--force` in `rerun` mode). Dedupes when
156
- Codex already reviewed the exact pushed HEAD (`ALREADY_REVIEWED` → skip to collect) or a marked
157
- request by the current GitHub user is still in flight (`ALREADY_REQUESTED` → pending). The
158
- request body is concise when the repo has `## Code Review Rules`, else carries the default
159
- actionable-issues focus. Records PR, URL, HEAD, and request time.
160
- 7. **Wait** (full/rerun unless `--no-wait`; submit stops before it) —
161
- `spur builder pr wait --since "$requestedAt" --head "$requestHead" --json`, using the request result so
162
- a fast response is not missed, `rerun` cannot reuse the prior review, and a moved HEAD fails loud.
163
- Polls every ~30s for up to
164
- ~10 minutes across the current HEAD's PR review and inline comments. Uncorrelated conversation
165
- comments are ignored. A current-HEAD clean review is a completed `CLEAN` outcome; findings are
166
- `FOUND`; timeout or no current-HEAD result is **pending, not failed** — collect later.
167
- 8. **Collect** — `spur builder pr collect --since "$requestedAt" --head "$requestHead" --json`. Normalize
168
- only the requested HEAD and request window; then invoke `status` with the same bounds for
169
- PR/base/CI/local state. Never turn an absent, stale, or moved-HEAD result into `clean`.
170
- `--head` is mandatory on wait/collect/status (0771): an empty or missing pin fails loud
171
- instead of silently reviewing whatever HEAD is current.
136
+ - `mode=full` by default; `--force` → `mode=rerun`; `--no-wait` → `mode=submit`.
137
+ - The workflow's `pending` terminal state is **pending, not failed**: report the requested or
138
+ in-flight state and collect later with `status`.
139
+ - When `--codex` is passed, the external review goes through the GitHub PR and an `@codex review`
140
+ request only — never a local Codex CLI review. If GitHub Codex Code Review is unavailable, stop
141
+ and report the setup/access problem; never silently fall back to a local review.
172
142
 
173
143
  ## Fix mode
174
144
 
175
145
  Only in `fix` mode:
176
146
 
177
- 1. **Collect before editing.** Invoke direct `collect --json --head "$(git rev-parse HEAD)"` plus
178
- `status --json --head "$(git rev-parse HEAD)"` and require a
179
- completed result for the current pushed HEAD. If the result is pending, stale, or unavailable,
180
- report it and stop without source edits. If it is explicitly clean, report no fixes and stop.
181
- 2. **Validate each finding.** Open the referenced code; trace callers/callees; verify the problem
182
- is reachable; check intended behavior and existing tests. Classify: `Confirmed`,
183
- `Likely valid`, `Needs investigation`, `Likely false positive`. Never edit for a likely false
184
- positive; investigate further before editing a `Needs investigation`.
185
- 3. **Fix legitimate issues** with the smallest coherent change. Preserve existing interfaces
186
- unless the defect requires otherwise; no unrelated refactoring; add or update tests when they
187
- materially demonstrate the fix; follow repository conventions. Inspect `git diff` — the patch
188
- must contain only intended review fixes.
189
- 4. **Verify** with repository-defined targeted tests/type checks/linters. Never claim a check
190
- passed unless it actually ran successfully.
191
- 5. **Commit** one focused review-fix commit. The message describes the actual defect
192
- (`fix: prevent duplicate transaction retry`), never `fix codex comments`. No unrelated files.
193
- 6. **Push** normally to the existing PR branch (never force), record the new HEAD, and discard the
194
- previous review identity.
195
- 7. **Re-review:** invoke the staged `request --force`, then wait/collect as usual. The new review
196
- must correspond to the new pushed HEAD — never present stale findings from the previous HEAD as
197
- the new result. Include composite CI/status fields in the final report.
198
-
199
- ## Rules mode
200
-
201
- Only in `rules` mode. Inspect the architecture, existing instructions, and current root
202
- `AGENTS.md`, then create or improve a section named exactly `## Code Review Rules`, preserving
203
- unrelated content. Prefer repository-specific invariants over generic advice, using only categories
204
- that matter to the project: data safety (atomic multi-step writes, idempotency, transaction
205
- boundaries), security (server-side authorization, untrusted client identifiers, secrets in logs),
206
- API compatibility (public contracts, CLI, serialized formats, event payloads, schema), concurrency
207
- (races, stale writes, retry semantics), migration safety (backward-compatible rollout,
208
- mixed-version operation), tests (which high-risk changes require regression coverage), and project
209
- invariants a reviewer unfamiliar with the codebase could miss. Avoid generic advice (`write clean
210
- code`) and anything lint/format already enforces mechanically. Keep it concise and actionable.
211
- Show the diff, summarize the meaningful rules added, and do not commit or push.
147
+ 1. **Collect findings before editing.** Use the latest local review verdict when the last `review`
148
+ was local. When the last review was Codex, invoke `spur builder pr-status --json` and read
149
+ `.review` — the current-HEAD Codex record. Treat the PR's pushed `headRefOid` as the review
150
+ identity: a result for an older commit is stale, and a result absent for the current HEAD is
151
+ pending, not clean. If the record is pending, stale, or unavailable, report it and stop without
152
+ source edits.
153
+ 2. **Validate each finding.** Open the referenced code; trace callers/callees; verify the problem is
154
+ reachable; check intended behavior and existing tests. Classify: `Confirmed`, `Likely valid`,
155
+ `Needs investigation`, `Likely false positive`. List every rejected finding with its reason;
156
+ never edit for a likely false positive.
157
+ 3. **Fix legitimate issues** with the smallest coherent change. No unrelated refactoring; add or
158
+ update tests when they materially demonstrate the fix; follow repository conventions. Inspect
159
+ `git diff` — the patch must contain only intended review fixes.
160
+ 4. **Verify** with repository-defined targeted checks. Never claim a check passed unless it ran
161
+ successfully.
162
+ 5. **Commit** one focused review-fix commit describing the actual defect (`fix: prevent duplicate
163
+ transaction retry`), never `fix codex comments`. No unrelated files.
164
+ 6. **Push** normally (never force) and report the new HEAD. `spur builder pr-open` handles a first
165
+ push.
166
+
167
+ ## Safety rules
168
+
169
+ **Git history — never:** force-push (`--force`/`--force-with-lease`), destructive `git reset`, `git
170
+ clean`, rewriting published history, closing or integrating the PR, deleting branches, or discarding
171
+ unrelated user changes.
172
+
173
+ **Local changes.** A GitHub PR only reviews pushed commits. `review` without `--codex` makes no
174
+ GitHub writes. `fix` pre-authorizes one focused fix commit for verified findings — still stop if
175
+ unrelated uncommitted changes make safe editing or committing ambiguous.
176
+
177
+ **Reviewer authority.** A remote reviewer is an independent reviewer, not an authority. For every
178
+ finding that may lead to a code change: inspect the referenced code, verify reachability and
179
+ intended behavior, inspect callers/callees, check existing tests, classify, reject false positives,
180
+ fix root causes rather than wording, prefer the smallest coherent patch, avoid drive-by refactors.
212
181
 
213
182
  ## Reporting
214
183
 
215
184
  Findings report:
216
185
 
217
186
  ```text
218
- PR
219
- #<number> <url>
220
-
221
- HEAD
222
- <short SHA>
223
-
224
- Codex review
225
- Clean | Findings | Pending | Unavailable
187
+ Reviewer
188
+ local (/sp:dev-review) | GitHub Codex
226
189
 
227
190
  Findings
228
191
 
@@ -232,62 +195,46 @@ Findings
232
195
  Why it matters:
233
196
  Evidence:
234
197
  Recommended next action:
235
-
236
- CI
237
- <status summary>
238
198
  ```
239
199
 
240
- Preserve filenames, line references, severity, and the important technical reasoning. Do not
241
- inflate suggestions into confirmed bugs. If the review completed without actionable findings, say
242
- so clearly.
243
-
244
- `wait` and `collect` must distinguish an explicit current-HEAD clean result from pending, stale, or
245
- unavailable data. `collect` and `fix` reports also include the composite PR/base/branch/HEAD/local/CI
246
- status; an unavailable CI signal remains `unavailable`, never an inferred pass.
247
-
248
- Always end with the compact summary:
249
-
250
- ```text
251
- PR: <number + URL | none>
252
- Branch: <branch>
253
- HEAD: <short SHA>
254
- Base: <base>
255
- CI: <status>
256
- Codex: clean | findings | pending | not requested | unavailable
257
- Findings: <count>
258
- ```
259
-
260
- `fix` mode appends: `Fixed: <n>`, `Rejected: <n>`, `New HEAD: <sha>`,
261
- `Re-review: clean | findings | pending | unavailable`. If findings remain, state the recommended
262
- next action.
263
-
264
- `status` mode prints the same summary block and nothing else — no file edits, PR creation, pushes,
265
- or review requests.
200
+ Preserve filenames, line references, severity, and the important technical reasoning. Do not inflate
201
+ suggestions into confirmed bugs. If a review completed without actionable findings, say so clearly.
202
+ `fix` appends: `Fixed: <n>`, `Rejected: <n>`, `New HEAD: <sha>`. `status` prints its summary block
203
+ and nothing else.
266
204
 
267
205
  ## Failure handling
268
206
 
269
- - **`gh` missing or unauthenticated** — stop and report; do not switch to browser automation.
270
- - **GitHub Codex unavailable** (not enabled/authorized for the repo) — preserve the error, explain
271
- the required repository/account setup, do not fall back to local Codex.
272
- - **PR creation failure** — report the actual git/GitHub state; never rewrite history as a
273
- workaround.
274
- - **Review timeout** — return `pending`, not `failed`, unless GitHub explicitly reports a failure.
275
- - **CI failure** — Codex review and CI are independent signals; always surface failing checks even
276
- when Codex reports clean.
207
+ - **No PR for the branch** — `pr-status --json` returns `pr: null` and `review: null`; `status`
208
+ reports `PR: none` and the branch report still prints.
209
+ - **`gh` missing, unauthenticated, or no GitHub remote** — `show-branches --pr` degrades with a
210
+ warning; `pr-status` and `pr-check` exit non-zero with an error object (their hygiene step shares
211
+ the gh-backed repository resolution). Report the branch report plus `PR: unavailable`, and stop
212
+ the Codex path. The review's own diff scope and `/sp:dev-review` need no `gh`.
213
+ - **`pr-check` BLOCK** — stop before any review; report the blocking files and never review a
214
+ tainted diff.
215
+ - **Empty diff** — "nothing to review"; stop.
216
+ - **Codex pending or wait timeout** — report `pending`, never failure; collect later.
217
+ - **A finding that refers to a stale head** — discard it, never fix against it.
218
+ - **A retired mode passed** — one notice line, then the replacement.
277
219
 
278
220
  ## Platform notes
279
221
 
280
- - The skill, command, workflow YAML, and script are platform-neutral; per-platform emission is
281
- owned by superskill. On platforms without a Skill tool, read this file and follow the protocol
282
- manually — the script subcommands are plain CLI invocations.
283
- - Prerequisites on any platform: `git`, GitHub CLI (`gh`) authenticated, and GitHub Codex Code
284
- Review enabled for the repository.
222
+ - The skill, command and workflow YAML are platform-neutral; per-platform emission is owned by
223
+ superskill. On platforms without a Skill tool, read this file and follow the protocol manually.
224
+ - Prerequisites: `git` for every path. `gh` authenticated with a GitHub remote wherever PR state is
225
+ touched: `status` (its `pr-status` half — the `show-branches` topology runs on `git` alone, and
226
+ its `--pr` enrichment only degrades with a warning), `review` (step 1's `pr-check --scan-only`),
227
+ `review --codex` (the workflow's check/open/review states), and `fix` when it reads a Codex
228
+ verdict or pushes through `pr-open`. The `git diff --name-only` scope, `/sp:dev-review`, and
229
+ `fix`'s local-verdict edit/commit path need only `git`. The `--codex` path additionally needs
230
+ GitHub Codex Code Review enabled for the repository.
285
231
 
286
232
  ## Additional Resources
287
233
 
288
- - **Workflow SSOT:** `pr-review.yaml` (seeded by `spur init`; tune per project —
289
- wait budget, `preReviewCmd`, dedupe policy)
290
- - **Script source:** `spur builder pr` (absorbed; was `plugins/sp/scripts/pr-reviewing.ts`) — subcommand CLI
234
+ - **Workflow SSOT (Codex path):** `pr-review.yaml` (seeded by `spur init`; tune per project — wait
235
+ budget, `preReviewCmd`, dedupe policy)
236
+ - **Command source:** the four flat verbs `pr-status` / `pr-check` / `pr-open` / `pr-review` plus the
237
+ read-only `show-branches` report — see `sp:spur-cli` `references/builder.md`
238
+ - **Local review:** `/sp:dev-review` — its dimensions live in `sp:code-verification` and
239
+ `sp:functional-review`, never re-implemented here
291
240
  - **Tests:** `packages/app/tests/services/pr-review/pr-review.test.ts` — stubbed git/gh suites
292
- - **Related skills:** `sp:code-verification` (local SECUA review), `sp:functional-review`
293
- (requirements traceability) — complements, never substitutes, the independent Codex review