9.8 KiB
React Presentation Mode Design
Status
Current design contract for the next Workflow Console slice.
Related Decisions
- React presentation mode before Astro
- Workflow console, agent demo, and defense presentation
- Demo autoplay and replay
Purpose
The console can now run and replay the prepared lda_report_workflow, but the
screen still reads as a debug console. The defense needs a route that can explain
the product quickly, survive 720p projection, and answer questions without
forcing the viewer through raw JSON.
This slice adds a React presentation mode inside web/apps/console. It is not a
separate slide framework. It is a staged compositor over real React components:
chat, workflow graph, operation evidence, typed interrupt approval, report
output, trace, and captions can enter, leave, or take focus as scripted beats
advance.
The first implementation is not expected to be the final defense script. It
should establish the presentation infrastructure and use a provisional script
that can be revised cheaply. The target editing experience is that adding or
changing a beat is a small semantic change, not a rewrite of a large TSX file.
For example, selecting a workflow node and showing its NodeUse detail should
be expressed as a short beat/state edit, with the reusable graph and spotlight
components handling the rest.
Product Boundary
The normal console remains the real product surface: dense, inspectable, operator-facing, and evidence-first.
Presentation mode is a defense-stage surface over the same data and controller. It may use replay by default, but it must not pretend a live LLM is making planning decisions. The chat persona is scripted/replayed operator interaction unless a later constrained macro explicitly runs.
Terminology:
- Console: ordinary workflow product UI.
- Presentation mode: cinematic staged route inside the React app.
- Beat: one named presentation moment.
- Scene component: a React component that renders one visible part of the stage.
- Operation block: a visible product call with raw and interpreted output.
- Presentation agent: scripted/replayed operator persona.
- Constrained demo agent: optional future macro client.
- External LLM agent: out of scope for the defense UI.
Route
Add a dedicated route inside the console app:
/present
The existing console page remains available separately. The exact console route
may be /console or the current root route, but presentation mode must not be a
mode toggle that permanently compromises the console layout.
Hash fragments select scripted beats:
/present#intro
/present#graph-reveal
/present#interrupt-approval
/present#trace-evidence
Hash navigation is preferred over query parameters because it is easy to copy during rehearsal, has no server-routing implications, and can survive a future static shell.
Interaction Model
Presentation mode is a hybrid of scripted beats and manual inspection.
Primary controls:
Space/ArrowRight: next beat.ArrowLeft: previous scripted beat.Esc: close the current overlay or evidence inspector.- Mouse/touch: inspect node, open evidence, submit approval, or jump timeline.
Backward navigation only rewinds visual/script state. It must not undo live workflow mutations. If the current run was live, going backward replays the stored stage state for explanation, not runtime rollback.
Replay mode is the default. Live mode is available but explicit.
Stage Model
Avoid building a generic layout engine. Beats should be semantic state, and components should decide their own motion and layout.
Acceptable state shape:
type BeatId =
| "intro"
| "chat-request"
| "tool-call-start"
| "graph-reveal"
| "interrupt-approval"
| "resume-output"
| "trace-evidence"
| "boundary-wrap";
type PresentationState = {
readonly beat: BeatId;
readonly selectedNodeId: string | null;
readonly chatMode: "full" | "rail" | "hidden";
readonly evidenceMode: "hidden" | "peek" | "open";
readonly playbackMode: "replay" | "live";
};
Do not store React components or large layer configuration objects inside beat data. The route rerenders normal React components from semantic state. CSS and motion handle the choreography.
Components
Keep the TSX files lean. Presentation behavior should be split into focused components:
presentation/
PresentationRoute
PresentationStage
BeatController
BeatRail
StageCaption
OperatorChat
ChatMessage
OperationBlock
WorkflowGraphStage
NodeSpotlight
ApprovalScene
ReportOutputScene
TraceEvidenceScene
EvidenceDrawer
The first implementation does not need every component above, but the route should not become a single large TSX file.
Component extraction from the existing console/demo UI is in scope for the first slice when it prevents duplicate graph, timeline, operation evidence, output, or trace rendering. This is maintenance reduction, not optional polish: presentation mode and console mode should share the useful product components while keeping their layout/composition separate.
Beat Outline
The first script should stay under eight beats:
- Intro: claim frame: planner decisions are separated from deterministic runtime execution.
- Chat request: operator asks for the thesis readiness report.
- Tool call start:
lda.chatruns the prepared workflow operation. - Graph reveal: workflow graph becomes primary; chat moves to a rail.
- Interrupt approval: typed
issue_reviewappears as an explicit human boundary. - Resume output: selected issue and markdown report are produced.
- Trace evidence: trace and raw/interpreted evidence show inspectability.
- Boundary wrap: clarify substrate versus autonomous agent claims.
Each beat should have one short caption. Avoid prose blocks. In Q&A, the operator should be able to jump directly to graph, interrupt, trace, or evidence beats.
Operation Block
Operation calls are first-class presentation elements. They bridge chat and the workflow substrate.
An operation block shows:
- equivalent CLI or JSON-RPC method;
- compact raw request/response;
- interpreted result;
- affected workflow/run ids;
- status and duration when available.
Example presentation:
$ uv run wf run start lda_report_case_study.default --input-file run-input.json
raw:
{ "status": "interrupted", "interrupt": { "kind": "issue_review" } }
interpreted:
Human approval required
1 proposed issue
Resume outcomes: submitted | cancelled
The block can appear compact inside chat and expand into a terminal-like panel. The interpreted side may highlight graph nodes or stage elements. Raw evidence remains available through the global evidence inspector.
Graph
Use a curated presentation graph backed by real workflow/run evidence.
The presentation graph may use clearer labels and positions than the raw plan, but it must not invent steps that do not exist. Each visible node should be able to point to one of:
- a workflow node id;
- a run trace frame;
- an operation block;
- a captured replay event.
Clicking a node can open NodeSpotlight, which shows the node purpose,
input/output summary, and related evidence.
Motion
Motion should make state changes understandable:
- chat can enter full-screen, then scoot into a rail;
- graph can bloom into the main stage;
- a clicked node can expand into a detail panel;
- evidence can peek from the side, then open;
- beat rail progress can advance subtly.
No slow typewriter effect. Chat messages appear as complete messages with a small fade or stagger. This resembles modern AI app streaming enough without wasting defense time or implying a live model.
Every motion path needs a reduced-motion fallback.
Visual Stack
Use React first. Add routing and motion before adopting a large component library.
Tailwind-style utilities and copy-owned components such as shadcn/ui are acceptable if they help speed up consistent layout. Avoid adopting a full chat or agent framework until runtime agent behavior exists. Templates may be copied as raw material, but the visual result should fit the lda.chat stage, not a generic SaaS/chat clone.
720p Constraint
Design for a 720px logical height and adaptive logical widths from 960px
through 1280px. See the
adaptive presentation canvas design.
Rules:
- one primary object per beat;
- one secondary detail at most;
- captions must be short;
- raw evidence is collapsed by default;
- long code/output wraps inside panels;
- the presenter must not need browser zoom during the main path.
Testing
Unit tests should cover:
- beat reducer/state transitions;
- hash-to-beat and beat-to-hash behavior;
- keyboard controls;
- replay-default startup;
- backward navigation does not call live mutation operations;
- operation block rendering for CLI/raw/interpreted output.
Browser smoke should cover:
- load
/present; - verify replay is the default;
- advance through all beats with keyboard;
- open node spotlight;
- open the evidence inspector;
- jump to
#interrupt-approval; - complete the replay path on
1024x768and1280x720viewports; - verify the normal console route still works.
Success Criteria
The slice is complete when:
/presentcan run the prepared replay story without an RPC server;- the same route can optionally use live mode when connected;
- keyboard controls can drive the main defense path;
- hash links jump to important beats;
- operation blocks make product calls visible and interpretable;
- graph, interrupt, output, trace, and evidence are available without clutter;
- the route is readable from
4:3through16:9supported ratios; - the normal console remains product-like and is not forced into cinematic layout choices.