# Presentation Scene Composition Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Recompose presentation Scenes 3, 4, and 5 so they use the 720p stage, and lightly tune Scene 10 graph/interrupt readability. **Architecture:** Keep the existing storyboard, route, reducer, and demo state intact. Rewrite only the scene renderers inside `SceneBody.tsx` and tune CSS in the existing presentation stylesheets. Scene 10 remains the same data flow; this slice changes hierarchy and readability, not demo behavior. **Tech Stack:** React, TypeScript, Vitest, Testing Library, CSS, existing Motion wrappers, existing Vite presentation route. ## Global Constraints - Follow design spec: `docs/superpowers/specs/2026-07-08-presentation-scene-composition-design.md`. - Do not introduce a generic diagram framework in this slice. - Do not replace the chat UI, Q&A panel, evidence inspector, storyboard catalog, or recursive architecture figure. - Do not add demo RPC calls, recording events, or new runtime state. - Preserve existing keyboard/hash navigation behavior. - Screenshot smoke output belongs under `web/apps/console/.visual-smoke/`, which is ignored. - Do not commit `.superpowers/` local progress files. --- ## File Structure - Modify: `web/apps/console/src/presentation/SceneBody.tsx` - Owns Scene 3, Scene 4, and Scene 5 markup. - Modify: `web/apps/console/src/presentation/SceneBody.test.tsx` - Adds structural tests for the recomposed scenes. - Modify: `web/apps/console/src/presentation/presentation.css` - Replaces the small-card scene CSS for positioning, boundary, and lifecycle. - Modify: `web/apps/console/src/presentation/styles/demo-workflow.css` - Tunes Scene 10 graph/contract readability and proportions. - Modify: `web/apps/console/src/presentation/DemoWorkflowScene.test.tsx` - Pins approval-contract readability without changing demo behavior. - Modify: `docs/current_roadmap.md` - Marks the composition pass complete after verification. - Move: `docs/superpowers/plans/2026-07-08-presentation-scene-composition.md` - To `docs/historical/superpowers/plans/2026-07-08-presentation-scene-composition.md` after implementation. --- ### Task 1: Recompose Scene 3 Positioning Map **Files:** - Modify: `web/apps/console/src/presentation/SceneBody.tsx` - Modify: `web/apps/console/src/presentation/SceneBody.test.tsx` - Modify: `web/apps/console/src/presentation/presentation.css` **Interfaces:** - Consumes: `SceneDefinition`, `SceneBeatDefinition`, `DiscussionLinks`, existing `StageCaption`. - Produces: a `PositioningScene` that renders `aria-label="positioning map"` and marks the center substrate with `data-positioning-active="true"` on `lda-position`. - [ ] **Step 1: Write failing tests for the positioning map** Add these tests inside `describe("SceneBody", () => { ... })` in `SceneBody.test.tsx`: ```tsx it("renders Scene 3 as a full positioning map", () => { const location: PresentationLocation = { kind: "main", sceneId: "positioning", beatId: "landscape", focusPath: [] }; render( , ); const map = screen.getByLabelText("positioning map"); expect(map).toHaveAttribute("data-positioning-active-region", "landscape"); expect(screen.getByText("Tool loops")).toBeInTheDocument(); expect(screen.getByText("Generated scripts")).toBeInTheDocument(); expect(screen.getByText("lda.chat")).toBeInTheDocument(); expect(screen.getByText("Agent graphs")).toBeInTheDocument(); expect(screen.getByText("MCP")).toBeInTheDocument(); }); it("emphasizes lda.chat in the positioning beat", () => { const location: PresentationLocation = { kind: "main", sceneId: "positioning", beatId: "lda-position", focusPath: [] }; render( , ); const substrate = screen.getByText("lda.chat").closest("[data-positioning-role='substrate']"); expect(substrate).toHaveAttribute("data-positioning-active", "true"); expect(screen.getByLabelText("positioning map")).toHaveAttribute("data-positioning-active-region", "lda"); }); ``` - [ ] **Step 2: Run positioning tests and verify they fail** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/SceneBody.test.tsx ``` Expected: FAIL because `positioning map`, `Generated scripts`, and the new data attributes do not exist. - [ ] **Step 3: Replace `PositioningScene` markup** In `SceneBody.tsx`, replace the current `PositioningScene` implementation with: ```tsx const PositioningScene = ({ scene, beat }: { scene: SceneDefinition; beat: SceneBeatDefinition }) => { const highlightLda = beat.id === "lda-position"; return ( <>

