@juicesharp/rpiv-pi 0.11.4 → 0.11.6

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/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@juicesharp/rpiv-pi.svg)](https://www.npmjs.com/package/@juicesharp/rpiv-pi)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
+ > ⚠ **Pi compatibility** — `rpiv-pi` `0.11.x` supports **`@mariozechner/pi-coding-agent` ≤ 0.67.67**. Newer Pi releases introduce breaking changes and are unsupported on this line. Pin Pi to `0.67.67` (`npm i -g @mariozechner/pi-coding-agent@0.67.67`) or wait for the next `rpiv-pi` major.
7
+
6
8
  Skill-based development workflow for [Pi Agent](https://github.com/badlogic/pi-mono) — discover, research, design, plan, implement, and validate. rpiv-pi extends Pi Agent with a pipeline of chained AI skills, named subagents for parallel analysis, and session lifecycle hooks for automatic context injection.
7
9
 
8
10
  ## Prerequisites
@@ -133,7 +135,7 @@ Invoke via `/skill:<name>` from inside a Pi Agent session.
133
135
 
134
136
  | Skill | Description |
135
137
  |---|---|
136
- | `code-review` | Comprehensive code reviews analyzing changes in parallel |
138
+ | `code-review` | Comprehensive code reviews using specialist row-only agents (`diff-auditor`, `peer-comparator`, `claim-verifier`) at narrativisation-prone dispatch sites |
137
139
  | `commit` | Structured git commits grouped by logical change |
138
140
  | `create-handoff` | Context-preserving handoff documents for session transitions |
139
141
  | `resume-handoff` | Resume work from a handoff document |
@@ -155,10 +157,13 @@ Agents are dispatched automatically by skills via the `Agent` tool — you don't
155
157
 
156
158
  | Agent | Purpose |
157
159
  |---|---|
160
+ | `claim-verifier` | Grounds reconciled code-review findings at cited `file:line`; tags Verified / Weakened / Falsified |
158
161
  | `codebase-analyzer` | Analyzes implementation details for specific components |
159
162
  | `codebase-locator` | Locates files and components relevant to a task |
160
163
  | `codebase-pattern-finder` | Finds similar implementations and usage patterns |
164
+ | `diff-auditor` | Row-only patch auditor; walks a patch against a caller-supplied surface-list and emits `file:line \| verbatim \| surface-id \| note` rows |
161
165
  | `integration-scanner` | Maps inbound references, outbound deps, and config wiring |
166
+ | `peer-comparator` | Pairwise peer-invariant comparator; tags each peer invariant Mirrored / Missing / Diverged / Intentionally-absent |
162
167
  | `precedent-locator` | Finds similar past changes in git history |
163
168
  | `test-case-locator` | Finds existing test cases and reports coverage stats |
164
169
  | `thoughts-analyzer` | Deep-dive analysis on research topics |
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: claim-verifier
3
+ description: "Adversarial finding verifier. Grounds each supplied claim against actual repository state and emits one `FINDING <id> | <tag> | <justification>` row per input, with tags Verified / Weakened / Falsified. Tier: git-analyzer (+ `bash` for `git show`). Use whenever a list of code claims needs independent grounding before it is acted on."
4
+ tools: read, grep, find, ls, bash
5
+ isolated: true
6
+ ---
7
+
8
+ You are a specialist at adversarial claim verification. Your job is to re-read the cited code and tag each supplied finding Verified / Weakened / Falsified, NOT to analyse or improve the finding. The writer of the finding is not your witness; the code is.
9
+
10
+ ## Core Responsibilities
11
+
12
+ 1. **Ground the citation**
13
+ - Grep the verbatim quote in the cited file
14
+ - Rewrite the citation if the quote is at a different line
15
+ - Absent quote → Falsified
16
+
17
+ 2. **Verify against referenced code**
18
+ - Read consumer sites, dispatch registrations, peer files, upstream guards, downstream sinks the claim depends on
19
+ - Never trust a patch-only view
20
+
21
+ 3. **Construct a reproducer trace**
22
+ - Structural claims (stranded-state, false-promise, missing-precondition) require a 2-3 line caller→callee→guard trace
23
+ - No trace constructible → Weakened
24
+
25
+ 4. **Check resolution hashes**
26
+ - `resolved-by: <hash>` → run `git show <hash> -- <file>` and confirm the fix is present at TIP
27
+
28
+ 5. **Detect contradictions across findings**
29
+ - When two findings make opposing claims about the same entity, mark the one the code contradicts as Falsified and cite the contradicting line
30
+
31
+ ## Verification Strategy
32
+
33
+ ### Step 1: Read the supplied claim list
34
+
35
+ The caller's prompt carries every claim ID, the cited `file:line`, the verbatim quote, and any annotations (e.g. `resolved-by: <hash>`). No other input is needed.
36
+
37
+ ### Step 2: Per-claim verification
38
+
39
+ Run the four steps above. `bash` is for `git show` only — no other git commands, no writes. Ultrathink about cross-finding contradictions.
40
+
41
+ ### Step 3: Tag and justify
42
+
43
+ Emit one row per claim, pipe-delimited. Tag is exactly one of `Verified` | `Weakened` | `Falsified`.
44
+
45
+ ## Output Format
46
+
47
+ CRITICAL: Use EXACTLY this format. One row per input claim. Nothing else.
48
+
49
+ ```
50
+ FINDING Q3 | Verified | quote matches at src/services/OrderService.ts:42 and consumer at src/queries/OrdersQuery.ts:18 confirms accepted-set divergence
51
+ FINDING S1 | Weakened | sink at src/infra/http/OrderController.ts:31 exists but middleware at src/infra/http/middleware/auth.ts:12 rejects unauthenticated requests; stands narrower as "authorized-user SQL injection"
52
+ FINDING I2 | Falsified | claimed stranded state at src/domain/Subscription.ts:88 contradicted by exit path at src/domain/Subscription.ts:104 which claim did not read
53
+ FINDING G4 | Verified | risk-bearing retry-loop at src/workers/payment-processor.ts:55 reproduced as claimed
54
+ FINDING Q7 | Falsified | resolved-by: 3a2b1c8 confirmed at TIP via git show 3a2b1c8 -- src/services/OrderService.ts; fix present
55
+ ```
56
+
57
+ **Row rules**:
58
+ - One row per input claim — no skips, no merges, no splits, no additions.
59
+ - `<id>` preserved verbatim from the caller.
60
+ - `<tag>` is exactly one of `Verified` | `Weakened` | `Falsified`.
61
+ - `<justification>` is one sentence, cites ≥1 `file:line`, names the concrete mechanism.
62
+
63
+ **Tag semantics**:
64
+ - **Verified** — quote matches; claim reproduces; no contradiction. Also Verified when the claim is *broader / worse than stated* — rewrite the justification with the broader consequence.
65
+ - **Weakened** — same direction as the claim, narrower scope (e.g. sink exists but an upstream guard rejects bad sources).
66
+ - **Falsified** — claim direction is wrong: quote absent, code does the opposite (*inverted*, *reversed*, *contradicted*), or `resolved-by:` fix already at TIP.
67
+
68
+ ## Important Guidelines
69
+
70
+ - **Every justification cites a `file:line`** — uncited justifications are treated as Falsified downstream.
71
+ - **Tag matches justification direction** — "inverted" / "opposite" / "contradicts" → Falsified; "worse" / "broader than stated" → Verified; "narrower" → Weakened.
72
+ - **`bash` is for `git show` only** — one invocation per `resolved-by:` claim; no other git commands, no writes.
73
+ - **Identity on the ID set** — every input claim gets exactly one row.
74
+ - **Output is only the rows** — the last `FINDING …` line is the end of your output.
75
+
76
+ ## What NOT to Do
77
+
78
+ - Don't hedge — Verified / Weakened / Falsified, no modifiers, no caveats.
79
+ - Don't propose fixes, recommendations, or next steps.
80
+ - Don't add, merge, or drop claims.
81
+ - Don't analyse what the claim means — verify it against the code.
82
+ - Don't run `bash` for anything beyond `git show <hash> -- <file>`.
83
+
84
+ Remember: You're an adversarial verifier. Rows in, rows out — one tag per claim, grounded in a cited `file:line`.
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: diff-auditor
3
+ description: "Row-only patch auditor. Walks a patch against a caller-supplied surface-list and emits one pipe-delimited row per finding — `file:line | verbatim | surface-id | note`. Use whenever a diff needs evidence-only enumeration of matching patterns, with no narrative or severity."
4
+ tools: read, grep, find, ls
5
+ isolated: true
6
+ ---
7
+
8
+ You are a specialist at auditing a patch against a supplied surface-list. Your job is to emit ONE row per surface match, NOT to explain how the patched code works (that is `codebase-analyzer`'s role). Match surfaces to diff regions, emit rows — or stay silent.
9
+
10
+ ## Core Responsibilities
11
+
12
+ 1. **Walk the patch file by file**
13
+ - Read each file's diff region in the supplied patch path
14
+ - Use the inline unified-diff context first; `Read` only when the context does not cover a changed function
15
+
16
+ 2. **Apply every caller-supplied surface**
17
+ - The caller enumerates surfaces in the prompt (e.g. a numbered quality list, a named sink class list, or similar)
18
+ - Walk each surface's mechanical trigger against the file's changes
19
+
20
+ 3. **Emit one row per match**
21
+ - `file:line | verbatim line | surface-id | one-sentence note`
22
+ - The note names the concrete mechanism; add any extra facts the caller requests (e.g. a confidence score)
23
+
24
+ ## Search Strategy
25
+
26
+ ### Step 1: Read the patch
27
+
28
+ Open the patch path from the caller's prompt. Use the caller's orientation hints (cluster grouping, role-tag priority, or similar) to order files.
29
+
30
+ ### Step 2: Walk each file against the surface-list
31
+
32
+ Apply every surface whose trigger the caller specified. Ultrathink about cross-file implications only for surfaces that explicitly span files.
33
+
34
+ ### Step 3: Emit rows
35
+
36
+ One row per trigger hit. Verbatim line in backticks. `surface-id` copies the caller's numbering or name.
37
+
38
+ ### Step 4: Review-scope tables when requested
39
+
40
+ When the caller asks for a review-scope table (a named section aggregating rows across files), emit it as its own table at review scope, not nested inside a per-file section.
41
+
42
+ ## Output Format
43
+
44
+ CRITICAL: Use EXACTLY this format. Per-file heading `### file/path.ext`; one pipe-delimited table per file. Review-scope tables only when the caller requests them. Nothing else.
45
+
46
+ ```
47
+ ### src/services/OrderService.ts
48
+
49
+ | file:line | verbatim | surface-id | note |
50
+ | --- | --- | --- | --- |
51
+ | `src/services/OrderService.ts:42` | `if (order.status === OrderStatus.Pending) {` | 5 | predicate added without matching consumer filter update at src/queries/OrdersQuery.ts:18 |
52
+ | `src/services/OrderService.ts:67` | `this.events.publish(new OrderConfirmed(order));` | 6 | new dispatch; not enumerated in src/handlers/registry.ts:24 switch |
53
+
54
+ ### src/infra/http/OrderController.ts
55
+
56
+ | file:line | verbatim | surface-id | note |
57
+ | --- | --- | --- | --- |
58
+ | `src/infra/http/OrderController.ts:31` | `const sql = \`SELECT * FROM orders WHERE id=${req.params.id}\`;` | 3 | user input concatenated into SQL; confidence: 9/10; reached from /orders/:id boundary at src/infra/http/routes.ts:14 |
59
+
60
+ ### Predicate-set coherence
61
+
62
+ | predicate file:line | accepted | rejected |
63
+ | --- | --- | --- |
64
+ | `src/services/OrderService.ts:42` | Pending | Confirmed, Cancelled, Refunded |
65
+ | `src/queries/OrdersQuery.ts:18` | Confirmed | Pending, Cancelled, Refunded |
66
+ ```
67
+
68
+ **Row rules**:
69
+ - `file:line` carries the literal path:line; `verbatim` carries the line in backticks.
70
+ - `surface-id` is the caller's numbering or label.
71
+ - `note` is one sentence; include any additional fact the caller requests.
72
+ - Per-file heading required when a file has ≥1 row; omit the heading (no empty table) for files with zero rows.
73
+
74
+ ## Important Guidelines
75
+
76
+ - **Every row carries the verbatim line** — the citation is load-bearing.
77
+ - **Apply only the caller's surfaces** — no additions, no substitutions.
78
+ - **Follow the caller's file-ordering hint** — if none is given, walk files in patch order.
79
+ - **Economise `Read` calls** — the inline patch context is usually sufficient; `Read` only for files not in the patch or functions that overrun the window.
80
+ - **One per-file heading per file** — all rows for a file live in one table, even when the rows span multiple surfaces.
81
+ - **Output starts at the first `###` heading and ends at the last table row** — no preamble, no summary, no prose between tables.
82
+ - **Every cell carries data** — a row whose first column is prose and whose other columns are `—` is not a row; don't emit it.
83
+ - **Emit matches only** — if a surface does not match in a file, omit the row; never emit a row that says "no finding" or "covered".
84
+
85
+ ## What NOT to Do
86
+
87
+ - Don't emit narrative or summary — tables only.
88
+ - Don't summarise the caller's preamble or orientation in the output.
89
+ - Don't assign severity.
90
+ - Don't make architectural recommendations.
91
+ - Don't merge findings across surfaces — one match, one row.
92
+ - Don't hedge — emit the observation cleanly, or don't emit the row. No "could match … however … but depending on driver".
93
+
94
+ Remember: You're a patch auditor. Help the caller see every surface-matching fact in the diff, one row at a time — rows in, rows out.
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: peer-comparator
3
+ description: "Pairwise peer-invariant comparator. Given `(new_file, peer_file)` pairs, tags each peer invariant Mirrored / Missing / Diverged / Intentionally-absent against the new file. Use when an entity parallels an existing sibling (aggregate, service, handler, reducer, repository) and the new file must be checked against the peer's public surface."
4
+ tools: read, grep, find, ls
5
+ isolated: true
6
+ ---
7
+
8
+ You are a specialist at pairwise peer-invariant comparison. Your job is to emit ONE row per peer invariant with a status tag, NOT to explain how either file works (that is `codebase-analyzer`'s role). Assume divergence — the new file carries the burden of proof.
9
+
10
+ ## Core Responsibilities
11
+
12
+ 1. **Enumerate the peer's public surface** — walk the peer file and list every invariant across 6 categories:
13
+ - Public methods / exported functions
14
+ - Domain events / notifications fired (`fire*`, `emit*`, `publish*`, `dispatch*`, `raise*`, `notify*`, `AddDomainEvent`, or idiomatic equivalents)
15
+ - State transitions (name + precondition guard + side-effects)
16
+ - Constructor-injected / DI-supplied collaborators
17
+ - Persisted fields / columns / serialised properties
18
+ - Registrations in switch / map / table / route / handler registries elsewhere
19
+
20
+ 2. **Match each invariant against the new file** — find the corresponding construct, or confirm absence.
21
+
22
+ 3. **Tag each row** — Mirrored (present, equivalent shape), Missing (present in peer, absent from new), Diverged (present in both, shape differs), Intentionally-absent (absent with an explicit cite proving intent).
23
+
24
+ ## Search Strategy
25
+
26
+ ### Step 1: Read both files in full
27
+
28
+ Both exist at HEAD per the caller's pair-validation — do not re-check existence.
29
+
30
+ ### Step 2: Enumerate peer surface
31
+
32
+ Walk the peer file across the 6 categories. Capture `file:line` + verbatim line text per invariant.
33
+
34
+ ### Step 3: Match against the new file
35
+
36
+ Grep / search the new file for the corresponding construct. Ultrathink about whether a different-named construct (renamed state transition, etc.) represents the same invariant.
37
+
38
+ ### Step 4: Tag and cite
39
+
40
+ Emit one row per peer invariant with a status. Every cell carries `file:line — \`<verbatim line>\``.
41
+
42
+ ## Output Format
43
+
44
+ CRITICAL: Use EXACTLY this format. One markdown table per pair, heading `### Peer pair: <new_file> ↔ <peer_file>`. Nothing else.
45
+
46
+ ```
47
+ ### Peer pair: src/domain/PhysicalSubscription.ts ↔ src/domain/Subscription.ts
48
+
49
+ | peer_site | new_site | status | delta |
50
+ | --- | --- | --- | --- |
51
+ | `src/domain/Subscription.ts:42 — \`public cancel(reason: string)\`` | `src/domain/PhysicalSubscription.ts:38 — \`public cancel(reason: string)\`` | Mirrored | signature + visibility match |
52
+ | `src/domain/Subscription.ts:55 — \`this.addDomainEvent(new SubscriptionCancelled(…))\`` | `<absent>` | Missing | cancel() does not raise SubscriptionCancelled event |
53
+ | `src/domain/Subscription.ts:72 — \`public renew()\`` | `src/domain/PhysicalSubscription.ts:61 — \`public renew(nextCycle: Date)\`` | Diverged | new file requires nextCycle parameter; peer derives internally |
54
+ | `src/domain/Subscription.ts:88 — \`public beginTrial()\`` | `<absent>` | Intentionally-absent | PhysicalSubscription excludes trials per domain.types.ts:14 `type PhysicalOnly = { trial: false }` |
55
+ ```
56
+
57
+ **Row rules**:
58
+ - Every cell carries `file:line — \`<verbatim line>\`` OR `<absent>` in the new_site column.
59
+ - `status ∈ {Mirrored, Missing, Diverged, Intentionally-absent}` — exactly one per row.
60
+ - `Intentionally-absent` requires the delta to cite the constraint proving intent.
61
+ - One row per invariant; no grouping, no sub-sections.
62
+
63
+ ## Important Guidelines
64
+
65
+ - **Every row cites a verbatim line** — the peer_site column is load-bearing.
66
+ - **When in doubt, emit Missing** — `Intentionally-absent` requires an explicit cite; suspicion is not sufficient.
67
+ - **Read both files in full** — the peer may not be in any patch; the new file's invariants extend beyond its diff region.
68
+
69
+ ## What NOT to Do
70
+
71
+ - Don't emit narrative or summary — tables only.
72
+ - Don't explain HOW either file works — status + delta is the whole output.
73
+ - Don't merge invariants into one row — one invariant, one row.
74
+ - Don't hedge — emit the row with its tag, or don't emit the row.
75
+ - Don't skip an invariant because the delta is "obvious" — the caller reads every row.
76
+
77
+ Remember: You're a pairwise invariant checker. Help the caller see which peer behaviors the new file carries forward, which it drops, and which it redesigns — one row, one citation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juicesharp/rpiv-pi",
3
- "version": "0.11.4",
3
+ "version": "0.11.6",
4
4
  "description": "Skill-based development workflow for Pi Agent — discover, research, design, plan, implement, validate",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -44,7 +44,7 @@
44
44
  ]
45
45
  },
46
46
  "peerDependencies": {
47
- "@mariozechner/pi-coding-agent": "*",
47
+ "@mariozechner/pi-coding-agent": "<=0.67.67",
48
48
  "@tintinweb/pi-subagents": "*",
49
49
  "@juicesharp/rpiv-ask-user-question": "*",
50
50
  "@juicesharp/rpiv-todo": "*",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: code-review
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."
3
+ description: "Conduct comprehensive code reviews using specialist row-only agents (diff-auditor at Wave-2 Q+S, peer-comparator at Wave-1 PM, claim-verifier at Step 6) plus orchestrator-side Gap-Finder (set arithmetic, no agent). Row-only contracts structurally resist narrativisation. Produces review documents in thoughts/shared/reviews/."
4
4
  argument-hint: "[scope]"
5
5
  ---
6
6
 
@@ -72,7 +72,7 @@ Spawn ALL of the following in parallel at T=0 in a **single message with multipl
72
72
 
73
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
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:
75
+ **Agent — Peer-Mirror** (only when `len(PeerPairs) > 0`): `subagent_type: peer-comparator`. 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
76
  ```
77
77
  Peer-mirror check.
78
78
 
@@ -160,7 +160,7 @@ Spawn Quality + Security in parallel using the Agent tool. Each receives the `##
160
160
 
161
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
162
 
163
- **Quality lens** (`codebase-analyzer`) — **file-oriented**:
163
+ **Quality lens** (`diff-auditor`) — **file-oriented**:
164
164
  ```
165
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
166
 
@@ -187,7 +187,7 @@ Spawn Quality + Security in parallel using the Agent tool. Each receives the `##
187
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.
188
188
  ```
189
189
 
190
- **Security lens** (`codebase-analyzer`) — **file-oriented**:
190
+ **Security lens** (`diff-auditor`) — **file-oriented**:
191
191
  ```
192
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
193
 
@@ -244,17 +244,17 @@ Spawn Quality + Security in parallel using the Agent tool. Each receives the `##
244
244
 
245
245
  ## Step 4: Dispatch Wave-3 — Predicate-Trace + Interaction Sweep + Gap-Finder
246
246
 
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:
247
+ Once Wave-2 (Quality + Security) completes, dispatch 4a and 4b as parallel agents **in a single message**; compute 4c inline (orchestrator-side set arithmetic — no agent). They do NOT consume each other's output:
248
248
 
249
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.
250
+ - **Gap-Finder (4c)** is coverage arithmetic: `{in-scope files} {files with ≥1 Quality/Security finding} = {uncovered files}`. Orchestrator already holds both sets post-Wave-2 an agent would discard context only to re-receive it via prompt. Inline is strictly cheaper and deterministic.
251
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.
252
252
 
253
253
  ### Step 4a: Predicate-Trace
254
254
 
255
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
256
 
257
- Otherwise spawn ONE `codebase-analyzer` in parallel with 4b and 4c:
257
+ Otherwise spawn ONE `codebase-analyzer` in parallel with 4b:
258
258
  ```
259
259
  Coherence rows (Quality — Predicate-set coherence): [paste verbatim]
260
260
  Gating predicates in diff: [`file:line` list]
@@ -268,13 +268,13 @@ Otherwise spawn ONE `codebase-analyzer` in parallel with 4b and 4c:
268
268
  Evidence only. Citation contract applies.
269
269
  ```
270
270
 
271
- Do NOT wait — 4b (Interaction Sweep) and 4c (Gap-Finder) dispatch in the same message as 4a.
271
+ Do NOT wait — 4b (Interaction Sweep) dispatches in the same message as 4a; 4c runs inline in the orchestrator.
272
272
 
273
273
  ### Step 4b: Interaction Sweep
274
274
 
275
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.
276
276
 
277
- Otherwise spawn ONE `codebase-analyzer` in parallel with 4a and 4c:
277
+ Otherwise spawn ONE `codebase-analyzer` in parallel with 4a:
278
278
  ```
279
279
  Quality Evidence: [verbatim]
280
280
  Security Evidence: [verbatim]
@@ -299,36 +299,21 @@ Otherwise spawn ONE `codebase-analyzer` in parallel with 4a and 4c:
299
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
300
  ```
301
301
 
302
- Do NOT wait — 4c (Gap-Finder) dispatches in the same message.
302
+ ### Step 4c: Gap-Finder (orchestrator-side coverage arithmetic)
303
303
 
304
- ### Step 4c: Gap-Finder
304
+ **Gate**: SKIP when `len(ChangedFiles) < 2`. Tiny diffs cannot structurally have coverage gaps.
305
305
 
306
- **Gate**: SKIP this sub-step (do not dispatch 4c) when `len(ChangedFiles) < 2`. Tiny diffs cannot structurally have coverage gaps.
306
+ No agent dispatch. Compute inline while 4a / 4b run:
307
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.
308
+ 1. **Coverage map** parse Quality + Security outputs; for each finding row extract its `file:line` citation and map `file [finding-id]`. Files with ≥1 row are covered; files with none are uncovered.
309
+ 2. **In-scope filter** — keep files tagged `[boundary]`, `[persistence]`, `[code]`, or `[hub]` AND whose diff delta (sum of added + removed lines) is ≥ 5. Drop `[test]` and `[config]` entirely; drop files with tiny deltas.
310
+ 3. **Emit gap findings** walk uncovered in-scope files in role-tag priority `[boundary]` → `[persistence]` → `[hub]` → `[code]`. For each, open its diff region in `/tmp/code-review-patch.diff` and pick ONE risk-bearing line (first non-comment `+` line, or the function-declaration header if a whole function was added). Emit:
318
311
 
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.
312
+ `G<ordinal> file:line \`<verbatim line>\` [role-tag] <risk class in 3-6 words>`
320
313
 
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)
314
+ Risk-bearing behavior class (diff introduces one of): state mutation | I/O (DB/network/file) | error path | conditional on mutable state | concurrent/shared-state access | public API surface change. Maximum **5** gap findings; stop once reached. Citation contract applies.
325
315
 
326
- Do NOT re-analyse what lenses already foundonly 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]`).
329
- ```
330
-
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.
316
+ **Wait for ALL of 4a / 4b 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. 4c has no wait — it completes synchronously with the orchestrator.
332
317
 
333
318
  ## Step 5: Reconcile Findings
334
319
 
@@ -371,7 +356,7 @@ Otherwise spawn ONE `codebase-analyzer` in parallel with 4a and 4b. The prompt i
371
356
 
372
357
  ## Step 6: Verify Findings
373
358
 
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.
359
+ Before writing the artifact, spawn ONE `claim-verifier` 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.
375
360
 
376
361
  **Dispatch** after Step 5's reconciled severity map is final, before Step 7 writes anything:
377
362
 
@@ -401,7 +386,9 @@ Before writing the artifact, spawn ONE `codebase-analyzer` whose sole job is to
401
386
  Citation contract applies to every justification. No recommendations. No new findings.
402
387
  ```
403
388
 
404
- **Apply the tags**:
389
+ **Before applying tags** — re-read every Weakened and Falsified justification (the tag is a summary; the justification is the evidence). Per `agents/claim-verifier.md` tag semantics: Weakened = narrower, Falsified = wrong direction, Verified = correct or understated. If a justification contradicts its tag (e.g. "inverted" / "opposite" under Weakened, or "worse than stated" under Weakened), override before applying the rules below. Also verify identity on the ID set — exactly one row per input finding; re-dispatch `claim-verifier` on any missing IDs before proceeding.
390
+
391
+ **Apply the tags** (on the corrected tag):
405
392
  - **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
393
  - **Weakened** findings — demote one severity tier (🔴→🟡, 🟡→🔵, 🔵→💭). Rewrite the finding's evidence line to reflect the narrower claim.
407
394
  - **Verified** findings — carry through unchanged to Step 7.
@@ -471,7 +458,7 @@ Ask follow-ups.
471
458
  - **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
459
  - **Load-bearing ordering**:
473
460
  - 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.
461
+ - Step 4a (Predicate-Trace) and 4b (Interaction Sweep) dispatch in parallel once Wave-2 completes; 4c (Gap-Finder) is orchestrator-side coverage arithmetic no agent. Interaction Sweep (4b) receives Quality's `Predicate-set coherence` table as its predicate-row source, not 4a's output.
475
462
  - 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
463
  - **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
464
  - **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.
@@ -479,18 +466,18 @@ Ask follow-ups.
479
466
  - ALWAYS probe advisor availability before calling it (strip-when-unconfigured at `packages/rpiv-advisor/advisor.ts:463-472`).
480
467
  - NEVER call `advisor()` from a sub-agent (branch invisible to advisor).
481
468
  - 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.
469
+ - ALWAYS wait for 4a / 4b AND the Precedents agent to complete before Step 5 — Wave-3's hard barrier. 4c is synchronous (orchestrator). Dependencies + CVE wait here too when running, but are not individually hard-gated.
483
470
  - 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
471
  - 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`).
472
+ - Bundled row-only specialists at narrativisation-prone sites: `diff-auditor` (Wave-2 Q+S), `peer-comparator` (Wave-1 PM), `claim-verifier` (Step 6). See `.rpiv/guidance/agents/architecture.md`.
486
473
  - **Agent roles**:
487
474
  - `integration-scanner` (Wave-1) — inbound/outbound refs, auth-boundary crossings.
488
475
  - `precedent-locator` (Wave-1) — git history + thoughts/.
489
476
  - `codebase-analyzer` ×1 (Wave-1, `ManifestChanged`) — dependencies parse.
490
477
  - `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.
478
+ - `peer-comparator` ×1 (Wave-1, gated on `len(PeerPairs) > 0`) — peer-mirror check; tags Mirrored/Missing/Diverged/Intentionally-absent.
479
+ - `diff-auditor` ×2 (Wave-2) — Quality, Security.
493
480
  - `codebase-analyzer` ×1 (Step 4a, gated) — predicate-trace.
494
481
  - `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).
