RFC-011 — Assistant conversation surface
RFC-011 — Assistant conversation surface (v0.7)
Section titled “RFC-011 — Assistant conversation surface (v0.7)”Context
Section titled “Context”Before v0.7, /assistant shipped as a single-turn “run” surface (seed-2df4). The IA conflated runs with conversations: the left rail listed the eight most-recent answer_runs; clicking one replaced the in-memory message list with that single turn alone. With migration 038_assistant_conversations already on main and the SSE handler at cmd/atlas-gateway/assistant_stream.go auto-creating a conversation if conversationId is absent, the backend modelled real multi-turn threads — but the UI never surfaced them.
A senior visual + interaction audit on top of that surface identified 25+ issues spanning a P0 token bug (text-loss referenced an undefined CSS variable so error banners rendered invisible), a generic empty state that hid the seven composer modes, a debug-style right rail, citation list with no anchor linkage, missing typing/streaming feedback, load-bearing refs duplicating state the reducer should have owned, no mobile layout, no error recovery, no tests.
The redesign closes those gaps in nine landing phases (seed-c7a1 through seed-c7a6), now all live.
Decision
Section titled “Decision”- Conversations are the unit of history. The left rail lists
assistant_conversationsordered byupdated_at; clicking a thread sets?c=<conversationId>and primes the composer to append a new turn to that thread. The SSE stream auto-creates a conversation on first submit when?c=is absent;run_createdevents promote the new id into the URL so the thread is shareable + resumable cross-device. Backed by the new?conversationId=Xfilter onGET /api/atlas/runs(Phase 5a, ordered byturn_index ASC) and the CRUD endpoints that landed in seed-2df4. No feature flag — the new IA is the canonical layout; the legacy run-rail layout was deleted. - Inline citations + EvidenceInspector. The right rail’s flat numbered citation list is replaced with djed-evidence-ui’s
EvidenceInspectorrendered from aClaimaggregated byanswerClaimFromRun. Source tier + freshness chips, lineage tab, and per-claim provenance all surface; clicking a citation firesassistant-citation-clickedtelemetry. Inline[¹]superscript anchors inside the answer prose are queued for thedjed-ai-copilot1.1.0 publish (it needs arenderAssistantContentslot); the rail-side inspector ships in Phase 4. - Plain-language live status. The raw djed
AssistantToolTrace(rendered “Backend: X · Yms” stage names) is replaced byAssistantLiveStatus— a vertical timeline of narrative steps (“Reading your question” → “Searching SAP knowledge (3 sources)” → “Drafting cited answer (claude-opus-4-7)”) emitted by the pureassistantStepCopy.tsbuilders. Motion-aware (framer-motion withprefers-reduced-motionhonored), uses Atlas tokens only. - Empty state teaches the surface.
AssistantHerorenders all sevenATLAS_COMPOSER_MODESas cards with two example prompts each. Clicking an example pre-fills the composer + selects the mode + firesassistant-mode-changedtelemetry withsource: 'empty_state'. The previous boilerplate (“Atlas workbench / Ask a source-grounded SAP migration question”) is gone. - Reducer owns ephemerality.
pendingAssistantId+turnFinalizedmoved from load-bearinguseRefs intoAssistantStreamState. New idempotent actions:submit_turn(pendingAssistantId),finalize_turn(no-op on re-dispatch),discard_pending.transport_erroralso clears the pending id so onError paths drop the orphan bubble cleanly.AssistantView.tsxhas zerouseRefdeclarations for streaming state. - Mobile parity via WorkbenchTriPane. The tri-pane primitive collapses to a single-column on phone;
leftDrawer+rightDrawerslots mountResponsiveSheet-wrapped Conversations and Run-details buttons so both rails are one tap away. Selecting a thread from the phone sheet auto-closes the drawer. - Keyboard + error recovery. Surface-scoped shortcuts:
Escaborts the in-flight stream;/focuses the composer (skipped when an editable element already has focus). On any non-doneterminal phase,AssistantErrorRecoverymounts between the message list and the composer with phase-specific actions: Retry (re-runs the last query in its prior mode vialastSubmittedRef), Try different mode (dropdown of the six non-current modes), Start new conversation (clears state + unsets?c=). - Externalized copy. Every user-facing English string lives in
assistantStrings.ts(groups:surface,rail,composer,badge,error,history). The future i18n channel swaps the export without touching component code. - Eslint guard rails.
LEGACY_TOKEN_PATTERNSextended to forbidtext-/bg-/border-(loss|profit|info|caution)phantom semantic tokens — these have no--color-*mapping inatlas-design/tokens.cssso they silently render unstyled. A second guard forbids inlineh-[calc(100vh-Nrem)]height arithmetic in surface files.
Consequences
Section titled “Consequences”- Legacy URL contract preserved.
?runId=Xdeep links continue to resolve: on mount, AssistantView fetches the run, reads itsconversationId, and redirects to?c=<convId>&runId=Xwith a two-weekconsole.warndeprecation. Thelegacy-redirecttelemetry event lets us measure the migration tail. After the deprecation window, the redirect goes silent. - Telemetry stream gains
assistant-*events.assistant-turn-submitted,-turn-completed,-turn-aborted,-feedback-submitted,-citation-clicked,-mode-changed,-history-opened,-conversation-started,-conversation-selected,-conversation-archived,-conversation-renamed. All flow throughreportAtlasEvent→atlas-ui-gateway→ existing analytics pipeline. No new dashboard config is required to ship — consumers query the raw event stream; a dedicated funnel dashboard can be added in a follow-up if usage signals demand it. - Test coverage.
assistantStream.test.tscovers nine reducer transitions including the idempotence guarantees;assistantWorkbench.test.tsandassistantApi.test.tscover the cache-state helpers + composer body.AssistantViewend-to-end tests and Playwright visual baselines for the/assistantchrome are queued in Phase 7 (this RFC’s companion); the build-surface playwright pattern (real-backend, no mocks,realBrowserProofEnabled()gate, clipped to stable region) carries over directly. - Upstream package extensions for inline-
[¹]+ multiline composer.djed-ai-copilot 1.1.0will addrenderAssistantContent?: (msg) => ReactNodetoAssistantMessageListProps;djed-evidence-uinext-minor addsmultiline?: booleantoQueryComposerProps(autosize<textarea>with Shift+Enter newline + Cmd/Ctrl+Enter submit). Atlas wires both via the existingfile:link during dev and adopts after publish.
Status
Section titled “Status”Accepted — implemented across seed-c7a1 → seed-c7a6 and deployed live on 2026-05-21.
| Phase | Seed | Subject |
|---|---|---|
| 0 | seed-c7a1 | P0 bug + telemetry shim + eslint guard |
| 1 | seed-c7a1 | AssistantHero empty-state capability surface |
| 2 | seed-c7a1 | Streaming feedback grammar (typing dot, live status, model badge) |
| 3 | seed-c7a1 | Reducer consolidation + externalized copy |
| 4 | seed-c7a1 | EvidenceInspector adoption |
| A | seed-c7a2 | Post-deploy polish — caution token + banned-terms allowlist |
| B | seed-c7a3 | Build-stack landing (evidence hydration, artifact polish, stage inspector) |
| D | seed-c7a4 | Wire-a backend reconciliation |
| E | seed-c7a5 | Visual baselines rewrite (real backend, no mocks) |
| 5 | seed-c7a6 | Conversation-first IA |
| 6a | seed-c7a6 | Mobile drawers + keyboard shortcuts + error recovery |
Phase 6b (multiline composer, requires djed-evidence-ui publish) and Phase 7 (full test scaffold including Playwright assistant baselines) are queued as follow-ups; both are additive and do not block the IA shift.