Files
lda-wf/docs/historical/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md
T

28 KiB

Defense Presentation Visual 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: Polish the weakest /present visuals for defense use: Scene 6 architecture, Scene 7 authoring, Scene 10 interrupt/evidence, and discussion speaker hints.

Architecture: Keep the current presentation route, storyboard, replay, and component model. Improve composition through small scene helpers, CSS layout states, and focused tests; do not introduce a new theme system, chat framework, or slide runtime. Use existing editorial/presentation tokens and keep all changes scoped under web/apps/console/src/presentation.

Tech Stack: React, TypeScript, CSS, React Flow, Vitest, Testing Library, Playwright CLI smoke screenshots.

Global Constraints

  • Follow design spec: docs/historical/superpowers/specs/2026-07-08-defense-presentation-visual-pass-design.md.
  • Do not change the 12-scene storyboard order.
  • Do not replace chat UI in this slice.
  • Do not add new dependencies.
  • Do not introduce a third global theme or new :root palette.
  • Preserve keyboard navigation: arrow keys for presentation, Escape for overlays, roving focus inside InteractiveFigure.
  • Respect motionDisabled and prefers-reduced-motion.
  • Keep /console unaffected.
  • Verify at 1280x720 and 1024x768.

File Structure

  • Modify web/apps/console/src/presentation/figures/InteractiveFigure.tsx
    • Add or refine a stage-scale figure size variant.
  • Modify web/apps/console/src/presentation/figures/interactive-figure.css
    • Make wide/stage figures larger, horizontally navigable, and readable.
  • Modify web/apps/console/src/presentation/scenes/ArchitectureScene.tsx
    • Use the improved figure size and add a scene-level data hook if needed.
  • Modify web/apps/console/src/presentation/scenes/ArchitectureScene.test.tsx
    • Pin architecture scene sizing and nested focus usability.
  • Modify web/apps/console/src/presentation/SceneBody.tsx
    • Replace the generic Scene 7 authoring card row with a named authoring loop visual or extracted component.
  • Modify web/apps/console/src/presentation/SceneBody.test.tsx
    • Pin authoring loop labels and active beat state.
  • Modify web/apps/console/src/presentation/DemoWorkflowScene.tsx
    • Add named beat layout states for Scene 10 approval/trace composition.
  • Modify web/apps/console/src/presentation/DemoWorkflowScene.test.tsx
    • Pin approval hero layout and canonical outcomes.
  • Modify web/apps/console/src/presentation/styles/demo-workflow.css
    • Improve Scene 10 graph/contract/receipt layout.
  • Modify web/apps/console/src/presentation/presentation.css
    • Improve authoring loop, discussion speaker note, and any shared presentation-only styles.
  • Modify web/apps/console/src/presentation/DiscussionPanel.test.tsx
    • Pin speaker hint as presenter note.
  • Modify docs/current_roadmap.md
    • Mark visual pass completed after implementation.
  • Move this plan to docs/historical/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md after implementation.

Task 1: Scene 6 Architecture Figure Scale

Files:

  • Modify: web/apps/console/src/presentation/figures/InteractiveFigure.tsx
  • Modify: web/apps/console/src/presentation/figures/interactive-figure.css
  • Modify: web/apps/console/src/presentation/scenes/ArchitectureScene.tsx
  • Test: web/apps/console/src/presentation/scenes/ArchitectureScene.test.tsx
  • Test: web/apps/console/src/presentation/figures/InteractiveFigure.test.tsx

Interfaces:

  • Consumes: InteractiveFigure props:

    • size?: "standard" | "wide"
  • Produces:

    • size?: "standard" | "wide" | "stage"
    • DOM attribute data-figure-size="stage" for Scene 6.
  • Step 1: Add failing tests for stage-sized architecture figure

In web/apps/console/src/presentation/scenes/ArchitectureScene.test.tsx, replace the existing wide-size test:

  it("uses the wide figure presentation for the defense architecture scene", () => {
    renderArchitecture({ focusPath: [] });
    expect(screen.getByRole("group", { name: /architecture/i })).toHaveAttribute("data-figure-size", "wide");
    expect(screen.getByTestId("architecture-scene")).toBeInTheDocument();
  });

with:

  it("uses the stage figure presentation for the defense architecture scene", () => {
    renderArchitecture({ focusPath: [] });
    expect(screen.getByRole("group", { name: /architecture/i })).toHaveAttribute("data-figure-size", "stage");
    expect(screen.getByTestId("architecture-scene")).toHaveAttribute("data-visual-pass", "architecture-stage");
  });

