PR: #324: Atlas Step-5 review UX: clarification render, CCB flip, streaming, thinking-lines, CCB wiring by @ankitmaheshwari-com
View PR →
Story-1267 · Atlas Step-5 · pramaan-docs ADR-110

Atlas Step-5 review UX — found & fixed live

Six fixes to the Step-5 matter-review surface, all discovered and verified live (localapp, real Atlas over the ADR-110 WebSocket rail). They make the hand-rolled review behave honestly: a clarification reads as a question, the description streams, the wait reads as deliberate work, and the Counsel Control Bar actually does something.

What changed

FixWhat & why
Clarification renderThe panel fell into the "Atlas couldn't reach the review service" error branch for any null proposal — including a needs_clarification turn, where Atlas correctly asked a question instead of proposing a frame. Split: verdict error → error hero; clarification → a calm "Atlas has a question — see the chat" state. The rail worked all along; the UI mislabelled it.
CCB flipThe Counsel Control Bar rendered above the selection (-translate-y-full) and got sliced by the modal's top edge when you selected near the top. Now flips below the selection when there's no room above (use-ccb-selection exposes the selection height).
Streaming renderThe review gated on verdict === "loading", but BAML fills verdict late in the JSON — so the loading skeleton hid the whole stream, then everything popped in at once. Now gates on proposal content (proposal.summary): the matter description types out live as Atlas composes.
Thinking-linesNew ThinkingState replaces the static "Atlas is reading… 2–5 seconds" caption — cycles ~24 Atlas matter-framing phrases (parties, cause of action, relief, forum, synthesis). Per-agent: these are Atlas's lines; a future agent supplies its own set. Keys in en.json + hi.json.
Re-fetch on editThe rail launched once via a boolean flag, so editing template/matter/parties and returning to Step 5 showed a stale proposal. Now gates on an input signature: changed inputs reset state and re-run Atlas; identical re-entry reuses the run.
CCB Command + WhyBoth were stubs (opened the drawer, never posted). Now route through onSendMessage — the same live WS rail the drawer input uses: Command sends the typed instruction with the quoted selection; Why asks Atlas to explain the selected framing.

Files

src/components/add-matter/step5-review/step5-review-form.tsx   gate + clarification + CCB flip + CCB wiring
src/components/add-matter/step5-review/thinking-state.tsx     new — cycling framing-phrase loader
src/components/add-matter/step5-review/use-ccb-selection.ts   expose selection height (flip)
src/lib/agents/use-atlas-rail.ts                              re-fetch on input-signature change
messages/en.json + messages/hi.json                           thinkingPhrases[24] + ccbCommandPrompt/ccbWhyPrompt
tests/unit/step5-review-verdict.test.tsx                      new — verdict→render branching

Verification

tsc clean · step5-review-verdict.test.tsx green · en/hi i18n parity intact
live: cycling thinking-lines → matter description streaming in mid-sentence;
clarification renders calm copy (not the error hero); CCB flips below near top.
Follow-ups (not this PR): smooth streaming needs the WS-rail/AgentCore un-buffering (#1266 — deltas arrive bunched); template card counts still show 0 (#13); flaky modal open / Clerk UserButton hydration "1 Issue" (#14, dev-only).
Substrate honored: drawer "Atlas" + active dot, no role label; no emojis; counsel ink-2 bubbles; all copy via next-intl in en + hi. A later AI-Elements refactor (pending an ADR) may supersede some of this presentational layer; the WS rail + agent_event_stream.v1 stay.

Files changed

7 file(s), +257 / -18 lines

Path Role + -
messages/en.jsonConfig+29-0
messages/hi.jsonConfig+30-0
src/components/add-matter/step5-review/step5-review-form.tsxComponent+52-13
src/components/add-matter/step5-review/thinking-state.tsxComponent+80-0
src/components/add-matter/step5-review/use-ccb-selection.tsComponent+3-0
src/lib/agents/use-atlas-rail.tsLibrary+14-5
tests/unit/step5-review-verdict.test.tsxTest+49-0