# Presentation Evaluation And Closing 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:** Replace the weak final two presentation scenes with a factual evaluation evidence board, an icon-supported contribution/future-work map, and a canonical end-of-defense discussion index. **Architecture:** Add three focused presentation components and two small typed projection modules. `SceneBody` remains a router. Scene facts live in typed, testable catalogs; the discussion index derives from the canonical `discussionBranches` catalog and uses an exhaustive branch-to-topic mapping. Existing presentation routing, `DiscussionPanel`, editorial tokens, and reduced-motion behavior remain authoritative. **Tech Stack:** React 19, TypeScript, Vitest, Testing Library, Lucide React icons already installed in the console package, CSS container queries, existing hash-based presentation navigation. ## Global Constraints - Follow `docs/superpowers/specs/2026-07-10-presentation-evaluation-closing-design.md` exactly. - Use test-driven development: add each behavioral test, run it and observe the expected failure, then add the minimum implementation. - Do not add a charting or icon dependency. Use `lucide-react`, which is already present, and always pair icons with visible text. - Do not show percentages, success-rate language, model rankings, or statistical significance. - Keep chat hidden for all Scene 13 and 14 beats. - Preserve exact counts: 36 total, 27 clean passes, 8 invalid samples, 1 failure, 7 automatic successes invalidated, and 3 automatic failures accepted. - Keep the contribution wording `Planner proposes; runtime executes.` - Keep all content readable at 1280x720 and 1024x768 and reachable at browser zoom. - Add comments around non-obvious exhaustive mappings and return-location behavior. - Do not modify Scenes 1 through 12. --- ### Task 1: Evaluation Evidence Projection And Scene **Files:** - Create: `web/apps/console/src/presentation/evaluation/evaluation-evidence.ts` - Create: `web/apps/console/src/presentation/evaluation/evaluation-evidence.test.ts` - Create: `web/apps/console/src/presentation/evaluation/EvaluationEvidenceScene.tsx` - Create: `web/apps/console/src/presentation/evaluation/EvaluationEvidenceScene.test.tsx` - Modify: `web/apps/console/src/presentation/presentation.css` **Interfaces:** - Consumes: `SceneDefinition`, `SceneBeatDefinition`, and `StageCaption`. - Produces: ```ts export type EvaluationBeatId = "cohort" | "validity" | "findings"; export type EvaluationFindingIcon = "schema" | "repair" | "binding" | "output" | "shell" | "contamination"; export type EvaluationEvidenceModel = { readonly cohortFactors: readonly { readonly value: string; readonly label: string }[]; readonly totalTrials: 36; readonly outcomes: readonly { readonly value: number; readonly label: string; readonly kind: "pass" | "invalid" | "fail" }[]; readonly auditCorrections: readonly { readonly automatic: string; readonly audited: string }[]; readonly findings: readonly { readonly label: string; readonly icon: EvaluationFindingIcon }[]; readonly validityStatement: string; }; export const evaluationEvidence: EvaluationEvidenceModel; export const isEvaluationBeatId: (value: string) => value is EvaluationBeatId; export const EvaluationEvidenceScene: React.FC<{ readonly scene: SceneDefinition; readonly beat: SceneBeatDefinition }>; ``` - Use Lucide icons such as `SearchCode`, `Wrench`, `Cable`, `FileOutput`, `Terminal`, and `ShieldAlert` for the six findings. Icons are decorative with `aria-hidden="true"`; visible labels carry meaning. - [ ] **Step 1: Write failing projection tests** Create tests that assert exact counts, the exact validity statement, all six finding labels, unique icon keys, and absence of percentage/ranking vocabulary: ```ts expect(evaluationEvidence.totalTrials).toBe(36); expect(evaluationEvidence.outcomes).toEqual([ { value: 27, label: "clean product-path passes", kind: "pass" }, { value: 8, label: "invalid evaluation samples", kind: "invalid" }, { value: 1, label: "failure", kind: "fail" }, ]); expect(evaluationEvidence.auditCorrections).toEqual([ { automatic: "7 automatic successes", audited: "invalid as clean evidence" }, { automatic: "3 automatic failures", audited: "accepted from saved evidence" }, ]); expect(evaluationEvidence.validityStatement).toBe( "Bounded longitudinal engineering evidence, not a controlled model comparison.", ); expect(evaluationEvidence.findings.map((finding) => finding.label)).toEqual([ "Schema discovery", "Repair hints", "Binding commands", "Output schemas", "Shell assumptions", "Source contamination", ]); expect(JSON.stringify(evaluationEvidence)).not.toMatch(/%|success rate|leaderboard|superior/i); ``` - [ ] **Step 2: Run projection tests and verify RED** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/evaluation/evaluation-evidence.test.ts ``` Expected: FAIL because `evaluation-evidence.ts` does not exist. - [ ] **Step 3: Implement the typed evidence catalog** Create the exact model above. Keep source facts in this module rather than spreading literals through JSX. Add this comment above `auditCorrections`: ```ts // These are campaign-specific audit disagreements, not a general accuracy // measure for automatic grading. ``` - [ ] **Step 4: Run projection tests and verify GREEN** Run the command from Step 2. Expected: all projection tests PASS. - [ ] **Step 5: Write failing scene tests** Render each beat and assert: ```tsx expect(screen.getByRole("group", { name: /evaluation evidence board/i })).toHaveAttribute("data-evaluation-beat", "cohort"); expect(screen.getByText("36")).toBeInTheDocument(); expect(screen.getByText("27")).toBeInTheDocument(); expect(screen.getByText("8")).toBeInTheDocument(); expect(screen.getByText("1")).toBeInTheDocument(); ``` For `validity`, assert both audit-correction rows and the validity statement. For `findings`, assert all six labels and six SVG icons beneath the labelled findings region. Assert the scene does not render `%`, `success rate`, or `leaderboard`. - [ ] **Step 6: Run scene tests and verify RED** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/evaluation/EvaluationEvidenceScene.test.tsx ``` Expected: FAIL because `EvaluationEvidenceScene` does not exist. - [ ] **Step 7: Implement the evaluation scene and CSS** Compose: ```tsx <>

