Skip to Content

Console

The console is the phase-2 addition to the shell described on the shell page: a program section at /p/[slug]/console inside the same AppShell, on Cobalt and Canvas with no new hue. This page holds the design decisions the web-console writer builds against and the gates that check them; the user-facing description is the console reference and the reasoning is About the console. Screenshots at 1440 and 390 px in both themes, captured with zero browser console errors, land on the screenshots page with the R1 release.

Layout

WidthBehaviour
1440 px and aboveconversation, canvas and run rail side by side; widths as above
1100 px and belowcanvas and run rail become a tabbed drawer
768 px and belowbottom sheet with full-width cards; read, approve, decline and stop only; artifact editing is desktop-only and the button says why

Cookies console_canvas and console_rail remember whether the two side regions are open (path /, SameSite=Lax); they hold layout only, never content. check:mobile at 390 x 844 covers /console and fails when any element outside a .table-scroller exceeds the viewport.

Components

ComponentResponsibility
thread-listthreads the viewer may read (own and shared, or every thread with program.threads.read), with the visibility marker
message-feedrole=feed composite; streamed text announced through a polite role=log in sentence chunks; citation markers [n] open the source viewer
composerfixed notice “Private to you. Quality reviewers and program leads can read this thread for review.”, run mode selector, Stop, slash commands /check, /draft, /compare, /brief, /pin; never obscures focus
plan-cardthe plan artifact with actions, tools, sources, expected writes, budget; Approve (Enter)
approval-cardone component for plan approval, write approval, connector consent and questions: what will be written, sources cited, downstream consequence, permission exercised (disabled with the key when lacking); Approve (Enter), Edit then approve, Decline (Esc, reason), Resume after gate_expired; receives focus on appearance, returns it on resolution
canvas, artifact-*UI-owned renderers for the ten artifact kinds; version selector; selection-to-edit; promote; version diff; footer “Agent-generated draft, unsigned.” with “Cites N sources.” and “Model configuration MC-n (recorded <date>)”
run-railsteps, tool calls (name, argument summary, scope, policy decision, permission_exercised, span id), sources read, budget used, SOP binding sentence, model configuration record; run cards persist with Cancel, needs input, trace id
source-viewertitle, provenance, licence code, retrieved_at, snapshot stamp, cited span, “Open in notebook” or “Open at publisher”; rendering per licence code
signature-dialogtitle “Decision signature (non-GxP pilot)”, statement, re-authentication with pending_signature in sessionStorage, statement_ack
notification-bellunread count; items link to the record; marking read is audited

Streaming behaviour

The web opens GET .../threads/{thread_id}/stream with fetch streaming (the browser’s EventSource cannot send Authorization), keeps the last seq and reconnects with Last-Event-ID within 2 s. The optimistic echo of the user’s message appears under 100 ms; the working indicator appears when the state event arrives (written in the message transaction); text_delta events append to the streaming message; tool_call_proposed and interrupt render cards; artifact_delta updates the canvas; message_complete and run_finished settle the state. A keepalive arrives every 15 s. The stream client’s reconnect and the approval card’s keyboard behaviour are unit-tested; the J1 journey (ask, plan, approve, finding created with a citation) is the end-to-end test against the dev servers.

Keyboard and accessibility rules

  • Single-key shortcuts (a accept, . record actions, Enter approve, Esc decline) are active only while focus is on the card or the record header (WCAG 2.1.4); users.settings.shortcuts switches to alt_chords or off.
  • Approval cards receive focus on appearance and return it on resolution; the sticky composer never obscures the focused element (2.4.11).
  • Interrupts carry an expires_at (default 24 h, extendable), so a gate never times out under a person’s hands without a way back (2.2.1); Resume re-opens the decision.
  • Agent-origin content never uses the pass tone until accepted; feedback renders as labelled icons, not status chips.

Tokens and status pairs

Cards 8 px radius, controls 4 px; motion 120, 180 and 240 ms honouring prefers-reduced-motion; IBM Plex Sans headings, Inter body; Midnight rail, Canvas page, White cards, Ice for the user bubble and cited spans, Slate metadata, Silver separators. Status pairs are identical in both themes. The contrast gate (web/scripts/check-contrast.mjs) gains the console pairs and its count is re-pinned in check-contrast.test.mjs; the docs check:tokens sibling pass compares the shared tokens against web/app/globals.css.

Gates that check the console

GateWhereExpected
tscweb0 errors
permissions syncweb (--docs from the workspace)permissions in sync: 81 strings (13 org, 68 program)
tone lintweb status.test.ts, docs lib/content.ts56 statuses; every *_STATUSES value rendered as a chip has a tone
contrastwebevery pair passes, console pairs included
check:mobileweb/console fits 390 x 844
vitestwebstream client reconnect, approval card keyboard, thread visibility copy
e2ewebJ1 against the dev servers; zero console errors at 1440 and 390, light and dark
attribution scanworkspaceno hits; “agent-generated” only

Source: web/lib/content.ts (consoleSection, consoleCopy, runModes, slashCommands, approvalActions), web/lib/status.ts, web/lib/api/types.ts (StreamEvent), web/app/globals.css, docs/scripts/token-pairs.json, PRODUCT-CONTRACT.md sections 10.1, 10.6 and 10.9, PRODUCT-PLAN.md Part 4 sections 3.1, 3.4, 3.8, 3.9, 3.10 and 4.8