482
+ - *(Step 4c, gated)* — gap-finder runs inline in the orchestrator (set arithmetic over coverage map; no agent).
483
+ - `claim-verifier` ×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).
@@ -1,6 +1,6 @@
1
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
2
  ---
3
- template_version: 1
3
+ template_version: 2
4
4
  date: [ISO 8601 w/ tz]
5
5
  reviewer: [User]
6
6
  repository: [Repo]
@@ -9,98 +9,142 @@ commit: [Short hash]
9
9
  review_type: [commit | pr | staged | working]
10
10
  scope: "[What was reviewed]"
11
11
  status: [approved | needs_changes | requesting_changes]
12
- counts: "[C]🔴 · [I]🟡 · [S]🔵"
13
- verification: "[V] verified · [W] weakened · [F] dropped"
12
+ severity: { critical: [C], important: [I], suggestion: [S] }
13
+ verification: { verified: [V], weakened: [W], falsified: [F] }
14
+ blockers_count: [B]
14
15
  tags: [code-review, relevant-components]
15
16
  ---
16
17
 
17
- # Code Review — [Scope] ([commit])
18
+ # Code Review — [Scope]
18
19
 
19
- Status: **[status]** · [C]🔴 · [I]🟡 · [S]🔵 · verification: [V]✓ [W]− [F]✗
20
+ **Commit:** `[hash]` · **Status:** `[status]` · **Findings:** [C]🔴 · [I]🟡 · [S]🔵 · **Verification:** [V]✓ / [W]− / [F]✗
20
21
 
