Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
b5acb57
fix(code-review): resolve review paths against the reviewed worktree
mikeangstadt Aug 28, 2026
23bd85f
test(code-review): isolate the containment check in the ISS-7382 disp…
mikeangstadt Aug 28, 2026
6bfca00
fix(code-review): make the review-root refusal abort the walker
mikeangstadt Aug 28, 2026
066aba4
fix(code-review): resolve the review-fleet findings on the review-roo…
mikeangstadt Aug 28, 2026
b60d49c
Merge remote-tracking branch 'origin/main' into fix/iss-7382-review-r…
wongk Sep 15, 2026
1d19535
fix(code-review): refuse dispatch when the diff's files drifted since…
wongk Sep 15, 2026
fe857dd
test(code-review): pin the exit-3 abort in both prefix harness walkers
wongk Sep 15, 2026
b58759a
fix(code-review): bump to 3.9.0 with regenerated changelog
wongk Sep 15, 2026
2ed4f35
fix(code-review): gate code intelligence on the reviewed root matchin…
wongk Sep 15, 2026
4038d25
fix(code-review): check git-quoted diff paths instead of skipping them
wongk Sep 15, 2026
9c4f270
Merge remote-tracking branch 'origin/main' into fix/iss-7382-review-r…
wongk Sep 15, 2026
f204c4c
fix(code-review): keep code intelligence on for worktree reviews, sco…
wongk Sep 15, 2026
997c2cf
fix(code-review): allow scoped queries that index as a side effect
wongk Sep 15, 2026
397c1d2
fix(code-review): pin the index tree so staged reviews detect drift
wongk Sep 15, 2026
028db95
refactor(code-review): share the review-root refusal and narrow scope…
wongk Sep 15, 2026
a65f7fd
docs(code-review): update 3.9.0 changelog for staged drift pinning
wongk Sep 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ All notable changes to the claude-plugins project will be documented in this fil

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Entries are listed newest-first; each plugin section is treated as released when merged to `main`.

### code-review v3.9.0

#### Fixed
- Reviewer and verifier agents resolved repo-relative source paths against the invoking session's working directory instead of the checkout under review (ISS-7382). `resolve-scope` emitted `review_root: ""` for every scope kind except a local PR-head worktree, and `shared_prompt.txt` and `verifier_prompt.txt` read an empty root as "read from the working directory" — which for a spawned agent is the session's checkout, not the tree the diff came from. `resolve-scope` now resolves `review_root` for every scope kind (the PR-head worktree when one is created, otherwise `git rev-parse --show-toplevel` of the invoking checkout), records the commit that checkout holds as `review_root_sha`, and exits `3` instead of emitting an empty root when the working directory is not inside a git worktree. This includes github mode, which previously emitted an empty `review_root`: once its PR-head check passes, `review_root` is the verified checkout itself and `review_root_sha` is its HEAD — the PR head for a head checkout, the merge commit for a `refs/pull/N/merge` checkout — so the dispatch drift check compares against what is actually checked out. Github mode still creates no worktree and still emits an empty `head_sha`, and its PR-head refusals run before any scope is emitted.
- The four stages that hand work to agents — `derive-spawn-spec`, `derive-static-spec`, `verify-prepare`, and `review-dismissed-prepare` — re-prove `review_root` before dispatching and exit `3` when they cannot. The root must be absolute, free of control characters, `<`, `>` and backticks, exist, and be the root of a git worktree. A PR-head worktree's HEAD must still equal `review_root_sha`, and a live checkout must still contain that commit. Every non-removed file in `diff_data.json` must exist under the root, and a root with neither a recorded commit nor a resolvable changed file is refused. `parse-diff` records names as `git diff --name-only` prints them, so a path holding a non-ASCII, control, `"` or `\` byte is stored C-quoted; those names are decoded (named escapes and 3-digit octal escapes) to the name on disk and go through the existence and drift checks like any other file, and an entry that starts with `"` but is not valid quoting is refused.
- Dispatch is also refused when a file the diff changes no longer matches `review_root_sha` in the working tree: a commit, reset, or uncommitted edit to that file after the scope was resolved, including uncommitted edits already present when a branch review starts. The comparison is one `git diff --name-only -z --no-renames <review_root_sha>` call intersected with the diff's file list, so no pathspec is passed and no path is glob-interpreted, and a failing git call refuses rather than passes. Changes to files outside the diff are still allowed. A `staged` review, whose diff is index-vs-HEAD, is compared against the index instead: `resolve-scope` records the index as `review_root_tree` (`git write-tree`, emitted for staged scope only), so an unstaged edit to a staged file or a re-stage after resolution is refused with a prompt to stage or stash those edits, and a staged scope without a valid `review_root_tree` is refused.
- Exit `3` now aborts the walk regardless of the stage's `on_failure`. `derive-spawn-spec`, `derive-static-spec`, and `verify-prepare` are `on_failure: continue`, so a plain non-zero exit would fall back to the static reviewer table or skip verification and dispatch agents against the same unproven tree. `_execute_stage_inprocess` and both walkers in `prefix_golden_harness.py` apply the override; every other non-zero exit still follows `on_failure`. `start.md` tells the orchestrator not to resume a stage that exited `3` from the `run-prefix` error fallback.
- A positional scope argument that is a git ref or revision range (e.g. `/code-review origin/main...HEAD`) is rejected with a pointer to `--base`, instead of being folded into a `--` pathspec that matched nothing and produced an empty, clean review.
- The reviewer and verifier prompts treat `review_root` as mandatory: resolve every source path under it, discard anything already read elsewhere, and stop rather than fall back to the working directory when it is empty or missing. A reviewer writes no output file in that case (an empty `findings` array would read as a clean review), and a verifier writes a `TENTATIVE` verdict. Tool-returned paths are validated against `<review_root>` in `shared_prompt.txt` and `code-review-worker-graph.md`, and `code-review-worker.md` states the same resolution rule. `spawn-reviewers` requires the `{REVIEW_ROOT}` substitution for every agent, taken from `spawn.json.spec.review_root` with `scope.json` as the fallback, and stops on an empty value; `verify-findings` stops when `verify_manifest.json` is absent; `present-local` stops `--review-dismissed` when `review-dismissed-prepare` exits non-zero.

