# Terminal-style review controls

**Date:** 2026-06-05
**Status:** Approved (design)

## Problem

Review feedback today is a multi-line `TextBox` plus four buttons (Approve / Reject /
Park / Cancel) tucked into the WorkConsole **Session** tab
(`WorkConsole.axaml:169-193`). It feels disconnected from the live terminal. Entering
feedback should feel like typing into the terminal, with action buttons docked at the
bottom — and merge/approve actions should live in an obvious, dedicated place.

## Goal

- Type review feedback directly in the **Output (terminal)** tab, prompt-style.
- Bottom-docked action strip on the terminal: `[Retry]` `[Reset]`.
- Move all git/merge/worktree actions (including **Approve**) into a new **Git** tab so
  it is obvious where each action lives.

## Tab structure

Three tabs in WorkConsole: **Output** · **Git** · **Session**.

| Tab | Contents |
| --- | --- |
| **Output** | Live `Log` (unchanged) + new review footer (below), footer gated on `IsWaitingForReview`. |
| **Git** | The current "Merge & worktree" block — merge-target dropdown, mergeability indicator, **Approve**, Open Diff, Merge, Worktree, Review Combined Diff, Merge All Subtasks. Visibility gated on `ShowMergeSection` / `IsWaitingForReview` as today. |
| **Session** | Child outcomes + empty-state only. |

### ViewModel changes (`DetailsIslandViewModel`)

- Add `public bool IsGitTab => SelectedTab == "git";`
- Add `[NotifyPropertyChangedFor(nameof(IsGitTab))]` alongside the existing
  `IsOutputTab` / `IsSessionTab` notifications on `SelectedTab` (`:139-144`).
- `SelectTab` already accepts a string parameter — no change beyond the new `"git"`
  value wired from XAML.
- No command renames (avoids breaking hand-rolled test fakes).

## Terminal footer (Output tab)

A `Border` docked `Bottom` inside the Output tab body, visible only when
`IsWaitingForReview`:

- Background `Surface2Brush`, top border `LineBrush` (`BorderThickness="0,1,0,0"`).
- A `❯` prompt-prefix `TextBlock` (mono, `TextMuteBrush`) + a borderless mono `TextBox`:
  - Bound `Text="{Binding ReviewFeedback, Mode=TwoWay}"`.
  - `AcceptsReturn="True"`, `TextWrapping="Wrap"`, transparent background, no border.
  - Starts ~1 line tall; grows with content up to `MaxHeight≈160`, then scrolls.
  - `PlaceholderText` e.g. "Feedback for the next run…".
- Right-aligned button strip:
  - `[Retry]` — `Classes="btn accent"` → `RejectReviewCommand`.
  - `[Reset]` — `Classes="btn"` → `ParkReviewCommand`.

`[Accept]` is **not** in the footer; approval happens on the Git tab via
`ApproveReviewCommand`. The old `Cancel` review button is dropped from this UI; cancel
remains reachable through the task's existing cancel control (`CancelReviewCommand`
stays on the ViewModel, just not surfaced here).

### Enter handling (`WorkConsole.axaml.cs`)

- Handle `KeyDown` on the input `TextBox`:
  - **Enter** without Shift → execute `RejectReviewCommand` (if it can execute) and set
    `e.Handled = true`.
  - **Shift+Enter** → fall through to default behavior (inserts newline).
- `RejectReviewAsync` already returns early on whitespace-only feedback
  (`DetailsIslandViewModel.cs:1464`), so pressing Enter with an empty prompt is a no-op
  with no extra guard needed.

## Command mapping

| Button | Location | Command | Effect |
| --- | --- | --- | --- |
| `[Retry]` | Output footer | `RejectReviewCommand` | Reject-to-queue with feedback; resumes the session (Queued). |
| `[Reset]` | Output footer | `ParkReviewCommand` | Park back to Idle. |
| `[Approve]` | Git tab | `ApproveReviewCommand` | Merge `SelectedMergeTarget` → Done (conflict keeps it in review). |

## Copy / empty state

- Update the Session empty-state text (`WorkConsole.axaml:270`) — it currently says
  "review and merge controls appear here once the run finishes", which is no longer
  accurate. Reword to reflect that only outcomes live on Session.
- Button labels remain literal strings (`Retry`, `Reset`, `Approve`), matching the
  existing review buttons (no new localization keys).

## Out of scope

- No changes to worker-side review/merge logic or `IWorkerClient` signatures.
- No merge-target selector duplicated into the terminal footer (Approve uses the Git
  tab dropdown / default target).
- No command renames on the ViewModel.

## Testing / verification

- Build `ClaudeDo.App` and `ClaudeDo.Worker` in `-c Release`.
- Manual visual verification (must be flagged — cannot be auto-verified):
  - Footer appears only in `WaitingForReview`, on the Output tab.
  - Enter sends Retry; Shift+Enter inserts a newline; empty Enter does nothing.
  - Git tab shows Approve + merge/worktree controls; Session shows only outcomes.