In web/apps/console/src/presentation/figures/InteractiveFigure.test.tsx, add:

  it("marks stage figures as horizontally navigable presentation maps", () => {
    renderFigure({ focusPath: [], size: "stage" });
    const figure = screen.getByRole("group", { name: /architecture/i });
    expect(figure).toHaveAttribute("data-figure-size", "stage");
    expect(figure.querySelector(".interactive-figure__canvas")).toBeInTheDocument();
  });
  • Step 2: Run failing tests

Run:

pnpm --dir web --filter @lda/console test -- src/presentation/scenes/ArchitectureScene.test.tsx src/presentation/figures/InteractiveFigure.test.tsx

Expected: FAIL because size="stage" is not accepted and ArchitectureScene still emits wide.

  • Step 3: Extend InteractiveFigure size type

In web/apps/console/src/presentation/figures/InteractiveFigure.tsx, change:

  readonly size?: "standard" | "wide";

to:

  readonly size?: "standard" | "wide" | "stage";
  • Step 4: Use stage from ArchitectureScene

In web/apps/console/src/presentation/scenes/ArchitectureScene.tsx, change:

    <section className="architecture-scene" data-testid="architecture-scene">

to:

    <section className="architecture-scene" data-testid="architecture-scene" data-visual-pass="architecture-stage">

Change:

        size="wide"

to:

        size="stage"
  • Step 5: Add stage figure CSS

In web/apps/console/src/presentation/figures/interactive-figure.css, keep existing wide rules and add stage rules below them:

.interactive-figure[data-figure-size="stage"] {
  overflow-x: auto;
  overflow-y: hidden;
  padding: 0 0 0.45rem;
  scrollbar-gutter: stable;
}

.interactive-figure[data-figure-size="stage"] .figure-breadcrumbs {
  min-height: 1.6rem;
  padding: 0.15rem 0 0.35rem;
}

.interactive-figure[data-figure-size="stage"] .interactive-figure__canvas {
  min-width: 1440px;
  min-height: 470px;
}

.interactive-figure[data-figure-size="stage"] .react-flow {
  border: 1px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 42%, transparent);
  border-radius: 0.65rem;
  background:
    linear-gradient(90deg, color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 92%, white), transparent 65%),
    color-mix(in oklch, var(--color-editorial-surface, oklch(0.96 0.012 82)) 94%, white);
}

.interactive-figure[data-figure-size="stage"] .figure-node {
  width: 256px;
  height: 112px;
  padding: 12px 16px;
}

.interactive-figure[data-figure-size="stage"] .figure-node__label {
  font-size: 16px;
}

.interactive-figure[data-figure-size="stage"] .figure-node__summary {
  font-size: 12.5px;
  line-height: 1.25;
}

If this causes visible overflow outside .presentation-canvas, keep overflow inside .interactive-figure only. Do not set global viewport overflow.

  • Step 6: Run focused tests

Run:

pnpm --dir web --filter @lda/console test -- src/presentation/scenes/ArchitectureScene.test.tsx src/presentation/figures/InteractiveFigure.test.tsx

Expected: PASS.

  • Step 7: Commit Task 1
git add web/apps/console/src/presentation/figures/InteractiveFigure.tsx web/apps/console/src/presentation/figures/interactive-figure.css web/apps/console/src/presentation/scenes/ArchitectureScene.tsx web/apps/console/src/presentation/scenes/ArchitectureScene.test.tsx web/apps/console/src/presentation/figures/InteractiveFigure.test.tsx
git commit -m "feat: enlarge architecture presentation figure"

Task 2: Scene 7 Authoring Loop Visual

Files:

  • Modify: web/apps/console/src/presentation/SceneBody.tsx
  • Modify: web/apps/console/src/presentation/presentation.css
  • Test: web/apps/console/src/presentation/SceneBody.test.tsx

Interfaces:

  • Consumes: storyboard beat IDs discover, author, diagnose, repair.

  • Produces: authoring loop DOM:

    • aria-label="agent authoring loop"
    • data-active-stage="<beat.id>"
    • stage buttons/items with data-authoring-active="true|false".
  • Step 1: Add failing authoring loop test

