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 |
--requirements-evidence <path> |
Attach a finalized schema-v2 Requirements proof as independent provenance in the review JSON; it does not affect the review verdict or exit code |
--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.
Requirements proof context
Use --requirements-evidence <path> to retain the provenance of a completed
Requirements proof beside the review result. The input must be a complete,
readable finalized proof accepted by the runtime loader: schema_version:
"2", execution_proof.run_stage: "final", valid SHA-256
mapping_digest and plan_digest values, a 40- or 64-character
hexadecimal execution_proof.source_ref, and a gate_decision of
pass or fail.
The resulting ReviewReport uses schema version 1.5 and records the
proof path, content digest, mapping and plan digests, source revision, and the
Requirements gate decision under requirements_evidence.
This is context only: Code Review does not reinterpret the Requirements proof, and the Requirements decision neither changes the review verdict nor its exit code. A finalized Requirements failure can therefore remain visible as provenance while an otherwise clean review reports its own independent result.
specfact code review run --json --out .specfact/code-review.json \
--requirements-evidence artifacts/requirements-evidence.json \
packages/specfact-code-review/src/specfact_code_review/run/commands.py
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 --path packages/specfact-code-review --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.