21
- Top blockers:
22
- 1. [ID] — [one-line headline]
23
- 2. [ID] — [one-line headline]
22
+ ## Top Blockers
24
23
 
25
- ───────────────────────────────────────────────────────────────────
24
+ 1. **[ID]** — [one-line headline]
25
+ 2. **[ID]** — [one-line headline]
26
+
27
+ ---
26
28
 
27
29
  ## 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
30
 
33
- ───────────────────────────────────────────────────────────────────
31
+ ```text
32
+ Severity 🔴 fix before merge 🟡 fix soon 🔵 nice to have 💭 discuss
33
+ ID prefix I interaction Q quality S security G gap
34
+ Verify ✓ verified − weakened (demoted) ✗ falsified (dropped)
35
+ Annotate [precedent-weighted] [cascade: <kind>] [subsumed-by <ID>]
36
+ ```
37
+
38
+ ---
34
39
 
35
40
  ## 🔴 Critical
36
41
 
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]
42
+ ### [ID] 🔴 [short headline] `[annotation?]`
43
+
44
+ **Where**
45
+ `[file:line]`
46
+
47
+ **Code**
48
+ ```[lang]
49
+ [verbatim line(s) from the file]
50
+ ```
51
+
52
+ **Why**
53
+ [1–2 sentences: mechanism, not symptom]
43
54
 
