# Presentation Coherence Pass 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:** Make presentation mode feel like one coherent product demo instead of a pile of individually fixed scenes.
**Architecture:** Add a small scene-coherence model that states what each scene is allowed to emphasize, then use it to guide two visible corrections: Scene 2 becomes a chat/tool-loop transcript instead of a left-to-right pipeline, and Scenes 8-12 expose stable product-flow surface metadata for visual hierarchy. This pass does not introduce new UI frameworks; it tightens existing React components and CSS.
**Tech Stack:** React 19, TypeScript, Vite, Tailwind 4 tokens already present in `editorial.css`, existing presentation CSS, Vitest + Testing Library, Playwright screenshot smoke.
## Global Constraints
- Do not add shadcn/ui, assistant-ui, AI SDK, Radix, lucide, or any other dependency.
- Do not change `/console`.
- Do not rewrite the storyboard order.
- Do not redesign baseline-good Scenes 3, 4, and 5.
- Keep chat secondary unless a beat is actively narrating, approving, or showing trace context.
- Each scene gets one primary artifact and at most one support surface.
- Preserve existing hash routes.
- Preserve current keyboard navigation.
- Keep 720p readability as the main constraint.
- Screenshot verification must include `1280x720` and `1024x768` for affected scenes.
---
## File Structure
- Create `web/apps/console/src/presentation/presentation-coherence.ts`
- Defines the scene matrix and helper functions.
- Gives future workers one place to inspect what each scene should visually prioritize.
- Create `web/apps/console/src/presentation/presentation-coherence.test.ts`
- Pins coverage for all 14 scenes and checks that each scene has one primary artifact.
- Modify `web/apps/console/src/presentation/opening/ProblemLoopScene.tsx`
- Replaces the left-side abstract tile rail with a vertical chat/tool transcript.
- Modify `web/apps/console/src/presentation/opening/ProblemLoopScene.test.tsx`
- Pins the transcript metaphor and keeps the reusable-automation side in simple language.
- Modify `web/apps/console/src/presentation/DemoWorkflowScene.tsx`
- Adds `data-primary-surface` and `data-support-surface` from the coherence model.
- Modify `web/apps/console/src/presentation/DemoWorkflowScene.test.tsx`
- Pins surface metadata for Scenes 8-12.
- Modify `web/apps/console/src/presentation/presentation.css`
- Adds transcript styling and surface-hierarchy CSS for the demo scenes.
- Modify `docs/current_roadmap.md`
- Mark this coherence pass completed after implementation.
- Move this plan to `docs/historical/superpowers/plans/` after completion.
---
### Task 1: Scene Coherence Matrix
**Files:**
- Create: `web/apps/console/src/presentation/presentation-coherence.ts`
- Create: `web/apps/console/src/presentation/presentation-coherence.test.ts`
**Interfaces:**
- Produces:
- `type PrimaryArtifact`
- `type SupportSurface`
- `type ChatRole`
- `type SceneCoherenceEntry`
- `sceneCoherenceMatrix: readonly SceneCoherenceEntry[]`
- `coherenceForScene(sceneId: string): SceneCoherenceEntry`
- `demoSurfaceForBeat(sceneId: string, beatId: string): { readonly primarySurface: string; readonly supportSurface: string }`
- Consumes:
- `scenes` from `web/apps/console/src/presentation/storyboard.ts`
- [ ] **Step 1: Write failing tests for matrix coverage and constraints**
Create `web/apps/console/src/presentation/presentation-coherence.test.ts`:
```ts
import { describe, expect, it } from "vitest";
import { scenes } from "./storyboard.js";
import {
coherenceForScene,
demoSurfaceForBeat,
sceneCoherenceMatrix,
} from "./presentation-coherence.js";
describe("presentation coherence matrix", () => {
it("covers every storyboard scene exactly once", () => {
const sceneIds = scenes.map((scene) => scene.id);
const matrixIds = sceneCoherenceMatrix.map((entry) => entry.sceneId);
expect(matrixIds).toEqual(sceneIds);
expect(new Set(matrixIds).size).toBe(sceneIds.length);
});
it("gives every scene one primary artifact and at most one support surface", () => {
for (const scene of scenes) {
const entry = coherenceForScene(scene.id);
expect(entry.primaryArtifact.length).toBeGreaterThan(0);
expect(entry.supportSurface).not.toContain("+");
expect(entry.chatRole).toMatch(/^(hidden|narration|approval|trace)$/);
}
});
it("keeps baseline scenes 3 through 5 stable", () => {
expect(coherenceForScene("positioning")).toMatchObject({
primaryArtifact: "positioning-map",
supportSurface: "discussion-rail",
chatRole: "hidden",
});
expect(coherenceForScene("planner-runtime")).toMatchObject({
primaryArtifact: "boundary-diagram",
supportSurface: "discussion-rail",
chatRole: "hidden",
});
expect(coherenceForScene("lifecycle")).toMatchObject({
primaryArtifact: "lifecycle-rail",
supportSurface: "current-state-panel",
chatRole: "hidden",
});
});
it("classifies demo beats into one primary surface and one support surface", () => {
expect(demoSurfaceForBeat("run-from-deployment", "graph")).toEqual({
primarySurface: "workflow-graph",
supportSurface: "run-receipt",
});
expect(demoSurfaceForBeat("typed-human-boundary", "approval")).toEqual({
primarySurface: "interrupt-approval",
supportSurface: "facts-only",
});
expect(demoSurfaceForBeat("resume-output-evidence", "trace")).toEqual({
primarySurface: "trace-evidence",
supportSurface: "output-summary",
});
});
});
```
- [ ] **Step 2: Run matrix tests and confirm failure**
Run:
```bash
pnpm --dir web --filter @lda/console test -- src/presentation/presentation-coherence.test.ts
```
Expected: FAIL because `presentation-coherence.js` does not exist.
- [ ] **Step 3: Implement coherence matrix**
Create `web/apps/console/src/presentation/presentation-coherence.ts`:
```ts
export type PrimaryArtifact =
| "opening-decomposition"
| "tool-loop-transcript"
| "positioning-map"
| "boundary-diagram"
| "lifecycle-rail"
| "interactive-architecture"
| "authoring-loop"
| "agent-handoff"
| "prepared-lifecycle"
| "workflow-graph"
| "interrupt-approval"
| "trace-evidence"
| "evaluation-board"
| "future-work-map";
export type SupportSurface =
| "none"
| "discussion-rail"
| "current-state-panel"
| "run-receipt"
| "facts-only"
| "output-summary";
export type ChatRole = "hidden" | "narration" | "approval" | "trace";
export type SceneCoherenceEntry = {
readonly sceneId: string;
readonly primaryArtifact: PrimaryArtifact;
readonly supportSurface: SupportSurface;
readonly chatRole: ChatRole;
readonly presenterFocus: string;
};
export const sceneCoherenceMatrix = [
{
sceneId: "thesis",
primaryArtifact: "opening-decomposition",
supportSurface: "discussion-rail",
chatRole: "hidden",
presenterFocus: "Move from AI-agent ambition to the submitted workflow substrate.",
},
{
sceneId: "problem",
primaryArtifact: "tool-loop-transcript",
supportSurface: "none",
chatRole: "hidden",
presenterFocus: "Contrast a one-off agent/tool loop with reusable automation requirements.",
},
{
sceneId: "positioning",
primaryArtifact: "positioning-map",
supportSurface: "discussion-rail",
chatRole: "hidden",
presenterFocus: "Place the system among scripts, tool loops, hosted automation, MCP, and agent graphs.",
},
{
sceneId: "planner-runtime",
primaryArtifact: "boundary-diagram",
supportSurface: "discussion-rail",
chatRole: "hidden",
presenterFocus: "Show that external planners propose while the runtime validates and records.",
},
{
sceneId: "lifecycle",
primaryArtifact: "lifecycle-rail",
supportSurface: "current-state-panel",
chatRole: "hidden",
presenterFocus: "Explain Draft -> Artifact -> Deployment -> Run as the durable lifecycle.",
},
{
sceneId: "architecture",
primaryArtifact: "interactive-architecture",
supportSurface: "discussion-rail",
chatRole: "hidden",
presenterFocus: "Use the recursive architecture figure as the only primary artifact.",
},
{
sceneId: "authoring",
primaryArtifact: "authoring-loop",
supportSurface: "discussion-rail",
chatRole: "hidden",
presenterFocus: "Show the authoring loop without turning it into generic process cards.",
},
{
sceneId: "agent-handoff",
primaryArtifact: "agent-handoff",
supportSurface: "none",
chatRole: "narration",
presenterFocus: "Introduce the prepared operator flow only as a bridge into product proof.",
},
{
sceneId: "prepared-lifecycle",
primaryArtifact: "prepared-lifecycle",
supportSurface: "none",
chatRole: "hidden",
presenterFocus: "Show the prepared workflow before execution starts.",
},
{
sceneId: "run-from-deployment",
primaryArtifact: "workflow-graph",
supportSurface: "run-receipt",
chatRole: "hidden",
presenterFocus: "Start a persisted run from a deployment and keep the graph dominant.",
},
{
sceneId: "typed-human-boundary",
primaryArtifact: "interrupt-approval",
supportSurface: "facts-only",
chatRole: "approval",
presenterFocus: "Show the typed interrupt, selected issues, and operator decision.",
},
{
sceneId: "resume-output-evidence",
primaryArtifact: "trace-evidence",
supportSurface: "output-summary",
chatRole: "trace",
presenterFocus: "Show resume, output, and trace as evidence from the same run.",
},
{
sceneId: "evaluation",
primaryArtifact: "evaluation-board",
supportSurface: "discussion-rail",
chatRole: "hidden",
presenterFocus: "Summarize evaluation as bounded evidence, not a model leaderboard.",
},
{
sceneId: "conclusion",
primaryArtifact: "future-work-map",
supportSurface: "discussion-rail",
chatRole: "narration",
presenterFocus: "End on boundary and future layers without overclaiming an autonomous agent.",
},
] as const satisfies readonly SceneCoherenceEntry[];
export const coherenceForScene = (sceneId: string): SceneCoherenceEntry => {
const entry = sceneCoherenceMatrix.find((candidate) => candidate.sceneId === sceneId);
if (!entry) {
throw new Error(`No presentation coherence entry for scene ${sceneId}`);
}
return entry;
};
export const demoSurfaceForBeat = (
sceneId: string,
beatId: string,
): { readonly primarySurface: string; readonly supportSurface: string } => {
if (sceneId === "prepared-lifecycle") {
return { primarySurface: "prepared-lifecycle", supportSurface: "none" };
}
if (sceneId === "run-from-deployment") {
return {
primarySurface: beatId === "operation" ? "run-operation" : "workflow-graph",
supportSurface: beatId === "operation" ? "none" : "run-receipt",
};
}
if (sceneId === "typed-human-boundary") {
return {
primarySurface: beatId === "interrupt" ? "interrupt-payload" : "interrupt-approval",
supportSurface: "facts-only",
};
}
if (sceneId === "resume-output-evidence") {
if (beatId === "resume") return { primarySurface: "resume-decision", supportSurface: "output-summary" };
if (beatId === "output") return { primarySurface: "workflow-output", supportSurface: "none" };
return { primarySurface: "trace-evidence", supportSurface: "output-summary" };
}
return { primarySurface: "none", supportSurface: "none" };
};
```
- [ ] **Step 4: Run matrix tests**
Run:
```bash
pnpm --dir web --filter @lda/console test -- src/presentation/presentation-coherence.test.ts
```
Expected: PASS.
- [ ] **Step 5: Commit matrix**
```bash
git add web/apps/console/src/presentation/presentation-coherence.ts web/apps/console/src/presentation/presentation-coherence.test.ts
git commit -m "feat: define presentation coherence matrix"
```
---
### Task 2: Replace Scene 2 Pipeline With Tool-Loop Transcript
**Files:**
- Modify: `web/apps/console/src/presentation/opening/ProblemLoopScene.tsx`
- Modify: `web/apps/console/src/presentation/opening/ProblemLoopScene.test.tsx`
- Modify: `web/apps/console/src/presentation/presentation.css`
**Interfaces:**
- Consumes:
- `ConceptNode` and `ConceptRail` from `ConceptPrimitives.tsx`.
- Produces:
- Scene 2 left side reads as a vertical conversation/tool loop, not a deterministic pipeline.
- Existing `ProblemLoopScene` export remains unchanged.
- [ ] **Step 1: Write failing tests for transcript metaphor**
Modify `web/apps/console/src/presentation/opening/ProblemLoopScene.test.tsx` to include:
```tsx
it("shows direct action as a vertical chat and tool transcript", () => {
render(
{turn.detail}
Useful once. Hard to reuse.