#### Changed
- `CODE_INTEL_ALLOWED` is now `false` only when `scope.json` → `worktree_path` is non-empty — the per-run PR-head worktree, created and torn down on every review — instead of whenever `review_root` is non-empty, which would disable code intelligence on every run now that `review_root` is always populated. Code intelligence stays on for branch, staged, and file-path review run from the primary checkout or from a separate git worktree, for local PR review already at the head, and in GitHub mode.
- The `spawn-reviewers` gate computes a second value, `CODE_INTEL_REQUIRE_ROOT_ARG`, and substitutes it next to `CODE_INTEL_ALLOWED` in every reviewer suffix that loads the code-intelligence protocol. It is `false` only when `scope.json` → `review_root` resolves (realpath) to the git toplevel of the session's primary working directory — the directory the session was started in, not the directory a helper process ran in — and `true` otherwise, including when either side cannot be determined. When it is `true`, the `shared_prompt.txt` protocol lets a reviewer call only tools it can point at `<review_root>` through a root / repo / workspace / project argument, because a tool called without one answers for the session's checkout, and a capability no such tool answers falls back to Grep/Glob. The protocol also now requires passing `<review_root>` as the root argument whenever a tool accepts one, and discarding any response whose resolved target is not the symbol that was asked about. Its indexing rule, which forbade reviews from ever indexing or re-indexing a repo, now forbids only calling a tool whose purpose is to index, re-index, or start or stop an indexing service; a query tool that builds or refreshes its index as a side effect of answering a query scoped to `<review_root>` is allowed. `impact_analyzer_prompt.txt`, `design_critic_suffix.txt`, `code-review-worker-graph.md`, and the `stage_03_resolve_scope` note in `start.md` are updated to match.
- `spawn.json.spec` now carries `review_root`, including on fallback specs, and `SCHEMA.md` documents the field.
- `_validated_review_root` is renamed `_validated_worktree_path` and still accepts only `<cr_dir>/pr_head_worktree`, because `stage_30_footer` deletes the path it returns. `re-assert` and `review-dismissed-consolidate`, which can run after that teardown, use `review_root` only when it can be proven, and otherwise print the reason to stderr and use their existing fallback.

### code-review v3.8.1

#### Fixed
Expand Down
2 changes: 1 addition & 1 deletion plugins/code-review/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "code-review",
"description": "Code review plugin",
"version": "3.8.1",
"version": "3.9.0",
"author": {
"name": "ClosedLoop",
"email": "support@closedloop.ai"
Expand Down
6 changes: 6 additions & 0 deletions plugins/code-review/SCHEMA.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,12 @@ ignored at spawn time.
"fallback_reason": "<string>", // only present when arbitrate_status="fallback"
"cr_dir": "<absolute path>",
"generated_at": "<ISO-8601 timestamp>",
"review_root": "<absolute path>", // the checkout the diff was PROVEN
// against; present on fallback specs
// too, and the primary source for the
// mandatory {REVIEW_ROOT} substitution
// at stage_20. Never empty — derivation
// exits 3 instead of emitting one.

// ── Agents to spawn ──────────────────────────────────────
"agents": [
Expand Down
10 changes: 9 additions & 1 deletion plugins/code-review/agents/code-review-worker-graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,18 @@ argument shape.
- **Availability is yours to determine.** Inspect your own tool roster. Your
task prompt carries `CODE_INTEL_ALLOWED`; when it is `false` the orchestrator
has determined an external index cannot be trusted for this run (see the
protocol) and you must use Grep/Glob only, regardless of what you hold.
protocol) and you must use Grep/Glob only, regardless of what you hold. It
also carries `CODE_INTEL_REQUIRE_ROOT_ARG`; when it is `true` you may call
only tools you can scope to `<review_root>` through a root argument (see the
protocol's scoping rules).
- **Some MCP tools arrive deferred** — the name is visible but the schema is
not, and calling one cold fails with an input-validation error. Use
`ToolSearch` to load the schemas of the tools you intend to use first.
- **Paths resolve under `<review_root>`, never your working directory.** Validate
every file path a tool returns against the task prompt's `<review_root>`: it
MUST be openable with Read at `<review_root>/<repo-relative path>`. Discard (and
never cite) any path that does not resolve under `<review_root>` or escapes it
via `..`.
- **Findings are evidence-bound regardless of substrate.** Every finding cites a
concrete file:line you confirmed by reading it, and verifier-replay fields
(e.g. `grep_query_used`) stay populated per your role prompt.
Expand Down
1 change: 1 addition & 0 deletions plugins/code-review/agents/code-review-worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ You are a code review worker agent. Your job is to read pre-extracted patch file
1. Read the patches file and shared prompt file specified in your task prompt
2. Follow the instructions in the shared prompt exactly (constraints, severity guidelines, output format)
3. Use Read, Grep, and Glob to explore the codebase for context when needed
- Repo-relative source paths resolve under the task prompt's `<review_root>`, NEVER your working directory — a spawned agent's cwd is the invoking session's checkout, not the code under review.
4. Write your findings JSON to the output file specified in `<output_file>`
5. Respond with a one-line summary: `DONE findings={count} file={path}`

Expand Down
Loading
Loading