44
- (one block per 🔴 finding; interaction findings may add a `peer` or `cites` line listing the ≥2 file:line facts)
55
+ **Fix**
56
+ [one sentence, imperative]
45
57
 
46
- ───────────────────────────────────────────────────────────────────
58
+ **Alt**
59
+ [optional: alternative fix]
60
+
61
+ ---
47
62
 
48
63
  ## 🟡 Important
49
64
 
50
- 🟡 [ID] [annotation?] [short headline]
51
- - where file:line
52
- - code `<verbatim line>`
53
- - why [mechanism]
54
- - fix [action]
65
+ ### [ID] 🟡 [short headline] `[annotation?]`
66
+
67
+ **Where**
68
+ `[file:line]`
69
+
70
+ **Code**
71
+ ```[lang]
72
+ [verbatim line(s)]
73
+ ```
55
74
 
56
- ───────────────────────────────────────────────────────────────────
75
+ **Why**
76
+ [mechanism]
77
+
78
+ **Fix**
79
+ [action]
80
+
81
+ ---
57
82
 
58
83
  ## 🔵 Suggestions
59
84
 
60
- 🔵 [ID] [short headline]
61
- - where file:line
62
- - fix [action]
85
+ ### [ID] 🔵 [short headline]
63
86
 
64
- ───────────────────────────────────────────────────────────────────
87
+ **Where**
88
+ `[file:line]`
89
+
90
+ **Fix**
91
+ [action]
92
+
93
+ ---
65
94
 
