Files
Mark 03d4b3343c docs(03): UI design contract — null-spec for verification-only phase
Phase 3 is verification-only; /gsd-ui-phase 3 trigger on "page" keyword
is a false positive. UI-SPEC.md confirms no new user-facing UI surface
in scope; locks the Phase 1 design system (Lora + IBM Plex Sans + Loom
palette + Mokosh mark + tokens.css + 17 i18n keys) as read-only
inherited context; declares minimal probe-page conventions for
internal Puppeteer test fixtures (Plans 03-01..03-05 per D-P3-01).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:04:00 +02:00

233 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: 3
slug: 03-spec-10-smoke-verification-dom-event-log-verification
status: draft
shadcn_initialized: false
preset: none
created: 2026-05-20
scope_kind: verification-only
ui_surface: none-user-facing
inherits_from:
- 01-12-SUMMARY.md (design system locked: Lora display + IBM Plex Sans UI + Loom palette + Mokosh mark + canonical tokens.css + 16 i18n keys with en↔ru parity)
- 01-10-SUMMARY.md (welcome page pattern: data-mokosh-slot + data-mokosh-key + data-mokosh-i18n-key three-pipeline DOM population)
---
# Phase 3 — UI Design Contract
> Visual and interaction contract for frontend phases. Generated by gsd-ui-researcher, verified by gsd-ui-checker.
---
## Scope Determination
**Phase 3 has NO user-facing UI surface in scope.**
The `/gsd-ui-phase 3` orchestrator triggered on the "page" keyword in 03-CONTEXT.md `<domain>` and `<specifics>`. After reading the upstream artifacts, the honest answer is that this is a false positive:
- 03-CONTEXT.md `<domain>` explicitly states: *"No new production-code feature work; the rrweb wiring + event-log wiring already shipped in Phase 1 (`src/content/index.ts`). Phase 3 confirms what's shipped + writes the §10 sweep VERIFICATION."*
- All "page" references in Phase 3 plans (03-01, 03-02, 03-03, 03-04, 03-05 per D-P3-01) point to **synthetic Puppeteer test fixtures internal to `tests/uat/extension-page-harness.ts`** — probe HTML for rrweb DOM verification (form + table + modal) and event-log trigger surfaces (password input + click target + 404 endpoint). These pages never ship in production and never reach an operator.
- All user-facing UI surfaces (popup, welcome page, brand identity, badges, icons, fonts, palette, i18n) were **LOCKED by Phase 1** (Plans 01-09 / 01-10 / 01-12 / 01-14). Phase 3 INHERITS them and MUST NOT modify them.
This UI-SPEC therefore captures **inherited design-system facts** that downstream Phase 3 planners and executors must respect (read-only), plus **minimal probe-page conventions** for the internal test fixtures. It contains NO new design directives.
---
## Design System (INHERITED — DO NOT MODIFY)
The design system is **closed for Phase 3.** Plan 01-12 Wave 7 operator brand-fit ack 2026-05-20 verbatim "all good" sealed the canonical artifacts. Phase 3 planners must NOT introduce new tokens, new fonts, new colors, new copy keys, new icons, new layout primitives, OR new component patterns into the user-facing surface.
| Property | Value | Source |
|----------|-------|--------|
| Tool | none (manual canonical token system) | Plan 01-12 Wave 1 Task 2 — `src/shared/tokens.css` |
| Preset | not applicable | — |
| Component library | none (vanilla DOM; three-pipeline populate pattern for welcome page) | Plan 01-10 patterns-established |
| Icon library | static PNG artifacts at `icons/icon{16,48,128}.png` (8-bit RGBA; Loom mark rasterized from `src/shared/brand/mokosh-mark.svg` via `scripts/rasterize-icons.sh`) | Plan 01-12 Wave 2 |
| Display font | `"Lora", "Iowan Old Style", "Times New Roman", serif` (Cyreal foundry; OFL-1.1; full Cyrillic via R2 substitution 2026-05-19) | Plan 01-12 Wave 1 Task 2 + brand-decisions-v1-followup-display-font.md |
| UI font | `"IBM Plex Sans", "Segoe UI", -apple-system, BlinkMacSystemFont, sans-serif` (OFL-1.1; full Cyrillic) | `src/shared/tokens.css` line 146 |
| Mono font | `"IBM Plex Mono", "SF Mono", Menlo, Consolas, monospace` (OFL-1.1; full Cyrillic) | `src/shared/tokens.css` line 147 |
**Read-only canonical sources:**
- `src/shared/tokens.css` (~355 lines) — single source of truth
- `src/shared/fonts/*.woff2` (8 files, ~155 KB total) — self-hosted under MV3 CSP
- `src/shared/brand/{mokosh-mark.svg,mokosh-lockup.svg}` — canonical brand assets
- `_locales/{en,ru}/messages.json` — 17 i18n keys per locale (Plan 01-12 + Plan 01-10 closure-cycle split notifStartup → notifStartupCta + notifRecordingStarted)
- `icons/icon{16,48,128}.png` — committed static artifacts (NOT regenerated at build time)
---
## Spacing Scale (INHERITED)
Declared values from `src/shared/tokens.css` lines 178-188. Phase 3 must not introduce new spacing values.
| Token | Value | Usage |
|-------|-------|-------|
| `--mks-space-1` | 4px | Icon gaps, inline padding |
| `--mks-space-2` | 8px | Compact element spacing |
| `--mks-space-3` | 12px | (used by component CSS as needed) |
| `--mks-space-4` | 16px | Default element spacing |
| `--mks-space-5` | 20px | (used by component CSS as needed) |
| `--mks-space-6` | 24px | Section padding |
| `--mks-space-8` | 32px | Layout gaps |
| `--mks-space-10` | 40px | (used by component CSS as needed) |
| `--mks-space-12` | 48px | Major section breaks |
| `--mks-space-16` | 64px | Page-level spacing |
| `--mks-space-20` | 80px | (used by component CSS as needed) |
Exceptions: none in Phase 3 (no new component CSS is in scope).
---
## Typography (INHERITED)
Declared values from `src/shared/tokens.css` lines 151-167 + semantic helpers lines 254-333. Phase 3 must not introduce new font sizes or weights.
| Role | Size | Weight | Line Height | Token / class |
|------|------|--------|-------------|---------------|
| Body | 15px | 400 (regular) | 1.5 | `.mks-body` |
| Label (small) | 13px | 400 | 1.5 | `.mks-body-sm` |
| Heading | 17px | 600 (semibold) | 1.3 | `.mks-h3` |
| Heading large | 20px | 600 | 1.3 | `.mks-h2` |
| Heading display | 28px | 400 | 1.15 | `.mks-h1` |
| Display | 40px (or 56px for hero) | 400 | 1.15 | `.mks-display-2` / `.mks-display-1` |
Inherited type scale (full list at `tokens.css` lines 151-158): 11, 13, 15, 17, 20, 28, 40, 56 px. Phase 3 must not add intermediate sizes.
Inherited weights (lines 164-167): 400 regular, 500 medium, 600 semibold, 700 bold.
---
## Color (INHERITED — Loom palette per D-04)
Declared values from `src/shared/tokens.css` lines 89-137. Phase 3 must not introduce new colors.
| Role | Value | Usage |
|------|-------|-------|
| Dominant (60%) | `--mks-linen-50` = #faf7f1 | Page background |
| Surface raised (cards/popup) | `--mks-linen-100` = #f3eee4 | Card / popup surface |
| Secondary (30%) | `--mks-linen-200` = #e8e0d0 | Hairline / divider on linen |
| Foreground primary | `--mks-ink-900` = #181b2a | Primary text, deepest surface |
| Accent (10%) — REC | `--mks-madder-600` = #b2543d | Recording state badge + REC dot only |
| Accent — success | `--mks-moss-600` = #5a7349 | "Готово ✓" SAVE-success state only |
| Accent — warning | `--mks-amber-600` = #c98b3a | Recoverable error / SAVING transient state only |
| Destructive | `--mks-brick-600` = #a23a2b | Unrecoverable error state only |
Accent reserved for: REC badge background; REC pulse-dot; SAVE button primary-CTA fill (madder-700 at hover); SAVING transient (amber-600); DONE transient (moss-600); ERROR (brick-600). Per Plan 01-12 Wave 4 BADGE_REC_COLOR flip from material-green to madder.
Phase 3 must NOT introduce additional accent surfaces. Probe-page fixtures (Section "Test Fixture Conventions" below) MAY remain unstyled.
---
## Copywriting Contract (INHERITED — read-only)
All operator-facing copy is locked. Phase 3 must NOT add operator-facing strings.
| Element | Copy | Source |
|---------|------|--------|
| Extension name (EN) | "Mokosh — Session Capture" | _locales/en/messages.json extName (D-07) |
| Extension name (RU) | "Mokosh — Запись сессии" | _locales/ru/messages.json extName |
| Extension description (EN) | "Thirty seconds ago, always at hand." | _locales/en/messages.json extDesc (D-08) |
| Extension description (RU) | "Тридцать секунд назад, всегда под рукой." | _locales/ru/messages.json extDesc |
| Primary CTA (popup SAVE) | "Сохранить отчёт об ошибке" (`popupSaveCta`) | Plan 01-09 + REQ-popup-ui |
| Empty state heading | "Готов к записи" (popupSavePrompt + popupInfoText) | Plan 01-12 Wave 3 |
| Saving transient | "Сохраняю..." (`popupSaving`) | Plan 01-09 state machine |
| Done transient | "Готово! ✓" (`popupSaveDone`) | Plan 01-09 state machine |
| Startup notification CTA | "Mokosh ready. Click to start a recording." (`notifStartupCta` — split from notifStartup per closure-cycle debug 4bba679) | Plan 01-10 cycle-1 debug fix |
| Recording started notification | (`notifRecordingStarted`) | Plan 01-10 cycle-1 debug fix |
| Recovery notification | (`notifRecovery`) | Plan 01-09 + Plan 01-12 |
| Welcome hero (RU) | "Тридцать секунд назад, всегда под рукой." (`welcomeHeroRu`) | Plan 01-10 D-08 |
| Welcome hero (EN) | "Thirty seconds ago, always at hand." (`welcomeHeroEn`) | Plan 01-10 D-08 |
| Toolbar tooltip (off / rec / err) | `tooltipOff` / `tooltipRecPrefix` / `tooltipErr` | Plan 01-12 Wave 3 |
**Phase 3 may emit VERIFICATION.md operator-instruction copy** (e.g. §10 #9 RAM-ceiling step: "Load extension; idle 5 min; open `chrome://memory-internals`; verify extension background RAM < 50 MB.") — that is documentation copy, not operator-facing UI, and is outside this contract.
**Destructive actions in Phase 3:** none. Phase 3 has no buttons, no confirmations, no UI state. It is a verification-only phase.
---
## Test Fixture Conventions (INTERNAL — Phase 3-scoped)
The five Phase 3 plans (per D-P3-01) extend `tests/uat/extension-page-harness.ts` with new `assertA*` methods (A29+ continuing from Plan 02-04's A24-A28). For rrweb DOM probing per §10 #4 (Plan 03-01) the harness page must include synthetic HTML structures sufficient to exercise rrweb's typical-page coverage.
**Probe HTML composition** (Plan 03-01 planner discretion per 03-CONTEXT.md `<decisions>` "Claude's Discretion" + `<specifics>`):
| Surface | Purpose | Minimum required CSS |
|---------|---------|----------------------|
| `<form>` with text + email + password input + submit button | rrweb input variety + §10 #8 password-filter probe (Plan 03-03) | unstyled OR minimal — fields need to be present in the DOM tree, not styled |
| `<table>` with `<thead>` + `<tbody>` + ≥2 rows | rrweb table rendering (`<tr>` / `<td>` snapshot coverage) | unstyled |
| Modal trigger button + modal `<dialog>` or absolutely-positioned `<div>` | rrweb modal + focus-trap + z-index snapshot coverage | `dialog { z-index: 1000; }` minimum if not using native `<dialog>` |
| 404-target trigger button (for `fetch(...)` → network_error) | §10 #5 event-log trigger (Plan 03-02) | unstyled |
| Error-trigger button (for `throw new Error(...)` → js_error) | §10 #5 event-log trigger (Plan 03-02) | unstyled |
**Probe HTML MUST NOT:**
- Import the canonical `src/shared/tokens.css` (the harness page already imports it for A18/A21 Lora-resolution coverage; the probe sub-tree should appear unstyled to keep rrweb snapshots focused on structural DOM, not on the design system)
- Use the canonical brand `var(--mks-*)` tokens (probe pages are not branded)
- Import any `_locales/*` strings via chrome.i18n (probe pages are not i18n'd; assertion text can be inline English)
- Inject any `data-mokosh-slot` / `data-mokosh-key` / `data-mokosh-i18n-key` attributes (those are reserved for the production welcome page DOM population pipelines per Plan 01-10)
**Probe HTML MAY use** plain `data-test-*` attributes for assertion-side querySelector targeting. This is the established pattern from prior harness fixtures.
**Synthetic password input convention** (Plan 03-03):
```html
<input type="password" id="probe-password" data-test="probe-password" />
```
The harness driver types a sentinel value (e.g. `"secret-do-not-log-123"`) into this input via `page.type`. Plan 03-03 assertion then greps `events.json` parsed from the assembled archive for absence of the sentinel. **Negative-assertion test pattern** — the absence of the sentinel proves the existing `src/content/index.ts:82` `if (target.type === 'password') return;` filter fires. This is the explicit PARTIAL §10 #8 closure per D-P3-02 charter alignment.
**FORBIDDEN_HOOK_STRINGS lockstep** (per Plan 02-04 + Plan 01-12 + Plan 01-13 patterns): the Phase 3 probe pages must NOT introduce new test-mode symbols into the production bundle. A29+ assertions ride existing production surfaces (rrweb's already-shipped wiring, the existing `fetch` interception, etc.) — they are NOT hooks. If a planner finds an A29+ assertion requires a new test-mode symbol, that symbol must be `__MOKOSH_UAT__` Vite-define-token gated AND added to FORBIDDEN_HOOK_STRINGS in `tests/background/no-test-hooks-in-prod-bundle.test.ts`. See Plan 02-04 SUMMARY for the most recent precedent.
---
## Registry Safety
| Registry | Blocks Used | Safety Gate |
|----------|-------------|-------------|
| shadcn official | none — manual canonical token system | not applicable |
| Third-party | none | not applicable |
Phase 3 introduces no third-party UI dependencies. The probe-page composition is hand-authored vanilla HTML inside the existing `tests/uat/` test surface.
---
## Inherited Visual Contracts to Preserve
Phase 3 verification will incidentally exercise these contracts (via existing harness assertions A0-A28 that MUST remain GREEN per 03-CONTEXT.md `<code_context>` Integration Points). Phase 3 must not regress any of them.
| Contract | Source | How Phase 3 preserves it |
|----------|--------|--------------------------|
| MV3 CSP self-host invariant (0 `googleapis` / 0 `https://fonts` in `dist/`) | Plan 01-12 Wave 1 Task 2 + `tests/build/no-remote-fonts.test.ts` | Phase 3 ships no new fonts; pre-checkpoint bundle gate (Plan 03-05) re-verifies |
| en↔ru i18n parity (17 keys × 2 locales) | Plan 01-12 Wave 3 + Plan 01-10 cycle-1 split + `tests/i18n/locale-parity.test.ts` | Phase 3 ships no new locale keys; pre-checkpoint bundle gate (Plan 03-05) re-verifies |
| Icons rendering at 16/48/128 (8-bit RGBA) | Plan 01-12 Wave 2 + `tests/build/icons-present.test.ts` + harness A19 | Phase 3 does not modify icons; A19 remains GREEN |
| `--mks-font-display` resolves to Lora stack | Plan 01-12 Wave 1 Task 2 + harness A21 | Phase 3 does not modify tokens.css; A21 remains GREEN |
| `--mks-rec` resolves to `rgb(178, 84, 61)` = #b2543d | Plan 01-12 Wave 4 BADGE_REC_COLOR + harness A17.7 | Phase 3 does not modify palette; A17.7 remains GREEN |
| BADGE_REC_COLOR madder + 3-state state machine | Plan 01-09 + Plan 01-12 Wave 4 | Phase 3 makes no badge changes |
| Welcome page first-install activation (onInstalled('install') + storage flag + tabs.create) | Plan 01-10 Wave 2 helper + harness A15/A16/A17 | Phase 3 makes no onboarding changes |
---
## Checker Sign-Off
This UI-SPEC is a **null-spec** for Phase 3 — it confirms the absence of in-scope UI surface and freezes inherited Phase 1 design facts as read-only. The 6 design quality dimensions are evaluated against the inherited surface, not against any new Phase 3 work.
- [x] Dimension 1 Copywriting: PASS (inherited; 17-key matrix locked; Phase 3 emits no new operator copy)
- [x] Dimension 2 Visuals: PASS (inherited; canonical brand artifacts unchanged; probe-page convention bans new visual surface)
- [x] Dimension 3 Color: PASS (inherited; Loom palette locked at `src/shared/tokens.css`; no new colors)
- [x] Dimension 4 Typography: PASS (inherited; 3 families × declared sizes/weights locked; no new sizes)
- [x] Dimension 5 Spacing: PASS (inherited; `--mks-space-*` scale locked; 4px base preserved)
- [x] Dimension 6 Registry Safety: PASS (no shadcn use; no third-party registry; vanilla DOM only)
**Approval:** pending checker review (draft status)
---
## Notes for Downstream Phase 3 Agents
**Planner (`gsd-planner`):** Phase 3 plans should NOT include any UI design tasks. Plans 03-01 through 03-05 are all verification (harness assertions + VERIFICATION.md aggregation) per D-P3-01. The probe-page HTML composition is internal harness work and falls under the "Test Fixture Conventions" section above.
**Executor (`gsd-executor`):** When extending `tests/uat/extension-page-harness.ts` or `tests/uat/extension-page-harness.html`, treat the existing canonical `<link rel="stylesheet" href="../../src/shared/tokens.css">` import as load-bearing (harness assertions A18 + A21 depend on it). Add probe HTML below the existing harness scaffold; do not strip the tokens.css link.
**UI auditor (if spawned):** Phase 3 has no user-facing surface to audit. Run audit against Phase 1 + Phase 2 surfaces (popup + welcome page + badges + notifications + manifest + icons) if a regression sweep is desired.
**Ceremony note:** If during execution the planner discovers Phase 3 needs operator-facing UI work (e.g. a new VERIFICATION.md operator instruction is genuinely UI-mediated), route through `/gsd-debug` or `/gsd-discuss-phase` per `feedback-gsd-ceremony-for-fixes.md`. Do not hot-edit this UI-SPEC or the canonical design system.