@juicesharp/rpiv-pi 0.11.5 → 0.11.7

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
@@ -135,7 +135,7 @@ Invoke via `/skill:<name>` from inside a Pi Agent session.
135
135
 
136
136
  | Skill | Description |
137
137
  |---|---|
138
- | `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 |
139
139
  | `commit` | Structured git commits grouped by logical change |
140
140
  | `create-handoff` | Context-preserving handoff documents for session transitions |
141
141
  | `resume-handoff` | Resume work from a handoff document |
@@ -157,10 +157,13 @@ Agents are dispatched automatically by skills via the `Agent` tool — you don't
157
157
 
158
158
  | Agent | Purpose |
159
159
  |---|---|
160
+ | `claim-verifier` | Grounds reconciled code-review findings at cited `file:line`; tags Verified / Weakened / Falsified |
160
161
  | `codebase-analyzer` | Analyzes implementation details for specific components |
161
162
  | `codebase-locator` | Locates files and components relevant to a task |
162
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 |
163
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 |
164
167
  | `precedent-locator` | Finds similar past changes in git history |
165
168
  | `test-case-locator` | Finds existing test cases and reports coverage stats |
166
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.5",
3
+ "version": "0.11.7",
4
4
  "description": "Skill-based development workflow for Pi Agent — discover, research, design, plan, implement, validate",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -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
 
@@ -8,7 +8,7 @@ argument-hint: "[scope]"
8
8
 
9
9
  Scope: $ARGUMENTS
10
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.**
11
+ Review changes across **Quality**, **Security**, **Dependencies** lenses with optional advisor adjudication. Valid scopes: `commit` | `staged` | `working` | hash | `A..B` | PR branch. **Empty scope defaults to feature-branch-vs-default-branch first-parent review** (default branch auto-detected; see Step 1).
12
12
 
13
13
  **How it works**:
14
14
  - Step 1 — resolve scope, read diff (with `-U30` context), derive flags, build semantic file map
@@ -22,31 +22,40 @@ Review changes across **Quality**, **Security**, **Dependencies** lenses with op
22
22
 
23
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
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.
25
+ Every Wave-2 agent prompt contains EXACTLY: (a) `Known Context:` followed by the Discovery Map verbatim, and (b) the literal string `.git/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.
26
26
 
27
27
  ## Step 1: Resolve Scope and Assemble the Diff
28
28
 
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.
29
+ 1. **Detect default branch**: `DEFAULT_BRANCH=$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's@^origin/@@')`. Fallback: probe `main` then `master` (`git rev-parse --verify --quiet <name>`); if neither resolves, ask the user which branch is the integration target before proceeding. Use `$DEFAULT_BRANCH` wherever the parser below says `<default>`.
36
30
 
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.
31
+ 2. **Interpret the Scope line** (from the header) and identify `OLDEST` + `NEWEST` commits (user-inclusive endpoints). Each branch carries a **strategy tag** used later by Assembly and Step 6:
32
+ - Empty → `OLDEST=$(git merge-base "$DEFAULT_BRANCH" HEAD)`, `NEWEST=HEAD`, strategy=`first-parent` (also skips the `BASE` computation below — use `BASE=OLDEST` directly)
33
+ - `commit` → `OLDEST=NEWEST=HEAD`, strategy=`working-tree`
34
+ - `staged` / `working` → no commits; see working-tree branch below, strategy=`working-tree`
35
+ - Single hash `h` → `OLDEST=NEWEST=h`, strategy=`explicit-range`
36
+ - Range `A..B` → verify A is ancestor of B (`git merge-base --is-ancestor A B`; swap if reversed); `OLDEST=A`, `NEWEST=B`, strategy=`explicit-range`
37
+ - 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). Strategy=`first-parent` (ancestry invariant preserves named commits under first-parent traversal).
38
+ - PR branch name → `OLDEST=$(git merge-base "$DEFAULT_BRANCH" HEAD)`, `NEWEST=HEAD`, strategy=`first-parent` — note: `OLDEST` is already the parent-of-first-PR-commit, so skip the `BASE` computation below and use `BASE=OLDEST` directly.
39
+ - Anything unrecognised (prose, branch name that fails to resolve, mixed list) → ask the user to clarify via `ask_user_question`: (A) "review current branch vs `$DEFAULT_BRANCH` (first-parent)", (B) "review uncommitted changes", (C) "restate scope". Do NOT silently guess.
40
+
41
+ 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. Also set `FP_FLAG="--first-parent"` when strategy=`first-parent`, else `FP_FLAG=""`.
38
42
 