{beat.caption}

...
    ...
...
    ...

{evaluationEvidence.validityStatement}

{scene.evidencePointer}

``` Use one board surface with a cohort equation, horizontal audited-outcome rail, two-row audit reconciliation, and connected finding ledger. Beat attributes control emphasis; no block is conditionally removed. At the existing 1080px container threshold, wrap the cohort equation and stack audit rows. Add 150-250ms opacity/transform transitions, covered by existing reduced-motion overrides. - [ ] **Step 8: Run tests and commit** Run both Task 1 test files. Expected: PASS. ```powershell git add web/apps/console/src/presentation/evaluation web/apps/console/src/presentation/presentation.css git commit -m "feat: add evaluation evidence board" ``` --- ### Task 2: Contribution And Future-Work Closing Scene **Files:** - Create: `web/apps/console/src/presentation/conclusion/conclusion-model.ts` - Create: `web/apps/console/src/presentation/conclusion/conclusion-model.test.ts` - Create: `web/apps/console/src/presentation/conclusion/ConclusionScene.tsx` - Create: `web/apps/console/src/presentation/conclusion/ConclusionScene.test.tsx` - Modify: `web/apps/console/src/presentation/presentation.css` **Interfaces:** - Consumes: `SceneDefinition`, `SceneBeatDefinition`, `StageCaption`. - Produces: ```ts export type ConclusionBeatId = "limits" | "future" | "conclusion" | "questions"; export type FutureWorkIcon = "agent" | "security" | "schedule" | "evaluation" | "runtime"; export const contributionNodes: readonly [ { readonly id: "planner"; readonly label: "External planner" }, { readonly id: "substrate"; readonly label: "Typed workflow substrate" }, { readonly id: "runtime"; readonly label: "Deterministic runtime" }, { readonly id: "evidence"; readonly label: "Persisted, inspectable evidence" }, ]; export const nonClaims: readonly string[]; export const futureWorkBranches: readonly { readonly id: string; readonly label: string; readonly example: string; readonly icon: FutureWorkIcon }[]; export const isConclusionBeatId: (value: string) => value is ConclusionBeatId; ``` - Map icons to existing Lucide components: `Bot`, `ShieldCheck`, `CalendarClock`, `ChartNoAxesCombined`, and `Workflow`. Pair every icon with visible label and example text. - [ ] **Step 1: Write failing model tests** Assert the four stable contribution nodes, exact three non-claims, exact five future-work branches, unique IDs/icons, and closing wording. ```ts expect(nonClaims).toEqual([ "Not a production sandbox", "Not a scheduler", "Not a broad agent benchmark", ]); expect(futureWorkBranches).toHaveLength(5); expect(new Set(futureWorkBranches.map((branch) => branch.icon)).size).toBe(5); ``` - [ ] **Step 2: Run model tests and verify RED** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/conclusion/conclusion-model.test.ts ``` Expected: FAIL because `conclusion-model.ts` does not exist. - [ ] **Step 3: Implement the closing model** Use these concrete examples: ```ts [ { id: "agent-interface", label: "Agent interface", example: "Chat or planner loop over wf operations", icon: "agent" }, { id: "security", label: "Security and credentials", example: "Secrets, RBAC, sandboxing, policy", icon: "security" }, { id: "scheduling", label: "Hosted operations", example: "Scheduling, daemon lifecycle, monitoring", icon: "schedule" }, { id: "evaluation", label: "Controlled evaluation", example: "Frozen prompts, more trials, independent audit", icon: "evaluation" }, { id: "runtime", label: "Runtime expansion", example: "Transactional stores, debugging, providers", icon: "runtime" }, ] ``` - [ ] **Step 4: Run model tests and verify GREEN** Run the command from Step 2. Expected: PASS. - [ ] **Step 5: Write failing component tests** Assert that all beats preserve the labelled `thesis contribution boundary` diagram. Assert the `limits` beat emphasizes three non-claims, the `future` beat exposes five labelled icon branches, and the `conclusion` beat renders `Planner proposes; runtime executes.` with future branches marked as receded. Do not test CSS color values; test semantic data attributes. - [ ] **Step 6: Run component tests and verify RED** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/conclusion/ConclusionScene.test.tsx ``` Expected: FAIL because `ConclusionScene` does not exist. - [ ] **Step 7: Implement the closing scene and CSS** Render the stable center as semantic HTML with CSS connectors, not React Flow. The diagram only has four fixed nodes and should not introduce graph interaction. Use: ```tsx
...