Add this test to web/apps/console/src/presentation/SceneBody.test.tsx:

  it("renders Scene 7 as an agent authoring loop with beat-specific emphasis", () => {
    const location: PresentationLocation = { kind: "main", sceneId: "authoring", beatId: "diagnose", focusPath: [] };
    render(
      <SceneBody
        location={location}
        demo={demo}
        selectedNodeId={null}
        selectNode={noop}
        openEvidence={noop}
        openDiscussion={noop}
        onFocusPathChange={noop}
        motionDisabled={false}
      />,
    );

    const loop = screen.getByLabelText("agent authoring loop");
    expect(loop).toHaveAttribute("data-active-stage", "diagnose");
    expect(screen.getByText("Discover capability")).toBeInTheDocument();
    expect(screen.getByText("Author draft")).toBeInTheDocument();
    expect(screen.getByText("Validate and diagnose")).toHaveAttribute("data-authoring-active", "true");
    expect(screen.getByText("Repair")).toBeInTheDocument();
    expect(screen.getByText("Compile or save")).toBeInTheDocument();
  });
  • Step 2: Run failing test

Run:

pnpm --dir web --filter @lda/console test -- src/presentation/SceneBody.test.tsx

Expected: FAIL because the current authoring scene renders generic step labels.

  • Step 3: Replace AuthoringScene data

In web/apps/console/src/presentation/SceneBody.tsx, replace:

const authoringSteps = [
  { id: "discover", label: "Discover" },
  { id: "author", label: "Author" },
  { id: "diagnose", label: "Diagnose" },
  { id: "repair", label: "Repair" },
];

with:

const authoringSteps = [
  { id: "discover", label: "Discover capability", detail: "wf schema / cap inspect" },
  { id: "author", label: "Author draft", detail: "wf draft create / add-step / bind" },
  { id: "diagnose", label: "Validate and diagnose", detail: "structured diagnostics + repair hints" },
  { id: "repair", label: "Repair", detail: "focused edit, no full rewrite" },
  { id: "compile", label: "Compile or save", detail: "artifact / deployment / run" },
] as const;
  • Step 4: Replace AuthoringScene markup

In SceneBody.tsx, replace the current AuthoringScene body with:

const AuthoringScene = ({ scene, beat }: { scene: SceneDefinition; beat: SceneBeatDefinition }) => (
  <>
    <StageCaption eyebrow="Act II · implemented" title={scene.title}>
      <p>{beat.caption}</p>
    </StageCaption>
    <div className="scene-body__authoring-loop" aria-label="agent authoring loop" data-active-stage={beat.id}>
      <div className="scene-body__authoring-loop-rail" aria-hidden="true" />
      {authoringSteps.map((step, i) => {
        const isActive = beat.id === step.id;
        const isPast = authoringSteps.findIndex((candidate) => candidate.id === beat.id) > i;
        return (
          <div
            key={step.id}
            className="scene-body__authoring-node"
            data-authoring-active={isActive}
            data-authoring-past={isPast}
          >
            <span className="scene-body__authoring-number">{i + 1}</span>
            <strong>{step.label}</strong>
            <small>{step.detail}</small>
          </div>
        );
      })}
    </div>
    <p className="scene-body__evidence">{scene.evidencePointer}</p>
  </>
);

This keeps the authoring scene declarative and avoids a new file for one local visual. If the file becomes unwieldy in review, extract to web/apps/console/src/presentation/scenes/AuthoringScene.tsx in a follow-up.

  • Step 5: Add authoring loop CSS

In web/apps/console/src/presentation/presentation.css, replace or override the old .scene-body__authoring rules with:

.scene-body__authoring-loop {
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0.75rem;
  margin-top: 1rem;
  padding: 1rem 0 0.2rem;
}

.scene-body__authoring-loop-rail {
  position: absolute;
  z-index: 0;
  top: 2.15rem;
  left: 8%;
  right: 8%;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-cyan), color-mix(in oklch, var(--accent-cyan) 20%, transparent));
}

.scene-body__authoring-node {
  position: relative;
  z-index: 1;
  display: grid;
  align-content: start;
  gap: 0.35rem;
  min-height: 8.6rem;
  border: 1px solid color-mix(in oklch, var(--stage-line) 72%, transparent);
  border-radius: 0.75rem;
  padding: 0.75rem;
  background: color-mix(in oklch, var(--stage-surface) 88%, transparent);
  transition: opacity 180ms ease, transform 180ms ease, border-color 180ms ease, background 180ms ease;
}

