docs: record presentation visual follow-up pass

This commit is contained in:
lda
2026-07-13 03:46:25 +07:00 Verified
parent 95c629e800
commit 8cf41a415c
6 changed files with 124 additions and 16 deletions
+12 -7
View File
@@ -264,8 +264,10 @@ Recommended next visual slices:
and a light prepared lifecycle canvas with synchronized secondary chat. and a light prepared lifecycle canvas with synchronized secondary chat.
Implementation: Implementation:
[`Scenes 7-9 editorial focal proof`](historical/superpowers/plans/2026-07-12-scenes-7-9-editorial-focal-proof.md). [`Scenes 7-9 editorial focal proof`](historical/superpowers/plans/2026-07-12-scenes-7-9-editorial-focal-proof.md).
10. Next: revise the remaining visual outliers only when a screenshot identifies 10. Completed: revise the remaining visual outliers only when a screenshot
a concrete hierarchy, overflow, or factual-readability problem. identifies a concrete hierarchy, overflow, or factual-readability problem.
Implementation:
[`presentation follow-up visual/story pass`](historical/superpowers/plans/2026-07-13-presentation-followup-visual-story-pass.md).
## Next: Scene 814 Defense Recomposition ## Next: Scene 814 Defense Recomposition
@@ -328,12 +330,15 @@ separate activity after these surfaces are stable.
live run facts. Distinguish declared, selected, read, and produced files; live run facts. Distinguish declared, selected, read, and produced files;
do not imply file reads without evidence. do not imply file reads without evidence.
10. **Active plan: presentation follow-up visual/story pass:** clarify Scene 1 10. **Completed: presentation follow-up visual/story pass:** clarified Scene 1
and the lifecycle-to-authoring narrative, give Scenes 7 and 9 a stronger and the lifecycle-to-authoring narrative, gave Scenes 7 and 9 a stronger
dominant artifact, make the Scene 10 graph easier to present, and densify dominant artifact, made the Scene 10 graph easier to present, and densified
Evaluation and Conclusion beats without inventing evidence. Evaluation and Conclusion beats without inventing evidence. The dated
review records the remaining factual input-browser, live-E2E, and full
screenshot-inspection follow-ups:
[`presentation follow-up visual review`](runbooks/presentation-followup-visual-review.md).
Implementation plan: Implementation plan:
[`presentation follow-up visual/story pass`](superpowers/plans/2026-07-13-presentation-followup-visual-story-pass.md). [`presentation follow-up visual/story pass`](historical/superpowers/plans/2026-07-13-presentation-followup-visual-story-pass.md).
Presentation wishlist / defense readiness: Presentation wishlist / defense readiness:
@@ -0,0 +1,78 @@
# Presentation Follow-Up Visual Review
Review date: 2026-07-13
This record closes the visual/story follow-up pass described by
[`presentation follow-up visual/story pass`](../historical/superpowers/plans/2026-07-13-presentation-followup-visual-story-pass.md).
It records what was checked, what is now presentable, and what remains a
factual or product follow-up rather than silently treating it as solved.
## Verification
- Presentation route contract: 7 changed routes assert one exact heading, one
primary visual region, and no outer document scroll.
- Focused evaluation, conclusion, and opening tests: 16 passed.
- Workflow graph tests: 34 passed.
- Full web gate: console 754 passed; RPC 52 passed and 6 skipped; server 46
passed.
- Full web typecheck and build passed; the build retains the known Vite chunk
size warning.
- Rehearsal capture: 42 routes at both `1280x720` and `1024x768` (84 PNGs).
- Typecheck: `pnpm --dir web typecheck` passed.
- Browser smoke: checked at `1280x720` and `1024x768` for the workflow graph,
evaluation findings, conclusion, and Scene 1 opening.
- Workflow graph: React Flow initializes with a measured `fitView`; all ten
nodes and both outcome branches remain inside the graph frame at both target
viewports.
## Fixed Visuals
| Area | Result |
|---|---|
| Scene 1 opening | Product goal, implementation boundary, and planner/tool-surface/runner decomposition are distinct. The opening caption remains editorial and borderless; its row sizes to content instead of clipping the lower padding. |
| Scene 5 to 7 story | Lifecycle vocabulary now leads into authoring and repair rather than presenting authoring as an isolated diagnostic screen. |
| Scenes 7 and 9 | Authoring and prepared-lifecycle evidence use a dominant artifact with secondary assistant/support surfaces. |
| Scene 10 graph | The graph is horizontal, factual, selectable, draggable/zoomable, and fit to the initialized React Flow viewport. Outcome shapes and edge labels remain visible. |
| Scene 13 findings | Six findings use a readable 3x2 layout with icons, campaign size, outcome counts, and the bounded-evidence statement visible together. |
| Scene 14 conclusion | The typed substrate and closing boundary are dominant; non-claims and future-work layers recede without being removed from their own beats. |
## Remaining Findings
### FACTUAL
- Scene 10 input remains a prepared-run manifest, not a factual file browser
distinguishing declared, selected, read, and produced files. This remains a
separate roadmap item.
- The prepared revision-request replay uses
`run_recorded_lda_report_revision`, while the submitted replay uses
`run_recorded_lda_report`. Do not describe the revision recording as the same
persisted run until a same-run recording is available.
### PRODUCT
- Live Scene 10-12 execution is health-checked and connectable, but still needs
a complete rehearsed start -> interrupt -> resume -> output -> trace path on
the running workflow server.
- The presentation chat remains a scripted/replay product surface. A live LLM
driver and streaming agent conversation are future work.
### BLOCKED / DEFERRED
- A full manual inspection of every screenshot generated by the 42-route,
two-viewport rehearsal script remains a rehearsal activity, not a claim that
every beat has been visually hand-approved.
- The final defense story-flow review and presenter companion assets remain
separate from this visual pass.
## Rehearsal Commands
```powershell
pnpm --dir web test -- --run
pnpm --dir web typecheck
pnpm --dir web build
./scripts/presentation-rehearsal.ps1
```
Use [`defense-presentation.md`](defense-presentation.md) for live/replay
fallbacks and [`presentation-rehearsal-matrix.md`](presentation-rehearsal-matrix.md)
for the route-by-route speaking line and evidence pointer.
@@ -80,17 +80,15 @@ describe("DiscussionPanel", () => {
expect(screen.getByText("Where is the AI agent in this thesis?")).toBeDefined(); expect(screen.getByText("Where is the AI agent in this thesis?")).toBeDefined();
expect(screen.getByText(/workflow substrate that external agents operate/i)).toBeDefined(); expect(screen.getByText(/workflow substrate that external agents operate/i)).toBeDefined();
expect(screen.getByText(/not a new planning algorithm/i)).toBeDefined(); expect(screen.getByText(/not a new planning algorithm/i)).toBeDefined();
expect(screen.getByText(/Answer directly first/i)).toBeDefined(); expect(screen.queryByText(/Answer directly first/i)).not.toBeInTheDocument();
expect(screen.getByLabelText("defense question")).toBeInTheDocument(); expect(screen.getByLabelText("defense question")).toBeInTheDocument();
}); });
it("renders speaker hints as presenter notes instead of answer content", () => { it("keeps speaker hints out of the audience-facing discussion panel", () => {
render(<DiscussionPanel branchId="where-is-ai-agent" onClose={onClose} />); render(<DiscussionPanel branchId="where-is-ai-agent" onClose={onClose} />);
const note = screen.getByLabelText("presenter note"); expect(screen.queryByLabelText("presenter note")).not.toBeInTheDocument();
expect(note).toHaveTextContent(/Answer directly first/i); expect(screen.queryByText(/Answer directly first/i)).not.toBeInTheDocument();
expect(note).toHaveTextContent(/Presenter note/i);
expect(note).toHaveClass("discussion-panel__presenter-note");
}); });
it("separates Q&A answer, provenance, and presenter note regions", () => { it("separates Q&A answer, provenance, and presenter note regions", () => {
@@ -101,7 +99,7 @@ describe("DiscussionPanel", () => {
expect(screen.getByLabelText("short defense answer")).toHaveTextContent(/workflow substrate/i); expect(screen.getByLabelText("short defense answer")).toHaveTextContent(/workflow substrate/i);
expect(screen.getByLabelText("answer expansion")).toHaveTextContent(/planning algorithm/i); expect(screen.getByLabelText("answer expansion")).toHaveTextContent(/planning algorithm/i);
expect(screen.getByLabelText("answer provenance")).toHaveTextContent(/Abstract/i); expect(screen.getByLabelText("answer provenance")).toHaveTextContent(/Abstract/i);
expect(screen.getByLabelText("presenter note")).toHaveTextContent(/Answer directly first/i); expect(screen.queryByLabelText("presenter note")).not.toBeInTheDocument();
}); });
it("uses context layout for non-Q&A discussion branches", () => { it("uses context layout for non-Q&A discussion branches", () => {
@@ -111,6 +111,33 @@ describe("PresentationRoute", () => {
15000, 15000,
); );
const visualRouteContracts = [
{ hash: "#scene/thesis/title", heading: "Design and Implementation of lda.chat", primary: "thesis opening" },
{ hash: "#scene/lifecycle/draft", heading: "Workflow Lifecycle", primary: "workflow lifecycle rail" },
{ hash: "#scene/authoring/diagnose", heading: "Author, Validate, Repair", primary: "agent authoring loop" },
{ hash: "#scene/prepared-lifecycle/validate", heading: "Prepared Workflow Lifecycle", primary: "prepared workflow authoring lifecycle" },
{ hash: "#scene/run-from-deployment/graph", heading: "Run From Deployment", primary: "workflow graph" },
{ hash: "#scene/evaluation/findings", heading: "Evaluation", primary: "evaluation evidence board" },
{ hash: "#scene/conclusion/conclusion", heading: "Limits and Conclusion", primary: "thesis contribution boundary" },
] as const;
it.each(visualRouteContracts)(
"keeps the primary visual contract for $hash",
async ({ hash, heading, primary }) => {
window.location.hash = hash;
const { PresentationRoute } = await import("./PresentationRoute.js");
render(<PresentationRoute />);
await waitFor(
() => expect(screen.getAllByRole("heading", { name: heading })).toHaveLength(1),
{ timeout: 12000 },
);
expect(screen.getByLabelText(primary, { exact: true })).toBeInTheDocument();
expect(document.documentElement.scrollHeight).toBeLessThanOrEqual(window.innerHeight);
},
15000,
);
it.each([ it.each([
"#scene/thesis/title", "#scene/thesis/title",
"#scene/problem/direct-actions", "#scene/problem/direct-actions",
@@ -62,7 +62,7 @@ describe("presentation.css", () => {
)?.groups?.body; )?.groups?.body;
expect(sceneBlock).toContain("grid-template-columns:"); expect(sceneBlock).toContain("grid-template-columns:");
expect(sceneBlock).toMatch(/minmax\(15rem, 0\.35fr\).*minmax\(0, 0\.65fr\)/); expect(sceneBlock).toMatch(/minmax\(12rem, 0\.26fr\).*minmax\(0, 0\.74fr\)/);
expect(sceneBlock).toContain("min-height: 0"); expect(sceneBlock).toContain("min-height: 0");
expect(sceneBlock).toContain("overflow: hidden"); expect(sceneBlock).toContain("overflow: hidden");
expect(sceneBlock).not.toContain("grid-template-rows:"); expect(sceneBlock).not.toContain("grid-template-rows:");
@@ -75,7 +75,7 @@ describe("presentation.css", () => {
expect(scene9Rules.filter((rule) => rule.includes("grid-template-columns:")).length).toBeGreaterThan(0); expect(scene9Rules.filter((rule) => rule.includes("grid-template-columns:")).length).toBeGreaterThan(0);
expect(scene9Rules.join("\n")).not.toContain("1.65fr"); expect(scene9Rules.join("\n")).not.toContain("1.65fr");
expect(scene9Rules.join("\n")).toMatch(/minmax\(15rem, 0\.35fr\)\s+minmax\(0, 0\.65fr\)/); expect(scene9Rules.join("\n")).toMatch(/minmax\(12rem, 0\.26fr\)\s+minmax\(0, 0\.74fr\)/);
}); });
it("bounds Scene 9 conversation scrolling and recenters Scene 8 at compact stage widths", () => { it("bounds Scene 9 conversation scrolling and recenters Scene 8 at compact stage widths", () => {