Skip to content

Review Workflow

This page covers day-to-day Apex Ray usage after installation and project initialization.

Choose A Review Target

Use one target per review run:

Target Command Use when
Unstaged worktree changes apex-ray review --worktree You are iterating locally before staging.
Staged changes apex-ray review --staged You want review to match the next commit.
Branch diff apex-ray review --base main You want PR-like review of main...HEAD.
Supplied diff file apex-ray review --diff change.diff You captured a patch outside the current worktree.
Partial report continuation apex-ray review --continue-from .apex-ray/reports/review.json You need to review skipped or residual context packs.

Reports are written under .apex-ray/reports/ by default. For stable automation, pass explicit paths:

apex-ray review \
  --base main \
  --llm \
  --output .apex-ray/reports/review.md \
  --json .apex-ray/reports/review.json \
  --html .apex-ray/reports/review.html \
  --sarif .apex-ray/reports/review.sarif

For --worktree, every writable report or cache path inside the repository must be untracked and Git-ignored so report/checkpoint/cache writes cannot change the review target. This includes custom LLM and analyzer cache paths and relative APEX_RAY_CACHE_HOME/XDG_CACHE_HOME values. The defaults created by apex-ray init satisfy this requirement; an external absolute path is also safe. Apex Ray checks these paths before running analyzers or providers.

Review Modes

No-LLM mode is deterministic and cheap:

apex-ray review --worktree --no-llm

It still parses the diff, runs available language analyzers, builds context packs, and reports review coverage surfaces.

LLM mode sends selected context packs to the configured provider, which may be a local CLI, a built-in direct API, or a custom compatible endpoint:

apex-ray review --worktree --llm

By default, the configured verifier reviews candidate findings before they are published. Use --no-verify only for exploratory runs where speed matters more than publication quality.

Reports

Apex Ray writes:

  • Markdown for local reading.
  • JSON for durable automation and continuation.
  • Optional HTML for browser-based inspection.
  • Optional SARIF 2.1.0 for GitHub code scanning and other compatible systems.

Reports include findings, analyzer warnings, selected context packs, skipped packs, LLM routes, cache usage, token estimates, coverage status, and continuation commands.

Report paths are latest snapshots by default. Reusing the same paths overwrites the previous latest report. apex-ray init enables report archives so per-run artifacts survive short-lived worktrees:

review:
  reports:
    archive: true
    archive_dir: ${local_data}/reports/runs
    retention: 20

Report artifacts can include source snippets, findings, file paths, provider metadata, and token estimates. Keep generated reports ignored unless a team intentionally curates a specific artifact.

Coverage And Continuation

LLM coverage modes control how broadly Apex Ray reviews a diff:

  • fast: capped deep review.
  • balanced: deep review for high-value packs plus shallow breadth under token budget.
  • exhaustive: prioritize every reviewable pack, while still honoring pack, deep-review, input-token, and provider limits.

Large diffs can still be partial. The report makes partial coverage explicit with reviewed and unreviewed pack IDs, residual priorities, skipped reasons, and continuation commands.

The report-level LLM completion status has a separate, deliberately strict meaning:

  • complete: every context pack and matching reviewer assignment in the report scope was reviewed and no partial coverage debt remains;
  • partial: reviewable work remains, but the run did not record a hard execution or budget failure;
  • incomplete: work remains because a pack could not fit the configured budget, a reviewer execution or verification failed, or required-reviewer policy debt remains;
  • disabled: LLM review was not enabled for the run.

Findings always describe the reviewed scope. “No blocking findings” or zero findings in a partial/incomplete report does not mean that the entire diff was reviewed cleanly. Unique context-pack coverage and reviewer assignments are also different counters: one pack reviewed by two specialists is one reviewed pack but two completed reviewer-pack assignments.

Continue only unreviewed P0 packs:

apex-ray review \
  --continue-from .apex-ray/reports/review.json \
  --residual-priority p0 \
  --llm

An ordinary continuation is one budgeted reviewer pass. The effective max_packs, max_deep_packs, and max_input_tokens values still apply to each selected reviewer; CLI --llm-max-* overrides remain run-wide cost limits. Repeat the command for another manual pass, or use bounded completion when the selected reviewer scope must be drained automatically.

Drain one baseline reviewer scope in bounded batches:

apex-ray review \
  --continue-from .apex-ray/reports/review.json \
  --reviewer correctness \
  --until-complete \
  --followup-max-pack-reviews 16 \
  --max-followup-passes 8 \
  --llm