.scene-body__authoring-node[data-authoring-active="true"] {
  transform: translateY(-0.35rem);
  border-color: var(--accent-cyan);
  background: color-mix(in oklch, var(--accent-cyan) 13%, var(--stage-surface));
}

.scene-body__authoring-node[data-authoring-past="true"] {
  opacity: 0.76;
}

.scene-body__authoring-node small {
  color: var(--text-muted);
  font: 0.72rem/1.35 var(--font-interface);
}

@media (max-width: 1050px) {
  .scene-body__authoring-loop {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .scene-body__authoring-loop-rail {
    display: none;
  }
}

Remove stale .scene-body__authoring-step selectors only if they are no longer used. Keep lifecycle selectors intact.

  • Step 6: Run focused test

Run:

pnpm --dir web --filter @lda/console test -- src/presentation/SceneBody.test.tsx

Expected: PASS.

  • Step 7: Commit Task 2
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: clarify authoring scene visual loop"

Task 3: Scene 10 Interrupt Contract Hero

Files:

  • Modify: web/apps/console/src/presentation/DemoWorkflowScene.tsx
  • Modify: web/apps/console/src/presentation/styles/demo-workflow.css
  • Test: web/apps/console/src/presentation/DemoWorkflowScene.test.tsx

Interfaces:

  • Consumes:

    • beat.id values interrupt, approval, resume, trace.
    • Existing InterruptContractPreview, WorkflowGraphStage, OperationBlock.
  • Produces:

    • data-demo-layout="operation|graph|interrupt|approval|evidence"
    • Approval beat contract rendered as the hero surface.
  • Step 1: Add failing layout tests

In web/apps/console/src/presentation/DemoWorkflowScene.test.tsx, add:

  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("workflow graph")).toBeInTheDocument();
  });

  it("marks trace beat as evidence layout", () => {
    renderBeat("trace", "interrupt-evidence");

    expect(screen.getByLabelText("demo workflow stage")).toHaveAttribute("data-demo-layout", "evidence");
    expect(screen.getByLabelText("workflow.runs.trace operation")).toBeInTheDocument();
  });
  • Step 2: Run failing tests

Run:

pnpm --dir web --filter @lda/console test -- src/presentation/DemoWorkflowScene.test.tsx

Expected: FAIL because demo workflow stage, data-demo-layout, and data-hero are absent.

  • Step 3: Add named layout helper

In web/apps/console/src/presentation/DemoWorkflowScene.tsx, add above the component:

type DemoWorkflowLayout = "operation" | "graph" | "interrupt" | "approval" | "evidence";

const layoutForBeat = (beatId: string): DemoWorkflowLayout => {
  if (beatId === "operation" || beatId === "resume") return "operation";
  if (beatId === "interrupt") return "interrupt";
  if (beatId === "approval") return "approval";
  if (beatId === "trace" || beatId === "output") return "evidence";
  return "graph";
};
  • Step 4: Use layout state in markup

Inside DemoWorkflowScene, after const execution = graphExecutionForBeat(beat.id);, add:

  const layout = layoutForBeat(beat.id);

Change:

      <div className="demo-workflow-stage" data-beat={beat.id}>

to:

      <div className="demo-workflow-stage" data-beat={beat.id} data-demo-layout={layout} aria-label="demo workflow stage">

Change:

                <InterruptContractPreview contract={contract} mode={contractMode} />

to:

                <InterruptContractPreview
                  contract={contract}
                  mode={contractMode}
                  hero={layout === "approval"}
                />
  • Step 5: Extend InterruptContractPreview props

Open web/apps/console/src/presentation/InterruptContractPreview.tsx. Add a hero?: boolean prop and emit data-hero.

Expected final signature:

type InterruptContractPreviewProps = {
  readonly contract: InterruptContractDisplay;
  readonly mode: "preview" | "approval";
  readonly hero?: boolean;
};

Expected root element shape:

<aside
  className="interrupt-contract-preview"
  data-mode={mode}
  data-hero={hero ? "true" : "false"}
  aria-label="typed interrupt contract"
>

If the file currently uses a different prop type name, keep its local naming and add the hero field there.

  • Step 6: Add approval layout CSS

In web/apps/console/src/presentation/styles/demo-workflow.css, add below .demo-workflow-stage__graph rules:

.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(19rem, 34%) minmax(0, 1fr);
  gap: 1rem;
}

.demo-workflow-stage[data-demo-layout="approval"] .interrupt-contract-preview,
.demo-workflow-stage[data-demo-layout="interrupt"] .interrupt-contract-preview {
  grid-column: 1;
  grid-row: 1;
}

