Code review run
specfact code review run executes the governed review pipeline for a set of files or for an auto-detected repo scope.
The command prints progress to the terminal (spinner/status while the pipeline prepares and runs). With --json, it writes a machine-readable ReviewReport JSON file (defaulting to review-report.json in the working directory when --out is omitted).
The pipeline reviews .py and .pyi only. The --focus docs facet selects Python files whose path contains a docs/ directory segment (for example tooling beside the Jekyll site), not Markdown documentation pages. For published-site link, front matter, and command-example checks on the modules docs tree, run python scripts/check-docs-commands.py in this repository (see CI and contributing docs).
Command
specfact code review run [FILES...]
Key options
| Option | Purpose |
|---|---|
--scope changed\|full |
Review changed files or the full repository when no positional files are provided |
--path <prefix> |
Narrow auto-discovered review files to one or more repo-relative prefixes |
--include-tests, --exclude-tests |
Control whether changed test files participate in auto-scope review |
--focus <facet> |
Limit auto-discovered scope to source, tests, docs, and/or simplify (repeatable); mutually exclusive with --include-tests / --exclude-tests |
--enforcement full\|changed\|shadow |
full blocks on any blocking finding in reviewed files; changed blocks only blocking findings on changed lines (default changed); shadow records evidence and never blocks |
--mode shadow\|enforce |
Deprecated compatibility alias: --mode enforce maps to --enforcement full and --mode shadow maps to --enforcement shadow |
--level error\|warning |
Optional reporting level override before scoring: error keeps errors only (drops warnings and info); warning keeps errors and warnings (drops info only); omit to keep all severities (JSON, verdict, and ci_exit_code use the filtered list) |
--bug-hunt |
Enable exploratory / bug-hunt style heuristics in the review pipeline |
--include-noise, --suppress-noise |
Keep or suppress known low-signal findings |
--json |
Emit a ReviewReport JSON file |
--out <path> |
JSON output path (only valid together with --json) |
--score-only |
Print just the reward delta integer |
--no-tests |
Skip the TDD gate |
--fix |
Apply Ruff autofixes, then rerun the review |
--preview-fixes |
For --focus simplify, compute non-mutating patch evidence for supported safe-mechanical simplification fixers |
--with-mutation |
For --focus simplify, record opt-in mutation proof evidence for cleanup candidates; unavailable tooling is inconclusive |
--interactive |
Prompt for scope decisions before execution |
--instructions |
Print AI-facing simplify / clean-code workflow instructions and exit without running review |
Invalid combinations
The command validates several incompatible flag mixes before the review pipeline runs.
The Typer entrypoint validates review flags first: it raises typer.BadParameter when --include-tests is combined with --exclude-tests, or when --focus is combined with --include-tests or --exclude-tests. Request validation then rejects incompatible output modes (--json with --score-only, or --out without --json), and rules for conflicting targeting styles reject mixing positional FILES... with --scope or --path. Those deeper checks still surface as typer.BadParameter with the messages below.
- Positional
FILES...with--scopeor--path: when you pass explicit paths, do not also pass--scopeor--path(those options apply only to auto-discovery). Runtime error:Choose positional files or auto-scope controls, not both. --focuswith--include-testsor--exclude-tests: use--focusor the include/exclude test flags, not both. Runtime error:Cannot combine --focus with --include-tests or --exclude-tests--include-testswith--exclude-tests: pick at most one test inclusion mode. Runtime error:Cannot use both --include-tests and --exclude-tests--outwithout--json:--outis accepted only when--jsonis also set. Runtime error:Use --out together with --json.--jsonwith--score-only: do not combine JSON report output with score-only mode (Use either --json or --score-only, not both.).--preview-fixeswith--fix: preview is non-mutating and cannot be combined with write mode. Runtime error:Cannot combine --preview-fixes with --fix.--preview-fixeswithout simplify focus: preview evidence is scoped to cleanup findings. Runtime error:Use --preview-fixes only with --focus simplify.--with-mutationwithout simplify focus: mutation proof is scoped to cleanup candidates. Runtime error:Use --with-mutation only with --focus simplify.
Supported targeting: either pass positional file paths for a fixed review set (the pipeline still only reviews Python sources it accepts, such as .py / .pyi), or omit files and use --scope / --path (and related test flags) for auto-discovery — do not mix positional paths with --scope or --path.
Examples
Auto-discovered scope (omit positional files)
# Tracked + untracked changes; tests excluded by default for auto-scope
specfact code review run --scope changed
# Same, with bug-hunt heuristics on the discovered file set
specfact code review run --scope changed --enforcement changed --bug-hunt
# Full index, limited to one package (repeat --path for more repo-relative prefixes)
specfact code review run --scope full --path packages/specfact-code-review
# Package sources plus that package’s unit tests
specfact code review run --scope full --path packages/specfact-code-review --path tests/unit/specfact_code_review
# Errors only before scoring — warnings and info omitted from JSON, verdict, and ci_exit_code
specfact code review run --scope changed --level error
# Longer CrossHair budgets for exploratory bug-hunt pass (with explicit files)
specfact code review run --enforcement changed --bug-hunt --json --out /tmp/review-bughunt.json packages/specfact-code-review/src/specfact_code_review/run/commands.py
Enforcement modes and JSON to a file
--enforcement changed is the default for the CLI: it writes every finding to JSON, but only blocking findings on changed lines fail the process. Legacy findings elsewhere in touched files remain visible in findings plus enforcement_summary evidence.
--enforcement full is the strictest mode: any blocking finding in the reviewed files fails the process, including existing issues on untouched lines.
--enforcement shadow runs the full toolchain but forces process exit code 0 and JSON ci_exit_code 0 so callers can ingest reports without failing a step; overall_verdict still reflects the real outcome. The older --mode shadow form remains available as a compatibility alias.
specfact code review run --scope changed --enforcement changed --json --out /tmp/review-report.json
specfact code review run --scope full --enforcement full --json --out /tmp/review-full.json
specfact code review run --scope changed --enforcement shadow --json --out /tmp/review-shadow.json
--focus facets (repeatable)
Use --focus with source, tests, docs, and/or simplify (union of facets, then intersect with scope). Do not combine --focus with --include-tests or --exclude-tests. The simplify facet produces simplification-focused reports: advisory ai_bloat findings plus high-confidence dry and kiss findings that carry deterministic metadata such as rewrite_hint, canonical_pattern, intent_key, estimated_deletion_lines, and related_locations. Simplification-focused JSON also includes cleanup_forecast, signal_trace, preserve_reasons, and remediation_packet fields when available.
specfact code review run --scope changed --focus tests
specfact code review run --scope full --path packages/specfact-code-review --focus source
specfact code review run --scope full --focus docs
specfact code review run --scope changed --enforcement shadow --focus simplify --preview-fixes --json --out .specfact/code-review.json
specfact code review run --scope changed --enforcement shadow --focus simplify --with-mutation --json --out .specfact/code-review.json
Use the canonical .specfact/code-review.json path unless every consumer in your workflow has been updated to read a custom simplify report path.
AI instructions fallback
When an IDE does not support bundled prompts or skills, print the same guided simplify workflow for an AI assistant:
specfact code review run --instructions
The output explains how to remove AI bloat and apply clean-code simplifications using SpecFact evidence, including cleanup_forecast, safe_mechanical, needs_tests, design_judgment, preserve, remediation_packet, patch previews, conservative keep/skip defaults, and per-file validation. It also tells assistants how to handle clean PR branches where --scope changed has no worktree files: find branch-delta Python files with a base-ref diff such as git diff --name-only <base-ref>...HEAD -- '*.py' '*.pyi', review those files as explicit positional files, and treat findings without guidance_kind as unguided advisories rather than auto-fix input. ai_bloat findings are cleanup signals, not proof of AI authorship.
Positional files (explicit Python paths)
Do not pass --scope or --path when FILES... are present.
specfact code review run --json --out /tmp/review-report.json packages/specfact-code-review/src/specfact_code_review/run/commands.py
specfact code review run --score-only packages/specfact-code-review/src/specfact_code_review/run/commands.py
specfact code review run --fix packages/specfact-code-review/src/specfact_code_review/run/commands.py
specfact code review run --no-tests packages/specfact-code-review/src/specfact_code_review/run/commands.py
Noise and interactive test inclusion
specfact code review run --scope changed --include-noise
specfact code review run --scope changed --suppress-noise
specfact code review run --scope changed --interactive
Bundle-owned resources
The review pipeline uses rules, skills, and policy payloads shipped with the installed Code Review bundle. Those assets are bundle-owned and should be refreshed through supported bundle and IDE setup flows rather than legacy core-owned paths.
The built-in specfact/ai-bloat-patterns policy pack is parallel to specfact/clean-code-principles. It maps advisory ai_bloat rules to the ai_bloat principle, emits severity=info, and stays score-neutral so simplification candidates do not block commits. Omit --level when producing the JSON report for /specfact.08-simplify; --level error intentionally filters info-level findings out of the command report.
Use --focus simplify when producing the IDE simplification queue:
specfact code review run --scope changed --enforcement shadow --focus simplify --preview-fixes --json --out .specfact/code-review.json
Simplify-focused reports keep advisory ai_bloat findings plus high-confidence dry and kiss findings that include deterministic simplification metadata. Metadata fields such as rewrite_hint, canonical_pattern, intent_key, estimated_deletion_lines, related_locations, signal_trace, preserve_reasons, and remediation_packet are additive; legacy consumers can keep reading the original finding fields. The report-level cleanup_forecast summarizes reviewed LOC, estimated deletion ranges, guidance-kind totals, normalized AI-bloat density, weighted bloat points, and cleanup-yield LOC per KLOC. Simplification findings remain score-neutral; enforce mode blocks only unresolved safe-mechanical cleanup candidates.