Skip to content
Merged
20 changes: 20 additions & 0 deletions docs/users/features/code-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,26 @@ The deterministic halves of the pipeline — argument parsing (`qwen review pars

Every run ends with one machine-readable line (`Review complete: <target> — <disposition>`), so scripts and CI wrappers can detect completion and outcome with a single `^Review complete: ` match.

## Headless runs (`qwen review run`)

`/review` is interactive. When a script or CI job needs to run a review and act on its outcome, use the headless wrapper:

```bash
qwen review run [target] [--json] [--fail-on request-changes] [--comment] [--quiet]
```

`target` is a PR number, a PR URL, or a file path; omit it to review the local working tree. The command runs this build's own CLI non-interactively (with stdin closed, so slash-command detection survives), streams the child's progress to **stderr**, and prints the verdict to **stdout** — or, with `--json`, the full result object. The verdict is read from the artifact `compose-review` writes (the same JSON the skill treats as the verdict authority), never parsed from the model's prose.

The exit code is the contract a gate should read:

| Exit | Meaning |
| ---- | ------------------------------------------------------------------------------------------------- |
| `0` | The review completed (whatever it decided) |
| `1` | It never reached a verdict — the child failed, timed out, or left no composed artifact |
| `3` | It completed with `REQUEST_CHANGES` **and** `--fail-on request-changes` was set (opt-in blocking) |

`3` (not `2`) lets a gate distinguish "the review is blocking" from "the tool broke" — yargs already uses `1` for usage errors — without parsing any output. `--timeout-minutes` (default 120, floored at 1) terminates a hung review and exits `1`, and cancelling the command (Ctrl+C / SIGTERM) terminates the review's process group rather than orphaning it.

## Cross-file Impact Analysis

A dedicated cross-file tracer (Agent 1c) owns this walk end-to-end. When code changes modify exported functions, classes, or interfaces, it searches for all callers and checks compatibility:
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const TOP_LEVEL_COMMANDS = [
['mcp', 'Manage MCP servers'],
[
'review <command>',
'Internal helpers used by the /review skill (PR worktree setup, context fetch, rules loading, presubmit checks, cleanup)',
'Run a review non-interactively (`run`), plus the internal helpers used by the /review skill (PR worktree setup, context fetch, rules loading, presubmit checks, cleanup)',
],
[
'serve',
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/commands/review.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ describe('reviewCommand', () => {

it('registers exactly the expected internal helper subcommands', () => {
expect(registeredSubcommands()).toEqual([
'run',
'parse-args',
'fetch-pr',
'capture-local',
Expand Down
6 changes: 4 additions & 2 deletions packages/cli/src/commands/review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ import { scriptLintCommand } from './review/script-lint.js';
import { submitCommand } from './review/submit.js';
import { testEfficacyCommand } from './review/test-efficacy.js';
import { cleanupCommand } from './review/cleanup.js';
import { runCommand } from './review/run.js';

export const reviewCommand: CommandModule = {
command: 'review',
describe:
'Internal helpers used by the /review skill (PR worktree setup, context fetch, rules loading, presubmit checks, cleanup)',
'Run a review non-interactively (`run`), plus the internal helpers used by the /review skill (PR worktree setup, context fetch, rules loading, presubmit checks, cleanup)',
builder: (yargs: Argv) =>
yargs
.command(runCommand)
.command(parseArgsCommand)
.command(fetchPrCommand)
.command(captureLocalCommand)
Expand All @@ -52,7 +54,7 @@ export const reviewCommand: CommandModule = {
.command(cleanupCommand)
.demandCommand(
1,
'Specify a subcommand: parse-args, fetch-pr, capture-local, plan-diff, pr-context, comment-status, load-rules, agent-prompt, build-test, script-lint, resolve-anchors, check-coverage, presubmit, test-efficacy, compose-review, submit, or cleanup.',
'Specify a subcommand: run, parse-args, fetch-pr, capture-local, plan-diff, pr-context, comment-status, load-rules, agent-prompt, build-test, script-lint, resolve-anchors, check-coverage, presubmit, test-efficacy, compose-review, submit, or cleanup.',
)
.version(false),
handler: () => {
Expand Down
Loading
Loading