@juicesharp/rpiv-pi 0.11.1 → 0.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juicesharp/rpiv-pi",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
4
4
  "description": "Skill-based development workflow for Pi Agent — discover, research, design, plan, implement, validate",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1,66 +1,111 @@
1
1
  ---
2
2
  name: code-review
3
- description: Three-pass parallel reviewer (quality, security, dependencies) with conditional advisor adjudication. Produces review documents in thoughts/shared/reviews/. Use when changes are ready for review.
4
- argument-hint: [scope]
3
+ description: "Three-wave parallel reviewer with file-oriented reasoning (quality, security, dependencies) and conditional advisor adjudication. File-centric framing: U30 diffs inline full-function context, Discovery Map uses semantic file summaries, and lens prompts read files as coherent units. Produces review documents in thoughts/shared/reviews/. Use when changes are ready for review."
4
+ argument-hint: "[scope]"
5
5
  ---
6
6
 
7
- ## Scope Source
8
-
9
- If the user has not specified what to review, ask them before proceeding. Scope is one of: `commit` (latest commit), `staged`, `working`, a commit hash or `A..B` range, or a PR branch name. Their input will appear as a follow-up paragraph after this skill body.
10
-
11
7
  # Code Review
12
8
 
13
- You are tasked with reviewing changes across three parallel lenses — **Quality**, **Security**, **Dependencies** — and synthesising their findings with optional stronger-model adjudication into an actionable `thoughts/shared/reviews/` artifact.
9
+ Scope: $ARGUMENTS
10
+
11
+ Review changes across **Quality**, **Security**, **Dependencies** lenses with optional advisor adjudication. Valid scopes: `commit` | `staged` | `working` | hash | `A..B` | PR branch. **If Scope above is empty, ask the user before proceeding.**
14
12
 
15
13
  **How it works**:
16
- - Resolve scope and assemble the diff (Step 1)
17
- - Phase-1 Discovery Map (Step 2 one agent + orchestrator-side git work)
18
- - Phase-2 three-lens review + precedents + conditional CVE lookup (Step 3 — parallel agents)
19
- - Cross-Finding Interaction Sweep (Step 4 — one synthesis agent over Phase-2 evidence, gated)
20
- - Reconcile findings via advisor (if present) or inline dimension-sweep (Step 5)
21
- - Grounded-questions developer checkpoint (Step 6)
22
- - Write the review artifact (Step 7)
23
- - Present and handle follow-ups (Steps 8–9)
14
+ - Step 1 resolve scope, read diff (with `-U30` context), derive flags, build semantic file map
15
+ - Step 2 — dispatch Wave-1: integration + precedents + (deps/CVE) + (peer-mirror); integration & peer-mirror gate Wave-2, precedents gates Step 5
16
+ - Step 3 dispatch Wave-2: Quality + Security lenses, file-oriented
17
+ - Step 4 — dispatch Wave-3: Predicate-Trace + Interaction Sweep + Gap-Finder, all gated
18
+ - Step 5 — reconcile via advisor or inline dimension-sweep (blocks on precedents)
19
+ - Step 6 — verify findings: re-read each cited file:line; drop/demote unverified
20
+ - Step 7 write artifact
21
+ - Steps 8–9 — present and handle follow-ups
22
+
23
+ **File-orientation contract**: agents reason about *files* as coherent units. Hunks are evidence *within* a file's analysis, never the unit of analysis. The `-U30` patch (Step 1) inlines function-level context so agents rarely need extra `Read` calls.
24
+
25
+ Every Wave-2 agent prompt contains EXACTLY: (a) `Known Context:` followed by the Discovery Map verbatim, and (b) the literal string `/tmp/code-review-patch.diff` as the patch path. Nothing else from Wave-1 outputs — NOT the raw integration-scanner dump, NOT precedent-locator output, NOT Dependencies/CVE output. See "Wave-2 context isolation" in Step 3 for the failure mode when this is violated. Wave-1 agents that do not consume the Discovery Map (precedents, dependencies, CVE) get `ChangedFiles` / manifest-diff only.
24
26
 
25
27
  ## Step 1: Resolve Scope and Assemble the Diff
26
28
 