39
43
  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)
44
+ - `git log "$RANGE" $FP_FLAG --name-only --pretty=format: | sort -u` → `ChangedFiles`
45
+ - `git log "$RANGE" $FP_FLAG --stat --reverse` → per-commit size summary
46
+ - `git log "$RANGE" $FP_FLAG --patch --reverse --no-merges -U30 > .git/code-review-patch.diff` → union patches with **30 lines of surrounding context per hunk** (function-level context inline). `$FP_FLAG` is orthogonal to `--no-merges`: first-parent prunes second-parent subtrees from reachability, `--no-merges` drops the merge commit itself from the log.
43
47
  - `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.
48
+ - **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. `FP_FLAG` is not applicable.
45
49
  - **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.
46
50
 
47
51
  3. **Bail-out**: if `ChangedFiles` is empty, print `No changes in scope [scope]. Exiting.` and STOP. Do not write an artifact.
48
52
 
49
- 4. **Derive flags** (orchestrator-side, used in later steps):
53
+ 4. **Derive scope + flags** (orchestrator-side, used in later steps):
54
+ - `InScopeFiles` — used by the Step 6 pre-filter. `ChangedFiles` reflects *tree-reachability* (inflated on branches that back-merged the default branch — each post-merge first-parent commit inherits the merge's tree, so `--name-only` includes every file the merge resolved); `InScopeFiles` reflects *commits' own diffs* and is what the developer actually authored. Derivation:
55
+ - strategy=`first-parent` (empty / PR branch / commit-list inputs) → `InScopeFiles = ⋃ git diff-tree --no-commit-id --name-only -r <h>` over `git log "$RANGE" --first-parent --no-merges --pretty=%H` (each feature commit's own file delta; back-merge sidecars drop out even when the merge is on the first-parent line). For commit-list input, iterate over the user-named hashes instead of the first-parent walk to preserve non-contiguous-list intent.
56
+ - strategy=`explicit-range` → `InScopeFiles = ChangedFiles` (user explicitly asked for range semantics; merges in the range are part of the intent).
57
+ - strategy=`working-tree` → `InScopeFiles = ChangedFiles` (no merge surface).
58
+ - **Invariant**: `InScopeFiles ⊆ ChangedFiles`. On back-merged feature branches, `InScopeFiles ⊊ ChangedFiles` is the primary mechanism by which sidecar findings get dropped at Step 6.
50
59
  - `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.
51
60
  - `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
61
  - `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`.
@@ -72,7 +81,7 @@ Spawn ALL of the following in parallel at T=0 in a **single message with multipl
72
81
 
73
82
  **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
83
 
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:
84
+ **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
85
  ```
77
86
  Peer-mirror check.
78
87
 
