From cb4f0a008ea73976a334c24c1d8355997f3e96ec Mon Sep 17 00:00:00 2001 From: "[._.]/ Adam Eivy" Date: Tue, 25 Aug 2026 15:19:17 -0700 Subject: [PATCH 1/2] feat: make do:review agent dispatch adaptive --- .claude/commands/improve/review.md | 7 +++- README.md | 2 +- commands/do/review.md | 63 ++++++++++++++++++++---------- install.sh | 2 +- lib/review-agent-selection.md | 52 ++++++++++++++++++++++++ test/review-loop-contract.test.js | 24 ++++++++++++ uninstall.sh | 2 +- 7 files changed, 127 insertions(+), 25 deletions(-) create mode 100644 lib/review-agent-selection.md diff --git a/.claude/commands/improve/review.md b/.claude/commands/improve/review.md index 164dadb..9bf916b 100644 --- a/.claude/commands/improve/review.md +++ b/.claude/commands/improve/review.md @@ -9,7 +9,10 @@ Analyze code review feedback on a PR, identify patterns our review system missed ## Architecture Overview -The `/do:review` system uses 5 parallel agents, each with focused reading strategies: +The `/do:review` system has one host orchestrator and six optional focused review +lenses. The orchestrator inspects each PR and selects zero or more lenses based on +the changed behavior; selected lenses run in parallel, and a simple change may use +no sub-agents at all: | Agent | File | Focus | |---|---|---| @@ -18,10 +21,12 @@ The `/do:review` system uses 5 parallel agents, each with focused reading strate | Security Audit | `lib/review-security-audit.md` | Trust boundaries, injection, SSRF, data exposure, access control | | Cross-File Tracing | `lib/review-cross-file-tracing.md` | State/lifecycle/concurrency across files: stale state propagation, lifecycle gaps, resource leaks, lock/flag exit paths, races | | Cross-File Contract | `lib/review-cross-file-contract.md` | Contracts across files: schema/shape agreements, validation parity, error classification, field-set enumerations, architectural-pattern adherence | +| Structural Ambition | `lib/review-structural-ambition.md` | Strict-mode structural concerns: code-judo simplifications, file-size growth, abstraction sprawl, boundary leaks, and bespoke duplicates | Additionally: - `lib/code-review-checklist.md` — master source-of-truth (canonical reference, not directly used by agents) - `commands/do/review.md` — orchestrator (dispatches agents, deduplicates, fixes, reports) +- `lib/review-agent-selection.md` — orchestrator's evidence-based lens-selection policy ## Phase 1: Parse Input & Fetch Feedback diff --git a/README.md b/README.md index e518dfe..53c5e21 100644 --- a/README.md +++ b/README.md @@ -293,7 +293,7 @@ By default the orchestrator that opened the PR applies every reviewer's fixes it ### Command-specific behavior -- **`/do:review`** — the listed agents run *after* the host CLI's own multi-agent self-review; the list names *additional* reviewers. +- **`/do:review`** — the host CLI inspects the change and selects only the focused self-review lenses it needs (possibly none); any `--review-with` agents run afterward as additional reviewers. - **`/do:better` / `/do:better-swift` / `/do:simplify` / `/do:depfree`** — the chosen reviewers run as the post-PR review loop (per PR, in parallel for the multi-PR better commands). **Omitting `--review-with` skips the review loop and the auto-merge** — PRs are left open for manual review. - **`/do:rpr`** — resolves review threads from any author (Copilot, human, or bot). Like every other command it has **no default reviewer**: omit `--review-with` (and set no saved default) and rpr requests nothing — it just fetches and resolves the unresolved threads the PR already carries. Name a reviewer and rpr requests it, then loops review → fix → re-review. It accepts only `--review-with` and `--reviewer-applies` (not `--review-iterations`, `--review-mode`, or the stop-mode flags), and it doesn't support `@` entries — it drops them with a notice. diff --git a/commands/do/review.md b/commands/do/review.md index b8cb379..fb15cbd 100644 --- a/commands/do/review.md +++ b/commands/do/review.md @@ -6,9 +6,9 @@ argument-hint: "[--strict|--nuclear] [--draft] [--review-with [,.. ## Parse Arguments Parse `$ARGUMENTS` for: -- **`--strict`** (alias: **`--nuclear`**): enable the Structural Ambition agent (6th agent) and promote structural findings to blocker tier. Use for branches you want to land cleanly — flags file-size growth past 1000 lines, ad-hoc conditionals bolted onto unrelated flows, thin wrappers, boundary leaks, and missed code-judo simplifications. +- **`--strict`** (alias: **`--nuclear`**): raise the structural-review bar and permit the Structural Ambition lens to be selected when the diff contains structural signals; promote structural findings to blocker tier. Strict mode does not force a focused agent when the orchestrator finds no structural concern. Use for branches you want to land cleanly — flags file-size growth past 1000 lines, ad-hoc conditionals bolted onto unrelated flows, thin wrappers, boundary leaks, and missed code-judo simplifications. - **`--draft`** (PR mode only): write the review payload to `/tmp/do-review-pr-{PR_NUM}-payload.json` and print the `gh api` command to publish it manually, instead of posting the review immediately. Ignored when `PR_MODE=false`. -- **`--review-with `** (optional): after the host CLI's self-review completes (the multi-agent flow defined below), delegate **additional** review passes to the named external CLIs in order. Accepted slugs per slot: `codex`, `agy` (aliases `gemini` / `antigravity` — all run the Antigravity CLI's `agy` binary), `claude`, `grok`, `cursor` (alias `cursor-agent` — the Cursor Agent CLI), `ollama` (bare `ollama` auto-selects the most capable installed coding model; `ollama[]` pins a specific installed model, e.g. `ollama[qwen2.5-coder:32b]` — strip the bracket into a per-entry `OLLAMA_MODEL`; `codex`/`claude`/`agy`/`grok`/`cursor` likewise accept a `[]` bracket — e.g. `codex[o3]`, `claude[claude-opus-4-8]`, `grok[grok-code-fast-1]` — stripped into a per-entry `REVIEW_MODEL`, empty → the reviewer's built-in default; `copilot` and `@` take no model bracket), `copilot` (**legacy** — GitHub's cloud Copilot review; still supported when you name it, never selected implicitly), or an arbitrary GitHub login `@` — any GitHub user or App/bot (e.g. `@octocat`, `@org-review-bot`, `@some-app[bot]`); slashdo requests its review on the PR and waits for it (GitHub only, never posts an approval itself). Split on `,`, trim whitespace, normalize `gemini`/`antigravity` → `agy`, `cursor-agent` → `cursor`, dedupe preserving first-occurrence order (for a model-taking agent — `codex`/`claude`/`agy`/`grok`/`cursor`/`ollama` — the `[]` bracket suffix is part of the dedup identity). Any slot may end in `~opt` (e.g. `ollama~opt`) to mark that reviewer **optional/non-blocking** — still requested and its findings still fixed, but an inconclusive result from it never contributes a merge-blocking `inconclusive` aggregate (a hard-error from it still does); strip `~opt` into a per-entry `{OPTIONAL}` flag before slug parsing, not part of the dedup identity (`ollama~opt` == `ollama`, optional-wins on collapse). A slot may also end in `~max=` (e.g. `claude~max=2`, `ollama~max=1`) to cap how many review → fix → re-review cycles **that one reviewer** runs, or `~effort=` (e.g. `codex[gpt-5.6-luna]~effort=max~opt`, `claude~effort=high~max=2`) to specify its reasoning effort level (`low`, `medium`, `high`, `xhigh`, `max`). Strip suffixes off the right of each token in any order before slug parsing. Deduplication preserves first-occurrence order and excludes `~` suffixes (survivor takes `~opt` if any had it, and cap/effort level from the first that carried them). Reject a malformed suffix with `Invalid --review-with suffix on {entry}: ~max must be a non-negative integer and ~effort must be one of low, medium, high, xhigh, max, each appearing at most once; the only suffixes are ~opt, ~max=, and ~effort=.` Abort with `Unknown --review-with value: {value}. Use one of: codex, agy, claude, grok, cursor, ollama, copilot, @ (each optionally suffixed ~opt, ~max=, and/or ~effort=).` on any unknown slug. The reserved token `none` (case-insensitive) is **not** validated as a slug — `--review-with none` means no delegated reviewers (set `REVIEW_AGENTS=[]`) and overrides any saved `review-with` default. If omitted, leave `REVIEW_AGENTS` **unset for now** — the saved-defaults step below fills it from `/do:config` if a default exists, and **only if it is still unset after that** is `REVIEW_AGENTS=[]` (no delegated passes — behavior matches the historical `/do:review` self-review only). **The host CLI is not implied in this list** — whichever CLI is hosting the review command (claude, codex, or agy) runs the self-review first regardless. The list names *additional* reviewers; an explicit `claude` entry while running under claude means "start a fresh claude headless session for a second-pass perspective," which is allowed. +- **`--review-with `** (optional): after the host CLI's self-review completes (the selection flow defined below), delegate **additional** review passes to the named external CLIs in order. Accepted slugs per slot: `codex`, `agy` (aliases `gemini` / `antigravity` — all run the Antigravity CLI's `agy` binary), `claude`, `grok`, `cursor` (alias `cursor-agent` — the Cursor Agent CLI), `ollama` (bare `ollama` auto-selects the most capable installed coding model; `ollama[]` pins a specific installed model, e.g. `ollama[qwen2.5-coder:32b]` — strip the bracket into a per-entry `OLLAMA_MODEL`; `codex`/`claude`/`agy`/`grok`/`cursor` likewise accept a `[]` bracket — e.g. `codex[o3]`, `claude[claude-opus-4-8]`, `grok[grok-code-fast-1]` — stripped into a per-entry `REVIEW_MODEL`, empty → the reviewer's built-in default; `copilot` and `@` take no model bracket), `copilot` (**legacy** — GitHub's cloud Copilot review; still supported when you name it, never selected implicitly), or an arbitrary GitHub login `@` — any GitHub user or App/bot (e.g. `@octocat`, `@org-review-bot`, `@some-app[bot]`); slashdo requests its review on the PR and waits for it (GitHub only, never posts an approval itself). Split on `,`, trim whitespace, normalize `gemini`/`antigravity` → `agy`, `cursor-agent` → `cursor`, dedupe preserving first-occurrence order (for a model-taking agent — `codex`/`claude`/`agy`/`grok`/`cursor`/`ollama` — the `[]` bracket suffix is part of the dedup identity). Any slot may end in `~opt` (e.g. `ollama~opt`) to mark that reviewer **optional/non-blocking** — still requested and its findings still fixed, but an inconclusive result from it never contributes a merge-blocking `inconclusive` aggregate (a hard-error from it still does); strip `~opt` into a per-entry `{OPTIONAL}` flag before slug parsing, not part of the dedup identity (`ollama~opt` == `ollama`, optional-wins on collapse). A slot may also end in `~max=` (e.g. `claude~max=2`, `ollama~max=1`) to cap how many review → fix → re-review cycles **that one reviewer** runs, or `~effort=` (e.g. `codex[gpt-5.6-luna]~effort=max~opt`, `claude~effort=high~max=2`) to specify its reasoning effort level (`low`, `medium`, `high`, `xhigh`, `max`). Strip suffixes off the right of each token in any order before slug parsing. Deduplication preserves first-occurrence order and excludes `~` suffixes (survivor takes `~opt` if any had it, and cap/effort level from the first that carried them). Reject a malformed suffix with `Invalid --review-with suffix on {entry}: ~max must be a non-negative integer and ~effort must be one of low, medium, high, xhigh, max, each appearing at most once; the only suffixes are ~opt, ~max=, and ~effort=.` Abort with `Unknown --review-with value: {value}. Use one of: codex, agy, claude, grok, cursor, ollama, copilot, @ (each optionally suffixed ~opt, ~max=, and/or ~effort=).` on any unknown slug. The reserved token `none` (case-insensitive) is **not** validated as a slug — `--review-with none` means no delegated reviewers (set `REVIEW_AGENTS=[]`) and overrides any saved `review-with` default. If omitted, leave `REVIEW_AGENTS` **unset for now** — the saved-defaults step below fills it from `/do:config` if a default exists, and **only if it is still unset after that** is `REVIEW_AGENTS=[]` (no delegated passes — behavior matches the historical `/do:review` self-review only). **The host CLI is not implied in this list** — whichever CLI is hosting the review command (claude, codex, or agy) runs the self-review first regardless. The list names *additional* reviewers; an explicit `claude` entry while running under claude means "start a fresh claude headless session for a second-pass perspective," which is allowed. - **`--review-stop-on-findings` / `--review-stop-on-clean`** (mutually exclusive, optional): stop-mode for the delegated passes. Default `REVIEW_STOP_MODE=all` (run every listed agent). `on-findings` stops after the first delegated reviewer that surfaces a non-empty change set; `on-clean` stops after the first delegated reviewer that reports zero findings. Abort with `--review-stop-on-findings and --review-stop-on-clean cannot be combined` if both appear. - **`--review-mode `** (optional): how the delegated passes are dispatched. `series` (default) runs the listed reviewers one-at-a-time so each sees the prior reviewer's committed fixes; `parallel` runs their reviews concurrently against one frozen baseline and then applies the deduped union of findings once (faster, but no reviewer sees another's fixes — `--reviewer-applies` and the stop-modes are ignored in this mode). Record as `REVIEW_MODE`; if omitted, leave it **unset for now** (the saved-defaults step fills it from the `review-mode` default; built-in default `series`). Abort with `--review-mode must be one of series, parallel (got: {value}).` on any other value. - **`--reviewer-applies`** (optional, boolean): forwarded to each delegated local-agent pass to route fixes through the reviewing CLI instead of the orchestrator. See `lib/local-agent-review-loop.md` "Editing mode" for the trade-offs. No effect on the copilot path, the `@` path, the ollama path (Ollama is non-agentic — always review-only), or the host's self-review. @@ -105,13 +105,24 @@ Before dispatching agents, understand what this change set claims to do: ## Dispatch Review Agents -Read the agent instruction files, then spawn agents **in parallel** using the Agent tool at the **`heavy` tier** — this host's strongest available model named by its alias (`model: "opus"` on Claude Code), per [lib/model-tiers.md](../../lib/model-tiers.md). Each agent reviews ALL changed files independently. +The host CLI is the review orchestrator. First inspect the scoped diff and run the +selection protocol below; then read the instruction file and spawn only the focused +agents the protocol selects. Selected agents run **in parallel** using the Agent +tool at the **`heavy` tier** — this host's strongest available model named by its +alias (`model: "opus"` on Claude Code), per [lib/model-tiers.md](../../lib/model-tiers.md). +Each selected agent reviews ALL changed files independently. **Review is judgment-heavy — don't downgrade it.** `heavy` here means the strongest tier available, not "whatever the session happens to be running," so a review launched from a mid-tier session still gets top-tier reviewers. Use the **alias**, never a fully-qualified version ID: the alias resolves to whatever version the org has configured, so it neither goes stale nor overrides a pinned deployment. If the dispatch is rejected for lack of entitlement to that tier, retry once with `model` omitted (inherit the session), say so, and continue rather than skipping the review. **The agents are deliberately short and principle-led.** Each agent's checklist is a prompt for attention — the reviewing agent's job is to think about the problem space, not pattern-match against bullets. The most expensive misses in past reviews were *consequence-reasoning* bugs (a fallback path producing a different shape than the happy path; an encoder corrupting a downstream parser; a test asserting a symptom instead of the contract) — none findable by adding more bullets. Trust the agent to reason; the checklist seeds the lens, not the conclusions. -Always dispatch agents 1–5. Dispatch agent 6 only when `STRICT_MODE=true`. +The host orchestrator does the full review itself even when no focused agent is +selected. Do not dispatch a focused agent merely because it exists below or because +strict mode is active; use the selection protocol and record the decision. + +### Select the review lenses + +!`cat ~/.claude/lib/review-agent-selection.md` @@ -165,9 +176,14 @@ Catches CONTRACT issues across files: schema/shape agreements, validation parity -### 6. Structural Ambition Agent (strict mode only) +### 6. Structural Ambition Agent (optional; strict mode required) -Dispatch only when `STRICT_MODE=true`. Catches STRUCTURAL issues the other agents miss: missed code-judo simplifications, file-size growth past 1000 lines, ad-hoc conditionals bolted onto unrelated flows, thin wrappers, boundary leaks, bespoke duplicates of canonical helpers, cast-heavy/optional-soup contracts. Push the bar to "this works AND the implementation feels inevitable in hindsight." +Dispatch only when `STRICT_MODE=true` **and** the selection protocol identifies a +structural signal. Catches STRUCTURAL issues the other agents miss: missed code-judo +simplifications, file-size growth past 1000 lines, ad-hoc conditionals bolted onto +unrelated flows, thin wrappers, boundary leaks, bespoke duplicates of canonical +helpers, cast-heavy/optional-soup contracts. Push the bar to "this works AND the +implementation feels inevitable in hindsight." !`cat ~/.claude/lib/review-structural-ambition.md` @@ -175,23 +191,28 @@ Dispatch only when `STRICT_MODE=true`. Catches STRUCTURAL issues the other agent ### How to dispatch -For each agent, construct its prompt by combining: -1. The agent's instruction content (from the sections above) +For each selected agent, construct its prompt by combining: +1. The agent's instruction content (from the sections above), plus the orchestrator's + recorded reason for selecting that lens 2. Project convention overrides from CLAUDE.md that affect the review (use the PR's CLAUDE.md/AGENTS.md when `PR_MODE=true`) 3. The list of changed files from the diff stat (or `gh pr diff --name-only` in PR mode) AND, in PR mode, the path to each file's full content under `/tmp/do-review-pr-{PR_NUM}/` 4. In PR mode only: the path to `/tmp/do-review-pr-{PR_NUM}-lines.json` (the commentable-lines map) and an instruction that **every finding MUST cite a `file:line` where `line` appears in the commentable-lines map** — otherwise the finding cannot be posted as an inline comment and should be downgraded to a summary-only finding 5. Instruction: "Read each changed file in full (not just diff hunks). Apply your reading lens — the checklist seeds attention but is NOT a script. Reason from principles about each new shape, flow, or contract: what's the smallest input that breaks this? What does the producer believe vs the consumer? What does the fallback path actually deliver? What does the documentation claim vs what the code does? Report findings that demonstrate consequence reasoning, not just pattern matches." 6. In PR mode only: "For every CRITICAL or IMPROVEMENT finding where a concrete fix is obvious, include a `suggestion:` block — the exact replacement text for the cited line(s). Use `start_line` and `line` to span multiple lines when the fix needs more than one line. The reviewer will package these as GitHub inline review suggestions." -Spawn agents 1–5 simultaneously. If `STRICT_MODE=true`, also spawn agent 6 in the same parallel batch. Each returns its findings independently. +Spawn the selected agents simultaneously in one parallel batch. If the selection is +empty, spawn no focused agents and continue with the host orchestrator's self-review. +Each selected agent returns its findings independently. ### Large PR handling -If the diff touches more than 20 files, tell each agent to batch files by directory and process groups sequentially within their parallel run. The orchestrator does not manage batching. +If the diff touches more than 20 files, tell each selected agent to batch files by +directory and process groups sequentially within their parallel run. The orchestrator +does not manage batching. ## Collect & Deduplicate -After all dispatched agents return: +After the host self-review and any selected agents return: 1. **Merge** all findings into a single list, tagged by source agent 2. **Deduplicate**: if two agents flagged the same `file:line` with overlapping descriptions, keep the most detailed version and note all agents that found it (overlap between Surface Scan and Surface Quality, or between Cross-File Tracing and Cross-File Contract, is expected for borderline issues — that's signal a finding is real, not noise). The Structural Ambition agent (strict mode) frequently overlaps with Surface Quality on wrapper/duplication findings — keep the Structural Ambition phrasing when it names a concrete reframing @@ -309,22 +330,22 @@ If the user wants to inspect comments before publishing, support a `--draft` fla ## Report -Print a summary table of what was reviewed and found: +Print a summary table of what was reviewed and found. The table is dynamic: always +include the host orchestrator, include only the focused agents actually selected, +and do not print rows for focused agents that were skipped. Before the table, print +the selected lenses with their reasons and note when the empty selection was +intentional. ``` ## Review Summary -| Agent | Files Checked | Issues Found | Fixed | -|-------|--------------|-------------|-------| -| Surface Scan (Runtime) | N | N | N | -| Surface Quality | N | N | N | -| Security Audit | N | N | N | -| Cross-File Tracing (State) | N | N | N | -| Cross-File Contract | N | N | N | -| Structural Ambition (strict) | N | N | N | +| Reviewer | Files Checked | Issues Found | Fixed | +|----------|--------------|-------------|-------| +| Host orchestrator (self-review) | N | N | N | +| {selected focused lens} | N | N | N | | **Total** | **N** | **N** | **N** | -Omit the Structural Ambition row when `STRICT_MODE=false`. +Omit all focused-lens rows when none were selected. ### Issues Fixed - file:line — description of fix (agent: Surface-Scan / Surface-Quality / Security / Cross-File-Tracing / Cross-File-Contract / Structural-Ambition) diff --git a/install.sh b/install.sh index 032258a..4906a5a 100755 --- a/install.sh +++ b/install.sh @@ -179,7 +179,7 @@ LIBS=( local-agent-review-loop model-tiers multi-reviewer-loop ollama-review-loop per-finding-root-cause plan-id-format plan-issue-mode post-review-doc-recommendations remediation-agent-template - review-config-defaults review-convergence-gate + review-agent-selection review-config-defaults review-convergence-gate swift-review-checklist swift-gotchas review-surface-scan review-surface-quality review-security-audit review-cross-file-tracing review-cross-file-contract diff --git a/lib/review-agent-selection.md b/lib/review-agent-selection.md new file mode 100644 index 0000000..c038060 --- /dev/null +++ b/lib/review-agent-selection.md @@ -0,0 +1,52 @@ +# Review Agent Selection + +The host CLI agent is the review orchestrator. It must inspect the scoped diff, +changed files, commit claims, and project conventions before deciding whether any +focused sub-agent is needed. The focused agents below are optional review lenses, +not a fixed checklist or a minimum fan-out. + +## Selection protocol + +After the PR-level coherence check and before dispatch: + +1. Read the changed files in full and summarize what the change actually does. +2. Start with an empty `SELECTED_REVIEW_AGENTS` list. Add a lens only when the + diff contains a concrete signal that its reading strategy will add coverage. +3. Record one short reason beside every selected lens. The reason must name the + changed behavior or boundary that triggered it, not merely repeat the lens + name. +4. If no focused lens is justified, dispatch no sub-agents. The host agent still + performs the complete self-review, and the report must say that the focused + pass was intentionally skipped and why. +5. When the signal is ambiguous but the consequence could be serious, select the + relevant lens. Saving a dispatch is not a reason to omit a lens that is clearly + needed. + +The decision is about review coverage, not file extensions alone. A small diff can +need several lenses when it changes a security boundary or a producer/consumer +contract; a larger mechanical or documentation-only diff may need none or only one. +If multiple lenses are selected, dispatch them in parallel. Each selected lens reads +all changed files, but reports only findings within its own mandate. + +## Lens signals + +| Lens | Select when the diff shows | Usually skip when | +|---|---|---| +| Surface Scan (Runtime) | Executable behavior, request handling, UI state, scripts, migrations, subprocesses, or error paths that can fail at runtime | The change is only prose, metadata, or a mechanically generated fixture with no runtime behavior | +| Surface Quality | Documentation or configuration claims, tests/fixtures, dependency metadata, or a behavior change whose intent and coverage need a file-local quality pass | The diff is a tiny, self-evident implementation edit and the host can verify its local quality directly | +| Security Audit | Authentication/authorization, untrusted input, secrets, URLs, shell/process execution, network calls, file paths, dependencies, or sensitive output | No trust boundary, privilege, external input, or sensitive data changes | +| Cross-File Tracing (State) | Async work, state machines, events, jobs, retries, lifecycle, persistence, concurrency, or a control/data flow spanning modules | A self-contained change with no stateful or cross-module lifecycle | +| Cross-File Contract | API/schema/type, serialization, persistence, configuration, event payload, or producer/consumer changes across a boundary | No changed shape or agreement crosses a module, layer, or documented interface | +| Structural Ambition | `--strict` is active **and** the diff contains non-trivial refactoring, new abstraction layers, large-file growth, conditional sprawl, boundary leakage, or duplicated canonical logic | `--strict` is absent, or strict mode is active only for a small isolated behavior/doc fix | + +These signals are prompts for judgment, not an exhaustive classifier. Select more +than one lens when the change crosses concerns, and do not select a lens solely +because its category appears in the generic review checklist. + +## Dispatch record + +The review summary must report the selected lenses and their reasons, plus the +focused lenses intentionally skipped when that is useful context. The summary must +also distinguish the host orchestrator's self-review from the optional focused +passes, so zero sub-agents is visible as an intentional decision rather than a +missing review. diff --git a/test/review-loop-contract.test.js b/test/review-loop-contract.test.js index 2be85ed..71332c1 100644 --- a/test/review-loop-contract.test.js +++ b/test/review-loop-contract.test.js @@ -18,6 +18,30 @@ const LOOPS_WITH_OPTIONAL_ARRAYS = [ ]; describe('review-loop parse contracts', () => { + it('lets the host orchestrator select focused review lenses from the diff', () => { + const command = readCommand('review.md'); + const selection = readLib('review-agent-selection.md'); + + assert.match(command, /The host CLI is the review orchestrator/); + assert.match(command, /Strict mode does not force a focused agent/); + assert.match(command, /selection protocol/); + assert.match(command, /Spawn the selected agents simultaneously/); + assert.match(command, /If the selection is\s+empty, spawn no focused agents/); + assert.doesNotMatch(command, /Always dispatch agents 1–5/); + assert.doesNotMatch(command, /Spawn agents 1–5 simultaneously/); + + assert.match(selection, /Start with an empty `SELECTED_REVIEW_AGENTS` list/); + assert.match(selection, /If no focused lens is justified, dispatch no sub-agents/); + assert.match(selection, /Structural Ambition \| `--strict` is active \*\*and\*\*/); + assert.match(selection, /selected lenses and their reasons/); + + const summaryStart = command.indexOf('## Report'); + const report = command.slice(summaryStart); + assert.match(report, /The table is dynamic/); + assert.match(report, /Host orchestrator \(self-review\)/); + assert.match(report, /Omit all focused-lens rows when none were selected/); + }); + it('requires structured local-agent verdicts without weakening Codex handling', () => { const body = readLib('local-agent-review-loop.md'); assert.match(body, /after stripping blank lines, the result must be either exactly `NO FINDINGS`/); diff --git a/uninstall.sh b/uninstall.sh index 2007098..3c37bf9 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -104,7 +104,7 @@ LIBS=( local-agent-review-loop model-tiers multi-reviewer-loop ollama-review-loop per-finding-root-cause plan-id-format plan-issue-mode post-review-doc-recommendations remediation-agent-template - review-config-defaults review-convergence-gate + review-agent-selection review-config-defaults review-convergence-gate swift-review-checklist swift-gotchas review-surface-scan review-surface-quality review-security-audit review-cross-file-tracing review-cross-file-contract From 2c97146195a81ffa4f88e708d75d1d2565bca66f Mon Sep 17 00:00:00 2001 From: "[._.]/ Adam Eivy" Date: Tue, 25 Aug 2026 15:31:37 -0700 Subject: [PATCH 2/2] chore: release v3.34.0 --- .changelogs/v3.34.0.md | 25 +++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 .changelogs/v3.34.0.md diff --git a/.changelogs/v3.34.0.md b/.changelogs/v3.34.0.md new file mode 100644 index 0000000..4b31443 --- /dev/null +++ b/.changelogs/v3.34.0.md @@ -0,0 +1,25 @@ +# Release v3.34.0 + +Released: 2026-08-25 + +## Highlights + +- **`/do:review` now scales its review effort to the change.** The host orchestrator inspects the PR before dispatching focused review lenses, so small or narrowly scoped changes can complete without unnecessary sub-agents. +- **Review coverage remains evidence-driven.** Security, cross-file, structural, surface, and quality lenses are selected only when the changed files provide a concrete signal, while strict mode still preserves its required checks without forcing every optional lens. +- **Zero focused agents is a valid outcome.** When the host review finds no focused lens warranted, it records that decision and continues with the host review rather than treating the absence of sub-agents as a failure. +- **The selection policy is centralized and test-protected.** The new library contract is installed and uninstalled with the rest of the shared review libraries, and the parser tests cover adaptive selection and reporting. + +## Changed + +- `/do:review` and the Claude improve-review command now document host-owned adaptive dispatch, selected-lens reasons, and skipped-lens reporting. +- The README describes the review command's adaptive agent behavior. +- Installer and uninstaller allowlists include the shared review-agent-selection policy. + +## Tests + +- `git diff --check release...main` passed. +- The full Node test suite passed: 390 tests, 64 suites, 0 failures. + +## Full Changelog + +**Full Diff**: https://github.com/atomantic/slashdo/compare/v3.33.3...v3.34.0 diff --git a/package.json b/package.json index 0419c51..efd2dfb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "slash-do", - "version": "3.33.3", + "version": "3.34.0", "description": "Curated slash commands for AI coding assistants — Claude Code, OpenCode, Antigravity CLI, Codex, and Grok Build", "author": "Adam Eivy ", "license": "MIT",