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