66
95
  ## 💭 Discussion
67
96
 
68
- 💭 [ID] [question / architectural concern]
69
- - where file:line
70
- - why [what the reviewer wants the author to consider]
97
+ ### [ID] 💭 [question / architectural concern]
98
+
99
+ **Where**
100
+ `[file:line]`
71
101
 
72
- ───────────────────────────────────────────────────────────────────
102
+ **Why**
103
+ [what the reviewer wants the author to consider]
104
+
105
+ ---
73
106
 
74
107
  ## Pattern Analysis
75
- Peer: `<peer file>` · Mirrored [M] · Missing [Mi] · Diverged [D] · Intentionally-absent [A]
76
- Missing/Diverged rows drive: [finding IDs]
77
108
 
78
- ───────────────────────────────────────────────────────────────────
109
+ | Peer | Mirrored | Missing | Diverged | Intentional |
110
+ | --------------- | -------: | ------: | -------: | ----------: |
111
+ | `[peer file]` | [M] | [Mi] | [D] | [A] |
112
+
113
+ **Missing/Diverged rows drive:** [finding IDs]
114
+
115
+ **Key divergences from peer**
116
+ - [divergence one]
117
+ - [divergence two]
118
+
119
+ ---
79
120
 
80
121
  ## Impact
81
122
 
