docs: record presentation surface normalization
This commit is contained in:
@@ -132,10 +132,14 @@ Presentation wishlist / defense readiness:
|
|||||||
the Scene 7 authoring loop and the Scene 10 chat rail, and ignored local
|
the Scene 7 authoring loop and the Scene 10 chat rail, and ignored local
|
||||||
`.visual-smoke/` screenshots. Implementation:
|
`.visual-smoke/` screenshots. Implementation:
|
||||||
[`presentation contrast readability`](historical/superpowers/plans/2026-07-08-presentation-contrast-readability.md).
|
[`presentation contrast readability`](historical/superpowers/plans/2026-07-08-presentation-contrast-readability.md).
|
||||||
2. Scene composition pass: make Scene 6's default architecture view show the
|
2. Completed: surface theme normalization pass made light chat, discussion
|
||||||
|
modals, and Q&A branches use the same editorial presentation surface.
|
||||||
|
Implementation:
|
||||||
|
[`presentation surface theme normalization`](historical/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md).
|
||||||
|
3. Scene composition pass: make Scene 6's default architecture view show the
|
||||||
full top-level path at `1280x720`, rebalance Scene 7 spacing after the
|
full top-level path at `1280x720`, rebalance Scene 7 spacing after the
|
||||||
contrast fix, and tune Scene 10's graph-vs-contract proportions.
|
contrast fix, and tune Scene 10's graph-vs-contract proportions.
|
||||||
3. Presentation craft pass: tune motion, discussion-chip placement, Q&A modal
|
4. Presentation craft pass: tune motion, discussion-chip placement, Q&A modal
|
||||||
hierarchy, evidence receipt placement, and remaining generic-slide styling
|
hierarchy, evidence receipt placement, and remaining generic-slide styling
|
||||||
after the compositions are stable.
|
after the compositions are stable.
|
||||||
- Presenter runbook:
|
- Presenter runbook:
|
||||||
|
|||||||
+599
@@ -0,0 +1,599 @@
|
|||||||
|
# Presentation Surface Theme Normalization 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:** Normalize `/present` chat and discussion/Q&A surfaces so light chat, direct discussion branches, and presenter notes share one editorial presentation vocabulary.
|
||||||
|
|
||||||
|
**Architecture:** Add a small semantic surface contract with `data-presentation-surface="editorial|night"` on presentation side-surfaces. Style `OperatorChat` and `DiscussionPanel` through that contract, keeping existing storyboard, layout, chat messages, and discussion routing intact. Do not introduce a new theme engine or component library in this slice.
|
||||||
|
|
||||||
|
**Tech Stack:** React, TypeScript, CSS, Vitest, Testing Library, Playwright CLI screenshot smoke.
|
||||||
|
|
||||||
|
## Global Constraints
|
||||||
|
|
||||||
|
- Follow design spec: `docs/superpowers/specs/2026-07-08-presentation-surface-theme-normalization-design.md`.
|
||||||
|
- Do not change `/console`.
|
||||||
|
- Do not replace chat UI.
|
||||||
|
- Do not alter storyboard content or scene composition.
|
||||||
|
- Do not add dependencies.
|
||||||
|
- Keep CSS scoped to presentation surfaces.
|
||||||
|
- Prefer semantic surface attributes over ad hoc color selectors.
|
||||||
|
- Generated `.visual-smoke/` screenshots must remain ignored.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
- Modify `web/apps/console/src/presentation/OperatorChat.tsx`
|
||||||
|
- Add `data-presentation-surface`.
|
||||||
|
- Modify `web/apps/console/src/presentation/OperatorChat.test.tsx`
|
||||||
|
- Pin editorial/night surface mapping.
|
||||||
|
- Modify `web/apps/console/src/presentation/DiscussionPanel.tsx`
|
||||||
|
- Add `data-presentation-surface="editorial"`.
|
||||||
|
- Modify `web/apps/console/src/presentation/DiscussionPanel.test.tsx`
|
||||||
|
- Pin discussion panel surface contract for Q&A branches and legacy branches.
|
||||||
|
- Modify `web/apps/console/src/presentation/presentation.css`
|
||||||
|
- Normalize chat/discussion/presenter-note surfaces.
|
||||||
|
- Modify `docs/current_roadmap.md`
|
||||||
|
- Mark surface normalization complete after implementation.
|
||||||
|
- Move this plan to `docs/historical/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md` after implementation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: Add Semantic Surface Attributes
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `web/apps/console/src/presentation/OperatorChat.tsx`
|
||||||
|
- Modify: `web/apps/console/src/presentation/OperatorChat.test.tsx`
|
||||||
|
- Modify: `web/apps/console/src/presentation/DiscussionPanel.tsx`
|
||||||
|
- Modify: `web/apps/console/src/presentation/DiscussionPanel.test.tsx`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes:
|
||||||
|
- `compositionForState(state).chatTheme`
|
||||||
|
- `DiscussionPanel` branch ID.
|
||||||
|
- Produces:
|
||||||
|
- `OperatorChat` root has `data-presentation-surface="editorial"` when `chatTheme === "light"`, otherwise `"night"`.
|
||||||
|
- `DiscussionPanel` root has `data-presentation-surface="editorial"`.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add failing OperatorChat surface test**
|
||||||
|
|
||||||
|
In `web/apps/console/src/presentation/OperatorChat.test.tsx`, add this test:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
it("maps light chat theme to the editorial presentation surface", () => {
|
||||||
|
const state = {
|
||||||
|
...initialPresentationState,
|
||||||
|
location: { kind: "main" as const, sceneId: "workflow-demo" as const, beatId: "graph", focusPath: [] },
|
||||||
|
};
|
||||||
|
|
||||||
|
render(<OperatorChat state={state} />);
|
||||||
|
|
||||||
|
const chat = screen.getByLabelText("scripted operator chat");
|
||||||
|
expect(chat).toHaveAttribute("data-chat-theme", "light");
|
||||||
|
expect(chat).toHaveAttribute("data-presentation-surface", "editorial");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a second test:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
it("maps dark chat theme to the night presentation surface", () => {
|
||||||
|
render(<OperatorChat state={initialPresentationState} />);
|
||||||
|
|
||||||
|
const chat = screen.getByLabelText("scripted operator chat");
|
||||||
|
expect(chat).toHaveAttribute("data-presentation-surface", "night");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Add failing DiscussionPanel surface tests**
|
||||||
|
|
||||||
|
In `web/apps/console/src/presentation/DiscussionPanel.test.tsx`, add:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
it("renders Q&A branches on the editorial presentation surface", () => {
|
||||||
|
render(<DiscussionPanel branchId="where-is-ai-agent" onClose={onClose} />);
|
||||||
|
|
||||||
|
expect(screen.getByRole("dialog")).toHaveAttribute("data-presentation-surface", "editorial");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders legacy discussion branches on the same editorial surface", () => {
|
||||||
|
render(<DiscussionPanel branchId="hosted-automation" onClose={onClose} />);
|
||||||
|
|
||||||
|
expect(screen.getByRole("dialog")).toHaveAttribute("data-presentation-surface", "editorial");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: Run failing tests**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm --dir web --filter @lda/console test -- src/presentation/OperatorChat.test.tsx src/presentation/DiscussionPanel.test.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: FAIL because `data-presentation-surface` is not emitted yet.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Add `OperatorChat` surface attribute**
|
||||||
|
|
||||||
|
In `web/apps/console/src/presentation/OperatorChat.tsx`, find:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const composition = compositionForState(state);
|
||||||
|
return (
|
||||||
|
<aside
|
||||||
|
className="operator-chat"
|
||||||
|
data-mode={composition.chatMode}
|
||||||
|
data-chat-theme={composition.chatTheme}
|
||||||
|
data-readable-surface={composition.chatTheme === "light" ? "light" : "dark"}
|
||||||
|
aria-label="scripted operator chat"
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace with:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const composition = compositionForState(state);
|
||||||
|
const presentationSurface = composition.chatTheme === "light" ? "editorial" : "night";
|
||||||
|
return (
|
||||||
|
<aside
|
||||||
|
className="operator-chat"
|
||||||
|
data-mode={composition.chatMode}
|
||||||
|
data-chat-theme={composition.chatTheme}
|
||||||
|
data-readable-surface={composition.chatTheme === "light" ? "light" : "dark"}
|
||||||
|
data-presentation-surface={presentationSurface}
|
||||||
|
aria-label="scripted operator chat"
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 5: Add `DiscussionPanel` surface attribute**
|
||||||
|
|
||||||
|
In `web/apps/console/src/presentation/DiscussionPanel.tsx`, find the root `<div>`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<div
|
||||||
|
ref={dialogRef}
|
||||||
|
className="discussion-panel"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-label={branch.title}
|
||||||
|
onKeyDown={trapKeyboardWithinDialog}
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
Add:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
data-presentation-surface="editorial"
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected result:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<div
|
||||||
|
ref={dialogRef}
|
||||||
|
className="discussion-panel"
|
||||||
|
data-presentation-surface="editorial"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-label={branch.title}
|
||||||
|
onKeyDown={trapKeyboardWithinDialog}
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 6: Run focused tests**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm --dir web --filter @lda/console test -- src/presentation/OperatorChat.test.tsx src/presentation/DiscussionPanel.test.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: PASS.
|
||||||
|
|
||||||
|
- [ ] **Step 7: Commit Task 1**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add web/apps/console/src/presentation/OperatorChat.tsx web/apps/console/src/presentation/OperatorChat.test.tsx web/apps/console/src/presentation/DiscussionPanel.tsx web/apps/console/src/presentation/DiscussionPanel.test.tsx
|
||||||
|
git commit -m "feat: mark presentation side surfaces"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 2: Normalize Chat Surface Styling
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `web/apps/console/src/presentation/presentation.css`
|
||||||
|
- Test: `web/apps/console/src/presentation/OperatorChat.test.tsx`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes:
|
||||||
|
- `.operator-chat[data-presentation-surface="editorial"]`
|
||||||
|
- `.operator-chat[data-presentation-surface="night"]`
|
||||||
|
- `.chat-message`
|
||||||
|
- `.chat-tool-part`
|
||||||
|
- Produces:
|
||||||
|
- Editorial chat cards are off-paper/tinted, not pure white.
|
||||||
|
- Night chat cards stay dark and readable.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add test for message surface class stability**
|
||||||
|
|
||||||
|
In `OperatorChat.test.tsx`, add this to the light-theme test from Task 1 after the `data-presentation-surface` assertion:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
expect(screen.getAllByText(/Found prepared workflow recipe/)[0]?.closest(".chat-message"))
|
||||||
|
.toHaveClass("chat-message");
|
||||||
|
```
|
||||||
|
|
||||||
|
This test does not assert computed color. It pins the DOM hook that CSS relies on.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Update chat CSS**
|
||||||
|
|
||||||
|
In `web/apps/console/src/presentation/presentation.css`, keep the base `.chat-message` dark readable style, then replace the current light override:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.operator-chat[data-readable-surface="light"] .chat-message {
|
||||||
|
border-color: color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 35%, transparent);
|
||||||
|
background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 92%, white);
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
with:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.operator-chat[data-presentation-surface="editorial"] .chat-message {
|
||||||
|
border-color: color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 34%, transparent);
|
||||||
|
background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 82%, var(--color-editorial-muted, oklch(0.48 0.025 65)) 18%);
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.operator-chat[data-readable-surface="light"] .chat-message strong {
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
with:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.operator-chat[data-presentation-surface="editorial"] .chat-message strong {
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.operator-chat[data-readable-surface="light"] .chat-tool-part {
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
with:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.operator-chat[data-presentation-surface="editorial"] .chat-tool-part {
|
||||||
|
border-color: color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 40%, transparent);
|
||||||
|
background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 70%, transparent);
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep `data-readable-surface` selectors only if another rule still uses them. Prefer the new semantic surface selectors for new rules.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Run focused test**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm --dir web --filter @lda/console test -- src/presentation/OperatorChat.test.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: PASS.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Commit Task 2**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add web/apps/console/src/presentation/presentation.css web/apps/console/src/presentation/OperatorChat.test.tsx
|
||||||
|
git commit -m "fix: normalize presentation chat surface"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 3: Normalize Discussion/Q&A Surface Styling
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `web/apps/console/src/presentation/presentation.css`
|
||||||
|
- Test: `web/apps/console/src/presentation/DiscussionPanel.test.tsx`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes:
|
||||||
|
- `.discussion-panel[data-presentation-surface="editorial"]`
|
||||||
|
- `.discussion-panel__qna`
|
||||||
|
- `.discussion-panel__presenter-note`
|
||||||
|
- Produces:
|
||||||
|
- Discussion panels use editorial surface colors.
|
||||||
|
- Q&A answers are readable.
|
||||||
|
- Presenter notes are demoted but legible.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add tests for Q&A/presenter-note hooks**
|
||||||
|
|
||||||
|
In `DiscussionPanel.test.tsx`, extend `"renders defense Q&A fields when present"` with:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
expect(screen.getByLabelText("defense question")).toBeInTheDocument();
|
||||||
|
```
|
||||||
|
|
||||||
|
Extend `"renders speaker hints as presenter notes instead of answer content"` with:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
expect(note).toHaveClass("discussion-panel__presenter-note");
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Update discussion panel CSS**
|
||||||
|
|
||||||
|
In `web/apps/console/src/presentation/presentation.css`, replace the base `.discussion-panel` rule:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.discussion-panel {
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid oklch(0.36 0.04 250);
|
||||||
|
background: oklch(0.16 0.025 250);
|
||||||
|
border-radius: 0.65rem;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
with:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.discussion-panel {
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 35%, transparent);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 88%, white);
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Update the following selectors to use editorial colors:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.discussion-panel h2 {
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion-panel__badge {
|
||||||
|
background: color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 18%, transparent);
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion-panel__evidence {
|
||||||
|
color: var(--color-editorial-muted, oklch(0.48 0.025 65));
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion-panel__summary {
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion-panel__qna {
|
||||||
|
border-color: color-mix(in oklch, var(--color-intent, oklch(0.53 0.17 250)) 28%, transparent);
|
||||||
|
background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 74%, white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion-panel__question,
|
||||||
|
.discussion-panel__short-answer {
|
||||||
|
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion-panel__expanded-answer {
|
||||||
|
color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 82%, var(--color-editorial-muted, oklch(0.48 0.025 65)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion-panel__presenter-note {
|
||||||
|
border-color: color-mix(in oklch, var(--color-human, oklch(0.68 0.17 55)) 38%, transparent);
|
||||||
|
background: color-mix(in oklch, var(--color-human, oklch(0.68 0.17 55)) 10%, var(--color-editorial-paper, oklch(0.975 0.012 82)));
|
||||||
|
color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 76%, var(--color-editorial-muted, oklch(0.48 0.025 65)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion-panel__presenter-note span {
|
||||||
|
color: color-mix(in oklch, var(--color-human, oklch(0.68 0.17 55)) 70%, var(--color-editorial-ink, oklch(0.19 0.015 65)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.discussion-panel__detail {
|
||||||
|
color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 82%, var(--color-editorial-muted, oklch(0.48 0.025 65)));
|
||||||
|
border-left-color: color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 42%, transparent);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep `.discussion-panel__return` as a clear action button, but ensure it does not look like a saturated unrelated pill. If needed, update it to:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.discussion-panel__return {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
border: 1px solid var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
padding: 0.4rem 0.75rem;
|
||||||
|
background: var(--color-editorial-ink, oklch(0.19 0.015 65));
|
||||||
|
color: var(--color-editorial-paper, oklch(0.975 0.012 82));
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: Run focused test**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm --dir web --filter @lda/console test -- src/presentation/DiscussionPanel.test.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: PASS.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Commit Task 3**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add web/apps/console/src/presentation/presentation.css web/apps/console/src/presentation/DiscussionPanel.test.tsx
|
||||||
|
git commit -m "fix: normalize discussion surface theme"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 4: Screenshot Smoke And Roadmap
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `docs/current_roadmap.md`
|
||||||
|
- Move: `docs/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md` to `docs/historical/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md`
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: Tasks 1-3.
|
||||||
|
- Produces: verified visual smoke and updated roadmap.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Run focused tests**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm --dir web --filter @lda/console test -- src/presentation/OperatorChat.test.tsx src/presentation/DiscussionPanel.test.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: PASS.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Run build checks**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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: Capture screenshot smoke**
|
||||||
|
|
||||||
|
Start dev server if needed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm --dir web dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Capture:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
New-Item -ItemType Directory -Force web/apps/console/.visual-smoke | Out-Null
|
||||||
|
pnpx playwright screenshot --viewport-size=1280,720 "http://127.0.0.1:5173/present#scene/positioning/landscape" web/apps/console/.visual-smoke/surface-positioning-1280x720.png
|
||||||
|
pnpx playwright screenshot --viewport-size=1280,720 "http://127.0.0.1:5173/present#scene/planner-runtime/planner" web/apps/console/.visual-smoke/surface-planner-runtime-1280x720.png
|
||||||
|
pnpx playwright screenshot --viewport-size=1280,720 "http://127.0.0.1:5173/present#scene/lifecycle/draft" web/apps/console/.visual-smoke/surface-lifecycle-1280x720.png
|
||||||
|
pnpx playwright screenshot --viewport-size=1280,720 "http://127.0.0.1:5173/present#discuss/where-is-ai-agent" web/apps/console/.visual-smoke/surface-qna-agent-1280x720.png
|
||||||
|
pnpx playwright screenshot --viewport-size=1280,720 "http://127.0.0.1:5173/present#discuss/evaluation-validity" web/apps/console/.visual-smoke/surface-qna-evaluation-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/surface-approval-1280x720.png
|
||||||
|
```
|
||||||
|
|
||||||
|
Manual acceptance:
|
||||||
|
- Chat is not a bright white card stack.
|
||||||
|
- Discussion/Q&A panels look editorial and readable.
|
||||||
|
- Presenter note is demoted but legible.
|
||||||
|
- Scene 3/4/5 direct surfaces do not look like mismatched dark modals.
|
||||||
|
- `.visual-smoke/` remains ignored by git.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Update roadmap**
|
||||||
|
|
||||||
|
In `docs/current_roadmap.md`, under `Next presentation visual slices`, replace:
|
||||||
|
|
||||||
|
```md
|
||||||
|
2. Surface theme normalization pass: make light chat, discussion modals, and
|
||||||
|
Q&A branches use the same editorial presentation surface instead of
|
||||||
|
jumping between overly white chat cards and dark modal interiors.
|
||||||
|
```
|
||||||
|
|
||||||
|
with:
|
||||||
|
|
||||||
|
```md
|
||||||
|
2. Completed: surface theme normalization pass made light chat, discussion
|
||||||
|
modals, and Q&A branches use the same editorial presentation surface.
|
||||||
|
Implementation:
|
||||||
|
[`presentation surface theme normalization`](historical/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md).
|
||||||
|
```
|
||||||
|
|
||||||
|
Renumber the remaining entries so the scene composition pass is `3` and the
|
||||||
|
presentation craft pass is `4`.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Archive plan**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git mv docs/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md docs/historical/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md
|
||||||
|
```
|
||||||
|
|
||||||
|
If the plan is not tracked yet, use PowerShell:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Move-Item docs/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md docs/historical/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 6: Commit Task 4**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add docs/current_roadmap.md docs/historical/superpowers/plans/2026-07-08-presentation-surface-theme-normalization.md
|
||||||
|
git commit -m "docs: record presentation surface normalization"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Final Verification
|
||||||
|
|
||||||
|
- [ ] Run focused tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm --dir web --filter @lda/console test -- src/presentation/OperatorChat.test.tsx src/presentation/DiscussionPanel.test.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: PASS.
|
||||||
|
|
||||||
|
- [ ] Run full web tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm --dir web test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: PASS.
|
||||||
|
|
||||||
|
- [ ] Run full web typecheck:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm --dir web typecheck
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: PASS.
|
||||||
|
|
||||||
|
- [ ] Run status checks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git diff --check
|
||||||
|
git status --short
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- No whitespace errors.
|
||||||
|
- No untracked `.visual-smoke/` files.
|
||||||
|
- Only intentional files remain if not yet committed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
|
||||||
|
- Chat no longer appears as a bright white card stack.
|
||||||
|
- Direct discussion routes are readable and editorial.
|
||||||
|
- Q&A branches and legacy branches use the same discussion surface.
|
||||||
|
- Presenter notes are demoted and legible.
|
||||||
|
- `/console` unchanged.
|
||||||
|
- No new dependency added.
|
||||||
|
- Scene composition remains deferred to the next slice.
|
||||||
Reference in New Issue
Block a user