@@ -143,9 +152,9 @@ Peer mirrors: [peer-mirror agent output verbatim — Missing/Diverged rows only;
143
152
 
144
153
  ## Step 3: Dispatch Wave-2 — Quality + Security Lenses
145
154
 
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.
155
+ 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 `.git/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
156
 
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`.
157
+ **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 `.git/code-review-patch.diff`.
149
158
 
150
159
  **DO NOT paste into Wave-2 prompts**, under any circumstance, even if the orchestrator has already received them:
151
160
  - raw integration-scanner output (the Discovery Map already summarises its auth/ref/wiring findings)
@@ -160,9 +169,9 @@ Spawn Quality + Security in parallel using the Agent tool. Each receives the `##
160
169
 
161
170
  **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
171
 
163
- **Quality lens** (`codebase-analyzer`) — **file-oriented**:
172
+ **Quality lens** (`diff-auditor`) — **file-oriented**:
164
173
  ```
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.
174
+ Analyse changes file by file. For each file in ChangedFiles, read its diff region in `.git/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
175
 
167
176
  **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
177
 
@@ -187,9 +196,9 @@ Spawn Quality + Security in parallel using the Agent tool. Each receives the `##
187
196
  **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
197
  ```
189
198
 
190
- **Security lens** (`codebase-analyzer`) — **file-oriented**:
199
+ **Security lens** (`diff-auditor`) — **file-oriented**:
191
200
  ```
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.
201
+ Analyse each changed file as a whole, looking for sinks in the classes below. For each file, grep the file's diff region in `.git/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
202
 
194
203
  **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
204
 
@@ -244,17 +253,17 @@ Spawn Quality + Security in parallel using the Agent tool. Each receives the `##
244
253
 
245
254
  ## Step 4: Dispatch Wave-3 — Predicate-Trace + Interaction Sweep + Gap-Finder
246
255
 
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:
256
+ 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
257
 
249
258
  - **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.
259
+ - **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
260
  - 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
261
 
253
262
  ### Step 4a: Predicate-Trace
254
263
 
255
264
  **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
265
 
257
- Otherwise spawn ONE `codebase-analyzer` in parallel with 4b and 4c:
266
+ Otherwise spawn ONE `codebase-analyzer` in parallel with 4b:
258
267
  ```
259
268
  Coherence rows (Quality — Predicate-set coherence): [paste verbatim]
260
269
  Gating predicates in diff: [`file:line` list]
@@ -268,13 +277,13 @@ Otherwise spawn ONE `codebase-analyzer` in parallel with 4b and 4c:
268
277
  Evidence only. Citation contract applies.
269
278
  ```
270
279
 
271
- Do NOT wait — 4b (Interaction Sweep) and 4c (Gap-Finder) dispatch in the same message as 4a.
280
+ Do NOT wait — 4b (Interaction Sweep) dispatches in the same message as 4a; 4c runs inline in the orchestrator.
272
281
 
273
282
  ### Step 4b: Interaction Sweep
274
283
 
275
284
  **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
285
 
277
- Otherwise spawn ONE `codebase-analyzer` in parallel with 4a and 4c:
286
+ Otherwise spawn ONE `codebase-analyzer` in parallel with 4a:
278
287
  ```
279
288
  Quality Evidence: [verbatim]
280
289
  Security Evidence: [verbatim]
@@ -299,36 +308,21 @@ Otherwise spawn ONE `codebase-analyzer` in parallel with 4a and 4c:
299
308
  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
309
  ```
301
310
 
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.
311
+ ### Step 4c: Gap-Finder (orchestrator-side coverage arithmetic)
307
312
 
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
+ **Gate**: SKIP when `len(ChangedFiles) < 2`. Tiny diffs cannot structurally have coverage gaps.
313
314
 
314
- Diff patch: Read `/tmp/code-review-patch.diff` (already assembled with `-U30`, so full function context is inline).
315
- Discovery Map: [verbatim]
315
+ No agent dispatch. Compute inline while 4a / 4b run:
316
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.
317
+ 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.
318
+ 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.
319
+ 3. **Emit gap findings** — walk uncovered in-scope files in role-tag priority `[boundary]` → `[persistence]` → `[hub]` → `[code]`. For each, open its diff region in `.git/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
320
 
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.
321
+ `G<ordinal> file:line \`<verbatim line>\` [role-tag] <risk class in 3-6 words>`
320
322
 
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)
323
+ 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
324
 
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.
325
+ **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
326
 
333
327
  ## Step 5: Reconcile Findings
334
328
 
@@ -371,9 +365,9 @@ Otherwise spawn ONE `codebase-analyzer` in parallel with 4a and 4b. The prompt i
371
365
 