.demo-workflow-stage[data-demo-layout="approval"] .workflow-graph-stage,
.demo-workflow-stage[data-demo-layout="interrupt"] .workflow-graph-stage {
  grid-column: 2;
  grid-row: 1;
}

.interrupt-contract-preview[data-hero="true"] {
  border-color: color-mix(in oklch, var(--accent-amber) 72%, white);
  background:
    linear-gradient(180deg, color-mix(in oklch, var(--accent-amber) 14%, transparent), transparent 48%),
    color-mix(in oklch, var(--stage-surface) 92%, black);
}

.interrupt-contract-preview[data-hero="true"] h2 {
  font-size: clamp(1.45rem, 2.3vw, 2rem);
}

@media (max-width: 1050px) {
  .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(17rem, 40%) minmax(0, 1fr);
  }
}

If CSS order conflicts with the existing :has(.interrupt-contract-preview) rule, place these rules after the :has rule so layout-specific selectors win.

  • Step 7: Run focused tests

Run:

pnpm --dir web --filter @lda/console test -- src/presentation/DemoWorkflowScene.test.tsx

Expected: PASS.

  • Step 8: Commit Task 3
git add web/apps/console/src/presentation/DemoWorkflowScene.tsx web/apps/console/src/presentation/InterruptContractPreview.tsx web/apps/console/src/presentation/styles/demo-workflow.css web/apps/console/src/presentation/DemoWorkflowScene.test.tsx
git commit -m "feat: make interrupt approval the demo hero"

Task 4: Presenter-Only Discussion Hint Treatment

Files:

  • Modify: web/apps/console/src/presentation/DiscussionPanel.tsx
  • Modify: web/apps/console/src/presentation/presentation.css
  • Test: web/apps/console/src/presentation/DiscussionPanel.test.tsx

Interfaces:

  • Consumes: speakerHint?: string on discussion branches.

  • Produces: presenter note element:

    • aria-label="presenter note"
    • class discussion-panel__presenter-note
  • Step 1: Add failing test

In web/apps/console/src/presentation/DiscussionPanel.test.tsx, add:

  it("renders speaker hints as presenter notes instead of answer content", () => {
    render(<DiscussionPanel branchId="where-is-ai-agent" onClose={onClose} />);

    const note = screen.getByLabelText("presenter note");
    expect(note).toHaveTextContent(/Answer directly first/i);
    expect(note).toHaveTextContent(/Presenter note/i);
  });
  • Step 2: Run failing test

Run:

pnpm --dir web --filter @lda/console test -- src/presentation/DiscussionPanel.test.tsx

Expected: FAIL if the current element uses discussion-panel__speaker-hint and lacks the accessible label.

  • Step 3: Rename the rendered hint

In DiscussionPanel.tsx, replace:

            <p className="discussion-panel__speaker-hint">
              <span>Speaker hint</span>
              {branch.speakerHint}
            </p>

with:

            <p className="discussion-panel__presenter-note" aria-label="presenter note">
              <span>Presenter note</span>
              {branch.speakerHint}
            </p>
  • Step 4: Update CSS

In presentation.css, replace .discussion-panel__speaker-hint selectors with .discussion-panel__presenter-note and keep the old class only if needed for a transition. Desired treatment:

.discussion-panel__presenter-note {
  margin: 0;
  padding: 0.55rem 0.65rem;
  border: 1px dashed color-mix(in oklch, var(--stage-line) 70%, transparent);
  border-radius: 0.55rem;
  background: color-mix(in oklch, var(--stage-surface) 72%, transparent);
  color: var(--text-muted);
  font-size: 0.82rem;
  line-height: 1.35;
}

