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 --scope or --path: when you pass explicit paths, do not also pass --scope or --path (those options apply only to auto-discovery). Runtime error: Choose positional files or auto-scope controls, not both.
  • --focus with --include-tests or --exclude-tests: use --focus or the include/exclude test flags, not both. Runtime error: Cannot combine --focus with --include-tests or --exclude-tests
  • --include-tests with --exclude-tests: pick at most one test inclusion mode. Runtime error: Cannot use both --include-tests and --exclude-tests
  • --out without --json: --out is accepted only when --json is also set. Runtime error: Use --out together with --json.
  • --json with --score-only: do not combine JSON report output with score-only mode (Use either --json or --score-only, not both.).
  • --preview-fixes with --fix: preview is non-mutating and cannot be combined with write mode. Runtime error: Cannot combine --preview-fixes with --fix.
  • --preview-fixes without simplify focus: preview evidence is scoped to cleanup findings. Runtime error: Use --preview-fixes only with --focus simplify.
  • --with-mutation without 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.