372
366
  ## Step 6: Verify Findings
373
367
 
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.
368
+ 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
369
 
376
- **Dispatch** after Step 5's reconciled severity map is final, before Step 7 writes anything:
370
+ **Dispatch** after Step 5's reconciled severity map is final, before Step 7 writes anything. First apply the **InScopeFiles pre-filter**: drop any finding whose cited `file` ∉ `InScopeFiles` (orchestrator-side set arithmetic, matches Step 4c's idiom). On `first-parent` strategies `InScopeFiles ⊊ ChangedFiles` is expected — this is where back-merge sidecar findings get dropped. Record the dropped count in `## Reconciliation Notes` so the omission is auditable. Then dispatch the filtered map:
377
371
 
378
372
  ```
379
373
  Verify each finding below against the actual repository state. You have Read access to the whole tree.
@@ -401,7 +395,9 @@ Before writing the artifact, spawn ONE `codebase-analyzer` whose sole job is to
401
395
  Citation contract applies to every justification. No recommendations. No new findings.
402
396
  ```
403
397
 
404
- **Apply the tags**:
398
+ **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.
399
+
400
+ **Apply the tags** (on the corrected tag):
405
401
  - **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
402
  - **Weakened** findings — demote one severity tier (🔴→🟡, 🟡→🔵, 🔵→💭). Rewrite the finding's evidence line to reflect the narrower claim.
407
403
  - **Verified** findings — carry through unchanged to Step 7.
@@ -471,7 +467,7 @@ Ask follow-ups.
471
467
  - **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
468
  - **Load-bearing ordering**:
473
469
  - 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.
470
+ - 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
471
  - 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
472
  - **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
473
  - **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 +475,19 @@ Ask follow-ups.
479
475
  - ALWAYS probe advisor availability before calling it (strip-when-unconfigured at `packages/rpiv-advisor/advisor.ts:463-472`).
480
476
  - NEVER call `advisor()` from a sub-agent (branch invisible to advisor).
481
477
  - 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.
478
+ - 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
479
  - 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
480
  - 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`).
481
+ - 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`.
482
+ - **Scope strategy is load-bearing at both ends**: Step 1 sets `strategy` and `FP_FLAG`; Step 6 pre-filters the reconciled severity map against `InScopeFiles` before `claim-verifier` dispatch. `--first-parent` is orthogonal to `--no-merges` / `-U30` — additive, not a replacement. Agent contracts (`claim-verifier.md:11-30` in particular) stay scope-blind by design; orchestrator owns scope.
486
483
  - **Agent roles**:
487
484
  - `integration-scanner` (Wave-1) — inbound/outbound refs, auth-boundary crossings.
488
485
  - `precedent-locator` (Wave-1) — git history + thoughts/.
489
486
  - `codebase-analyzer` ×1 (Wave-1, `ManifestChanged`) — dependencies parse.
490
487
  - `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.
488
+ - `peer-comparator` ×1 (Wave-1, gated on `len(PeerPairs) > 0`) — peer-mirror check; tags Mirrored/Missing/Diverged/Intentionally-absent.
489
+ - `diff-auditor` ×2 (Wave-2) — Quality, Security.
493
490
  - `codebase-analyzer` ×1 (Step 4a, gated) — predicate-trace.
494
491
  - `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).
492
+ - *(Step 4c, gated)* — gap-finder runs inline in the orchestrator (set arithmetic over coverage map; no agent).
493
+ - `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).
@@ -8,6 +8,8 @@ branch: [Branch]
8
8
  commit: [Short hash]
9
9
  review_type: [commit | pr | staged | working]
10
10
  scope: "[What was reviewed]"
11
+ scope_strategy: [first-parent | explicit-range | working-tree]
12
+ in_scope_files_count: [N]
11
13
  status: [approved | needs_changes | requesting_changes]
12
14
  severity: { critical: [C], important: [I], suggestion: [S] }
13
15
  verification: { verified: [V], weakened: [W], falsified: [F] }