.discussion-panel__presenter-note span {
  display: block;
  margin-bottom: 0.2rem;
  color: var(--accent-amber);
  font: 750 0.64rem/1 var(--font-mono, monospace);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
  • Step 5: Run focused tests

Run:

pnpm --dir web --filter @lda/console test -- src/presentation/DiscussionPanel.test.tsx

Expected: PASS.

  • Step 6: Commit Task 4
git add web/apps/console/src/presentation/DiscussionPanel.tsx web/apps/console/src/presentation/DiscussionPanel.test.tsx web/apps/console/src/presentation/presentation.css
git commit -m "feat: demote discussion speaker hints"

Task 5: Screenshot Smoke And Docs

Files:

  • Modify: docs/current_roadmap.md
  • Move: docs/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md to docs/historical/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md

Interfaces:

  • Consumes: Tasks 1-4.

  • Produces: verified visual pass and live roadmap link.

  • Step 1: Run focused tests

Run:

pnpm --dir web --filter @lda/console test -- src/presentation/scenes/ArchitectureScene.test.tsx src/presentation/figures/InteractiveFigure.test.tsx src/presentation/SceneBody.test.tsx src/presentation/DemoWorkflowScene.test.tsx src/presentation/DiscussionPanel.test.tsx

Expected: PASS.

  • Step 2: Run build checks

Run:

pnpm --dir web --filter @lda/console typecheck
pnpm --dir web --filter @lda/console build
git diff --check

Expected:

  • Typecheck passes.

  • Build succeeds. Existing chunk-size warning is acceptable if unchanged.

  • No whitespace errors.

  • Step 3: Run screenshot smoke

Start dev server if not already running:

pnpm --dir web dev

In another terminal, create screenshot directory:

New-Item -ItemType Directory -Force web/apps/console/.visual-smoke | Out-Null

Capture 1280x720 screenshots:

pnpx playwright screenshot --viewport-size=1280,720 "http://127.0.0.1:5173/present#scene/architecture/client" web/apps/console/.visual-smoke/scene-06-client-1280x720.png
pnpx playwright screenshot --viewport-size=1280,720 "http://127.0.0.1:5173/present#scene/architecture/runtime/focus/runtime-providers" web/apps/console/.visual-smoke/scene-06-runtime-1280x720.png
pnpx playwright screenshot --viewport-size=1280,720 "http://127.0.0.1:5173/present#scene/authoring/discover" web/apps/console/.visual-smoke/scene-07-authoring-1280x720.png
pnpx playwright screenshot --viewport-size=1280,720 "http://127.0.0.1:5173/present#scene/interrupt-evidence/approval" web/apps/console/.visual-smoke/scene-10-approval-1280x720.png

Capture 1024x768 architecture fallback:

pnpx playwright screenshot --viewport-size=1024,768 "http://127.0.0.1:5173/present#scene/architecture/runtime/focus/runtime-providers" web/apps/console/.visual-smoke/scene-06-runtime-1024x768.png

Inspect screenshots manually. Acceptance:

  • No slide-level scrollbars.
  • Scene 6 figure is larger and horizontally navigable if needed.
  • Scene 7 authoring loop is readable and not generic tiny cards.
  • Scene 10 approval makes the interrupt contract visually primary.
  • Speaker hints in discussion modal look like presenter notes, not answer body.

Do not commit .visual-smoke screenshots unless the repo already tracks visual snapshots. If needed, add web/apps/console/.visual-smoke/ to .gitignore.

  • Step 4: Update roadmap

In docs/current_roadmap.md, under Presentation wishlist / defense readiness, replace:

- Visual pass for Scenes 6, 7, and 10: fix spacing, graph scale, captions,
  evidence receipt placement, and remove remaining generic AI-slide styling.

with:

- Completed: visual pass for Scenes 6, 7, and 10 fixed architecture figure
  scale, authoring-loop clarity, interrupt/evidence emphasis, and presenter-note
  treatment. Implementation:
  [`defense presentation visual pass`](historical/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md).
  • Step 5: Archive plan

Run:

git mv docs/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md docs/historical/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md

If the plan file is not tracked yet, use PowerShell:

Move-Item docs/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md docs/historical/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md
  • Step 6: Commit Task 5
git add docs/current_roadmap.md docs/historical/superpowers/plans/2026-07-08-defense-presentation-visual-pass.md
git commit -m "docs: record defense presentation visual pass"

Final Verification

  • Run full web tests:
pnpm --dir web test

Expected: PASS.

  • Run full web typecheck:
pnpm --dir web typecheck

Expected: PASS.

  • Run full web build:
pnpm --dir web build

Expected: PASS; unchanged chunk-size warning is acceptable.

  • Check git status:
git status --short

Expected: only intentional files are changed or clean after commits.


Review Checklist

  • Scene 6 is bigger and usable, not just scaled down to fit.
  • Scene 7 communicates a public-surface authoring loop.
  • Scene 10 makes typed interrupt approval the hero.
  • Q&A speaker hints are not visually equivalent to audience answers.
  • No /console styling changed.
  • No new dependency added.
  • No screenshot artifacts committed unless intentionally tracked.
  • No global overflow hacks added.