docs: plan react presentation mode
This commit is contained in:
@@ -19,7 +19,7 @@ Build one local-first web workspace that serves three related needs:
|
||||
|
||||
1. a reusable Workflow Console for inspecting a running `wf` JSON-RPC server;
|
||||
2. a reliable defense demonstration of the complete workflow lifecycle;
|
||||
3. a compact thesis presentation with live-demo and recorded-replay routes.
|
||||
3. a compact thesis presentation mode with live-demo and recorded-replay routes.
|
||||
|
||||
The application also demonstrates where an agent belongs in the product. A
|
||||
constrained agent translates a natural-language request into typed parameters
|
||||
@@ -43,7 +43,7 @@ web/
|
||||
apps/
|
||||
console/ # React + Vite
|
||||
server/ # Hono + Effect boundary
|
||||
presentation/ # Astro, added in the presentation slice
|
||||
presentation/ # optional later static shell, if needed
|
||||
packages/
|
||||
rpc/
|
||||
ui/ # added only after shared components exist
|
||||
@@ -376,10 +376,12 @@ Routes:
|
||||
- `/replay`: recorded fallback;
|
||||
- `/appendix`: backup architecture, evaluation, and implementation slides.
|
||||
|
||||
The presentation transitions directly into the demo and back. Astro may be
|
||||
added as a separate static presentation app and served by the Hono process. The
|
||||
exact slide library is selected in the presentation slice; the route and shared
|
||||
component boundaries are fixed by this design.
|
||||
The presentation transitions directly into the demo and back. The next
|
||||
presentation slice should be a React presentation mode inside the existing
|
||||
console before adding a separate static shell. Astro may be added later for
|
||||
static appendix pages or route wrapping, but it is not the default next surface.
|
||||
See
|
||||
[`React presentation mode before Astro`](../../adr/0003-react-presentation-mode-before-astro.md).
|
||||
|
||||
## Implementation Order
|
||||
|
||||
@@ -389,8 +391,9 @@ component boundaries are fixed by this design.
|
||||
registry.
|
||||
4. Workflow Console read/inspect views, graph, trace, and raw drawers.
|
||||
5. Lifecycle job, autoplay, typed approval, issue board, and replay.
|
||||
6. Constrained demo agent and replaceable model gateway.
|
||||
7. Astro defense presentation and appendix routes.
|
||||
6. React presentation mode for the defense demo.
|
||||
7. Constrained demo agent and replaceable model gateway.
|
||||
8. Optional static slide or appendix shell after presentation mode is clear.
|
||||
|
||||
Each slice gets its own executable implementation plan. Do not combine the
|
||||
Python contract change, web foundation, agent integration, and presentation
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
# React Presentation Mode Design
|
||||
|
||||
## Status
|
||||
|
||||
Current design contract for the next Workflow Console slice.
|
||||
|
||||
## Related Decisions
|
||||
|
||||
- [React presentation mode before Astro](../../adr/0003-react-presentation-mode-before-astro.md)
|
||||
- [Workflow console, agent demo, and defense presentation](2026-07-01-workflow-console-agent-demo.md)
|
||||
- [Demo autoplay and replay](2026-07-03-demo-autoplay-replay.md)
|
||||
|
||||
## 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:
|
||||
|
||||
```text
|
||||
/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:
|
||||
|
||||
```text
|
||||
/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 drawer.
|
||||
- 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:
|
||||
|
||||
```ts
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
1. **Intro:** claim frame: planner decisions are separated from deterministic
|
||||
runtime execution.
|
||||
2. **Chat request:** operator asks for the thesis readiness report.
|
||||
3. **Tool call start:** `lda.chat` runs the prepared workflow operation.
|
||||
4. **Graph reveal:** workflow graph becomes primary; chat moves to a rail.
|
||||
5. **Interrupt approval:** typed `issue_review` appears as an explicit human
|
||||
boundary.
|
||||
6. **Resume output:** selected issue and markdown report are produced.
|
||||
7. **Trace evidence:** trace and raw/interpreted evidence show inspectability.
|
||||
8. **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:
|
||||
|
||||
```text
|
||||
$ 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 drawer.
|
||||
|
||||
## 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 `1280x720` as a first-class target.
|
||||
|
||||
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:
|
||||
|
||||
1. load `/present`;
|
||||
2. verify replay is the default;
|
||||
3. advance through all beats with keyboard;
|
||||
4. open node spotlight;
|
||||
5. open evidence drawer;
|
||||
6. jump to `#interrupt-approval`;
|
||||
7. complete the replay path on a `1280x720` viewport;
|
||||
8. verify the normal console route still works.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
The slice is complete when:
|
||||
|
||||
1. `/present` can run the prepared replay story without an RPC server;
|
||||
2. the same route can optionally use live mode when connected;
|
||||
3. keyboard controls can drive the main defense path;
|
||||
4. hash links jump to important beats;
|
||||
5. operation blocks make product calls visible and interpretable;
|
||||
6. graph, interrupt, output, trace, and evidence are available without clutter;
|
||||
7. the route is readable at `1280x720`;
|
||||
8. the normal console remains product-like and is not forced into cinematic
|
||||
layout choices.
|
||||
Reference in New Issue
Block a user