# ThothII workflow UI contracts - Pi reasoning arrives as nested `message_update.assistantMessageEvent.type = thinking_delta`. The backend maps it to the named SSE event `activity_delta`; the frontend EventSource must explicitly subscribe to that name. Model activity is separate from final `text_delta` output. - Session create/resume must preserve the configured or persisted thinking level. Forcing `thinking: off` disables the upstream signal and makes the activity panel legitimately empty. - A join-only `reviewer_decide` proposal is one complete, atomic join set. The read-only `join-review` widget persists every proposed join on Continue; `Other — specify` persists none and requires the model to propose the complete corrected set again. Ledger read, sequence assignment, and atomic replacement share a per-session cross-process writer lock. - A v2 phase summary accepts `open_questions?: string[]`. Validate this at the gate boundary and normalize legacy malformed entries defensively in the viewer so one object cannot crash React. - `SqlViewer`'s horizontal/vertical layout control is meaningful only with multiple SQL blocks; hide it for the single CTE result shown by `CteResultViewer`. - A Pi turn is `idle`, `running`, `waiting`, or `failed`. A reviewer gate/request moves it to `waiting`; the reviewer response and steering move it back to `running`; provider failures and unexpected Pi child exits mark it `failed` without forwarding raw failure detail. - Resume preserves `running`/`waiting` runtimes. After manifest/readiness validation, every cold path clears old SSE buffer/subscribers before reopen—including when a crashed child has already left no runtime—and reuses persisted provider/model/thinking. Failed validation does not clear. - A successful Resume of the already selected session increments the stream generation so React closes the old EventSource and opens the same session URL again. Failed Resume must not reconnect. - SSE endpoints are intentionally keep-alive. Browser cleanup and one-off probes must explicitly close the EventSource or cancel/abort the response reader after their terminal event. - The Model activity panel is an in-memory chronological projection of the prompt, thinking, assistant output, sanitized tool lifecycle, reviewer gates, status messages, and turn lifecycle. It starts with the local F1 prompt and is deliberately not persisted as chat history. - Pi tool events may cross the backend/client boundary only as call id, tool name, and `running`/`completed`/`failed` status. Tool updates, arguments, partial/final results, commands, raw output, and raw errors remain server-side. - The frontend uses Tailwind CSS 3.4. Shared primitives must use concrete Tailwind 3-compatible spacing utilities; Tailwind 4 custom-spacing syntax can compile to no effective padding here.