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>
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
---
|
||||
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.
|
||||
Reference in New Issue
Block a user