{beat.caption}

Direct action

Tool loops Fast action, no durable lifecycle
Generated scripts Inspectable code, weak deployment records
This thesis lda.chat

Typed workflow substrate for external agents and human operators.

  • Lifecycle
  • Validation
  • Persisted records

Adjacent systems

Hosted automation Managed triggers and app integrations
Agent graphs Durable planner loops
MCP Capability protocol boundary

{scene.evidencePointer}

); }; ``` - [ ] **Step 4: Replace positioning CSS** In `presentation.css`, replace the existing `.scene-body__positioning-grid`, `.scene-body__positioning-card`, and `.scene-body__positioning-card--active` rules with: ```css .scene-body__positioning-map { display: grid; grid-template-columns: minmax(13rem, 0.9fr) minmax(20rem, 1.35fr) minmax(13rem, 0.9fr); gap: 1rem; align-items: stretch; margin-top: 1.1rem; min-height: 20rem; } .scene-body__positioning-column { display: grid; align-content: start; gap: 0.7rem; } .scene-body__positioning-label { margin: 0; color: var(--color-editorial-muted, oklch(0.48 0.025 65)); font: 700 0.68rem/1 var(--font-mono, monospace); letter-spacing: 0.08em; text-transform: uppercase; } .scene-body__positioning-tile, .scene-body__positioning-substrate { border: 1px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 30%, transparent); border-radius: 0.85rem; background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 78%, white); color: var(--color-editorial-ink, oklch(0.19 0.015 65)); } .scene-body__positioning-tile { min-height: 5.8rem; padding: 0.85rem; } .scene-body__positioning-tile strong { display: block; margin-bottom: 0.35rem; color: var(--color-editorial-ink, oklch(0.19 0.015 65)); } .scene-body__positioning-tile span { color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 72%, var(--color-editorial-muted, oklch(0.48 0.025 65))); font-size: 0.82rem; line-height: 1.35; } .scene-body__positioning-substrate { display: grid; align-content: center; gap: 0.8rem; padding: 1.15rem; box-shadow: inset 0 0 0 1px color-mix(in oklch, var(--accent-cyan, oklch(0.7 0.16 195)) 18%, transparent); } .scene-body__positioning-substrate strong { color: var(--color-editorial-ink, oklch(0.19 0.015 65)); font-size: 2rem; line-height: 0.95; } .scene-body__positioning-substrate p { max-width: 28ch; margin: 0; color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 82%, var(--color-editorial-muted, oklch(0.48 0.025 65))); } .scene-body__positioning-substrate ul { display: flex; flex-wrap: wrap; gap: 0.45rem; margin: 0; padding: 0; list-style: none; } .scene-body__positioning-substrate li { border: 1px solid color-mix(in oklch, var(--accent-cyan, oklch(0.7 0.16 195)) 42%, transparent); border-radius: 999px; padding: 0.25rem 0.5rem; color: var(--color-editorial-ink, oklch(0.19 0.015 65)); font-size: 0.72rem; font-weight: 700; } .scene-body__positioning-map[data-positioning-active-region="lda"] .scene-body__positioning-tile { opacity: 0.58; } .scene-body__positioning-substrate[data-positioning-active="true"] { transform: translateY(-0.25rem); border-color: color-mix(in oklch, var(--accent-cyan, oklch(0.7 0.16 195)) 68%, transparent); background: color-mix(in oklch, var(--accent-cyan, oklch(0.7 0.16 195)) 8%, var(--color-editorial-paper, oklch(0.975 0.012 82))); } ``` - [ ] **Step 5: Run tests and commit Task 1** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/SceneBody.test.tsx pnpm --dir web --filter @lda/console typecheck ``` Expected: PASS. Commit: ```powershell git add web/apps/console/src/presentation/SceneBody.tsx web/apps/console/src/presentation/SceneBody.test.tsx web/apps/console/src/presentation/presentation.css git commit -m "feat: recompose positioning scene" ``` --- ### Task 2: Recompose Scene 4 Planner Runtime Boundary **Files:** - Modify: `web/apps/console/src/presentation/SceneBody.tsx` - Modify: `web/apps/console/src/presentation/SceneBody.test.tsx` - Modify: `web/apps/console/src/presentation/presentation.css` **Interfaces:** - Consumes: `BoundaryScene` beat IDs `planner`, `runtime`, and `boundary`. - Produces: a boundary region with `aria-label="planner runtime boundary"` and `data-boundary-active`. - [ ] **Step 1: Write failing boundary tests** Add these tests to `SceneBody.test.tsx`: ```tsx it("renders Scene 4 as a planner runtime boundary", () => { const location: PresentationLocation = { kind: "main", sceneId: "planner-runtime", beatId: "boundary", focusPath: [] }; render( , ); const boundary = screen.getByLabelText("planner runtime boundary"); expect(boundary).toHaveAttribute("data-boundary-active", "boundary"); expect(screen.getByText("Planner")).toBeInTheDocument(); expect(screen.getByText("Runtime")).toBeInTheDocument(); expect(screen.getByText(/CLI/)).toBeInTheDocument(); expect(screen.getByText(/JSON-RPC/)).toBeInTheDocument(); }); it("marks the planner side active on the planner beat", () => { const location: PresentationLocation = { kind: "main", sceneId: "planner-runtime", beatId: "planner", focusPath: [] }; render( , ); expect(screen.getByLabelText("planner runtime boundary")).toHaveAttribute("data-boundary-active", "planner"); expect(screen.getByText("Planner").closest("[data-boundary-side='planner']")).toHaveAttribute("data-boundary-emphasis", "active"); }); ``` - [ ] **Step 2: Run boundary tests and verify they fail** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/SceneBody.test.tsx ``` Expected: FAIL because the new aria label and data attributes do not exist. - [ ] **Step 3: Replace `BoundaryScene` markup** In `SceneBody.tsx`, replace the current `BoundaryScene` with: ```tsx const boundaryActiveForBeat = (beatId: string): "planner" | "runtime" | "boundary" => { if (beatId === "runtime") return "runtime"; if (beatId === "boundary") return "boundary"; return "planner"; }; const BoundaryScene = ({ scene, beat }: { scene: SceneDefinition; beat: SceneBeatDefinition }) => { const active = boundaryActiveForBeat(beat.id); const plannerActive = active === "planner" || active === "boundary"; const runtimeActive = active === "runtime" || active === "boundary"; return ( <>