--until-complete writes the best report it can produce and reports why it stopped. Add --strict-coverage when an incomplete result must exit non-zero; reports are still written before that exit. --strict-coverage implies the same completion loop, so it can also be used without spelling --until-complete.

After every completed follow-up batch, Apex Ray writes each configured Markdown and JSON latest-report file through an atomic replacement. If the process is later interrupted, the JSON file is a valid resume point for another --continue-from run rather than a partially written artifact. Optional HTML, SARIF, telemetry, and archives are finalized after the loop.

Each follow-up batch is capped in reviewer-pack assignments by --followup-max-pack-reviews, and --max-followup-passes bounds the number of batches. Provider retries and verification requests are additional calls. The loop stops early on completion, no eligible work, or no measurable progress. It cannot be combined with --auto-followup, continuation pack/slice/priority filters, or --no-llm.

Pass one or more --reviewer flags to make the completion scope explicit. If they are omitted, a configuration with several enabled reviewers must have exactly one required: true baseline reviewer; otherwise the command rejects the ambiguous scope. A configuration with only one enabled reviewer and the built-in general-reviewer configuration are unambiguous. On a fresh review, that uniquely required baseline is the only reviewer run by the completion command; other configured reviewers are not started implicitly.

Explicit reviewer completion applies only to context packs matching the selected reviewer filters and to that reviewer's assignments. It does not drain unrelated global packs. The scoped coverage_completion result can therefore be complete while the report-level LLM coverage remains partial because debt exists outside the selected matching scope. Use an unfiltered baseline reviewer when the completion check is intended to cover the full reviewable diff.

exhaustive alone is not a completion contract: it still obeys the configured caps. Use bounded completion when the selected reviewer scope is a release or CI requirement, and size its limits for the expected worst case.

Safe Continuation Targets

New reports fingerprint their review input. Before a continuation makes an LLM call, Apex Ray verifies the saved target:

  • base reviews retain HEAD, merge-base, and diff identities;
  • staged and worktree reviews retain HEAD and diff identities;
  • incremental pre-push Git ranges retain their range start, HEAD, and diff identities and remain live Git targets;
  • only user-supplied --diff files become immutable, detached report snapshots.

If the live base, staged, worktree, or incremental range target changed, continuation stops and asks for a fresh review instead of attributing archived context packs to the new diff. The completion loop repeats this check around every batch. A detached --diff continuation prints a notice because live Git state is not part of its target.

Reports produced by older Apex Ray versions have no input snapshot. Ordinary non-completion --continue-from remains available for compatibility, but Apex Ray prints a warning and can only review archived context packs; it cannot prove that they match the current Git state. --until-complete and --strict-coverage reject such reports because a multi-batch completion contract cannot run safely without target validation. Run a fresh review to use bounded completion.

Continue with automatic P0 follow-up after a first pass:

apex-ray review \
  --base main \
  --llm \
  --auto-followup \
  --auto-followup-max-pack-reviews 16

This CLI switch retains the focused P0 behavior. The automatic pass is capped by reviewer-pack assignment, so a context pack matched by two specialist reviewers consumes two assignments. Explicit --continue-from or bounded completion commands remain available when you intentionally want to process more residual work.

Pre-Push Gate

apex-ray gate pre-push runs the configured gate policy over review.base...HEAD.

Default gate behavior:

  • writes .apex-ray/reports/pre-push.md and .apex-ray/reports/pre-push.json;
  • blocks on verified high or critical findings;
  • blocks on failed LLM coverage quality gate;
  • blocks on critical partial coverage;
  • prints live progress to stderr and a compact blocking summary to stdout.

The generated configuration enables a generalized automatic follow-up capped at 16 primary reviewer-pack assignments. It selects the exact packs behind the blocking decision: the default critical partial threshold contributes P0 work, major expands threshold debt to P0/P1, and minor to P0/P1/P2; provider/verifier failures, unfinished selected required-reviewer assignments, configured source/high-risk thresholds, and high-risk depth debt remain eligible by their concrete pack IDs. Matching assignments deferred by reviewer limits remain visible as warnings unless an explicit strict/complete coverage policy requires them. Retries, provider fallbacks, and finding verification may add requests. See Pre-Push Gate configuration for the canonical and legacy keys.

Run it manually before relying on hook behavior:

apex-ray gate pre-push