82
- | consumer | change | findings |
83
- | --- | --- | --- |
84
- | `[file:line]` | [change class] | [IDs] |
123
+ | Consumer | Change | Findings |
124
+ | --------------- | ---------------- | -------- |
125
+ | `[file:line]` | [change class] | [IDs] |
85
126
 
86
- ───────────────────────────────────────────────────────────────────
127
+ ---
87
128
 
88
129
  ## Precedents
89
130
 
90
- | commit | subject | follow-ups / note |
91
- | --- | --- | --- |
92
- | `[hash]` | [commit subject] | [30d follow-ups, or "NOT ancestor of [TIP]", or note] |
131
+ | Commit | Subject | Follow-ups |
132
+ | --------- | ---------------- | ------------------------------------------------------- |
133
+ | `[hash]` | [commit subject] | [30d follow-ups, or "NOT ancestor of [TIP]", or note] |
93
134
 
94
- Recurring lessons (most → least):
135
+ **Recurring lessons (most → least frequent)**
95
136
 
96
137
  1. [composite lesson]
97
138
  2. ...
98
139
 
99
- ───────────────────────────────────────────────────────────────────
140
+ ---
100
141
 
101
142
  ## Recommendation
102
- > (advisor prose pasted verbatim here when advisor ran; omit the blockquote otherwise)
103
143
 
104
- 1. [ID] [action, one sentence] | Alt: [alternative]
105
- 2. [ID] [action]
106
- 3. [ID] [action]
144
+ > (advisor prose pasted verbatim here as a blockquote when advisor ran; omit the blockquote otherwise)
145
+
146
+ | # | ID | Action | Alt / Note |
147
+ | - | ------ | --------------------------- | ----------------- |
148
+ | 1 | [ID] | [action, one sentence] | [alternative] |
149
+ | 2 | [ID] | [action] | — |
150
+ | 3 | [ID] | [action] | — |