Planner proposes; runtime executes.

``` Use familiar left-to-right reading order and visible arrow connectors. At 4:3, keep planner/substrate/runtime horizontal and move evidence beneath substrate; future branches wrap around the central line without overlap. Apply one cyan emphasis to the substrate and neutral treatments elsewhere. - [ ] **Step 8: Run tests and commit** Run both Task 2 test files. Expected: PASS. ```powershell git add web/apps/console/src/presentation/conclusion web/apps/console/src/presentation/presentation.css git commit -m "feat: add contribution closing map" ``` --- ### Task 3: Canonical Defense Discussion Index And Questions Beat **Files:** - Create: `web/apps/console/src/presentation/discussion/defense-discussion-index.ts` - Create: `web/apps/console/src/presentation/discussion/defense-discussion-index.test.ts` - Create: `web/apps/console/src/presentation/discussion/DefenseDiscussionIndex.tsx` - Create: `web/apps/console/src/presentation/discussion/DefenseDiscussionIndex.test.tsx` - Modify: `web/apps/console/src/presentation/storyboard.ts` - Modify: `web/apps/console/src/presentation/storyboard.test.ts` - Modify: `web/apps/console/src/presentation/storyboard-navigation.test.ts` - Modify: `web/apps/console/src/presentation/presentation.css` **Interfaces:** - Consumes: canonical `discussionBranches`, `DiscussionBranchDefinition`, `DiscussionBranchId`, and `openDiscussion(branchId: string)`. - Produces: ```ts export type DefenseDiscussionTopicId = | "contribution" | "positioning" | "runtime" | "authoring" | "demo" | "evaluation" | "production"; export type DefenseDiscussionGroup = { readonly id: DefenseDiscussionTopicId; readonly label: string; readonly branches: readonly DiscussionBranchDefinition[]; }; export const discussionTopicByBranchId: Record; export const defenseDiscussionGroups: readonly DefenseDiscussionGroup[]; export const DefenseDiscussionIndex: React.FC<{ readonly openDiscussion: (branchId: string) => void }>; ``` - Use Lucide topic icons (`BadgeHelp`, `Map`, `Boxes`, `FileCode2`, `PlaySquare`, `ChartNoAxesCombined`, `Rocket`) in group headings, always with visible labels. - [ ] **Step 1: Write failing exhaustive projection tests** Assert that every canonical branch ID occurs exactly once and no mapping key is stale: ```ts const indexedIds = defenseDiscussionGroups.flatMap((group) => group.branches.map((branch) => branch.id)); expect(indexedIds).toHaveLength(discussionBranches.length); expect(new Set(indexedIds)).toEqual(new Set(discussionBranches.map((branch) => branch.id))); expect(Object.keys(discussionTopicByBranchId).sort()).toEqual( discussionBranches.map((branch) => branch.id).sort(), ); ``` - [ ] **Step 2: Run projection tests and verify RED** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/discussion/defense-discussion-index.test.ts ``` Expected: FAIL because `defense-discussion-index.ts` does not exist. - [ ] **Step 3: Implement the exhaustive topic mapping** Create the explicit `Record`. Add this comment: ```ts // This explicit record is intentionally exhaustive: adding a Q&A branch must // also place it in the end-of-defense index instead of silently hiding it. ``` Derive group branch objects from `discussionBranches`; do not duplicate titles, answers, claim classes, or evidence pointers. Use this complete mapping: ```ts export const discussionTopicByBranchId: Record = { "where-is-ai-agent": "contribution", "title-ai-agent-wording": "contribution", "direct-orchestration": "positioning", "generated-scripts": "positioning", "hosted-automation": "positioning", "durable-agent-graphs": "positioning", "mcp-agent-scale": "positioning", "not-just-scripts": "positioning", "not-just-cli": "runtime", "lifecycle-states": "runtime", "run-persistence": "runtime", "raw-plan-import": "authoring", "validation-diagnostics": "authoring", "why-schemas": "authoring", "typed-interrupts": "authoring", "replay-provenance": "demo", "demo-reliability": "demo", "prepared-replay-boundary": "demo", "evaluation-validity": "evaluation", "provider-security": "production", "security-production-boundary": "production", "production-readiness": "production", }; ``` - [ ] **Step 4: Run projection tests and verify GREEN** Run the command from Step 2. Expected: PASS. - [ ] **Step 5: Write failing component and storyboard tests** Component tests assert seven group headings, every canonical branch title, icon presence in group headings, and `openDiscussion` receiving the selected canonical branch ID. Storyboard tests assert: ```ts expect(findBeat("conclusion", "questions")).toBeDefined(); expect(findBeat("evaluation", "cohort")?.chatMode).toBe("hidden"); expect(findBeat("conclusion", "conclusion")?.chatMode).toBe("hidden"); expect(findBeat("conclusion", "questions")?.chatMode).toBe("hidden"); expect(locationFromHash("#scene/conclusion/questions")).toEqual({ kind: "main", sceneId: "conclusion", beatId: "questions", focusPath: [], }); ``` - [ ] **Step 6: Run tests and verify RED** Run: ```powershell pnpm --dir web --filter @lda/console test -- src/presentation/discussion/DefenseDiscussionIndex.test.tsx src/presentation/storyboard.test.ts src/presentation/storyboard-navigation.test.ts ``` Expected: FAIL because the component and `questions` beat do not exist. - [ ] **Step 7: Implement the Questions beat and index UI** Append: ```ts sceneBeat("questions", "Questions", "Discussion topics gathered for examiner questions.", { chatMode: "hidden", chatTheme: "light", }) ``` Also explicitly set `chatMode: "hidden"` on every Scene 13 and Scene 14 beat. Render the index as a labelled `