{beat.caption}

External operator

Planner

  • Proposes workflow structure
  • Revises steps and bindings
  • Chooses public operations
CLI / JSON-RPC typed workflow operations
lda.chat substrate

Runtime

  • Validates schemas and routes
  • Executes deterministic nodes
  • Records traces and resume state

{scene.evidencePointer}

); }; ``` - [ ] **Step 4: Replace boundary CSS** In `presentation.css`, replace `.scene-body__boundary`, `.scene-body__boundary-side`, `.scene-body__boundary-divider`, and related dim rules with: ```css .scene-body__boundary { display: grid; grid-template-columns: minmax(0, 1fr) minmax(8rem, 0.26fr) minmax(0, 1fr); gap: 1rem; align-items: stretch; margin-top: 1.2rem; min-height: 20rem; } .scene-body__boundary-pane { display: grid; align-content: center; gap: 0.85rem; border: 1px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 32%, transparent); border-radius: 1rem; padding: 1.1rem; background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 82%, white); color: var(--color-editorial-ink, oklch(0.19 0.015 65)); } .scene-body__boundary-pane[data-boundary-emphasis="reduced"] { opacity: 0.58; } .scene-body__boundary-pane h3 { margin: 0; color: var(--color-editorial-ink, oklch(0.19 0.015 65)); font-size: 1.8rem; line-height: 1; } .scene-body__boundary-pane > span { color: var(--color-editorial-muted, oklch(0.48 0.025 65)); font: 700 0.68rem/1 var(--font-mono, monospace); letter-spacing: 0.08em; text-transform: uppercase; } .scene-body__boundary-pane ul { display: grid; gap: 0.45rem; margin: 0; padding-left: 1rem; color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 78%, var(--color-editorial-muted, oklch(0.48 0.025 65))); } .scene-body__boundary-seam { display: grid; place-content: center; gap: 0.35rem; border-inline: 2px solid color-mix(in oklch, var(--accent-cyan, oklch(0.7 0.16 195)) 58%, transparent); color: var(--color-editorial-ink, oklch(0.19 0.015 65)); text-align: center; } .scene-body__boundary-seam strong { font-size: 0.85rem; } .scene-body__boundary-seam span { color: var(--color-editorial-muted, oklch(0.48 0.025 65)); font-size: 0.72rem; line-height: 1.25; } .scene-body__boundary[data-boundary-active="boundary"] .scene-body__boundary-seam { background: color-mix(in oklch, var(--accent-cyan, oklch(0.7 0.16 195)) 7%, transparent); } ``` - [ ] **Step 5: Run tests and commit Task 2** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/SceneBody.test.tsx pnpm --dir web --filter @lda/console typecheck ``` Expected: PASS. Commit: ```powershell git add web/apps/console/src/presentation/SceneBody.tsx web/apps/console/src/presentation/SceneBody.test.tsx web/apps/console/src/presentation/presentation.css git commit -m "feat: recompose planner runtime scene" ``` --- ### Task 3: Recompose Scene 5 Lifecycle Rail **Files:** - Modify: `web/apps/console/src/presentation/SceneBody.tsx` - Modify: `web/apps/console/src/presentation/SceneBody.test.tsx` - Modify: `web/apps/console/src/presentation/presentation.css` **Interfaces:** - Consumes: lifecycle beat IDs `draft`, `artifact`, `deployment`, and `run`. - Produces: `aria-label="workflow lifecycle rail"` and a changing current-state explanation panel. - [ ] **Step 1: Write failing lifecycle tests** Add these tests to `SceneBody.test.tsx`: ```tsx it("renders Scene 5 as a full workflow lifecycle rail", () => { const location: PresentationLocation = { kind: "main", sceneId: "lifecycle", beatId: "deployment", focusPath: [] }; render( , ); const rail = screen.getByLabelText("workflow lifecycle rail"); expect(rail).toHaveAttribute("data-lifecycle-active-stage", "deployment"); expect(screen.getByText("Draft")).toBeInTheDocument(); expect(screen.getByText("Artifact")).toBeInTheDocument(); expect(screen.getByText("Deployment")).toBeInTheDocument(); expect(screen.getByText("Run")).toBeInTheDocument(); expect(screen.getByText("Source binding")).toBeInTheDocument(); }); it("updates the lifecycle explanation with the active beat", () => { const { rerender } = render( , ); expect(screen.getByLabelText("current lifecycle state")).toHaveTextContent("Mutable authoring state"); rerender( , ); expect(screen.getByLabelText("current lifecycle state")).toHaveTextContent("Execution record and trace"); }); ``` - [ ] **Step 2: Run lifecycle tests and verify they fail** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/SceneBody.test.tsx ``` Expected: FAIL because the rail label and current-state panel do not exist. - [ ] **Step 3: Extend lifecycle data and replace `LifecycleScene`** In `SceneBody.tsx`, replace `lifecycleStages` and `LifecycleScene` with: ```tsx const lifecycleStages = [ { id: "draft", label: "Draft", role: "Mutable authoring state", detail: "Iterate before freezing a workflow definition." }, { id: "artifact", label: "Artifact", role: "Immutable workflow definition", detail: "Save a versioned plan that can be deployed." }, { id: "deployment", label: "Deployment", role: "Source binding", detail: "Bind workflow requirements to configured runtime sources." }, { id: "run", label: "Run", role: "Execution record and trace", detail: "Persist status, outputs, interrupts, and trace evidence." }, ] as const; const LifecycleScene = ({ scene, beat }: { scene: SceneDefinition; beat: SceneBeatDefinition }) => { const activeIndex = Math.max(0, lifecycleStages.findIndex((stage) => stage.id === beat.id)); const activeStage = lifecycleStages[activeIndex] ?? lifecycleStages[0]; return ( <>