If a bounded pass leaves blocking P0 debt, the next eligible incremental attempt resumes the validated pre-push report for another bounded pass. The printed continuation commands also write back to that report, so a completed manual continuation clears the carried debt. If commits were added in the meantime, Apex Ray requires one additional gate run to review that pending delta. Response and analyzer caches reduce repeated work throughout this process. If a carried coverage retry has no eligible work while newer commits are pending, the gate refreshes the full current base range immediately instead of repeatedly starving that delta. Continuation guidance uses POSIX shell syntax on macOS/Linux and explicitly PowerShell-safe syntax on Windows.

Local False Positives

For a confirmed one-off local false positive, create an expiring local suppression instead of bypassing the gate:

apex-ray findings list --from-report .apex-ray/reports/pre-push.json
apex-ray findings suppress apex-<id> \
  --from-report .apex-ray/reports/pre-push.json \
  --reason "This path is guarded before the reviewed helper is called."

Use suppressions sparingly. Inspect the finding evidence, current code, and relevant tests or invariants before suppressing. The reason should be concrete enough for a later agent to audit; do not suppress uncertain findings or real defects just to get a push through.

The next apex-ray gate pre-push run still writes the raw finding in the report, but the gate decision lists it under suppressed findings and does not block on it. Suppressions are local, expire automatically, and become stale when the matching context pack changes. When that happens, the gate output/report prints the stale suppression and prior reason, and the finding blocks again until it is re-checked. Use apex-ray findings suppressions, apex-ray findings unsuppress sup-<id>, or apex-ray findings prune for cleanup.

Commit a kind: false_positive memory card only for repeated, generalizable calibration. Do not commit raw local suppressions.

Caches

Apex Ray uses two local caches by default:

  • ${local_data}/cache/llm for provider responses keyed by prompt context and routing. With the default review.local_data.root: git_common, linked worktrees from the same local clone share this cache.
  • analyzer repo index caches where a backend supports them. Today this applies to TypeScript/JavaScript and Dart repository analysis; the Python analyzer is in-process and does not yet maintain a persistent repo index cache.

Refresh LLM cache entries:

apex-ray review --worktree --llm --refresh-cache

Refresh analyzer cache entries:

apex-ray review --worktree --refresh-analyzer-cache

Disable the LLM cache for one run:

apex-ray review --worktree --llm --no-cache

Privacy Boundary

Without --llm, Apex Ray stays local and deterministic.

With --llm, Apex Ray sends selected diff and context-pack content to the configured provider. A local CLI controls its own network and account boundary; a direct API provider sends HTTPS requests to its configured service endpoint. Review the applicable CLI, API, gateway, account, privacy, and retention policy before using Apex Ray on private code. Caches, telemetry, and archived reports are local files, while CI artifacts and SARIF follow the retention and access policy of the CI platform. All may contain repository paths, model names, finding counts, provider metadata, and source snippets.

For a pull-request workflow with protected API secrets, reviewer matrices, artifacts, and SARIF upload, see GitHub Actions.

Common Troubleshooting

Run setup diagnostics:

apex-ray doctor

Typical issues:

  • Config: not found: run apex-ray init in the target repository or pass --config.
  • Python analyzer available: false: reinstall Apex Ray or run from a healthy source checkout. The Python analyzer is built in and should normally be available whenever the CLI imports successfully.
  • TypeScript analyzer built: false: reinstall the published package, or in a source checkout run the TypeScript analyzer build from Development.
  • Dart analyzer available: false: select the project's Dart/Flutter SDK, activate FVM, or configure review.analyzer.dart.command; then resolve dependencies with the same SDK. See Dart analyzer configuration.
  • Dart package imports are unresolved: run flutter pub get or dart pub get in the relevant workspace or package using the SDK shown by doctor.
  • Dart results remain stale after an SDK or package metadata change: run one review with --refresh-analyzer-cache, then return to normal cached reviews.
  • Provider command not found: for a CLI provider, install the configured Codex CLI or Claude Code CLI, or override its executable path in .apex-ray/config.local.yml.
  • API credential or endpoint rejected: check the selected environment-variable names and, in CI, APEX_RAY_API_ALLOWED_HOSTS plus the role-specific APEX_RAY_API_ALLOWED_BASE_URL_ENV_VARS, APEX_RAY_API_ALLOWED_API_KEY_ENV_VARS, and APEX_RAY_API_ALLOWED_HEADER_ENV_VARS policies. For a custom CI orchestrator, set trusted job variable APEX_RAY_CI=true.
  • Hook cannot find apex-ray: install Apex Ray on the user PATH used by git hooks, or update the hook environment.