From focused-review
Run unified code reviews through a 5-phase discovery-consolidation-assessment pipeline
How this skill is triggered — by the user, by Claude, or both
Slash command
/focused-review:focused-review [branch|commit|staged|unstaged|full|refresh|configure|post-mortem|post-comments] [path ...][branch|commit|staged|unstaged|full|refresh|configure|post-mortem|post-comments] [path ...]The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are the orchestrator for the focused-review plugin. Your mode depends on the argument.
POST-COMMENTS.mdREFRESH.mddefaults/code-duplication.mddefaults/concern-framework.mddefaults/concerns/architecture.mddefaults/concerns/bugs.mddefaults/concerns/security.mddefaults/general-review.mdscripts/focused-review.pyscripts/tests/__init__.pyscripts/tests/test_concerns.pyscripts/tests/test_discover.pyscripts/tests/test_plugin_manifests.pyscripts/tests/test_post_comments.pyscripts/tests/test_post_comments_ado.pyscripts/tests/test_pr_utils.pyscripts/tests/test_prepare_review.pyscripts/tests/test_rules_dir_resolution.pyscripts/tests/test_run_concerns.pyYou are the orchestrator for the focused-review plugin. Your mode depends on the argument.
Before any mode-specific logic, locate the Python helper and resolve all configuration.
The Python helper script is at scripts/focused-review.py within this skill file's directory. Construct the full path from this skill file's location.
Run:
python {script_path} resolve-config --repo .
Parse the JSON output and store these values for use throughout:
script_path — confirmed full path to the Python helperrules_dir — directory containing review rule files (e.g. review/rules/)concerns_dir — directory containing concern files (e.g. review/concerns/)defaults_dir — built-in defaults shipped with the pluginsources — explicit source files from focused-review.json (may be empty)Parse the user's argument (available as $ARGUMENTS):
configure or refresh → Read REFRESH.md from the same directory as this skill file and follow its instructions. Pass along the resolved Script path, Rules directory, Concerns directory, Defaults directory, and Configured sources values.post-comments (followed by a PR URL) → Read POST-COMMENTS.md from the same directory as this skill file and follow its instructions. Pass along the resolved Script path and the PR URL (the remaining argument text after post-comments).post-mortem (with optional finding numbers) → Post-Mortem ModeIf none of the above match, proceed to Step B.
The user's argument may contain an explicit scope keyword, free-text describing what to review, or both. Your job is to determine three things: scope (branch, commit, staged, unstaged, or full), paths (optional list of directories/globs), and base ref (optional, for branch scope only — overrides the configured base).
1. Explicit scope keyword — if the argument starts with one of branch, commit, staged, unstaged, full, use it directly. Everything after the keyword is path filters (and optionally a base ref).
/review branch src/ → scope branch, paths ["src/"]/review full → scope full, no paths/review staged **/*.cs → scope staged, paths ["**/*.cs"]2. Empty or missing argument — scope branch, no paths.
3. Free-text (no explicit scope keyword) — infer the scope from intent:
| User intent | Scope | Examples |
|---|---|---|
| Describes code to review, no mention of changes/diffs | full | "review all the unit tests", "review the auth module", "review src/services/" |
| Mentions a path without qualifying it | full | "review path/to/something" |
| Says "changes" but specifies a diff type | that type | "review unstaged changes", "review what I committed" |
| Says "changes" without specifying a diff type | ambiguous — see below | "review changes in src/auth" |
Handling ambiguity: When the user says "changes" but doesn't specify which kind (branch diff? staged? unstaged?), check for an unattended directive — phrases like "CI run", "don't ask questions", "unattended", "just do it".
branch (most common CI use case) and proceed.Base ref extraction: If the user mentions comparing against a specific branch or ref (e.g., "against origin/dev", "compared to develop", "vs upstream/release"), extract it as the base ref. This only applies to branch scope. If not mentioned, omit it — the Python script resolves the base from focused-review.json config (key: "base_branch"), falling back to origin/main.
Path extraction: After determining the scope, extract path filters from the remaining text. The user may describe paths in natural language ("the auth module in src/services/auth") — resolve these to actual directory or glob paths. If the user describes files by type or pattern ("all the unit tests", "*.cs files"), convert to appropriate globs (e.g., **/*Tests*.cs, **/*.cs).
Examples of full resolution:
review all the unit tests → scope full, paths ["**/*Tests*", "**/*Test*", "**/*_test*", "**/test_*"] (adapt globs to the repo's test naming convention)review branch → scope branch, no pathsreview unstaged changes → scope unstaged, no pathsreview path/to/something → scope full, paths ["path/to/something"]review changes in src/auth (interactive) → ask user to clarify scope, paths ["src/auth"]review changes in src/auth, CI run don't ask questions → scope branch, paths ["src/auth"]review branch against origin/dev → scope branch, no paths, base ref origin/devreview changes vs develop → scope branch, base ref developStore the resolved scope, paths, and base ref for use in Step 1.
Five-phase pipeline: Discovery → Consolidation → Assessment → (Rebuttal) → Presentation.
Rules and concerns run in parallel during Phase 1. Subsequent phases validate and refine findings.
Your role is orchestration only. You do not generate diffs, discover files, read rules, or review code yourself. You run the Python script, then dispatch subagents using its output. Every step below either runs the Python script or launches subagents — if you find yourself running git commands or reading source files, you are doing it wrong.
Run the Python helper with the scope from the argument (default branch):
python {script_path} prepare-review --repo . --scope {scope} {path_args} {base_args}
Where:
{path_args} is --path {path1} {path2} ... if paths were parsed in Mode Selection, or omitted entirely if no paths were specified.{base_args} is --base {base_ref} if the user specified a base ref in Mode Selection, or omitted entirely to use the configured default (from focused-review.json "base_branch" key, falling back to origin/main).The script handles everything: git operations, diff generation, file discovery, rule matching, and chunking. It writes all artifacts to a timestamped run directory (.agents/focused-review/{timestamp}/) and prints a JSON summary to stdout.
Error handling:
REFRESH.md (same directory as this skill file). After refresh completes, re-run this prepare-review step with the same scope.Parse the JSON summary. Store the run_dir field — this is the timestamped directory where all artifacts for this review run are stored. All downstream paths use this directory.
If agents is 0 and concern_prompts is 0, tell the user no rules matched and no concerns apply, and stop.
Read {run_dir}/dispatch.json (rule dispatch) and {run_dir}/concern-dispatch.json (concern dispatch).
IMPORTANT: Do NOT read the rule files, diff/chunk files, or concern prompt files yourself. The subagents and concern runner read their own files. You only need the metadata from dispatch.json (paths, model) to construct the agent prompts — never view or cat the rule or diff content.
Concurrency cap: 12 agents at a time. The concern runner counts as 4 agents (it runs 4 concurrent copilot sessions internally). This means:
Rule agents — For each entry in dispatch.json, launch a review-runner Task agent. Each agent's prompt must contain exactly:
rule_path: {entry.rule_path}
chunk_path: {chunk_path_value}
scope: {entry.scope}
chunk: {chunk_index} of {total_chunks}
findings_path: {run_dir}/findings/rule--{rule-name}.md
Where:
chunk_path_value is entry.chunk_path when not null, or {run_dir}/changed-files.txt when null (for full scope)chunk line: include as {chunk_index} of {total_chunks} when both are present. Omit the line entirely when chunk_index is null.{rule-name} is the rule filename without extension from rule_path (e.g. null-handling from review/rules/null-handling.md). When a rule has multiple chunks, append the chunk index: rule--null-handling--2.md.Use the model specified in each entry's model field. If "inherit", pass your own model (the model you are currently running as — check your system prompt's <model> tag for the id attribute) to the Task tool's model parameter. This ensures subagents run at the same quality level as the orchestrator.
Concern runner — If concern-dispatch.json has entries, start the Python concern runner in the first batch alongside rule agents. Use the powershell tool with mode="sync" and initial_wait: 300 (concern sessions can take several minutes):
python {script_path} run-concerns --repo . --run-dir {run_dir} --inherit-model {your_model_id}
Where {your_model_id} is the same model ID you used for inherit rules above (from your system prompt's <model> tag id attribute).
This launches copilot -p sessions in parallel via ThreadPoolExecutor. It reads concern-dispatch.json from the run directory and writes findings to {run_dir}/findings/concern--{name}--{model}.md.
Batch execution procedure:
If dispatch.json is empty (no rules matched), only run concerns. If concern-dispatch.json is empty (no concerns), only run rules.
Rule agents write their findings directly to {run_dir}/findings/. The concern runner does the same. After all batches complete, verify the findings directory has the expected files before proceeding.
Launch a focused-review:review-consolidator Task agent with this prompt:
findings_dir: {run_dir}/findings
output_path: {run_dir}/consolidated.md
This agent reads all finding files from Phase 1 (rule--*.md and concern--*.md), deduplicates semantically (same location + same issue = one finding), merges provenance, and writes {run_dir}/consolidated.md with up to 30 prioritized findings.
Wait for completion. If the agent fails, report the error and skip to Step 6 with whatever findings are available. If the consolidated report shows 0 findings, skip to Step 6 and report "no findings".
Skip this step for full scope (no diff to assess against). Proceed directly to Step 6 using the consolidated report.
Read {run_dir}/consolidated.md. Parse each finding section (headings starting with ### C-). Count the total findings. If 0, skip to Step 6.
Derive the project context path: take the parent directory of rules_dir (e.g., if rules_dir is review/rules/, the parent is review/) and check if project.md exists there. If it does, use it as project_context_path. If not, omit the line from the assessor prompt.
For each finding, launch a focused-review:review-assessor Task agent. Derive the assessment ID from the finding ID: C-01 → A-01, C-02 → A-02, etc.
finding_id: {e.g. C-01}
assessment_id: {e.g. A-01}
finding_text: {the full text of this one finding section, from ### C-XX to the next --- or end}
diff_path: {run_dir}/diff.patch
rules_dir: {rules_dir}
concerns_dir: {concerns_dir}
project_context_path: {path to review/project.md — omit this line if file doesn't exist}
output_path: {run_dir}/assessments/{assessment_id}.md
Launch assessors in parallel — all in a single response (up to 12; if more, use subsequent responses for remaining batches). Each assessor investigates one finding independently.
Wait for all assessors to complete. If individual assessors fail, continue with the rest.
After all assessors complete, read every .md file in {run_dir}/assessments/ (in ID order: A-01, A-02, ...). Assemble {run_dir}/assessed.md by:
**Verdict:** lines)# Assessment Report
**Findings assessed:** {total}
**Confirmed:** {count}
**Questionable:** {count}
**Invalid:** {count}
---
---Skip this step for full scope (no diff to assess against).
Read {run_dir}/assessed.md. Find any findings with Severity Critical or High that received a verdict of Invalid.
If none exist, skip to Step 6.
For each such finding, launch a general-purpose Task agent (launch all rebuttals in parallel in a single response):
You are a rebuttal agent. A high-priority finding was assessed as Invalid. Challenge this assessment.
Read the assessed finding and the diff. Construct arguments for why this finding IS valid despite the assessor's counter-arguments. Consider edge cases, race conditions, subtle interactions, and error paths the assessor may have missed.
Finding ID: {A-XX}
File: {file path from finding}
Title: {title from finding}
Description: {description from finding}
Assessment reasoning: {assessment reasoning from finding}
Counter-arguments: {counter-arguments from finding}
Diff path: {run_dir}/diff.patch
Write your rebuttal to {run_dir}/rebuttals/{A-XX}.md with:
- Your counter-counter-arguments
- Whether the assessor's dismissal holds up under scrutiny
- Final recommendation: Reinstate (with what severity) or Uphold Invalid
After all rebuttals complete, read each rebuttal file. For any finding where the rebuttal recommends "Reinstate", note the finding ID and reinstated severity — you will apply these overrides when compiling the report in Step 6.
Determine the data source and type (check in order, use the first that exists):
{run_dir}/assessed.md exists → data_source_type: assessed{run_dir}/consolidated.md exists → data_source_type: consolidateddata_source_type: raw_findings (path: {run_dir}/findings)Build the rebuttal_overrides value: if Step 5 produced any "Reinstate" recommendations, format as a JSON list of {"id": "A-XX", "severity": "High", "reasoning": "..."}. Otherwise omit the line.
Launch a focused-review:review-reporter Task agent:
data_source: {path to assessed.md, consolidated.md, or findings/ — all within run_dir}
data_source_type: {assessed|consolidated|raw_findings}
report_path: {run_dir}/review.md
scope: {scope}
rule_count: {rule_count}
concern_count: {concern_count}
rebuttal_overrides: {JSON list or omit}
The report is named review.md within the timestamped run directory.
Wait for completion. Relay the agent's text output directly to the user — copy-paste it verbatim. Do not read the report file. Do not rephrase, reformat, or create your own summary table. The reporter agent's output already contains the report path, pipeline stats, findings table with "Found by" column, and rule quality notes. Your only job is to pass it through.
User-triggered analysis after reviewing a report. The user marks findings they consider invalid. The system traces each back to its source rule or concern via provenance, analyzes the false-positive pattern, and suggests specific adjustments. Suggest-only — does not edit rule or concern files.
Find the most recent review report across all run directories in .agents/focused-review/:
python -c "from pathlib import Path; dirs=sorted(d for d in Path('.agents/focused-review').iterdir() if d.is_dir()); reports=[(d / 'review.md') for d in dirs if (d / 'review.md').exists()]; print(str(reports[-1]).replace(chr(92),'/') if reports else 'NONE')"
If NONE, tell the user no review report exists and stop.
Read the report file.
Parse the arguments after post-mortem for finding numbers. Accept comma-separated, space-separated, or mixed (e.g., 1,3,5 or 1 3 5 or 1, 3, 5).
If no numbers provided, present the numbered summary table from the report and ask the user which findings they consider invalid. Wait for their response before continuing.
For each specified number, locate the corresponding finding in the report (match the ### {n}. heading in the Confirmed or Questionable sections). Extract:
rule:sealed-classes, concern:bugs (opus))If a number doesn't match any finding, warn the user and skip it.
Parse each finding's Provenance field into individual sources. Each source follows one of these formats:
rule:{name} → source file is {rules_dir}/{name}.mdconcern:{name} ({model}) → source file is {concerns_dir}/{name}.md, falling back to {defaults_dir}/concerns/{name}.mdBuild a map: source → list of findings traced to it.
For each unique source, read the source file. If the file doesn't exist, note it as "source removed or renamed" and still include it in the analysis (the finding provenance itself is sufficient context).
For each source that produced one or more invalid findings, analyze the false-positive pattern:
For rule sources:
## Rule, ## Requirements, and ## Wrong / ## Correct sectionsapplies-to glob matches files where the rule doesn't apply → suggest narrowing the globsonnet or inheritFor concern sources:
## What to Check and ## Evidence Standards (including its Anti-patterns to avoid list)applies-to restrictionWrite to the same run directory as the reviewed report — e.g. if the report is at .agents/focused-review/20260402-103000/review.md, write to .agents/focused-review/20260402-103000/post-mortem.md:
# Post-Mortem: Invalid Finding Analysis
**Date:** {ISO timestamp}
**Review report:** {report filename}
**Findings analyzed:** {count}
---
## Source Analysis
### {Rule|Concern}: {source name}
**Invalid findings traced here:** {count}
{for each finding:}
- Finding #{n}: [{severity}] {title} (`{file}`)
**Pattern:** {what these false positives have in common — 1-2 sentences}
**Root cause:** {category from Step 4}
**Recommendation:** {specific, actionable suggestion — 1-3 sentences describing what to change}
**Suggested edit:**
> In `{source file path}`, {section to modify}:
> ```
> {show the specific text to add or change}
> ```
---
{repeat for each source}
## Summary
| Source | Type | Invalid Findings | Root Cause | Action |
|--------|------|-----------------|------------|--------|
| {name} | rule/concern | {count} | {root cause} | {one-line action} |
Tell the user:
/focused-review refresh and incorporate the recommendations, or edit the rule/concern files directly."Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub 0101/focused-review --plugin focused-review