27
- 1. **Parse the scope argument** (follow-up paragraph or the skill's argument):
28
- - `commit` → `git diff HEAD~1 HEAD`
29
- - `staged` `git diff --cached`
30
- - `working` → `git diff`
31
- - Commit hash `abc1234` → `git show abc1234`
32
- - Range `A..B` → `git diff A..B`
33
- - PR branch name → `git diff $(git merge-base main HEAD)..HEAD` (or the branch vs its base)
29
+ 1. **Interpret the Scope line** (from the header) and identify `OLDEST` + `NEWEST` commits (user-inclusive endpoints):
30
+ - `commit` → `OLDEST=NEWEST=HEAD`
31
+ - `staged` / `working` no commits; see working-tree branch below
32
+ - Single hash `h` → `OLDEST=NEWEST=h`
33
+ - Range `A..B` → verify A is ancestor of B (`git merge-base --is-ancestor A B`; swap if reversed); `OLDEST=A`, `NEWEST=B`
34
+ - Commit list (`h1,h2,h3` or whitespace-separated) find endpoints via `git rev-list --topo-order`; `OLDEST` = farthest-from-HEAD, `NEWEST` = nearest. Reject if not on a single linear ancestry (ask user to clarify).
35
+ - PR branch name → `OLDEST=$(git merge-base main HEAD)`, `NEWEST=HEAD` note: `OLDEST` is already the parent-of-first-PR-commit, so skip the `BASE` computation below and use `BASE=OLDEST` directly.
36
+
37
+ 2. **Compute the range once**: `BASE=$(git rev-parse "$OLDEST^")`, `TIP=$NEWEST`, `RANGE="$BASE..$TIP"`. This gives a range that INCLUDES `OLDEST`'s own changes (standard `A..B` excludes `A`). Every subsequent git command uses `$RANGE` — do NOT inline a `^` character in templates; orchestrators sometimes drop it.
34
38
 
35
- 2. **Read the full diff FIRST** (orchestrator-side, before any agent dispatch):
36
- - `git diff --name-only [scope]` → `ChangedFiles` list
37
- - `git diff --stat [scope]` → size summary
38
- - `git diff -U0 [scope]` → hunk ranges for Phase-2 prompts (inline, don't dump to user)
39
- - `git log -1 --format="%s%n%n%b" [scope-ref]` → commit-message context when applicable
39
+ 3. **Assemble the UNION of changes** (not the net endpoint-diff so reverted intermediate work stays visible). Save the patch to a tempfile once with generous context; do NOT re-run `git log --patch` to slice windows later:
40
+ - `git log "$RANGE" --name-only --pretty=format: | sort -u` → `ChangedFiles`
41
+ - `git log "$RANGE" --stat --reverse` → per-commit size summary
42
+ - `git log "$RANGE" --patch --reverse --no-merges -U30 > /tmp/code-review-patch.diff` → union patches with **30 lines of surrounding context per hunk** (function-level context inline)
43
+ - `git log "$RANGE" --reverse --format="%H %s%n%n%b%n---"` → commit-message context
44
+ - **Working-tree branch** (`staged` / `working`, no `$RANGE`): `git diff --cached --name-only` / `git diff --name-only`; `git diff --cached --stat` / `git diff --stat`; `git diff --cached -U30` / `git diff -U30`. Commit-message context is N/A.
45
+ - **Patch-size fallback**: `-U30` produces ~2–3× the size of `-U0`. If the resulting patch exceeds ~1MB, drop to `-U10` for this run; never use `-U0` — it defeats the skill's design.
40
46
 
41
47
  3. **Bail-out**: if `ChangedFiles` is empty, print `No changes in scope [scope]. Exiting.` and STOP. Do not write an artifact.
42
48
 
43
49
  4. **Derive flags** (orchestrator-side, used in later steps):
44
- - `ManifestChanged` = ChangedFiles intersects {`package.json`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`} OR a `peerDependencies` field was touched.
50
+ - `ManifestChanged` = ChangedFiles intersects any dependency manifest or lockfile (e.g. `package.json`/lockfile, `Cargo.toml`/`Cargo.lock`, `go.mod`/`go.sum`, `pyproject.toml`/`requirements*.txt`/`poetry.lock`, `Gemfile*`, `*.csproj`, `pom.xml`/`build.gradle*`, `composer.json`, …) OR a peer/optional/dev-dependency field was touched.
45
51
  - `LockstepSelfReview` = repository root contains `scripts/sync-versions.js` AND every `packages/*/package.json` shares the same `version:` AND the diff touches `packages/*/package.json`.
52
+ - `HasGatingPredicate` = diff adds or modifies a **status/enum-comparison predicate** (`Status == X`, `Status is X or Y`, `X.Contains(Status)`, pattern-match on a discriminator) OR introduces a new value into an enum referenced by existing gating predicates. NOT merely the presence of `if (!x) return`.
46
53
  - `ReviewType` = one of `commit | pr | staged | working`.
54
+ - `PeerPairs` = `(new_file, peer_file)` tuples. `new_file` is in `git log "$RANGE" --diff-filter=A --name-only` (working-tree: `git diff --diff-filter=A --name-only [--cached]`). `peer_file` exists at HEAD (`git ls-tree HEAD`) and matches one heuristic:
55
+ - **Stem similarity ≥ 60%** of the longer stem (e.g. `PhysicalProductSubscription` ↔ `Subscription`).
56
+ - **Interface/impl pair**: `I<Name>` ↔ `<Name>`, `<Name>` ↔ `<Name>.impl`, `<Name>{Abstract,Base,Protocol}` ↔ `<Name>`.
57
+ - **Shared suffix** from `{Handler, Service, Repository, Aggregate, Reducer, Controller, Resolver, Command, Query, Job, Processor, Strategy, Policy, Event, Listener, Subscriber, Publisher, Exception, Eligibility, Ability, QueryParam, Specification, Factory, Builder}`.
47
58
 
48
- ## Step 2: Phase-1 Discovery Map (parallel agents)
59
+ Drop a pair only when the peer doesn't exist at HEAD, no heuristic matches, or both files were added in this diff. Empty list ⇒ skip the peer-mirror agent. Co-modified peers are KEPT — the agent Reads them at HEAD (post-diff tree state), so any invariant present at HEAD counts as peer evidence regardless of whether the peer was edited in this diff.
49
60
 
50
- Spawn ONE agent in parallel with orchestrator-side work:
61
+ ## Step 2: Dispatch Wave-1 Integration + Precedents + Deps/CVE + Peer-Mirror
62
+
63
+ Spawn ALL of the following in parallel at T=0 in a **single message with multiple Agent tool calls**. Do NOT wait for integration-scanner before dispatching precedents / dependencies / CVE — they do not consume Discovery-Map output, only `ChangedFiles` and the manifest diff (both orchestrator-produced in Step 1).
51
64
 
52
65
  **Agent — Integration map:**
53
66
  - subagent_type: `integration-scanner`
54
67
  - Prompt: "Map inbound references, outbound dependencies, and infrastructure wiring for the following changed files: [ChangedFiles, one per line]. Flag any auth-boundary crossings (middleware, guards, interceptors, authorize-style decorators) and config/DI/event registration touching these paths. Do NOT analyse code quality — connections only, in your standard output format."
55
68
 
56
- While the agent runs, the orchestrator produces the rest of the Discovery Map inline from Step 1's data:
69
+ **Agent Precedents** (always): use the `precedent-locator` prompt defined in Step 3 below dispatch it here, not in Wave-2. Input it needs: `ChangedFiles` only.
70
+
71
+ **Agent — Dependencies** (only when `ManifestChanged`): use the `codebase-analyzer` Dependencies prompt defined in Step 3 below — dispatch here. Input it needs: touched manifest paths + `LockstepSelfReview` flag.
72
+
73
+ **Agent — CVE / advisory** (only when `ManifestChanged`): use the `web-search-researcher` prompt defined in Step 3 below — dispatch here. Input it needs: parsed `name@version` list from the manifest diff (orchestrator extracts and hands over directly).
74
+
75
+ **Agent — Peer-Mirror** (only when `len(PeerPairs) > 0`): `subagent_type: codebase-analyzer`. Input: the `PeerPairs` list verbatim, nothing else — no Discovery Map (it isn't built yet and the agent doesn't need it), no patch path (the work is peer-vs-new entity comparison, not diff analysis). Prompt:
76
+ ```
77
+ Peer-mirror check.
78
+
79
+ PeerPairs (orchestrator-computed):
80
+ [list of (new_file, peer_file) tuples]
81
+
82
+ For each pair, Read BOTH files in full. Enumerate the peer's PUBLIC surface as rows:
83
+ - every public method / exported function
84
+ - every domain event / notification / message fired (language-agnostic: method calls named `fire*`, `emit*`, `publish*`, `dispatch*`, `raise*`, `notify*`, `AddDomainEvent`, or idiomatic equivalents)
85
+ - every state transition (name + precondition guard + side-effects)
86
+ - every constructor-injected / DI-supplied collaborator
87
+ - every persisted field / column / serialised property
88
+ - every registration this file contributes to a switch/map/table/route/handler registry elsewhere (match by type name appearing in a `switch`/`match`/`when`/dispatch table)
89
+
90
+ For each row, check the new file. Emit ONE row per peer invariant:
91
+
92
+ peer_site (file:line — `<verbatim line>`) | new_site (file:line — `<verbatim line>` OR `<absent>`) | status | one-sentence delta
93
+
94
+ status ∈ {Mirrored, Missing, Diverged, Intentionally-absent}.
95
+
96
+ "Intentionally-absent" requires an explicit cite — a comment in the new file, a commit-message line mentioning the omission, or a type-system constraint that makes the invariant inapplicable (e.g. the peer's `Trial*` methods are absent because the new entity's type says it doesn't support trials). Suspicion is not sufficient; when in doubt, emit Missing.
97
+
98
+ Output format: markdown table per pair, heading `### Peer pair: <new_file> ↔ <peer_file>`. No prose outside the tables. No severity. No recommendations. Citation contract applies to every cell.
99
+ ```
100
+
101
+ While these agents run, the orchestrator produces the rest of the Discovery Map inline from Step 1's data:
57
102
  - `ChangedFiles`, `ManifestChanged`, `LockstepSelfReview`, `ReviewType`
58
- - Hunk ranges per file (from `git diff -U0`)
103
+ - **Semantic file map** (per file: `path (+A -B)` + role tag + top-level symbol names touched; see format and rules below)
59
104
  - Commit-message context (if applicable)
60
105
 
61
- **Wait for ALL agents to complete** before proceeding.
106
+ **Wait for `integration-scanner` AND the peer-mirror agent (when dispatched)** before dispatching Wave-2. Wave-2 agents consume both via the Discovery Map (auth-boundary crossings, inbound refs, peer-mirror Missing/Diverged rows). Precedents / Dependencies / CVE continue running in the background; **Precedents MUST be awaited before Step 5 begins** (Reconciliation reads its follow-up-within-30-days counts to weight severity; see Step 5). Dependencies / CVE also merge in at Step 5 but may arrive later in the wait barrier.
62
107
 
63
- **Synthesize the Discovery Map** — a compact text block that Phase-2 agents receive verbatim as `Known Context`:
108
+ **Synthesize the Discovery Map** — a compact block that Wave-2 agents receive verbatim as `Known Context`. Each file line carries a *role tag* and a *symbols-touched hint*; files are clustered by shared directory prefix so agents orient without re-reading the patch.
64
109
 
65
110
  ```
66
111
  ## Discovery Map
@@ -68,219 +113,303 @@ While the agent runs, the orchestrator produces the rest of the Discovery Map in
68
113
  Review type: [ReviewType]
69
114
  Scope: [scope argument]
70
115
  Commit/range: [git ref]
71
- Changed files ([N]):
72
- path/a.ts (+A -B)
73
- path/b.ts (+A -B)
74
- Hunks:
75
- path/a.ts: L10-23, L45-60
76
- path/b.ts: L5-8
77
116
  Manifest changed: [yes|no]
78
117
  Lockstep self-review: [yes|no]
79
- Auth-boundary crossings: [from integration-scanner output, file:line]
80
- Inbound refs: [from integration-scanner output]
81
- Outbound deps: [from integration-scanner output]
82
- Wiring/config: [from integration-scanner output]
118
+
119
+ Changed files ([N]):
120
+
121
+ ## [cluster shared directory prefix]
122
+ path/file.ext (+A -B) [role-tag] — top 1–3 symbols touched
123
+ ...
124
+
125
+ Auth-boundary crossings: [integration-scanner, file:line]
126
+ Inbound refs (files with ≥3 consumers): [integration-scanner]
127
+ Outbound deps: [integration-scanner]
128
+ Wiring/config: [integration-scanner]
129
+ Peer mirrors: [peer-mirror agent output verbatim — Missing/Diverged rows only; Mirrored and Intentionally-absent rows are summarised as counts]
83
130
  ```
84
131
 
85
- ## Step 3: Phase-2 Three-Lens Review (parallel agents)
132
+ **Clustering**: group files by longest shared directory prefix yielding clusters of 2+ files; singletons form their own cluster labelled with the filename. Emerges from the repo — no framework assumptions.
133
+
134
+ **Role-tag** (one tag per file, first match wins):
135
+ 1. `[boundary]` — in integration-scanner's auth-boundary output
136
+ 2. `[persistence]` — path contains `migration`/`schema`/`repository`/`dao`/`model`, or matches an ORM/migration convention visible in the repo
137
+ 3. `[test]` — path contains `/test`/`/spec`/`__tests__`, or filename ends in a test suffix (`.test.*`, `.spec.*`, `_test.*`, `Test.*`)
138
+ 4. `[config]` — in integration-scanner's wiring/config output, or is a manifest/lockfile/settings file
139
+ 5. `[hub]` — in integration-scanner's inbound-refs with ≥3 consumers
140
+ 6. `[code]` — default
141
+
142
+ **Symbols-touched hint**: extract top 1–3 top-level definitions from the diff's `+` lines using a heuristic appropriate to the file's language (class/function/def/fn/struct/trait/interface/type/export). Cap at ~80 chars. Leave blank if ambiguous — orientation, not completeness.
143
+
144
+ ## Step 3: Dispatch Wave-2 — Quality + Security Lenses
145
+
146
+ Spawn Quality + Security in parallel using the Agent tool. Each receives the `## Discovery Map` block inline as `Known Context` above its task, and a pointer to `/tmp/code-review-patch.diff` for the diff itself. Precedents / Dependencies / CVE are already running from Wave-1 — do NOT re-dispatch them here; the prompts below document what those Wave-1 agents received, they are not re-issued.
147
+
148
+ **Wave-2 context isolation (LOAD-BEARING — violations cause silent quality collapse)**: Each Wave-2 agent receives EXACTLY two things, nothing else: (1) the Discovery Map (digested form) and (2) the literal path string `/tmp/code-review-patch.diff`.
149
+
150
+ **DO NOT paste into Wave-2 prompts**, under any circumstance, even if the orchestrator has already received them:
151
+ - raw integration-scanner output (the Discovery Map already summarises its auth/ref/wiring findings)
152
+ - precedent-locator output
153
+ - Dependencies lens output
154
+ - CVE lens output
155
+ - any prior Wave-2 or Wave-3 output from earlier runs in the same Pi session
86
156
 
87
- Spawn these agents in parallel using the Agent tool. Each receives the `## Discovery Map` block inline as `Known Context` above its task.
157
+ **Why this is load-bearing**: summary context induces *narrativisation* — the agent treats the preamble as "the orchestrator already framed the findings, I just classify them" instead of independently reading the patch file. Observed failure signatures when this is violated: Quality drops from ~40 tool calls / 3M tokens / 500s to ~5-15 tool calls / 300k tokens / 100-200s, and returns hallucinated findings (invented statuses, mis-cited line numbers, claims that files are "missing from patch" when they are in fact present).
88
158
 
89
- **Always spawn:**
159
+ **Self-check before dispatching Wave-2**: read your outgoing Agent prompt. If it contains any content from Wave-1 agent RESULTS beyond the Discovery Map you synthesised, strip it. The Discovery Map is the contract; raw outputs are reconciliation-only.
90
160
 
91
- **Quality lens:**
92
- - subagent_type: `codebase-analyzer`
93
- - Prompt:
161
+ **Citation contract** (applies to every Wave-2+ agent, every step): every `file:line` citation MUST be accompanied by the literal line text in backticks — format `file:line — \`<verbatim line>\` — <note>`. Omit findings whose lines you cannot quote verbatim.
162
+
163
+ **Quality lens** (`codebase-analyzer`) — **file-oriented**:
94
164
  ```
95
- Known Context:
96
- [paste Discovery Map verbatim]
165
+ Analyse changes file by file. For each file in ChangedFiles, read its diff region in `/tmp/code-review-patch.diff` (patch has `-U30` — full function context is already inline; rarely need an extra Read call), form a mental model of what the file does and what the diff changes about it, then apply the 13 surfaces below to the file as a whole. Cite `file:line` with verbatim line text (citation contract) for every finding. Omit findings not traceable to a diff-touched change. No severity.
166
+
167
+ **File order strategy**: prioritise by role tag — `[boundary]` files first (security-sensitive), then `[persistence]` (durable-state surfaces), then `[hub]` (blast-radius amplifiers), then `[code]`, then `[config]`, then `[test]` last. Within the same tag, prioritise files with the largest diffs.
168
+
169
+ **Per file**, write a short section (`### file/path.ext`) containing only the surfaces that APPLY to that file's changes. Use sub-headings for grouped evidence. A surface may be flagged across multiple files — report the evidence where it lives, and rely on cross-layer surfaces (8, 9) to tie them together.
97
170
 
98
- Task: Trace data flow through each changed hunk. For every hunk, enumerate `file:line` observations in these buckets do NOT classify severity, the orchestrator does:
99
- 1. Logic-bug risks: missing validation, dropped error paths, off-by-one, null/undefined misses, incorrect branch ordering, forgotten return/await, state mutations without guards.
100
- 2. Pattern divergence: where the hunk deviates from the surrounding file's existing style/structure (cite the nearby line the hunk broke from).
101
- 3. Blast radius: any inbound reference in the Discovery Map that the hunk's behavior change could affect (`consumer.ext:line` + what changes for it).
102
- 4. Test coverage gaps: any risk-bearing behavior the hunk introduces that has no adjacent test reference.
171
+ **Surfaces** each surface's mechanical trigger decides whether it APPLIES to a given file's changes. Walk every applicable trigger:
103
172
 
104
- Return evidence only. No recommendations.
173
+ 1. **Logic & flow** (always, per file with new/modified code) — validation, error paths, off-by-one, null misses, branch ordering, return/await, unguarded mutation.
174
+ 2. **Pattern coherence** (≥2 similar constructs within a file, or ≥2 files in the same cluster) — cite nearby line broken from.
175
+ 3. **Blast radius** (Discovery Map lists inbound refs to this file, OR this file is flagged as a hub) — `consumer:line` + what changes for each inbound ref.
176
+ 4. **Test coverage gaps** (always, checked once across the whole changeset) — for each risk-bearing function/method added/changed, check whether any `[test]`-tagged file in ChangedFiles contains a corresponding test. Flag risk-bearing behavior with no adjacent test.
177
+ 5. **Predicate-set coherence** (`HasGatingPredicate`) — ≥2 conditionals on the same enum/type across the changeset. Tabulate `predicate file:line | accepted | rejected`. Flag mismatches. Surface 5 output MUST use heading `### Predicate-set coherence` at review-scope level (not nested inside a per-file section) — downstream step consumes it verbatim.
178
+ 6. **Registration coverage** (changeset adds discriminator value / enum variant / handler key / route / event type / strategy entry) — every dispatch/registry/switch across ChangedFiles that must enumerate it. Cite each registration site + each enumeration site. Flag gaps.
179
+ 7. **Query/write symmetry** (changeset adds setter/linker, shape change, or new persisted field) — trace BOTH creation and renewal/update paths; cite the setter file:line AND the reader file:line.
180
+ 8. **Cross-layer drift** (same entity/enum/key appears in ≥2 files in different clusters or role tags — e.g. model ↔ DTO ↔ schema ↔ registry ↔ presentation) — open each file, tabulate presence, flag asymmetry. When the entity is a **key fanned out across parallel tables** (locale maps, theme maps, strategy registries, handler/command tables, feature-flag tables), every table must carry the added key and none must retain a removed/renamed one — flag orphaned references and missing entries.
181
+ 9. **Peer-member consistency** (a file gains a new method/hook/case/handler in a set of peers — class methods, hook siblings, reducer cases, handler registrations, CLI subcommands) — tabulate the invariants the peers share (state mutation, emitted event/signal, precondition guard, bookkeeping counter, teardown symmetry); flag omissions in the new member.
182
+ 10. **Durable-state hygiene** (file is a schema migration, repository/DAO, file-backed config, KV/cache, serialized artifact, or adds a new persisted field) — trace the forward-write AND the reverse/rollback path; flag irreversible or data-losing rollback, missing lookup affordance for a new query field (index, key, sorted structure), iteration over an unbounded/mutable source without a stable cursor, and new invariants at the storage layer not mirrored by the in-memory validator.
183
+ 11. **Shared-state acquisition** (file introduces async handler, event listener, singleton init, queue consumer, file-lock region, or global cache mutation) — trace acquire/release around every mutation; flag unguarded check-then-act across an `await`/callback/IPC boundary, stale reads while another writer is in flight, non-commutative acquire order between distinct state slots, and replay/retry paths that lack an idempotency key.
184
+ 12. **Multi-step commitment** (file issues ≥2 writes that must all succeed or all be undone — DB transaction, cross-table mutation, multi-file write, filesystem+network pair, multi-API orchestration, compensating-action chain) — trace the commit boundary; flag missing undo/compensation on partial failure, retry paths that re-apply non-idempotent steps, and divergence between two stores that must agree without a coordinating primitive.
185
+ 13. **Error handling & idempotency** (file adds a failure-response construct — retry loop, catch/except block, error boundary, fallback branch, circuit breaker, timeout, resumable step) — trace the error-propagation path; flag swallowed errors, retry without an idempotency key, fallback that silently degrades observable behavior, unjustified timeout values.
186
+
187
+ **Economising Reads**: issue a `Read` only when (a) you need a file NOT in ChangedFiles (hub, peer, test), or (b) the changed function is longer than the `-U30` window can show. Never re-Read a file just to re-orient — that's what the symbols-touched hint is for.
105
188
  ```
106
189
 
107
- **Security lens:**
108
- - subagent_type: `codebase-analyzer`
109
- - Prompt:
190
+ **Security lens** (`codebase-analyzer`) — **file-oriented**:
110
191
  ```
111
- Known Context:
112
- [paste Discovery Map verbatim]
113
-
114
- Task: Grep each changed hunk for the following sink patterns and list every match with `file:line` + surrounding 3 lines. Cross-reference the Discovery Map's Auth-boundary crossings.
115
- For each hit, additionally return `confidence: N/10` reflecting how certain you are that a user-controlled input can reach this sink under current deployment. Do NOT report hits with confidence < 8.
116
- - Command execution: `exec(`, `execSync(`, `execFile(`, `child_process`, `spawn(`
117
- - Dynamic evaluation: `eval(`, `new Function(`
118
- - SQL template-interpolation: multi-line `` `SELECT ... ${ ``, `` `INSERT ... ${ ``, `` `UPDATE ... ${ ``, `` `DELETE ... ${ ``
119
- - XSS sinks: `innerHTML =`, `dangerouslySetInnerHTML`, `document.write(`
120
- - Path traversal: string concatenation into `fs.readFile`, `fs.writeFile`, `path.join` with user input
121
- - SSRF: `fetch(`, `http.request(`, `axios(`, `got(` where HOST or PROTOCOL (not just path) is user-controlled
122
- - Secrets in diff: `api_key`, `secret`, `password`, `BEGIN PRIVATE KEY`, `.env` content literal
123
- - Missing auth guard: auth-boundary crossings (from Discovery Map) reaching a traced sink without an upstream guard
124
-
125
- Hard exclusionsdo NOT report:
126
- - DOS / resource exhaustion / rate limiting / memory or CPU exhaustion
127
- - Missing hardening in isolation (no traced sink), lack of audit logs
128
- - Theoretical race conditions / timing attacks without a concrete reproducer
129
- - Log spoofing, prototype pollution, tabnabbing, open redirects, XS-Leaks, regex DOS, regex injection
130
- - Client-side-only authn/authz gaps (server is the authority)
131
- - XSS in React/Angular/tsx files unless via `dangerouslySetInnerHTML`, `bypassSecurityTrustHtml`, or equivalent
132
- - Findings whose sole source is an environment variable, CLI flag, or UUID (trusted in our threat model)
133
- - Findings in test-only files or `.ipynb` notebooks without a concrete untrusted-input path
134
- - Outdated-dependency CVEs (handled by the dependencies/CVE lens)
135
-
136
- For each hit, name the pattern and quote the line. Return evidence only. No CVE lookups — that is a separate agent.
192
+ Analyse each changed file as a whole, looking for sinks in the classes below. For each file, grep the file's diff region in `/tmp/code-review-patch.diff` (patch has `-U30` — sink context is inline) for the sink patterns, and for each hit provide the verbatim line (citation contract) plus 2 surrounding lines and `confidence: N/10` that user-controlled input can reach the sink under current deployment. Drop hits with confidence < 8. Cross-reference Discovery Map auth-boundary crossings and inbound refs — a sink in a file reached from an auth-boundary file is in scope even if the sink file itself doesn't cross the boundary.
193
+
194
+ **File order strategy**: `[boundary]` files first (direct source→sink exposure); then `[persistence]` (query injection, unsafe deserialization); then `[code]` (command exec, SSRF, explicit-trust rendering); then `[hub]` / `[config]`; skip `[test]` unless a test helper touches a sink.
195
+
196
+ IN-SCOPE RULE: only report findings whose sink line is inside a changed file's diff region (add/modify/adjacent-context rewrite). Pre-existing sinks in files the diff did not change are out of scope, UNLESS the diff changes how data flows TO the sink (e.g. new user-controlled source routed to an untouched sink) then cite both locations. When in doubt, trace data flow from Discovery Map boundary crossings through the changed files.
197
+
198
+ Sink classes match the concept in whatever language the diff uses:
199
+ - **Command execution** shell/process spawn w/ user input (e.g. `exec`, `subprocess.run(shell=True)`, `Runtime.exec`, …).
200
+ - **Dynamic code / unsafe deserialization** — `eval` / dynamic-function constructors; deserializers that can execute code (e.g. `pickle.loads`, `yaml.load` w/o safe loader, `ObjectInputStream`, `BinaryFormatter`, …).
201
+ - **Query injection** user input concatenated or interpolated into a query string interpreted by an external engine (SQL, NoSQL operators, LDAP filters, XPath, GraphQL constructed as string). Parameterized/prepared queries and typed query builders are safe.
202
+ - **Explicit-trust rendering** — user input emitted into a channel that will interpret it as code/markup rather than data. In-scope only when the framework's explicit-trust API is invoked (`dangerouslySetInnerHTML`, `bypassSecurityTrustHtml`, `v-html`, `template.HTML`, `mark_safe`, `html_safe`, triple-stache, raw-HTML markdown, …), plain `innerHTML =` / `document.write(` in vanilla/server-rendered code, or equivalent passthroughs in non-HTML renderers (unescaped ANSI-escape emission to a TTY, unquoted shell-prompt interpolation, template-engine raw blocks).
203
+ - **Path traversal** user-controlled components into file-system APIs without normalization/allowlist.
204
+ - **SSRF** outbound HTTP/TCP with user-controlled host OR protocol (not just path).
205
+ - **Secrets in diff** — literal credentials, API keys, PEM blocks, connection strings w/ embedded passwords, `.env` content.
206
+ - **Missing trust-boundary check** a traced sink reached from a Discovery-Map boundary crossing (HTTP handler, RPC endpoint, IPC message, CLI flag that flows to a privileged operation, webhook receiver) without an upstream authorization/validation step (middleware, guard, attribute/decorator, allowlist check, signature verification).
207
+
208
+ Do NOT report: DOS/resource exhaustion/rate-limiting, missing hardening without a traced sink, theoretical races/timing without reproducer, log spoofing/prototype pollution/tabnabbing/open redirects/XS-Leaks/regex DOS, client-side-only authn/authz (server is the authority), findings sourced only from env var / CLI flag / UUID, test-only or notebook files without a concrete untrusted-input path, outdated-dependency CVEs (CVE lens handles).
209
+
210
+ Name the sink class and the matched idiom. Evidence only. No CVE lookups.
137
211
  ```
138
212
 
139
- **Dependencies lens:**
140
- - subagent_type: `codebase-analyzer`
141
- - Prompt (only when `ManifestChanged` is true; otherwise SKIP this lens and omit the `### Dependencies` H3 block from the artifact):
213
+ **Dependencies lens** (`codebase-analyzer`, only when `ManifestChanged`; otherwise SKIP and omit `### Dependencies` in artifact):
142
214
  ```
143
- Known Context:
144
- [paste Discovery Map verbatim]
145
- Lockstep self-review: [LockstepSelfReview yes|no]
146
-
147
- Task: Parse the diff of `package.json` / `package-lock.json` / `pnpm-lock.yaml` / `yarn.lock`. List:
148
- 1. Added dependencies: `name@version` with `file:line`.
149
- 2. Bumped dependencies: `name: old -> new` with `file:line`.
150
- 3. Removed dependencies.
151
- 4. `peerDependencies` changes.
152
- 5. License field changes or additions in the lockfile.
153
- 6. When Lockstep self-review is `yes`: flag only intra-monorepo version drift where a sibling pin diverges from the lockstep `version:` in `packages/*/package.json`. Treat `"*"` peer pins as intentional.
154
- 7. When Lockstep self-review is `no`: flag any version-conflict between direct dep and lockfile resolution.
155
-
156
- Return evidence only. No CVE lookups — that is a separate agent.
215
+ Lockstep self-review: [yes|no]
216
+
217
+ Identify the ecosystem from touched manifests (npm, Cargo, Go modules, PyPI/Poetry, Bundler, NuGet, Maven/Gradle, …). Parse the changed manifest(s) and list:
218
+ 1. Added deps: `name@version` with `file:line`.
219
+ 2. Bumped deps: `name: old -> new` with `file:line`.
220
+ 3. Removed deps.
221
+ 4. Peer / optional / dev-scope changes (whatever the ecosystem calls them).
222
+ 5. License field changes in manifest or lockfile.
223
+ 6. Lockstep=yes: flag only intra-monorepo drift where a sibling pin diverges from the lockstep version. Treat wildcard peer pins as intentional.
224
+ 7. Lockstep=no: flag version conflicts between direct dep and lockfile resolution.
225
+
226
+ Evidence only. No CVE lookups.
157
227
  ```
158
228
 
159
- **Precedents lens:**
160
- - subagent_type: `precedent-locator`
161
- - Prompt:
229
+ **Precedents lens** (`precedent-locator`):
162
230
  ```
163
- Planned change: code review of [scope]. Changed files: [ChangedFiles].
164
- Find the most similar past changes that touched these files or files nearby. For each precedent, report the commit hash, blast radius, any follow-up fixes within 30 days, and the one-sentence takeaway. Distil composite lessons across all precedents.
231
+ Code review of [scope]. Changed files: [ChangedFiles].
232
+ Find similar past changes touching these files or nearby. Per precedent: commit hash, blast radius, follow-up fixes within 30 days, one-sentence takeaway. Distil composite lessons.
165
233
  ```
166
234
 
167
- **Conditional spawn** (only when `ManifestChanged` is true):
168
-
169
- **CVE/advisory lens:**
170
- - subagent_type: `web-search-researcher`
171
- - Prompt:
235
+ **CVE/advisory lens** (`web-search-researcher`, only when `ManifestChanged`):
172
236
  ```
173
- For each of the following dependency changes, look up known CVEs / GitHub Advisories / OSS Index entries in the target version. Return LINKS alongside findings. If a vulnerability exists, summarize severity (Critical / High / Moderate / Low), affected version range, and whether the bumped-to version is fixed.
237
+ Look up CVEs / GitHub Advisories / OSS Index entries for the target versions. Return LINKS. Per vulnerability: severity (Critical/High/Moderate/Low), affected range, whether bumped-to version is fixed.
174
238
 
175
- Dependencies to check:
176
- [name@version, one per line — extracted by orchestrator from the diff]
239
+ Dependencies:
240
+ [name@version per line — orchestrator-extracted]
177
241
  ```
178
242
 
179
- **Wait for ALL agents to complete** before proceeding.
243
+ **Wait for Quality + Security to complete** before proceeding. Precedents / Dependencies / CVE from Wave-1 may still be running; gather them before Step 5, not before Step 4.
180
244
 
181
- ## Step 4: Cross-Finding Interaction Sweep
245
+ ## Step 4: Dispatch Wave-3 — Predicate-Trace + Interaction Sweep + Gap-Finder
182
246
 
183
- **Gate**: SKIP this step (go directly to Step 5) when EITHER `len(ChangedFiles) < 2` OR the Quality lens returned fewer than 4 total observations across all hunks. Emergent interactions need surface area; tiny diffs cannot structurally produce them.
247
+ Once Wave-2 (Quality + Security) completes, dispatch all three gated agents below **in a single message with multiple Agent tool calls**. They do NOT consume each other's output:
184
248
 
185
- Otherwise, spawn ONE additional agent after all Phase-2 agents complete:
249
+ - **Interaction Sweep (4b)** receives Quality's `Predicate-set coherence` table directly as its predicate-row source. Quality's table already flags mismatches — Predicate-Trace (4a) only *elaborates* them through consumers. Interaction Sweep's categories 1–6 don't need 4a at all; categories 7–9 (stranded-state, false-promise, co-tenant filter gap) operate on the same rows 4a would trace.
250
+ - **Gap-Finder (4c)** is explicitly a coverage-check against lens findings. The skill's rule *"Do NOT re-analyse what lenses already found"* (Step 4c body below) means it deliberately ignores 4a/4b output — running it in parallel preserves intent.
251
+ - If Predicate-Trace (4a) surfaces a row that was not visible in Quality's table, append it via a Step 9 follow-up — cheaper than a serial gate.
186
252
 
187
- **Interaction sweep:**
188
- - subagent_type: `codebase-analyzer`
189
- - Prompt:
253
+ ### Step 4a: Predicate-Trace
254
+
255
+ **Gate**: SKIP this sub-step (do not dispatch 4a) unless `HasGatingPredicate` is true AND the Quality lens returned ≥2 rows in its `Predicate-set coherence` table referencing the same enum/type. If skipped, 4b and 4c still dispatch.
256
+
257
+ Otherwise spawn ONE `codebase-analyzer` in parallel with 4b and 4c:
258
+ ```
259
+ Coherence rows (Quality — Predicate-set coherence): [paste verbatim]
260
+ Gating predicates in diff: [`file:line` list]
261
+
262
+ Per predicate, return: `predicate file:line | inputs | promise (what TRUE/matching branch implies) | consumer file:line | consumer filter | fulfils? | gap`.
263
+
264
+ Flag:
265
+ - *False promise* — matching branch depends on a consumer/filter elsewhere that excludes this entity's source/type/state.
266
+ - *Stranded state* — entity reaches state X via one conditional, but every conditional that operates on this entity elsewhere excludes X (no exit path).
267
+
268
+ Evidence only. Citation contract applies.
190
269
  ```
191
- Known Context:
192
- [paste Discovery Map verbatim]
193
270
 
194
- Quality Evidence:
195
- [paste Quality lens output verbatim]
271
+ Do NOT wait — 4b (Interaction Sweep) and 4c (Gap-Finder) dispatch in the same message as 4a.
272
+
273
+ ### Step 4b: Interaction Sweep
196
274
 
197
- Security Evidence:
198
- [paste Security lens output verbatim]
275
+ **Gate**: SKIP this sub-step (do not dispatch 4b) when EITHER `len(ChangedFiles) < 2` OR the Quality lens returned fewer than 4 total observations across all files. Emergent interactions need surface area; tiny diffs cannot structurally produce them.
199
276
 
200
- Precedents:
201
- [paste precedents output verbatim]
277
+ Otherwise spawn ONE `codebase-analyzer` in parallel with 4a and 4c:
278
+ ```
279
+ Quality Evidence: [verbatim]
280
+ Security Evidence: [verbatim]
281
+ Predicate-set coherence rows (verbatim from Quality's table — full Step 4a output is NOT required and is NOT awaited): [verbatim | "not applicable"]
282
+ Precedents: [verbatim if Wave-1 finished; else "deferred to Step 5"]
202
283
 
203
- Task: Perform a cross-finding interaction sweep. Group the evidence by shared entity, state machine, workflow, data flow path, API boundary, background process, or producer-consumer contract.
284
+ Group evidence by shared entity, state machine, workflow, data flow path, API boundary, background process, or producer-consumer contract.
204
285
 
205
- For each group, check whether multiple local observations combine into an emergent defect, including:
206
- 1. contradictory assumptions between components or layers,
286
+ Per group, check for emergent defects:
287
+ 1. contradictory assumptions between components/layers,
207
288
  2. unreachable, stuck, or non-terminal states,
208
289
  3. retry/reprocess mechanisms made inert by another behavior,
209
- 4. duplicate-processing or idempotency gaps created by ordering or missing guards,
290
+ 4. duplicate-processing / idempotency gaps from ordering or missing guards,
210
291
  5. guards in one layer invalidating transitions in another,
211
- 6. one finding masking, amplifying, or permanently triggering another.
292
+ 6. one finding masking, amplifying, or permanently triggering another,
293
+ 7. stranded state — state X reachable via one conditional but every conditional operating on this entity elsewhere excludes X,
294
+ 8. false-promise predicate — matching branch's consumer excludes this entity's source/type/state,
295
+ 9. co-tenant filter gap — shared discriminator filter where a new or terminal value the diff touches falls through every consumer's filter.
296
+
297
+ Return only findings with ≥2 concrete `file:line` facts from different files/components, each quoted verbatim per the citation contract. No recommendations. No single-location repeats.
298
+
299
+ For findings involving ordering/races/concurrency across processes or handlers, name the ordering primitive that would prevent the race (distributed lock, exclusive-key wrapper, ordered partition, transaction, idempotency key, etc.) and explain why it does NOT apply here. Drop the finding if the primitive exists in the diff or nearby and your argument against it is speculative.
300
+ ```
301
+
302
+ Do NOT wait — 4c (Gap-Finder) dispatches in the same message.
303
+
304
+ ### Step 4c: Gap-Finder
305
+
306
+ **Gate**: SKIP this sub-step (do not dispatch 4c) when `len(ChangedFiles) < 2`. Tiny diffs cannot structurally have coverage gaps.
307
+
308
+ Otherwise spawn ONE `codebase-analyzer` in parallel with 4a and 4b. The prompt intentionally omits 4a/4b output (they are not awaited); Gap-Finder's job is to find FILES (or specific risk-bearing regions within them) no LENS covered, not to audit 4a/4b. Scope is deliberately limited to risk-bearing file roles with non-trivial deltas — the 5-finding cap makes a full walk wasteful:
309
+ ```
310
+ All lens findings so far:
311
+ Quality Evidence: [verbatim]
312
+ Security Evidence: [verbatim | "not applicable"]
313
+
314
+ Diff patch: Read `/tmp/code-review-patch.diff` (already assembled with `-U30`, so full function context is inline).
315
+ Discovery Map: [verbatim]
316
+
317
+ **In-scope files only**: restrict the walk to files tagged `[boundary]`, `[persistence]`, `[code]`, or `[hub]` AND whose diff delta is ≥ 5 lines (added + removed). SKIP all `[test]` and `[config]` files, and skip files with tiny deltas. These categories almost never produce gap findings under the 5-finding cap, and walking them consumes the bulk of Gap-Finder's runtime without improving recall.
318
+
319
+ Task: Walk the in-scope files. For each file, check whether ANY existing finding above already covers its risk-bearing behaviors. A file's behavior is "risk-bearing" if the diff introduces: state mutations, I/O operations (DB/network/file), error paths, conditional logic on mutable state, concurrent/shared-state access, or a public API surface change.
320
+
321
+ Flag files whose risk-bearing behavior has NO corresponding finding. For each flagged file:
322
+ - Quote the specific `file:line` range and verbatim code per the citation contract
323
+ - State what risk-bearing behavior it contains (method name, behavior class)
324
+ - Explain why no existing finding covers it (1 sentence)
212
325
 
213
- Return only interaction findings backed by explicit evidence from at least two concrete file:line locations from different files or different components. No recommendations. Do not repeat single-location findings.
326
+ Do NOT re-analyse what lenses already found only flag GAPS in coverage. Maximum 5 gap findings total across the changeset. Stop walking once 5 gaps are flagged. Citation contract applies.
327
+
328
+ File order: follow role-tag priority (`[boundary]` → `[persistence]` → `[hub]` → `[code]`).
214
329
  ```
215
330
 
216
- **Wait for the interaction-sweep agent to complete** before proceeding.
331
+ **Wait for ALL of 4a / 4b / 4c AND the Precedents agent from Wave-1 to complete** before proceeding to Step 5 (Reconciliation). Precedents is a **hard gate** — severity weighting in Step 5 reads its follow-up-within-30-days counts. Dependencies / CVE (when dispatched) also merge in here but are not individually hard-gated; wait for them too unless they clearly exceed the review SLA, in which case omit `## Dependencies` and note it in the artifact.
217
332
 
218
333
  ## Step 5: Reconcile Findings
219
334
 
220
- 1. **Compile evidence** from every lens and the interaction sweep (when it ran):
221
- - Quality evidence → classify each `file:line` observation into severity:
222
- - 🔴 Critical: traced flow contradiction (dropped error path, missing validation on a known sink, null-deref).
223
- - 🟡 Important: blast-radius × complexity-delta (hot path + new allocation, visible ABI change without migration).
224
- - 🔵 Suggestion: pattern divergence with a concrete nearby template.
225
- - 💭 Discussion: composite-lesson architecture concerns.
226
- - Security evidence → classify:
227
- - 🔴 sink hit with a CONCRETE user-reachable source→sink path traced through Discovery Map auth-boundary crossings. Reject any hit lacking an explicit trace.
228
- - 🟡 crypto-only concrete issues: weak hash in an auth/integrity role (MD5/SHA1), non-constant-time compare on secrets, hardcoded key material in diff. Do NOT use 🟡 for "missing hardening".
229
- - 🔵 pattern divergence from a secure example in the SAME file (cite the nearby secure `file:line`).
230
- - 💭 architectural question.
231
- - Dependencies evidence classify:
232
- - 🔴 Known-exploitable CVE in a touched dep (Critical/High per advisory DB) OR lockstep-contract violation (would trip `scripts/sync-versions.js`).
233
- - 🟡 Moderate CVE, outdated major with a migration path, license incompatibility with the project license.
234
- - 🔵 Minor/transitive drift.
235
- - 💭 Architectural dep question.
236
- - Interaction-sweep evidence → classify (🔴/🟡 only; no 💭 tier — the sweep must produce concrete emergent defects, not speculation):
237
- - 🔴 Critical: concrete emergent failure across 2+ `file:line` facts from different files/components (stranded state, duplicate-processing path, inert retry, producer/consumer contradiction).
238
- - 🟡 Important: concrete multi-component mismatch with bounded blast radius or an existing mitigation.
239
- - Precedents → compile into a separate `## Precedents & Lessons` section orthogonal to per-lens findings. Composite lessons go at the bottom of that section.
335
+ **Barrier**: Step 5 MUST NOT begin until the Precedents agent has returned. Severity weighting depends on historical follow-up counts; starting reconciliation without them produces mis-weighted severities that the verification pass (Step 6) cannot correct.
336
+
337
+ **Resolution integrity check** (load-bearing): when Precedents returns a commit that claims to resolve or supersede a current finding, run `git merge-base --is-ancestor <precedent-hash> <TIP>` before accepting the resolution.
338
+ - Ancestor: the precedent IS in the reviewed branch; mark the finding `resolved-by: <hash>` and demote its severity to 💭 (kept for context).
339
+ - Not ancestor: the precedent is on a different branch / not merged; treat it as **context only**. Do NOT mark the finding resolved; annotate the precedent's row in `## Precedents` third column `NOT ancestor of [TIP] (context only)`.
340
+ - Orchestrator unable to run git (e.g., `staged` / `working` scope with no commit): skip the check and annotate `resolution: unverified`.
341
+
342
+ 1. **Compile and classify evidence** per lens:
343
+ - **Quality** 🔴 traced flow contradiction (dropped error path, missing validation on a sink, null-deref); 🟡 blast-radius × complexity-delta (hot path + new allocation, ABI change without migration); 🔵 pattern divergence with nearby template; 💭 composite-lesson architecture concern.
344
+ - **Security** — 🔴 concrete user-reachable source→sink trace via Discovery Map auth-boundary (reject hits without explicit trace); 🟡 concrete crypto issue (weak hash in auth/integrity role, non-constant-time compare, hardcoded key material); 🔵 divergence from a secure example in the same file; 💭 architectural question.
345
+ - **Dependencies** — 🔴 Critical/High CVE in touched dep OR lockstep-contract violation; 🟡 Moderate CVE, outdated major with migration path, license incompatibility; 🔵 minor/transitive drift; 💭 architectural dep question.
346
+ - **Interaction-sweep** 🔴/🟡 only (no 💭): 🔴 concrete emergent failure across ≥2 files/components; 🟡 multi-component mismatch with bounded blast radius or existing mitigation. **Promotion rule**: when ≥2 lens findings share the same entity/flow and combine into an emergent failure, the aggregate is 🔴 even if each constituent was 🟡/🔵. The interaction IS the defect — don't leave constituents at their original severity and skip the cross-finding bullet.
347
+ - **Gap-finder** — 🟡 uncovered risk-bearing region in a changed file with no lens coverage; 🔵 low-impact gap (style-only or defensive-only region missed). No 🔴 (gap findings are uncertain by nature).
348
+ - **Peer-mirror** treat every Missing/Diverged row as a finding. Base severity 🔵. **Bump to 🟡** when the missing invariant is a domain-event emission, a precondition guard on a state-mutating method, or a persisted-field invariant. **Bump to 🔴** when the missing invariant intersects a dispatch site the diff touches (switch/map/table/registry enumerating the peer's type alongside the new type — detectable from integration-scanner's `Wiring/config` output and the Discovery Map's `[config]`/`[hub]` files). Rationale: a missing mirror on a dispatched invariant is a silent-stranded-state cascade constituent; on a non-dispatched invariant it is a style issue. Record every peer-mirror bump in `## Reconciliation Notes`.
349
+ - **Precedents** → compile into `## Precedents` (table: `hash | subject | 30d-follow-ups | note`), composite lessons below. **Severity weighting**: for each current finding, count precedent commits touching the same symbol/file that had ≥1 follow-up fix within 30 days. If count ≥ 2, bump the finding one severity tier (🔵→🟡, 🟡→🔴); cap at 🔴. Record the bump by annotating the finding's title line `[precedent-weighted]` — do NOT emit a separate reconciliation section.
240
350
 
241
351
  2. **Probe advisor availability** — attempt a probe by checking whether `advisor` is in the active tool set (main-thread visibility). If yes, proceed to advisor path; otherwise take the inline path.
242
352
 
243
353
  3. **Advisor path** (when advisor is active):
244
354
  - Print a main-thread `## Pre-Adjudication Findings` block first — the advisor reads `getBranch()`, so evidence must be flushed before the call.
245
- - Call `advisor()` (zero-param). If it returns usable prose, paste it verbatim into `## Advisor Adjudication` and skip the inline path. Otherwise fall through.
355
+ - Call `advisor()` (zero-param). If it returns usable prose, paste it verbatim as a blockquote at the top of `## Recommendation` and skip the inline path. Otherwise fall through.
246
356
 
247
357
  4. **Inline path** (advisor unavailable or errored):
248
358
  - Run a dimension-sweep modeled on `skills/design/SKILL.md:83-116`: Data model / API surface / Integration / Scope / Verification / Performance.
249
359
  - For every finding, ask: does another finding contradict this severity given the Discovery Map? If yes, note the tension.
250
- - Produce a short `## Reconciliation Notes` block inside the artifact capturing any severity moves and the rationale.
360
+ - Record every severity move as a title-line annotation on the affected finding (`[precedent-weighted]`, `[cascade: <kind>]`, `[subsumed-by <ID>]`). No standalone reconciliation section.
251
361
 
252
362
  5. **Emit the reconciled severity map** — authoritative severity per finding, carrying the advisor's guidance when present. Keep the per-pass grouping (do NOT tag each finding with its originating lens in prose; the H2 it sits under is the tag).
253
- - Interaction findings live in their own `### Cross-Finding Interactions` H3 under `## Issues Found`, not folded into per-lens H3s.
254
- - When an interaction finding subsumes multiple local findings, keep the local findings if still actionable, but lead with the interaction finding and explain the relationship in `## Reconciliation Notes`.
363
+ - Interaction findings carry `I<n>` IDs and appear under the severity H2 that matches their final tier (`## 🔴 Critical`, `## 🟡 Important`). The old `### Cross-Finding Interactions` sub-heading is retired severity is the top-level grouping.
364
+ - When an interaction finding subsumes a local finding at the root-cause level, keep the local finding only if its evidence is independently actionable; annotate the local finding's title line `[subsumed-by I<n>]`.
365
+ - Distinct structural defects MUST remain distinct findings even when related. Specifically: a *stranded state* (entity reaches X, no exit path) and a *false-promise predicate* (TRUE branch promises unreachable behavior) are separate defects even when they arise in the same subsystem — do NOT collapse them. Collapse only when the narrative, fix, and evidence locations are identical.
366
+ - **Cascade detection** (load-bearing): before emitting severities, scan findings for these triples and emit a 🔴 Cross-Finding bullet if any fires —
367
+ • *{entity reaches state X} + {no event on that transition} + {consumer filter excludes X}* = **silent stranded state**
368
+ • *{check-then-act on shared resource} + {no ordering primitive} + {retry/replay path}* = **duplicate-processing cascade**
369
+ • *{spec A accepts Y} + {spec B rejects Y} + {workflow depends on both}* = **contradictory-predicate deadlock**
370
+ Also check `thoughts/shared/reviews/*.md` and Precedents: if a prior review names a cascade whose constituents appear in current findings, cite it and assert reproduction. Missed cascades are the biggest historical quality regression; prefer false positives here.
255
371
 
256
- ## Step 6: Developer Checkpoint
372
+ ## Step 6: Verify Findings
257
373
 
258
- Use the grounded-questions-one-at-a-time pattern. Every question must reference real findings with `file:line` evidence and pull a DECISION from the developer.
374
+ Before writing the artifact, spawn ONE `codebase-analyzer` whose sole job is to ground every reconciled finding in the actual code at its cited `file:line`. This catches two classes of error the lenses cannot self-detect: (a) *confident assertions* the agent never opened a file to confirm, and (b) *rationalisations* ("intentional-by-design", "pre-existing", "not a real deadlock") that contradict what the code does. Lens agents reason from the patch; the verifier reasons from the file.
259
375
 
260
- **Present a compiled scan first** (under 20 lines):
376
+ **Dispatch** after Step 5's reconciled severity map is final, before Step 7 writes anything:
261
377
 
262
- ```
263
- Review: [scope]
264
- Files: [N]
265
- Quality: [C🔴/I🟡/S🔵/D💭]
266
- Security: [C/I/S/D]
267
- Dependencies: [C/I/S/D | not-applicable]
268
- Precedents: [N composite lessons, top: "[one-line]"]
269
- Advisor: [adjudicated | inline]
270
- ```
378
+ ```
379
+ Verify each finding below against the actual repository state. You have Read access to the whole tree.
380
+
381
+ Findings (verbatim from Step 5):
382
+ [paste the full reconciled severity map — each finding with its file:line citation, verbatim line quote per the citation contract, and severity tier]
383
+
384
+ For EACH finding:
385
+ 1. Open the cited file at the cited line using Read. Confirm the verbatim quote appears at that line.
386
+ 2. If the finding makes a claim about behavior reachable elsewhere (consumer filters, dispatch registrations, peer aggregates, upstream guards, downstream sinks), Read those referenced files too. Do NOT trust the patch-only view.
387
+ 3. If the finding claims a state is "stranded" / a predicate is "false-promise" / a precondition is "missing" — construct a concrete 2–3 line reproducer trace: "caller at A:L invokes B:L with entity in state X; guard at C:L rejects; exit path would require D which the code does not provide." If you cannot construct it, the finding is Weakened.
388
+ 4. If the finding was marked `resolved-by: <hash>` in Step 5, Read the resolving commit's changes on the reviewed branch (via `git show <hash> -- <file>`) and confirm the resolution is actually present at TIP.
389
+
390
+ Return ONE tag per finding — output format:
391
+
392
+ FINDING <id> | <tag> | <one-sentence justification citing a file:line>
271
393
 
272
- Wait for the developer's response. Then ask **one question at a time**, waiting for each answer.
394
+ Tags:
395
+ - Verified — quote matches, claim is reproducible against the actual code, no contradiction found
396
+ - Weakened — claim is partially true but narrower than stated (severity should drop one tier), OR it relies on a consumer-side assumption that the actual consumer does not make
397
+ - Falsified — quote does not match, OR the claimed behavior is contradicted by code the lens did not read (peer site, upstream guard, existing handler, resolution already applied)
273
398
 
274
- **Question patterns:**
399
+ Be explicit about contradictions. If finding A says "intentional by design" and finding B says "stranded state" about the same entity, mark the one whose claim the code does NOT support as Falsified and cite the contradicting line.
275
400
 
276
- - **Severity dispute**: Only ask when the advisor re-ranked a finding or when inline reconciliation surfaced a contradiction. Use `ask_user_question` — Options: "Keep [original severity] (Recommended)" / "Downgrade" / "Escalate" — with `file:line` evidence in the description.
277
- - **Scope ambiguity**: "❓ Question: finding at `file:line` lies in a test helper — does the team count test-only issues? Include in artifact or not?"
278
- - **False-positive confirmation**: Only ask when a security/dep finding hinges on context the orchestrator cannot see (e.g., `exec()` with a variable that the developer might know is constant).
401
+ Citation contract applies to every justification. No recommendations. No new findings.
402
+ ```
403
+
404
+ **Apply the tags**:
405
+ - **Falsified** findings — remove from the artifact entirely. Their ID is retired (never reused); the retirement is counted in the frontmatter `verification` string (`F` dropped) and nowhere else.
406
+ - **Weakened** findings — demote one severity tier (🔴→🟡, 🟡→🔵, 🔵→💭). Rewrite the finding's evidence line to reflect the narrower claim.
407
+ - **Verified** findings — carry through unchanged to Step 7.
408
+ - **Edge case**: if a 🔴 Cross-Finding Interaction bullet relies on constituents that are now Falsified or Weakened, re-evaluate the interaction. Drop the interaction if it no longer stands on ≥2 Verified constituents from different files.
409
+
410
+ **Gate**: if verification removes / demotes ALL 🔴 findings AND there are no remaining 🟡 findings, set `status: approved` in the artifact frontmatter. Otherwise `status: needs_changes` (or `requesting_changes` for verified 🔴 > 3).
279
411
 
280
- **Critical rules:**
281
- - Ask ONE question at a time. Wait before asking the next.
282
- - Lead with the most load-bearing finding.
283
- - Skip the checkpoint entirely if no disputes surfaced and the developer set `status: approved` in the scan response.
412
+ **Do not skip this step** — it is the only mechanism that stops confident-but-unread lens assertions from reaching the artifact.
284
413
 
285
414
  ## Step 7: Write the Review Document
286
415
 
@@ -290,158 +419,78 @@ Wait for the developer's response. Then ask **one question at a time**, waiting
290
419
  - Branch + commit: from git-context injected at session start, or `git branch --show-current` / `git rev-parse --short HEAD` (fallback: `no-branch` / `no-commit`).
291
420
  - Reviewer: user from injected git-context (fallback: `unknown`).
292
421
 
293
- 2. **Write the artifact** using the Write tool (no Edit — this skill writes once per run):
422
+ 2. **Write the artifact** using the Write tool (no Edit — this skill writes once per run).
294
423
 
295
- ```markdown
296
- ---
297
- date: [ISO 8601 with timezone]
298
- reviewer: [User]
299
- repository: [Repo name]
300
- branch: [Branch]
301
- commit: [Short hash]
302
- review_type: [commit|pr|staged|working]
303
- scope: "[What was reviewed]"
304
- critical_issues: [Count across all lenses]
305
- important_issues: [Count]
306
- suggestions: [Count]
307
- status: [approved|needs_changes|requesting_changes]
308
- tags: [code-review, relevant-components]
309
- last_updated: [YYYY-MM-DD]
310
- last_updated_by: [User]
311
- ---
424
+ **Finding IDs**: lens-prefix + ordinal, stable across severity moves. `I` = interaction, `Q` = quality, `S` = security, `G` = gap. Ordinals never renumber — if a finding is dropped by Step 6, its ID is retired, not reused.
312
425
 
313
- # Code Review: [Scope Description]
314
-
315
- **Date**: [full ISO date]
316
- **Reviewer**: [User]
317
- **Repository**: [Repo]
318
- **Branch**: [Branch]
319
- **Commit**: [Short hash]
320
-
321
- ## Review Summary
322
- [3–5 sentences: overall verdict, highest-severity finding per lens, advisor outcome.]
323
-
324
- ## Issues Found
325
-
326
- ### Cross-Finding Interactions
327
- (Omit this H3 block entirely when the interaction sweep was skipped per the Step 4 gate, OR when the sweep returned no findings. Only 🔴/🟡 tiers — no 💭.)
328
- #### 🔴 Critical
329
- - `file:line` + `file:line` (≥ 2 distinct locations) — [emergent defect narrative: which local facts combine, and how the failure path is reached]
330
- #### 🟡 Important
331
- - `file:line` + `file:line` — [multi-component mismatch + blast radius or existing mitigation]
332
-
333
- ### Quality
334
- #### 🔴 Critical
335
- - `file:line` — [evidence + one-sentence fix pointer]
336
- #### 🟡 Important
337
- - `file:line` — [evidence + fix pointer]
338
- #### 🔵 Suggestions
339
- - `file:line` — [nearby template reference + suggested alignment]
340
- #### 💭 Discussion
341
- - `file:line` — [open question or trade-off]
342
-
343
- ### Security
344
- #### 🔴 Critical
345
- - `file:line` — [sink quoted + exploitability rationale referencing auth-boundary from Discovery Map]
346
- #### 🟡 Important
347
- - `file:line` — [missing hardening + secure precedent]
348
- #### 🔵 Suggestions
349
- - `file:line` — [pattern divergence from secure example]
350
- #### 💭 Discussion
351
- - `file:line` — [architectural question]
352
-
353
- ### Dependencies
354
- (Omit this H3 block entirely when the Dependencies lens was skipped — i.e., `ManifestChanged` was false.)
355
- #### 🔴 Critical
356
- - `dep@ver` (`package.json:line`) — [CVE id + link + affected-range + fix version]
357
- #### 🟡 Important
358
- - `dep@ver` — [moderate CVE / license / lockstep note with link]
359
- #### 🔵 Suggestions
360
- - `dep@ver` — [minor/transitive drift]
361
- #### 💭 Discussion
362
- - `dep@ver` — [architectural dep question]
363
-
364
- ## Precedents & Lessons
365
- - `commit hash` — [precedent + one-sentence takeaway]
366
- - Composite lessons (most-recurring first):
367
- 1. [lesson 1]
368
- 2. [lesson 2]
369
-
370
- ## Pattern Analysis
371
- [How changes align with or diverge from existing patterns in the changed files. Cite `file:line` of the nearest established pattern.]
372
-
373
- ## Impact Assessment
374
- [Files and inbound refs affected per the Discovery Map. Enumerate each affected consumer with `file:line` and what changes for it.]
375
-
376
- ## Historical Context
377
- [Links to thoughts/ docs referenced by precedent-locator; one line each, no summaries.]
378
-
379
- ## Advisor Adjudication
380
- (Omit this H2 entirely when the advisor did not run — its presence IS the signal that adjudication occurred.)
381
- [Advisor model prose pasted VERBATIM. Do not edit or paraphrase.]
382
-
383
- ## Reconciliation Notes
384
- (Include only when the inline path ran, OR when developer dispute in Step 5 moved a severity.)
385
- [Short prose: which findings shifted severity and why.]
386
-
387
- ## Recommendation
388
- [Clear verdict: Approved / Needs Changes / Requesting Changes. Cite the top 1–3 items that drove the verdict with `file:line`.]
389
- ```
426
+ **Title-line annotations** (appear in square brackets on the finding's title line, point-of-demand for reconciliation facts):
427
+ - `[precedent-weighted]` — severity bumped by Step 5's precedent follow-up weighting.
428
+ - `[cascade: <kind>]` — severity set by Step 5's cascade-detection triple (`stranded-state`, `duplicate-processing`, `contradictory-predicate-deadlock`).
429
+ - `[subsumed-by <ID>]` — root-cause subsumed by another finding but kept because its specific evidence is independently actionable.
430
+
431
+ **Section-omission rules**: omit entirely (no empty placeholders) when —
432
+ - `## 💭 Discussion` — no 💭 findings.
433
+ - `## Pattern Analysis` — no peer-mirror pair existed for this diff.
434
+ - `## Impact` — integration-scanner returned no inbound refs to changed files.
435
+ - `## Precedents` precedent-locator returned no precedents.
436
+
437
+ **What is NOT emitted to the artifact**: verification outcomes in prose (frontmatter `verification` string is the only channel), advisor availability / dispatch path / tool failures (skill trace, not review content), `last_updated` / `last_updated_by` (git mtime + git author carry this for a write-once artifact).
438
+
439
+ **Advisor prose**, when advisor ran, is pasted verbatim as a blockquote at the top of `## Recommendation`, not as a standalone section.
440
+
441
+ **Template shape**: Read the full template at `templates/review.md` (house pattern per `.rpiv/guidance/skills/architecture.md:66` — `templates/` subfolder, runtime-read, never inlined). At emission time: Read `templates/review.md`, fill every `[placeholder]` with reconciled-and-verified values from Steps 5 and 6, apply the section-omission rules above (delete the whole section AND its trailing separator line when its input is empty), strip the leading `<!-- -->` comment, and Write the result to the target path.
390
442
 
391
- ## Step 8: Present and Chain
443
+ ## Step 8: Present Summary
392
444
 
393
445
  ```
394
446
  Review written to:
395
447
  `thoughts/shared/reviews/[filename].md`
396
448
 
397
- [C] critical, [I] important, [S] suggestions across [Q] quality, [Se] security, [D] dependency issues.
398
- Advisor: [adjudicated | inline]
399
- Status: [verdict]
449
+ Severity: [C] critical · [I] important · [S] suggestions
450
+ Lenses: [Q] quality · [Se] security · [D] dependencies
451
+ Verification: [V] verified · [W] weakened · [F] falsified (dropped)
452
+ Advisor: [adjudicated | inline]
453
+ Status: [approved | needs_changes | requesting_changes]
400
454
 
401
455
  Top items:
402
- 1. `file:line` — [headline]
403
- 2. `file:line` — [headline]
404
- 3. `file:line` — [headline]
456
+ 1. [ID] — `file:line` — [headline]
457
+ 2. [ID] — `file:line` — [headline]
458
+ 3. [ID] — `file:line` — [headline]
405
459
 
406
- Ask follow-ups, or run `/skill:revise` to address the findings.
460
+ Ask follow-ups.
407
461
  ```
408
462
 
409
463
  ## Step 9: Handle Follow-ups
410
464
 
411
- - If the user asks for deeper analysis of a specific finding, spawn a targeted `codebase-analyzer` on that area (1 agent max) and append a `## Follow-up [timestamp]` section using the Edit tool.
412
- - Update frontmatter: `last_updated`, `last_updated_by`, and `last_updated_note: "Appended follow-up on [area]"`.
413
- - Never rewrite prior findings; only append.
465
+ - If the user asks for deeper analysis of a specific finding, spawn a targeted `codebase-analyzer` on that area (1 agent max) and append a `## Follow-up [ISO 8601 timestamp]` section using the Edit tool. The section heading's timestamp is the append-time record — no frontmatter update needed.
466
+ - Never rewrite prior findings; only append. Retired IDs (Falsified in Step 6) stay retired; follow-ups introduce new IDs with the same lens-prefix scheme (next ordinal).
414
467
 
415
468
  ## Important Notes
416
469
 
417
- - **No tool-permission widening**: `allowed-tools` is intentionally omitted — the skill inherits `Agent`, `ask_user_question`, `advisor`, `Write`, `web_search`, `todo` per `.rpiv/guidance/skills/architecture.md:40`. Do NOT re-add the line.
418
- - **Always use parallel Agent tool calls** in Phase-2 to maximise efficiency.
419
- - **Always read the full diff FIRST** (Step 1) before spawning any Phase-1 or Phase-2 agent.
420
- - **Always pass the Discovery Map inline** as `Known Context` to every Phase-2 agent agents are `isolated: true` and cannot see sibling transcripts.
421
- - **Security-lens precision stance**: prefer false negatives over false positives. Security evidence must carry `confidence ≥ 8` and 🔴 requires an explicit source→sink trace. Missing hardening without a traced sink is NOT a finding. Keep the Security-lens exclusion list in sync with the reference FP-filter precedents.
422
- - **Critical ordering**: Follow the numbered steps exactly.
423
- - ALWAYS resolve scope and bail on empty diff (Step 1) before Phase-1.
424
- - ALWAYS wait for Phase-1 completion before Phase-2 dispatch.
425
- - ALWAYS wait for ALL Phase-2 agents to complete before the interaction sweep (Step 4).
426
- - ALWAYS run the Cross-Finding Interaction Sweep (Step 4) after ALL Phase-2 agents complete and BEFORE severity classification in Step 5, UNLESS the Step 4 gate skipped it.
427
- - NEVER emit an interaction finding unless it cites at least two concrete `file:line` facts from different files/components.
428
- - ALWAYS wait for the interaction sweep (when it ran) to complete before reconciliation (Step 5).
429
- - ALWAYS probe advisor availability before calling `advisor()` (strip-when-unconfigured at `packages/rpiv-advisor/advisor.ts:463-472`).
430
- - ALWAYS emit the `## Pre-Adjudication Findings` block to the main branch BEFORE calling `advisor()` the advisor reads `getBranch()` (main-thread-only at `packages/rpiv-advisor/advisor.ts:336`) and will not see evidence you did not flush.
431
- - ALWAYS preserve the severity taxonomy emoji + naming (🔴 Critical / 🟡 Important / 🔵 Suggestions / 💭 Discussion) and the existing frontmatter keys verbatim — discovery agents `thoughts-locator` and `thoughts-analyzer` grep these.
432
- - NEVER call `advisor()` from inside a sub-agent — its branch is invisible to the advisor.
433
- - NEVER parse advisor prose mechanically — paste verbatim into `## Advisor Adjudication`.
434
- - NEVER add a new bundled agent to support this skill zero-new-agents contract per `packages/rpiv-pi/extensions/rpiv-core/agents.ts:148-268` sync cost.
435
- - **Severity classification**:
436
- - Evidence from agents justifies each issue's severity.
437
- - Every finding carries a `file:line`.
438
- - Correct-pattern examples cited where available.
439
- - Fixes are concrete (pointer, not vague).
440
- - **Agent roles (for this skill)**:
441
- - `integration-scanner` (Phase-1): inbound refs, outbound deps, auth-boundary crossings.
442
- - `codebase-analyzer` × 3 (Phase-2): one per lens evidence-only, no recommendations (honors the guardrail at `packages/rpiv-pi/agents/codebase-analyzer.md:113-119`).
443
- - `codebase-analyzer` × 1 (Step 4, gated): cross-finding interaction sweep emergent defects only, evidence-backed across multiple locations, no recommendations.
444
- - `precedent-locator` (Phase-2, always): git history + thoughts/ for lessons.
445
- - `web-search-researcher` (Phase-2, conditional on `ManifestChanged`): CVE / GitHub Advisory / OSS Index lookups with LINKS.
446
- - **File reading**: read the diff FULLY (no limit/offset) via `git` commands before spawning agents. Let agents read their scoped targets; the orchestrator does not need to read source files for non-risk findings.
447
- - CC auto-loads CLAUDE.md files when agents read files in a directory — no need to scan for them explicitly.
470
+ - **Frontmatter**: `allowed-tools` is intentionally omitted — the skill inherits `Agent`, `ask_user_question`, `advisor`, `Write`, `web_search`, `todo` per `.rpiv/guidance/skills/architecture.md:40`. Do NOT re-add the line.
471
+ - **Security-lens precision stance**: prefer false negatives. Evidence must carry `confidence ≥ 8`; 🔴 requires an explicit source→sink trace. Missing hardening without a traced sink is NOT a finding.
472
+ - **Load-bearing ordering**:
473
+ - Wave-1 fans out at T=0 — integration-scanner, Precedents, (when `ManifestChanged`) Dependencies + CVE, and (when `len(PeerPairs) > 0`) the peer-mirror agent dispatch in a single multi-Agent message. integration-scanner AND peer-mirror gate Wave-2 (both feed the Discovery Map Wave-2 consumes); **Precedents is a hard gate on Step 5** (its follow-up-within-30-days counts drive severity weighting; reconciling without them produces mis-weighted severities the verification pass cannot correct); Dependencies + CVE soft-gate Step 5.
474
+ - Step 4a (Predicate-Trace), 4b (Interaction Sweep), 4c (Gap-Finder) dispatch in parallel once Wave-2 completes. Interaction Sweep (4b) receives Quality's `Predicate-set coherence` table as its predicate-row source, not 4a's output.
475
+ - When Quality's `Predicate-set coherence` surface returns ≥2 rows with mismatched values on the same enum/type, the 4b sweep MUST evaluate categories 7–9 against those rows.
476
+ - **File orientation is load-bearing**: patches MUST use `-U30` (or `-U10` fallback for >1MB patches), never `-U0`. The Discovery Map's semantic file map (clusters + role tags + symbols-touched hint) is the orientation primitive, not per-hunk line ranges. Lens prompts organise findings per file (`### file/path.ext`), not per hunk. Agents SHOULD NOT issue extra `Read` calls for files already represented in the patch unless specifically needed for a cross-file trace.
477
+ - **Wave-2 context isolation**: Quality and Security prompts MUST NOT include Wave-1 background-agent output (precedent-locator, Dependencies, CVE) even when those agents have finished before Wave-2 dispatches. Summary context from those agents causes the lens agents to narrativise instead of independently analyse the diff — the observed failure mode is a ~5× speedup coupled with hallucinated findings and mis-cited line numbers. Pass only Discovery Map + patch file path.
478
+ - ALWAYS emit `## Pre-Adjudication Findings` to the main branch BEFORE calling `advisor()` — advisor reads `getBranch()` (main-thread-only, `packages/rpiv-advisor/advisor.ts:336`).
479
+ - ALWAYS probe advisor availability before calling it (strip-when-unconfigured at `packages/rpiv-advisor/advisor.ts:463-472`).
480
+ - NEVER call `advisor()` from a sub-agent (branch invisible to advisor).
481
+ - NEVER parse advisor prose paste verbatim as a blockquote at the top of `## Recommendation`.
482
+ - ALWAYS wait for 4a / 4b / 4c AND the Precedents agent to complete before Step 5 — Wave-3's hard barrier. Dependencies + CVE wait here too when running, but are not individually hard-gated.
483
+ - ALWAYS run Step 6 (verification pass) between reconciliation and artifact write. It is the only mechanism that catches lens agents asserting claims they never opened a file to confirm, and the only mechanism that validates `resolved-by` annotations against the actual branch via `git merge-base --is-ancestor`. Skipping Step 6 silently re-admits the failure mode this skill was designed to prevent.
484
+ - PRESERVE severity emoji/naming and frontmatter keys verbatim — `thoughts-locator` / `thoughts-analyzer` grep these.
485
+ - NEVER add a new bundled agent — zero-new-agents contract (`packages/rpiv-pi/extensions/rpiv-core/agents.ts:148-268`).
486
+ - **Agent roles**:
487
+ - `integration-scanner` (Wave-1)inbound/outbound refs, auth-boundary crossings.
488
+ - `precedent-locator` (Wave-1) — git history + thoughts/.
489
+ - `codebase-analyzer` ×1 (Wave-1, `ManifestChanged`) dependencies parse.
490
+ - `web-search-researcher` (Wave-1, `ManifestChanged`) CVE/advisory lookups with LINKS.
491
+ - `codebase-analyzer` ×1 (Wave-1, gated on `len(PeerPairs) > 0`) — peer-mirror check; tabulates peer's public surface against the newly-added file, tags each row Mirrored/Missing/Diverged/Intentionally-absent.
492
+ - `codebase-analyzer` ×2 (Wave-2) — Quality, Security.
493
+ - `codebase-analyzer` ×1 (Step 4a, gated) — predicate-trace.
494
+ - `codebase-analyzer` ×1 (Step 4b, gated) interaction sweep.
495
+ - `codebase-analyzer` ×1 (Step 4c, gated)gap-finder (coverage verification).
496
+ - `codebase-analyzer` ×1 (Step 6, always) — verification pass (grounds every reconciled finding at its cited file:line; tags Verified / Weakened / Falsified; Falsified dropped, Weakened demoted one tier).
@@ -0,0 +1,102 @@
1
+ <!-- Emitted by code-review SKILL.md Step 7. Placeholders in [brackets] are filled at emission; section-omission rules live inline in SKILL.md. -->
2
+ ---
3
+ template_version: 1
4
+ date: [ISO 8601 w/ tz]
5
+ reviewer: [User]
6
+ repository: [Repo]
7
+ branch: [Branch]
8
+ commit: [Short hash]
9
+ review_type: [commit | pr | staged | working]
10
+ scope: "[What was reviewed]"
11
+ status: [approved | needs_changes | requesting_changes]
12
+ counts: "[C]🔴 · [I]🟡 · [S]🔵"
13
+ verification: "[V] verified · [W] weakened · [F] dropped"
14
+ tags: [code-review, relevant-components]
15
+ ---
16
+
17
+ # Code Review — [Scope] ([commit])
18
+
19
+ Status: **[status]** · [C]🔴 · [I]🟡 · [S]🔵 · verification: [V]✓ [W]− [F]✗
20
+
21
+ Top blockers:
22
+ 1. [ID] — [one-line headline]
23
+ 2. [ID] — [one-line headline]
24
+
25
+ ───────────────────────────────────────────────────────────────────
26
+
27
+ ## Legend
28
+ 🔴 fix before merge · 🟡 fix soon · 🔵 nice to have · 💭 discuss
29
+ IDs: I=interaction Q=quality S=security G=gap
30
+ verification: ✓ verified − weakened (demoted) ✗ falsified (dropped)
31
+ annotations: [precedent-weighted] [cascade: <kind>] [subsumed-by <ID>]
32
+
33
+ ───────────────────────────────────────────────────────────────────
34
+
35
+ ## 🔴 Critical
36
+
37
+ 🔴 [ID] [annotation?] [short headline]
38
+ - where file:line
39
+ - code `<verbatim line from the file>`
40
+ - why [1–2 lines: mechanism, not symptom]
41
+ - fix [one sentence, imperative]
42
+ - alt [optional: alternative fix]
43
+
44
+ (one block per 🔴 finding; interaction findings may add a `peer` or `cites` line listing the ≥2 file:line facts)
45
+
46
+ ───────────────────────────────────────────────────────────────────
47
+
48
+ ## 🟡 Important
49
+
50
+ 🟡 [ID] [annotation?] [short headline]
51
+ - where file:line
52
+ - code `<verbatim line>`
53
+ - why [mechanism]
54
+ - fix [action]
55
+
56
+ ───────────────────────────────────────────────────────────────────
57
+
58
+ ## 🔵 Suggestions
59
+
60
+ 🔵 [ID] [short headline]
61
+ - where file:line
62
+ - fix [action]
63
+
64
+ ───────────────────────────────────────────────────────────────────
65
+
66
+ ## 💭 Discussion
67
+
68
+ 💭 [ID] [question / architectural concern]
69
+ - where file:line
70
+ - why [what the reviewer wants the author to consider]
71
+
72
+ ───────────────────────────────────────────────────────────────────
73
+
74
+ ## Pattern Analysis
75
+ Peer: `<peer file>` · Mirrored [M] · Missing [Mi] · Diverged [D] · Intentionally-absent [A]
76
+ Missing/Diverged rows drive: [finding IDs]
77
+
78
+ ───────────────────────────────────────────────────────────────────
79
+
80
+ ## Impact
81
+
82
+ consumer change findings
83
+ ──────────────────────────────── ────────────── ────────
84
+ [file:line] [change class] [IDs]
85
+
86
+ ───────────────────────────────────────────────────────────────────
87
+
88
+ ## Precedents
89
+ [hash] "[commit subject]" [30d follow-ups | NOT ancestor of [TIP] | note]
90
+
91
+ Recurring lessons (most → least):
92
+ 1. [composite lesson]
93
+ 2. ...
94
+
95
+ ───────────────────────────────────────────────────────────────────
96
+
97
+ ## Recommendation
98
+ > (advisor prose pasted verbatim here when advisor ran; omit the blockquote otherwise)
99
+
100
+ 1. [ID] [action, one sentence] | Alt: [alternative]
101
+ 2. [ID] [action]
102
+ 3. [ID] [action]
@@ -2,7 +2,6 @@
2
2
  name: revise
3
3
  description: Update existing implementation plans based on feedback. Makes surgical edits while preserving structure and quality. Use when plans need adjustments after review or during implementation.
4
4
  argument-hint: "[plan-path] [feedback]"
5
- allowed-tools: Edit, Read, Bash(git *), Glob, Grep, Agent
6
5
  ---
7
6
 
8
7
  # Iterate Implementation Plan
@@ -15,16 +14,30 @@ When this command is invoked:
15
14
 
16
15
  1. **Parse the input to identify**:
17
16
  - Plan file path (e.g., `thoughts/shared/plans/2025-10-16_09-00-00_feature.md`)
17
+ - Whether the user accidentally provided a review artifact path instead (e.g., `thoughts/shared/reviews/2025-10-16_10-00-00_feature.md`)
18
18
  - Requested changes/feedback
19
19
 
20
20
  2. **Handle different input scenarios**:
21
21
 
22
+ **If a REVIEW artifact path is provided**:
23
+ ```
24
+ `revise` updates implementation plans, not review artifacts.
25
+
26
+ If you want to act on code-review findings, provide the target plan path plus the changes to make.
27
+
28
+ Example:
29
+ `/skill:revise thoughts/shared/plans/2025-10-16_09-00-00_feature.md "Address the findings from thoughts/shared/reviews/2025-10-16_10-00-00_feature.md by tightening validation in Phase 2 and expanding success criteria."`
30
+ ```
31
+ Wait for user input.
32
+
22
33
  **If NO plan file provided**:
23
34
  ```
24
35
  I'll help you iterate on an existing implementation plan.
25
36
 
26
37
  Which plan would you like to update? Please provide the path to the plan file (e.g., `thoughts/shared/plans/2025-10-16_09-00-00_feature.md`).
27
38
 
39
+ If you're coming from `/skill:code-review`, pass the relevant plan path and summarize which findings should change the plan.
40
+
28
41
  Tip: You can list recent plans with `ls -lt thoughts/shared/plans/ | head`
29
42
  ```
30
43
  Wait for user input, then re-check for feedback.
@@ -240,3 +253,11 @@ Assistant: I've found the plan. What changes would you like to make?
240
253
  User: Add more specific success criteria
241
254
  Assistant: [Proceeds with update]
242
255
  ```
256
+
257
+ **Scenario 4: User passes a review artifact instead of a plan**
258
+ ```
259
+ User: /skill:revise thoughts/shared/reviews/2025-10-16_10-00-00_feature.md
260
+ Assistant: `revise` updates implementation plans, not review artifacts. Please provide the target plan path plus the changes to make.
261
+ User: /skill:revise thoughts/shared/plans/2025-10-16_09-00-00_feature.md "Address the review findings by splitting Phase 2 and adding validation coverage"
262
+ Assistant: [Proceeds with update]
263
+ ```