{beat.caption}

{lifecycleStages.map((stage, i) => (
{i + 1} {stage.label} {stage.role} {i < lifecycleStages.length - 1 && }
))}

{scene.evidencePointer}

); }; ``` - [ ] **Step 4: Replace lifecycle CSS** In `presentation.css`, replace `.scene-body__lifecycle`, `.scene-body__lifecycle-stage`, `.scene-body__lifecycle-number`, `.scene-body__lifecycle-arrow`, and active-state lifecycle rules with: ```css .scene-body__lifecycle { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.65rem; align-items: stretch; margin-top: 1.2rem; } .scene-body__lifecycle-stage { position: relative; display: grid; align-content: start; gap: 0.5rem; min-height: 9rem; border: 1px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 32%, transparent); border-radius: 0.9rem; padding: 0.9rem; background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 82%, white); color: var(--color-editorial-ink, oklch(0.19 0.015 65)); } .scene-body__lifecycle-stage[data-lifecycle-active="false"] { opacity: 0.68; } .scene-body__lifecycle-stage[data-lifecycle-active="true"] { opacity: 1; transform: translateY(-0.25rem); border-color: color-mix(in oklch, var(--accent-cyan, oklch(0.7 0.16 195)) 58%, transparent); background: color-mix(in oklch, var(--accent-cyan, oklch(0.7 0.16 195)) 8%, var(--color-editorial-paper, oklch(0.975 0.012 82))); } .scene-body__lifecycle-stage strong { color: var(--color-editorial-ink, oklch(0.19 0.015 65)); font-size: 1.2rem; } .scene-body__lifecycle-stage small { color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 72%, var(--color-editorial-muted, oklch(0.48 0.025 65))); line-height: 1.3; } .scene-body__lifecycle-number { display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; border-radius: 50%; background: color-mix(in oklch, var(--accent-cyan, oklch(0.7 0.16 195)) 74%, white); color: var(--color-editorial-ink, oklch(0.19 0.015 65)); font: 800 0.72rem/1 var(--font-mono, monospace); } .scene-body__lifecycle-arrow { position: absolute; right: -0.55rem; top: 50%; color: var(--color-editorial-muted, oklch(0.48 0.025 65)); transform: translateY(-50%); } .scene-body__lifecycle-current { display: grid; gap: 0.3rem; margin-top: 0.9rem; border: 1px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 28%, transparent); border-radius: 0.85rem; padding: 0.8rem 0.9rem; background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 86%, white); color: var(--color-editorial-ink, oklch(0.19 0.015 65)); } .scene-body__lifecycle-current span { color: var(--color-editorial-muted, oklch(0.48 0.025 65)); font: 700 0.66rem/1 var(--font-mono, monospace); letter-spacing: 0.08em; text-transform: uppercase; } .scene-body__lifecycle-current strong, .scene-body__lifecycle-current p { margin: 0; } .scene-body__lifecycle-current p { color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 76%, var(--color-editorial-muted, oklch(0.48 0.025 65))); } ``` Keep the existing `.scene-body__authoring-number` styles by splitting any combined selector that used `.scene-body__lifecycle-number, .scene-body__authoring-number`. After this task, `.scene-body__authoring-number` must still render the Scene 7 numbered circles. - [ ] **Step 5: Run tests and commit Task 3** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/SceneBody.test.tsx pnpm --dir web --filter @lda/console typecheck ``` Expected: PASS. Commit: ```powershell git add web/apps/console/src/presentation/SceneBody.tsx web/apps/console/src/presentation/SceneBody.test.tsx web/apps/console/src/presentation/presentation.css git commit -m "feat: recompose lifecycle scene" ``` --- ### Task 4: Tune Scene 10 Demo Graph And Interrupt Contract **Files:** - Modify: `web/apps/console/src/presentation/DemoWorkflowScene.test.tsx` - Modify: `web/apps/console/src/presentation/styles/demo-workflow.css` **Interfaces:** - Consumes: existing `DemoWorkflowScene` approval beat and `InterruptContractPreview`. - Produces: a readable graph/contract layout without changing data or component props. - [ ] **Step 1: Add an approval readability test** In `DemoWorkflowScene.test.tsx`, extend the existing `"makes the Scene 10 approval contract the primary visual"` test: ```tsx it("makes the Scene 10 approval contract the primary visual", () => { renderBeat("approval", "interrupt-evidence"); const stage = screen.getByLabelText("demo workflow stage"); expect(stage).toHaveAttribute("data-demo-layout", "approval"); expect(screen.getByLabelText("typed interrupt contract")).toHaveAttribute("data-hero", "true"); expect(screen.getByLabelText("typed interrupt contract")).toHaveTextContent("Operator decision"); expect(screen.getByLabelText("typed interrupt contract")).toHaveTextContent("Resume outcomes"); expect(screen.getByLabelText("workflow graph")).toBeInTheDocument(); }); ``` If the test already contains the first three assertions, replace it with the block above. - [ ] **Step 2: Run demo scene tests and verify they pass before CSS** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/DemoWorkflowScene.test.tsx ``` Expected: PASS. This confirms the task is visual/readability only. - [ ] **Step 3: Tune demo workflow CSS** In `web/apps/console/src/presentation/styles/demo-workflow.css`, update only existing selectors. Use these target values: ```css .demo-workflow-stage[data-demo-layout="approval"] .demo-workflow-stage__graph, .demo-workflow-stage[data-demo-layout="interrupt"] .demo-workflow-stage__graph { grid-template-columns: minmax(18rem, 0.78fr) minmax(26rem, 1.22fr); align-items: stretch; } .demo-workflow-stage[data-demo-layout="approval"] .interrupt-contract-preview, .demo-workflow-stage[data-demo-layout="interrupt"] .interrupt-contract-preview { min-width: 0; color: var(--text-primary); } .demo-workflow-stage[data-demo-layout="approval"] .workflow-graph-stage, .demo-workflow-stage[data-demo-layout="interrupt"] .workflow-graph-stage { min-height: 18rem; } .presentation-route .workflow-graph-stage__node { color: var(--text-primary); } .workflow-graph-stage__node strong { color: var(--text-primary); } .workflow-graph-stage__node small, .workflow-graph-stage__node-state { color: color-mix(in oklch, var(--text-primary) 76%, var(--text-muted)); } .workflow-graph-stage__node[data-execution-state="future"] { opacity: 0.72; } .workflow-graph-stage__node[data-execution-state="completed"] { opacity: 0.9; } .interrupt-contract-preview__schema pre { max-height: 7.5rem; color: color-mix(in oklch, var(--text-primary) 82%, var(--text-muted)); } ``` Do not duplicate selectors if they already exist. Merge these values into the current blocks. - [ ] **Step 4: Run tests and commit Task 4** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/DemoWorkflowScene.test.tsx pnpm --dir web --filter @lda/console typecheck ``` Expected: PASS. Commit: ```powershell git add web/apps/console/src/presentation/DemoWorkflowScene.test.tsx web/apps/console/src/presentation/styles/demo-workflow.css git commit -m "fix: tune demo graph contract readability" ``` --- ### Task 5: Screenshot Smoke, Roadmap, And Archive **Files:** - Modify: `docs/current_roadmap.md` - Move: `docs/superpowers/plans/2026-07-08-presentation-scene-composition.md` to `docs/historical/superpowers/plans/2026-07-08-presentation-scene-composition.md` **Interfaces:** - Consumes: completed scene composition tasks. - Produces: verified screenshot set and live roadmap entry pointing to the archived plan. - [ ] **Step 1: Run focused verification** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/SceneBody.test.tsx src/presentation/DemoWorkflowScene.test.tsx pnpm --dir web --filter @lda/console typecheck pnpm --dir web --filter @lda/console build ``` Expected: - SceneBody and DemoWorkflowScene tests pass. - Typecheck prints no TypeScript errors. - Build succeeds with the existing Vite chunk-size warning only. - [ ] **Step 2: Capture screenshot smoke** With `pnpm dev` running, use the existing browser smoke method used by prior presentation slices. Capture these routes at `1280x720`: ```text http://127.0.0.1:5173/present#scene/positioning/landscape http://127.0.0.1:5173/present#scene/positioning/lda-position http://127.0.0.1:5173/present#scene/planner-runtime/planner http://127.0.0.1:5173/present#scene/planner-runtime/boundary http://127.0.0.1:5173/present#scene/lifecycle/draft http://127.0.0.1:5173/present#scene/lifecycle/run http://127.0.0.1:5173/present#scene/workflow-demo/approval ``` Save screenshots under: ```text web/apps/console/.visual-smoke/ ``` Expected visual checks: - Scene 3 uses the center of the canvas and reads as a map. - Scene 4 has a clear central boundary and two large panes. - Scene 5 has a readable Draft -> Artifact -> Deployment -> Run rail. - Scene 10 graph labels and interrupt-contract labels are readable. - No stage scrollbars are visible. - [ ] **Step 3: Update roadmap** In `docs/current_roadmap.md`, update the presentation visual slices list so item 3 reads: ```markdown 3. Completed: scene composition pass expanded the positioning map, planner/runtime boundary, lifecycle rail, and Scene 10 demo graph/contract readability. Implementation: [`presentation scene composition`](historical/superpowers/plans/2026-07-08-presentation-scene-composition.md). 4. Presentation craft pass: tune motion, discussion-chip placement, Q&A modal hierarchy, evidence receipt placement, and remaining generic-slide styling after the compositions are stable. ``` - [ ] **Step 4: Archive the plan** Run: ```powershell Move-Item docs/superpowers/plans/2026-07-08-presentation-scene-composition.md docs/historical/superpowers/plans/2026-07-08-presentation-scene-composition.md ``` - [ ] **Step 5: Run docs/status checks** Run: ```powershell rg -n '2026-07-08-presentation-scene-composition' docs/current_roadmap.md docs/historical/superpowers/plans docs/superpowers/plans git status --short git diff --check ``` Expected: - `docs/current_roadmap.md` points to the historical plan path. - No active plan with this filename remains in `docs/superpowers/plans/`. - `.visual-smoke/` is ignored. - `.superpowers/` is not staged. - `git diff --check` reports no whitespace errors. - [ ] **Step 6: Commit Task 5** Commit: ```powershell git add docs/current_roadmap.md docs/historical/superpowers/plans/2026-07-08-presentation-scene-composition.md git commit -m "docs: record presentation scene composition" ``` --- ## Final Verification Run: ```powershell pnpm --dir web test pnpm --dir web typecheck pnpm --dir web build git diff --check git status --short ``` Expected: - All web tests pass, except any explicitly reported pre-existing flaky timeout must be named in the final report with the failing test. - Typecheck is clean. - Build succeeds with only the existing Vite chunk-size warning. - Whitespace check is clean. - Git status has no unintended files; `.superpowers/` and `.visual-smoke/` are not staged. ## Self-Review - Spec coverage: Tasks 1-3 cover Scenes 3, 4, and 5. Task 4 covers Scene 10. Task 5 covers screenshots, roadmap, and plan archival. - Completion-word scan: no unresolved implementation markers are present. - Type consistency: all new attributes and labels referenced by tests are produced by the matching scene renderers. - Scope check: no chat replacement, Q&A rewrite, evidence-inspector redesign, route change, or demo state change is included.