# Review Progress Observability Design

## Summary

Improve `/code-review` observability without exposing model reasoning or flooding the conversation. While a review is running, Pi shows a continuously animated status with the current stage, completed work, and elapsed time. The conversation retains a small set of structured milestone messages containing useful process summaries.

Pi's startup welcome content is outside this package's control. A blank startup caused by `quietStartup: true` is handled through troubleshooting documentation rather than by mutating the user's global Pi settings.

## Goals

- Make it visually clear that `/code-review` is still running during long model calls.
- Show the current review stage and meaningful completion counts.
- Preserve concise milestone summaries in the conversation.
- Report the stage that failed or was cancelled.
- Remove all transient UI state after success, failure, or cancellation.
- Keep the orchestrator independent from Pi's UI APIs.

## Non-goals

- Displaying chain-of-thought, hidden reasoning, prompts, or raw agent JSON.
- Streaming complete child-agent responses into the conversation.
- Adding user controls for animation speed, colors, or milestone verbosity.
- Changing Pi's `quietStartup` setting from the extension.
- Changing the review policy, concurrency limits, or publication rules.

## User Experience

### Transient Running Status

While the command is active, a widget above the editor and a compact footer status show a rotating spinner, current stage, progress count when applicable, and elapsed time. Example:

```text
⠹ Code review · Independent reviewers 3/5 · 28s
```

The animation advances every 400 milliseconds even when no subprocess event arrives. This distinguishes a slow model call from a stalled or static command.

The status progresses through these user-facing stages:

1. Resolving pull request.
2. Preparing review snapshot.
3. Triaging change.
4. Summarizing task.
5. Running independent reviewers, including `n/5` completion.
6. Validating candidates, including `n/total` completion.
7. Aggregating findings.
8. Publishing GitHub review when `--comment` is present.

The transient widget and footer status are cleared in a `finally` path. No timer survives command completion.

### Conversation Milestones

The extension adds persistent custom messages only at meaningful boundaries:

- PR resolved: PR number, changed-file count, and linked-issue count.
- Triage completed: review/skip decision and concise reason.
- Task summary completed: the structured summary returned by the summary agent.
- Independent review completed: completed reviewer count and candidate-finding count.
- Validation completed: validated candidate count and accepted high-confidence count.
- Final result: the existing rendered report, incomplete-stage diagnostic, or cancellation result.

Per-agent starts, animation frames, and raw outputs are not persisted. This keeps the session readable while still showing what work occurred.

## Architecture

### Orchestrator Progress Events

`runReview` accepts an optional `onProgress` callback. The orchestrator emits typed domain events and does not import Pi extension or TUI types.

Events cover:

- Stage start.
- Triage completion and decision.
- Summary completion and summary text.
- Individual reviewer completion and cumulative count.
- Reviewer batch completion and candidate count.
- Individual validator completion and cumulative count.
- Validation completion and accepted count.
- Aggregation completion.
- Stage failure with a safe diagnostic.

The callback may be synchronous or asynchronous. Event delivery is awaited at stage boundaries so ordering is deterministic. Completion events from parallel reviewers and validators use counters updated in the orchestrator before emission.

Progress reporting is observational. A progress-rendering failure must not change review findings or publication eligibility; the extension catches UI reporting errors and continues the review.

### Extension Progress Presenter

The extension owns a small progress presenter with three responsibilities:

1. Maintain the current label, optional count, start time, and animation frame.
2. Refresh `ctx.ui.setWidget` and `ctx.ui.setStatus` every 400 milliseconds.
3. Convert selected orchestrator events into persistent custom messages through `pi.sendMessage` with `triggerTurn: false`.

The presenter exposes `update`, `milestone`, and `dispose` operations. `dispose` is idempotent, clears the interval, removes the widget, and clears the footer status.

The presenter uses only string-based Pi UI APIs. It does not import internal TUI components or depend on Pi implementation details beyond the public extension contract.

### Preflight Progress

PR resolution, checkout verification, instruction resolution, and snapshot writing occur before `runReview`, so the extension emits those stage updates directly. Once the orchestrator starts, its typed events drive subsequent status changes.

GitHub publication remains driven by the extension and updates the same presenter before and after the existing `publishReview` call.

## Data and Privacy Boundaries

Milestones may include PR identity, file and issue counts, the task summary already produced for reviewer context, candidate counts, and final accepted findings. They must not include:

- System prompts or appended prompt files.
- Hidden reasoning or thinking blocks.
- Raw JSONL subprocess events.
- Rejected finding details.
- Authentication data, environment variables, or temporary paths.

Errors are reduced to the same safe messages already exposed in the final incomplete report or Pi notification.

## Error and Cancellation Behavior

- A failed required review stage emits a failure progress event before `runReview` returns `incomplete`.
- Cancellation changes the visible stage to cancelled before transient UI cleanup and renders the existing aborted result.
- UI update exceptions are ignored after best-effort cleanup; they do not fail a valid review.
- Snapshot disposal remains in its existing `finally` block.
- Progress presenter disposal wraps the entire command handler so failures during PR resolution also clear the animation.

## Startup Troubleshooting

The README documents that Pi suppresses verbose startup content when `~/.pi/agent/settings.json` contains:

```json
"quietStartup": true
```

Users can set it to `false` for normal startup output or run `pi --verbose` for a one-time override. The package has no install script and does not read or write this setting.

## Testing

### Orchestrator Tests

- Verify the ordered stage sequence for a clean review.
- Verify reviewer completion counts from 1 through 5.
- Verify validator totals and completion counts when candidates exist.
- Verify no validation progress is emitted for zero candidates.
- Verify failure and cancellation events identify the active stage.
- Verify omitting `onProgress` preserves existing behavior.

### Presenter Tests

- Use fake timers to verify spinner frames and elapsed time change.
- Verify stage and count updates appear in widget and footer calls.
- Verify only selected milestones create custom messages.
- Verify `dispose` clears the timer, widget, and footer status exactly and remains safe when called twice.
- Verify a UI reporting exception does not interrupt the review.

### Regression Verification

- Run formatting, TypeScript checks, and the complete Vitest suite.
- Run the package tarball check to confirm all runtime files are published.
- Exercise `/code-review` against a real PR when local Pi credentials and GitHub access are available, confirming animation, milestone retention, final report rendering, and cleanup.

## Acceptance Criteria

- During every long-running review stage, the UI visibly changes at least once per second.
- The current stage is visible throughout execution.
- Parallel reviewer and validator progress uses accurate cumulative counts.
- The conversation retains concise summaries of the resolved PR, triage, task summary, reviewer batch, validation batch, and final result.
- No raw model reasoning or raw subprocess output is displayed.
- Transient status and timers are removed on all exit paths.
- Existing review results and GitHub publication behavior remain unchanged.
- README startup troubleshooting accurately explains `quietStartup` and `pi --verbose`.
