= [
{ id: "read_docs", label: "Read documents", detail: "5 selected", kind: "node", x: 14, y: 58 },
{ id: "build_report", label: "Build report", detail: "Markdown", kind: "node", x: 34, y: 36 },
{ id: "review_issues", label: "Issue review", detail: "Typed interrupt", kind: "interrupt", x: 52, y: 58 },
{ id: "create_issues", label: "Create issues", detail: "Selected only", kind: "node", x: 70, y: 36 },
{ id: "end_completed", label: "Completed", detail: "Persisted run", kind: "end", x: 86, y: 58 },
];
```
Add the proof type and prop:
```ts
export type WorkflowGraphProof = {
readonly runId: string | null;
readonly traceLabel: string;
readonly evidenceLabel: string;
};
type WorkflowGraphStageProps = {
readonly execution: GraphExecutionPresentation;
readonly selectedNodeId: string | null;
readonly selectNode: (nodeId: string) => void;
readonly proof?: WorkflowGraphProof;
};
```
Update the component signature:
```ts
export const WorkflowGraphStage = ({
execution,
selectedNodeId,
selectNode,
proof,
}: WorkflowGraphStageProps) => {
```
Render this immediately after the legend:
```tsx
{proof && (
Run{proof.runId ?? "run unavailable"}
Trace{proof.traceLabel}
Evidence{proof.evidenceLabel}
)}
```
- [ ] **Step 4: Add graph proof CSS and compact node sizing**
In `web/apps/console/src/presentation/styles/demo-workflow.css`, update graph CSS:
```css
.workflow-graph-stage__proof {
position: absolute;
z-index: 4;
left: 0.8rem;
bottom: 0.7rem;
display: flex;
flex-wrap: wrap;
gap: 0.55rem;
max-width: calc(100% - 1.6rem);
color: var(--text-secondary);
font: 600 0.58rem/1.2 var(--font-mono, monospace);
}
.workflow-graph-stage__proof span {
display: inline-flex;
align-items: center;
gap: 0.3rem;
border: 1px solid oklch(0.36 0.04 250 / 0.7);
border-radius: 999px;
padding: 0.18rem 0.45rem;
background: oklch(0.09 0.018 250 / 0.78);
}
.workflow-graph-stage__proof b {
color: var(--accent-cyan);
font-weight: 700;
text-transform: uppercase;
}
.workflow-graph-stage__proof code {
max-width: 14rem;
overflow: hidden;
color: var(--text-primary);
text-overflow: ellipsis;
white-space: nowrap;
}
```
Then tune the existing node rule:
```css
.presentation-route .workflow-graph-stage__node {
width: clamp(7rem, 10vw, 8.75rem);
min-height: 4.15rem;
padding: 0.58rem 0.68rem;
}
```
If the existing rule has other properties, preserve them and update only these values.
- [ ] **Step 5: Run tests and verify they pass**
Run:
```powershell
pnpm --dir web --filter @lda/console test -- src/presentation/WorkflowGraphStage.test.tsx
```
Expected: pass.
- [ ] **Step 6: Commit Task 2**
```powershell
git add web/apps/console/src/presentation/WorkflowGraphStage.tsx web/apps/console/src/presentation/WorkflowGraphStage.test.tsx web/apps/console/src/presentation/styles/demo-workflow.css
git commit -m "fix: keep demo workflow graph in frame"
```
---
### Task 3: Pass Run Proof Into The Graph
**Files:**
- Modify: `web/apps/console/src/presentation/DemoWorkflowScene.tsx`
- Modify: `web/apps/console/src/presentation/DemoWorkflowScene.test.tsx`
**Interfaces:**
- Consumes:
- `WorkflowGraphStage` `proof?: WorkflowGraphProof`
- `runStart` event from the prepared replay.
- Produces: graph proof labels on every graph beat.
- [ ] **Step 1: Write failing scene tests**
In `web/apps/console/src/presentation/DemoWorkflowScene.test.tsx`, add:
```tsx
it("passes run proof into graph-heavy beats", () => {
const { unmount } = renderBeat("graph");
expect(screen.getByLabelText("workflow graph proof")).toHaveTextContent("run_recorded_lda_report");
expect(screen.getByLabelText("workflow graph proof")).toHaveTextContent("5 workflow nodes");
unmount();
renderBeat("approval", "interrupt-evidence");
expect(screen.getByLabelText("workflow graph proof")).toHaveTextContent("JSON-RPC evidence");
});
```
- [ ] **Step 2: Run tests and verify they fail**
Run:
```powershell
pnpm --dir web --filter @lda/console test -- src/presentation/DemoWorkflowScene.test.tsx
```
Expected: fail because graph proof is not rendered.
- [ ] **Step 3: Pass proof into `WorkflowGraphStage`**
In `web/apps/console/src/presentation/DemoWorkflowScene.tsx`, add:
```ts
const runProof = {
runId: runStart?.resultingIds.runId ?? null,
traceLabel: "5 workflow nodes",
evidenceLabel: "JSON-RPC evidence",
};
```
Then update `WorkflowGraphStage` usage:
```tsx
```
Add this comment above `runProof`:
```ts
// Presentation-only proof labels keep the graph tied to the recorded run
// without changing the canonical replay event payload.
```
- [ ] **Step 4: Run tests and verify they pass**
Run:
```powershell
pnpm --dir web --filter @lda/console test -- src/presentation/DemoWorkflowScene.test.tsx src/presentation/WorkflowGraphStage.test.tsx
```
Expected: pass.
- [ ] **Step 5: Commit Task 3**
```powershell
git add web/apps/console/src/presentation/DemoWorkflowScene.tsx web/apps/console/src/presentation/DemoWorkflowScene.test.tsx
git commit -m "feat: tie demo graph to run proof"
```
---
### Task 4: Fix Receipt And Outcome Panel Collision
**Files:**
- Modify: `web/apps/console/src/presentation/styles/demo-workflow.css`
- Modify: `web/apps/console/src/presentation/DemoWorkflowScene.test.tsx`
**Interfaces:**
- Consumes: existing `data-demo-layout` attributes.
- Produces: layout hooks proving outcome panels sit below the receipt row.
- [ ] **Step 1: Write a regression test for layout hooks**
In `web/apps/console/src/presentation/DemoWorkflowScene.test.tsx`, add:
```tsx
it("marks outcome-panel layouts so CSS can clear the receipt row", () => {
renderBeat("approval", "interrupt-evidence");
expect(screen.getByLabelText("demo workflow stage")).toHaveAttribute("data-demo-layout", "approval");
expect(screen.getByLabelText("demo outcome proof")).toBeInTheDocument();
expect(screen.getByLabelText("workflow.runs.start execution receipt")).toBeInTheDocument();
});
```
This test does not measure CSS in JSDOM; it pins the DOM contract that the CSS uses.
- [ ] **Step 2: Run the test**
Run:
```powershell
pnpm --dir web --filter @lda/console test -- src/presentation/DemoWorkflowScene.test.tsx
```
Expected: pass if Task 3 is complete. If it fails, fix missing labels before editing CSS.
- [ ] **Step 3: Update CSS to clear the receipt row**
In `web/apps/console/src/presentation/styles/demo-workflow.css`, find the `.demo-workflow-stage:has(.demo-outcome-panel)` block. Add or update:
```css
.demo-workflow-stage:has(.demo-outcome-panel) .demo-outcome-panel {
margin-top: 3.15rem;
min-height: 0;
}
.demo-workflow-stage[data-demo-layout="approval"] .demo-outcome-panel,
.demo-workflow-stage[data-demo-layout="evidence"] .demo-outcome-panel {
align-self: stretch;
overflow: hidden;
}
```
Add this comment above the first rule:
```css
/* The operation receipt is absolute at the top of graph beats. Outcome panels
need the same top clearance or their headings clip under the receipt row. */
```
Then ensure `.demo-workflow-stage__graph` already has `padding-top: 3.15rem;`. If not, add it.
- [ ] **Step 4: Run focused tests**
Run:
```powershell
pnpm --dir web --filter @lda/console test -- src/presentation/DemoWorkflowScene.test.tsx
```
Expected: pass.
- [ ] **Step 5: Commit Task 4**
```powershell
git add web/apps/console/src/presentation/DemoWorkflowScene.test.tsx web/apps/console/src/presentation/styles/demo-workflow.css
git commit -m "fix: clear demo outcome panels below receipt"
```
---
### Task 5: Browser Smoke And Roadmap
**Files:**
- Modify: `docs/current_roadmap.md`
- Move: `docs/superpowers/plans/2026-07-09-demo-product-proof-layout.md` to `docs/historical/superpowers/plans/2026-07-09-demo-product-proof-layout.md`
**Interfaces:**
- Consumes: completed layout fixes.
- Produces: archived plan and roadmap entry.
- [ ] **Step 1: Run verification**
Run:
```powershell
pnpm --dir web --filter @lda/console test -- src/presentation
pnpm --dir web --filter @lda/console typecheck
pnpm --dir web --filter @lda/console build
git diff --check
```
Expected:
- Presentation tests pass.
- Typecheck passes.
- Build passes with only the pre-existing chunk-size warning if it appears.
- `git diff --check` has no whitespace errors. Windows LF/CRLF notices are acceptable.
- [ ] **Step 2: Capture browser smoke screenshots**
With `pnpm dev` running:
```powershell
pnpx --package @playwright/cli playwright-cli -s=proof-layout open "http://127.0.0.1:5173/present#scene/workflow-demo/graph"
pnpx --package @playwright/cli playwright-cli -s=proof-layout resize 1280 720
pnpx --package @playwright/cli playwright-cli -s=proof-layout screenshot --filename web/apps/console/.visual-smoke/proof-layout-09-graph.png
pnpx --package @playwright/cli playwright-cli -s=proof-layout open "http://127.0.0.1:5173/present#scene/workflow-demo/interrupt"
pnpx --package @playwright/cli playwright-cli -s=proof-layout screenshot --filename web/apps/console/.visual-smoke/proof-layout-09-interrupt.png
pnpx --package @playwright/cli playwright-cli -s=proof-layout open "http://127.0.0.1:5173/present#scene/interrupt-evidence/approval"
pnpx --package @playwright/cli playwright-cli -s=proof-layout screenshot --filename web/apps/console/.visual-smoke/proof-layout-10-approval.png
pnpx --package @playwright/cli playwright-cli -s=proof-layout open "http://127.0.0.1:5173/present#scene/interrupt-evidence/output"
pnpx --package @playwright/cli playwright-cli -s=proof-layout screenshot --filename web/apps/console/.visual-smoke/proof-layout-10-output.png
```
Acceptance criteria:
- No beige chat rail appears on graph/interrupt/approval/output beats.
- All graph nodes are fully visible.
- The outcome panel heading is not clipped.
- The graph includes run/trace/evidence proof labels.
- No visible scrollbar appears at `1280x720`.
- [ ] **Step 3: Update roadmap**
In `docs/current_roadmap.md`, under `Presentation wishlist / defense readiness`, add this item after demo climax craft pass:
```md
6. Completed: demo product proof layout pass hid chat during graph-heavy
beats, kept workflow graph nodes in frame, added run-proof labels inside
the graph, and cleared outcome panels below the receipt row. Implementation:
[`demo product proof layout`](historical/superpowers/plans/2026-07-09-demo-product-proof-layout.md).
7. Presentation craft pass: tune motion, discussion-chip placement, Q&A modal
hierarchy, evidence receipt placement, and remaining generic-slide styling
after the demo proof layout is stable.
```
Renumber the previous open craft-pass item if needed.
- [ ] **Step 4: Archive the plan**
Run:
```powershell
Move-Item docs/superpowers/plans/2026-07-09-demo-product-proof-layout.md docs/historical/superpowers/plans/2026-07-09-demo-product-proof-layout.md
```
Verify:
```powershell
rg -n "demo-product-proof-layout|demo product proof layout" docs/current_roadmap.md docs/superpowers/plans docs/historical/superpowers/plans
```
Expected:
- Roadmap points to `historical/superpowers/plans/2026-07-09-demo-product-proof-layout.md`.
- No active copy remains under `docs/superpowers/plans/`.
- [ ] **Step 5: Commit Task 5**
```powershell
git add docs/current_roadmap.md docs/historical/superpowers/plans/2026-07-09-demo-product-proof-layout.md
git add -u docs/superpowers/plans/2026-07-09-demo-product-proof-layout.md
git commit -m "docs: record demo product proof layout pass"
```
---
## Final Verification
Run:
```powershell
pnpm --dir web --filter @lda/console test -- src/presentation
pnpm --dir web --filter @lda/console typecheck
pnpm --dir web --filter @lda/console build
git diff --check
git status --short
```
Expected:
- Presentation tests pass.
- Typecheck passes.
- Build passes with only the known Vite chunk warning if it appears.
- `git diff --check` is clean.
- `git status --short` is clean.
## Self-Review
- Spec coverage: the plan addresses the observed screenshot failures: chat width, graph clipping, weak graph proof, and outcome panel clipping.
- Placeholder scan: no placeholder markers or unspecified tests are present.
- Type consistency: `WorkflowGraphProof` is defined in `WorkflowGraphStage.tsx`, consumed by `DemoWorkflowScene.tsx`, and verified by component and scene tests.
- Scope check: no chat framework replacement, backend dependency, runtime change, recording change, or scene route change is included.