Snapshot WIP: solver HP epic progress, BPHX/HX physics, BMAD skill refresh.
Some checks failed
CI / check (push) Has been cancelled
Some checks failed
CI / check (push) Has been cancelled
Capture uncommitted solver robustness work (regularization, domain errors, linear solver lifecycle, tube DP/MSH), web workbench updates, and synced BMAD skills across IDE agent folders before starting BPHX pressure-drop. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
9
.agent/skills/bmad-ux/assets/color-themes.md
Normal file
9
.agent/skills/bmad-ux/assets/color-themes.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Color Themes Renderer
|
||||
|
||||
Subagent prompt. Produce one self-contained HTML page at the supplied `.working/color-themes-{n}.html` path showing 4-6 distinct theme variations side by side so the user can pick.
|
||||
|
||||
Each variation: header (name + one-line emotional register), token chips for every semantic role decided so far, and one realistic UI snippet using the palette (content drawn from the conversation, not lorem). Include light and dark side-by-side when both modes are in scope. Avoid near-identical pastels — variations must differ in register, not just hue.
|
||||
|
||||
Inline CSS only, system font stack, no JS, no network. Document concrete hex values in `<style>` comments per variation so the user can lift them if they pick that theme. The spine itself stays semantic.
|
||||
|
||||
Return to the parent: file path, one-line per variation, mode coverage. Do not dump HTML into the parent context. If interactive, open the file with `python3 -c "import webbrowser, pathlib; webbrowser.open(pathlib.Path('PATH').resolve().as_uri())"`.
|
||||
9
.agent/skills/bmad-ux/assets/design-directions.md
Normal file
9
.agent/skills/bmad-ux/assets/design-directions.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Design Directions Renderer
|
||||
|
||||
Subagent prompt. Produce 3-6 distinct visual directions for the product's hero screen, each a separate self-contained HTML file at `.working/direction-{slug}.html` (or one combined `directions-{n}.html` if the parent's intent says side-by-side).
|
||||
|
||||
Each direction is a *complete visual personality* applied to the same key screen — not a palette swap. Differ on density, type weight, motion implication, brand register. Each file: 2-3 sentence rationale, near-1:1 hero screen mockup in a phone or browser frame, ideally a secondary screen, at least one state variant visible (aging row, empty state, etc).
|
||||
|
||||
Use real product content from the conversation. Voice/tone from `.memlog.md` applied to every visible string — no lorem. Inline CSS, system fonts, no JS or network. Document hex values in `<style>` comments per direction.
|
||||
|
||||
Return to the parent: file paths, one-line personality summary per direction, what hero screen was depicted. Do not dump HTML into parent context. If interactive, open each file in the browser.
|
||||
158
.agent/skills/bmad-ux/assets/design-example-editorial.md
Normal file
158
.agent/skills/bmad-ux/assets/design-example-editorial.md
Normal file
@@ -0,0 +1,158 @@
|
||||
---
|
||||
name: Linen & Logic
|
||||
colors:
|
||||
surface: '#fbf9f4'
|
||||
surface-dim: '#dbdad5'
|
||||
surface-bright: '#fbf9f4'
|
||||
surface-container-lowest: '#ffffff'
|
||||
surface-container-low: '#f5f3ee'
|
||||
surface-container: '#f0eee9'
|
||||
surface-container-high: '#eae8e3'
|
||||
surface-container-highest: '#e4e2dd'
|
||||
on-surface: '#1b1c19'
|
||||
on-surface-variant: '#4e453d'
|
||||
inverse-surface: '#30312e'
|
||||
inverse-on-surface: '#f2f1ec'
|
||||
outline: '#80756b'
|
||||
outline-variant: '#d1c4b9'
|
||||
surface-tint: '#715a3f'
|
||||
primary: '#59452b'
|
||||
on-primary: '#ffffff'
|
||||
primary-container: '#735c41'
|
||||
on-primary-container: '#f5d6b4'
|
||||
inverse-primary: '#e0c1a1'
|
||||
secondary: '#a43b2c'
|
||||
on-secondary: '#ffffff'
|
||||
secondary-container: '#fd7d69'
|
||||
on-secondary-container: '#71160b'
|
||||
tertiary: '#374a5f'
|
||||
on-tertiary: '#ffffff'
|
||||
tertiary-container: '#4f6278'
|
||||
on-tertiary-container: '#caddf8'
|
||||
error: '#ba1a1a'
|
||||
on-error: '#ffffff'
|
||||
error-container: '#ffdad6'
|
||||
on-error-container: '#93000a'
|
||||
primary-fixed: '#fdddbb'
|
||||
primary-fixed-dim: '#e0c1a1'
|
||||
on-primary-fixed: '#281804'
|
||||
on-primary-fixed-variant: '#58432a'
|
||||
secondary-fixed: '#ffdad4'
|
||||
secondary-fixed-dim: '#ffb4a7'
|
||||
on-secondary-fixed: '#400200'
|
||||
on-secondary-fixed-variant: '#842417'
|
||||
tertiary-fixed: '#d0e4ff'
|
||||
tertiary-fixed-dim: '#b4c8e2'
|
||||
on-tertiary-fixed: '#071d30'
|
||||
on-tertiary-fixed-variant: '#35485d'
|
||||
background: '#fbf9f4'
|
||||
on-background: '#1b1c19'
|
||||
surface-variant: '#e4e2dd'
|
||||
typography:
|
||||
display-lg:
|
||||
fontFamily: Libre Caslon Text
|
||||
fontSize: 48px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.1'
|
||||
letterSpacing: -0.02em
|
||||
display-lg-mobile:
|
||||
fontFamily: Libre Caslon Text
|
||||
fontSize: 36px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.1'
|
||||
headline-md:
|
||||
fontFamily: Libre Caslon Text
|
||||
fontSize: 32px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.2'
|
||||
headline-sm:
|
||||
fontFamily: Libre Caslon Text
|
||||
fontSize: 24px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.3'
|
||||
body-lg:
|
||||
fontFamily: DM Sans
|
||||
fontSize: 18px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.6'
|
||||
letterSpacing: 0.01em
|
||||
body-md:
|
||||
fontFamily: DM Sans
|
||||
fontSize: 16px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.6'
|
||||
label-caps:
|
||||
fontFamily: DM Sans
|
||||
fontSize: 12px
|
||||
fontWeight: '500'
|
||||
lineHeight: '1.4'
|
||||
letterSpacing: 0.1em
|
||||
caption:
|
||||
fontFamily: DM Sans
|
||||
fontSize: 13px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.4'
|
||||
rounded:
|
||||
sm: 0.125rem
|
||||
DEFAULT: 0.25rem
|
||||
md: 0.375rem
|
||||
lg: 0.5rem
|
||||
xl: 0.75rem
|
||||
full: 9999px
|
||||
spacing:
|
||||
unit: 8px
|
||||
gutter: 24px
|
||||
margin-mobile: 20px
|
||||
margin-desktop: 64px
|
||||
editorial-gap: 80px
|
||||
---
|
||||
|
||||
## Brand & Style
|
||||
|
||||
The design system is rooted in the philosophy of "Slow Design"—an intentional departure from the frantic pace of fast fashion. It evokes a tactile, "linen-weight" sensation through high-end editorial layouts and a restrained aesthetic. The target audience values provenance over presence, seeking a reflective and sophisticated discovery experience that feels as much like a boutique magazine as a digital marketplace.
|
||||
|
||||
The style is **Editorial Minimalism** with **Tactile** accents. It prioritizes breathable white space, asymmetrical layouts that mimic printed lookbooks, and a soft, sun-faded palette. Every interaction is designed to be deliberate and "anti-hype," eschewing aggressive animations for subtle transitions and quiet confidence.
|
||||
|
||||
## Colors
|
||||
|
||||
The palette is inspired by natural fibers and weathered landscapes.
|
||||
- **Warm White (#F9F7F2)** serves as the primary canvas, providing a soft, non-clinical background that reduces eye strain.
|
||||
- **Bone (#E3DED1)** and **Dust (#C2B9A7)** are used for structural depth, subtle dividers, and secondary surfaces.
|
||||
- **Tobacco (#735C41)** is the primary ink color, used for high-contrast typography and essential UI elements.
|
||||
- **Sun-faded Red (#B84A39)** and **Wool Blanket Blue (#4A5D73)** are used sparingly as "organic accents"—highlighting editorial picks or signifying subtle state changes without disrupting the tranquil atmosphere.
|
||||
|
||||
## Typography
|
||||
|
||||
Typography is the primary vehicle for the brand’s sophisticated voice.
|
||||
- **Libre Caslon Text** is the voice of the curator. Its classic proportions and elegant serifs provide the editorial weight required for discovery and storytelling.
|
||||
- **DM Sans** provides a quiet, functional counterpoint. It is used for body copy and navigational elements, ensuring clarity without competing with the headlines.
|
||||
|
||||
Large display titles should often use "optical sizing" logic—tighter leading and slightly negative letter spacing to create a cohesive visual block. Labels are always tracked out (0.1em) to maintain a sense of airy premiumness.
|
||||
|
||||
## Layout & Spacing
|
||||
|
||||
This design system employs a **Fluid Editorial Grid**. While it follows a 12-column structure on desktop, it encourages "asymmetrical breathing room"—intentionally leaving columns empty to direct focus toward high-quality imagery.
|
||||
|
||||
Spacing is generous. The `editorial-gap` (80px+) should be used between major content sections to allow the user to pause and reflect. Mobile layouts should maintain a minimum of 20px side margins to ensure the content feels framed like a page, rather than bleeding to the edges of the device. Elements should lean toward vertical stacks to mimic the scroll of a digital journal.
|
||||
|
||||
## Elevation & Depth
|
||||
|
||||
Depth is communicated through **Tonal Layering** and **Ambient Shadows** rather than sharp borders.
|
||||
- **Surfaces:** Use the "Bone" color to define containers against the "Warm White" base.
|
||||
- **Shadows:** Shadows are highly diffused and tinted with the "Tobacco" hue (`rgba(115, 92, 65, 0.08)`). They should feel like a soft glow of light hitting fabric, with large blur radii (20px+) and very low opacity.
|
||||
- **Borders:** When borders are necessary, they are 1px thick and rendered in "Dust," creating a "ghost" outline that barely separates elements from the background.
|
||||
|
||||
## Shapes
|
||||
|
||||
The shape language is **Soft (0.25rem)**. While a sharp edge feels too aggressive and a pill-shape feels too digital/tech-heavy, a subtle rounding of corners mimics the natural softening of woven textiles over time.
|
||||
|
||||
Larger containers (Cards, Modals) may use `rounded-lg` (0.5rem) to emphasize their tactile, object-like quality. Imagery should always follow these corner radii to maintain a cohesive, "framed" appearance.
|
||||
|
||||
## Components
|
||||
|
||||
- **Buttons:** Primary buttons use a solid "Tobacco" fill with "Warm White" text. Secondary buttons are "Bone" with "Tobacco" text or simply "Tobacco" text with a 1px "Dust" border. Padding is generous horizontally to create an elegant, elongated silhouette.
|
||||
- **Cards:** Editorial cards feature large imagery, a "headline-sm" title, and a "caption" subline. Shadows are only applied on hover to simulate a gentle lift.
|
||||
- **Inputs:** Minimalist underlines in "Dust" that transition to "Tobacco" on focus. Label text remains in "label-caps" above the field.
|
||||
- **Chips/Tags:** Used for material types (e.g., "100% Linen"). These are rendered in "Bone" backgrounds with "Tobacco" text, using the "Soft" corner radius.
|
||||
- **Icons:** Must be "Hand-drawn" or "Fine-line" style. Lines should have slight imperfections and vary in weight to reinforce the tactile, artisanal nature of the fashion being discovered.
|
||||
- **Navigation:** A simple, centered bottom bar or a top-weighted "Ghost" header that disappears on scroll to maximize the editorial viewport.
|
||||
93
.agent/skills/bmad-ux/assets/design-example-mobile.md
Normal file
93
.agent/skills/bmad-ux/assets/design-example-mobile.md
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
name: Quill
|
||||
description: Daily writing companion. Calm, intentional, dark-mode-by-default. No streaks, no gamification.
|
||||
colors:
|
||||
surface-base: '#FAF9F7'
|
||||
surface-raised: '#FFFFFF'
|
||||
ink-primary: '#1A1B1F'
|
||||
ink-secondary: '#6B655A'
|
||||
ink-disabled: '#B5AFA5'
|
||||
accent: '#A87434'
|
||||
border-hairline: '#E8E4DD'
|
||||
surface-base-dark: '#1A1B1F'
|
||||
surface-raised-dark: '#23252B'
|
||||
ink-primary-dark: '#F0EDE8'
|
||||
ink-secondary-dark: '#A39E94'
|
||||
ink-disabled-dark: '#5E5A53'
|
||||
accent-dark: '#D4A574'
|
||||
border-hairline-dark: '#2E3036'
|
||||
typography:
|
||||
title:
|
||||
note: 'Platform native — iOS Title 1 · Android Headline Small'
|
||||
body:
|
||||
note: 'Platform native — iOS Body · Android Body Large'
|
||||
meta:
|
||||
note: 'Platform native — iOS Footnote · Android Body Small'
|
||||
rounded:
|
||||
sm: 6px
|
||||
md: 12px
|
||||
spacing:
|
||||
'1': 4px
|
||||
'2': 8px
|
||||
'3': 12px
|
||||
'4': 16px
|
||||
'5': 24px
|
||||
'6': 32px
|
||||
---
|
||||
|
||||
## Brand & Style
|
||||
|
||||
Quill is designed against the grain of contemporary habit apps. Where most products weaponize the user's calendar with streak counters and re-engagement nudges, Quill insists on something quieter — a daily prompt, a place to write, and the unspoken assurance that today's entry is enough. Showing up is the point, not the streak.
|
||||
|
||||
The visual language follows. Calm surfaces in warm off-white (light) or deep ink (dark, the default). Generous breathing room. No chromatic color competing for attention except a single warm tobacco that signals save-and-send. Text-first. Hand-on-paper, not buzz-on-screen.
|
||||
|
||||
## Colors
|
||||
|
||||
The palette is restrained on purpose — a writing surface should not compete with the writing.
|
||||
|
||||
- **Warm White (`#FAF9F7`)** is the primary canvas in light mode. Slightly warm to reduce eye strain and keep the surface from feeling clinical.
|
||||
- **Deep Ink (`#1A1B1F`)** is the dark-mode canvas and the primary body text color in light mode. Quill defaults to dark because most writing happens at night.
|
||||
- **Tobacco (`#A87434` light / `#D4A574` dark)** is the only chromatic color. Used exclusively for the save indicator and primary action — never for decoration, never for state badges.
|
||||
- **Hairline (`#E8E4DD` light / `#2E3036` dark)** separates list items at the lowest possible contrast. Anything heavier feels like UI rather than paper.
|
||||
|
||||
Avoid: red error fills (Quill is a journal, not a form), gradients (the surface is paper), and saturated accent variants — one accent, used sparingly.
|
||||
|
||||
## Typography
|
||||
|
||||
Platform conventions are the spec. iOS uses Title 1 / Body / Footnote; Android uses Headline Small / Body Large / Body Small. Dynamic type honored at every level — the largest accessibility setting must still render legibly without truncation.
|
||||
|
||||
Headlines are rare. The Today prompt is set in `title`; everything else is `body` or `meta`. No display sizes, no all-caps labels.
|
||||
|
||||
## Layout & Spacing
|
||||
|
||||
Scale: 4 / 8 / 12 / 16 / 24 / 32 px. The largest gaps land between major surfaces; the smallest sit between tightly related elements. Vertical rhythm follows a hard rule: composer breathes, list items don't.
|
||||
|
||||
Mobile margins follow platform conventions (iOS 16pt, Android 16dp). Single-column always; modal stacks one level deep, never two.
|
||||
|
||||
## Elevation & Depth
|
||||
|
||||
Quill avoids elevation as a visual device. Cards and composer surfaces sit on `surface-raised`, distinguished from `surface-base` only by tone. Shadows are reserved for the rare moment of literal physical metaphor — never for hierarchy. Hierarchy comes from layout and typography, not shadow.
|
||||
|
||||
## Shapes
|
||||
|
||||
`rounded/sm` (6px) for inputs, list rows, and small surfaces. `rounded/md` (12px) for cards and the composer. Nothing fully rounded; no pills, no perfect circles for surfaces. The aesthetic is paper-with-soft-corners, not iOS-button-pill.
|
||||
|
||||
Imagery follows container corners exactly.
|
||||
|
||||
## Components
|
||||
|
||||
- **Prompt card** — `surface-raised`. One per day. Today's prompt in `title`. Tap to open composer. No icon, no decoration; the prompt itself is the affordance.
|
||||
- **Composer** — Full-screen text view. Clean text field, generous vertical padding, single-line save indicator in the header.
|
||||
- **Save indicator** — Text only. Uses `ink-secondary`, never a checkmark icon, never a colored badge.
|
||||
- **Entry row** (Library) — Date in `meta`, first line of body in `body` (truncated to one line). Hairline divider only, no fill.
|
||||
- **Settings row** — Label left, value or chevron right. Tobacco accent only on destructive confirmations.
|
||||
|
||||
## Do's and Don'ts
|
||||
|
||||
| Do | Don't |
|
||||
|---|---|
|
||||
| Single accent color, used sparingly on save & primary action | Color-code by sentiment, mood, or category |
|
||||
| Text-only state indicators (`Saved.`) | Iconography for state (✓, ⚠, ●) |
|
||||
| Hairline dividers at lowest legible contrast | Card shadows, gradient fills, accent fills behind text |
|
||||
| Generous vertical rhythm in composer | Compress to fit more on screen |
|
||||
| Honor platform conventions for navigation | Override platform nav with custom drawer or hamburger |
|
||||
109
.agent/skills/bmad-ux/assets/design-example-shadcn.md
Normal file
109
.agent/skills/bmad-ux/assets/design-example-shadcn.md
Normal file
@@ -0,0 +1,109 @@
|
||||
---
|
||||
name: Drift
|
||||
description: Focused task tracker for solo founders and small async teams. shadcn/ui on Next.js + Tailwind; this DESIGN.md specifies the brand-layer delta only.
|
||||
colors:
|
||||
# Brand overrides on top of shadcn defaults. All unlisted tokens inherit
|
||||
# from shadcn (background, foreground, muted, muted-foreground, popover,
|
||||
# popover-foreground, card, card-foreground, border, input, ring, destructive).
|
||||
primary: '#0F4C81'
|
||||
primary-foreground: '#FFFFFF'
|
||||
accent: '#F59E0B'
|
||||
accent-foreground: '#1A1208'
|
||||
primary-dark: '#5C8AC2'
|
||||
primary-foreground-dark: '#0A1A2A'
|
||||
accent-dark: '#FBC470'
|
||||
accent-foreground-dark: '#1A1208'
|
||||
typography:
|
||||
# Body, label, and muted inherit from shadcn (Geist Sans). Only display is overridden.
|
||||
display:
|
||||
fontFamily: 'Instrument Serif'
|
||||
fontSize: 36px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.15'
|
||||
letterSpacing: -0.01em
|
||||
display-sm:
|
||||
fontFamily: 'Instrument Serif'
|
||||
fontSize: 24px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.2'
|
||||
rounded:
|
||||
# Tighter than shadcn defaults — Drift reads sharper.
|
||||
sm: 4px
|
||||
md: 6px
|
||||
lg: 8px
|
||||
spacing:
|
||||
# shadcn / Tailwind defaults inherited; no overrides.
|
||||
components:
|
||||
button-primary:
|
||||
background: '{colors.primary}'
|
||||
foreground: '{colors.primary-foreground}'
|
||||
radius: '{rounded.md}'
|
||||
focus-card:
|
||||
background: '{colors.accent}'
|
||||
foreground: '{colors.accent-foreground}'
|
||||
radius: '{rounded.md}'
|
||||
border: 'none'
|
||||
command-palette-result-active:
|
||||
background: '{colors.accent}'
|
||||
foreground: '{colors.accent-foreground}'
|
||||
---
|
||||
|
||||
## Brand & Style
|
||||
|
||||
Drift is a focused task tracker for solo founders and small async teams. The product premise is that *work is a moving thing* — momentum matters more than perfectly groomed backlogs, and the right tool surfaces what you're working on *now* without making you administer a system to find it. The brand expression follows: a serif display moment in an otherwise sober sans-serif surface, a single warm accent that means *this is what's live*, and visual restraint everywhere else.
|
||||
|
||||
Drift inherits shadcn/ui defaults wholesale. This DESIGN.md specifies only the brand-layer deltas — primary color, accent color, display typography, slightly tighter corners, and a handful of brand-specific components. The 80% of components that ship from shadcn (Button, Card, Dialog, Sheet, Command, Popover, Toast) inherit shadcn's visual specs as-is. Customizing those is *explicitly* against the brand discipline — shadcn's defaults are the contract.
|
||||
|
||||
## Colors
|
||||
|
||||
The Drift palette is two colors of brand-layer plus shadcn defaults for everything else.
|
||||
|
||||
- **Primary Navy (`#0F4C81` light / `#5C8AC2` dark)** is the brand color. Used on primary buttons, active nav items, link underlines, and the "current week" indicator. Replaces shadcn's default `primary`.
|
||||
- **Focus Amber (`#F59E0B` light / `#FBC470` dark)** is the accent. Used exclusively to indicate the task or project currently in focus — the one you're working on *right now*. Never used for chrome, never used decoratively, never used for state badges. Amber means "live."
|
||||
- **All other tokens** (`background`, `foreground`, `muted`, `muted-foreground`, `border`, `input`, `ring`, `card`, `popover`, `destructive`) inherit from shadcn defaults. If the brand can't justify overriding a token, it doesn't override it.
|
||||
|
||||
Avoid: chromatic flourishes, gradient surfaces, custom destructive colors (use shadcn's), more than two brand colors. The discipline is two-colors-and-stop.
|
||||
|
||||
## Typography
|
||||
|
||||
Body / label / caption inherit shadcn's Geist Sans ramp. Only the `display` role is brand-overridden, set in **Instrument Serif** at 36px (24px small variant). The serif moment appears in:
|
||||
|
||||
- Empty-state hero text on Today and project surfaces
|
||||
- Project titles in the project detail header
|
||||
- The "Welcome back, {name}" greeting at first session of the day
|
||||
|
||||
Everything else stays in Geist Sans. The serif is a punctuation mark, not a default voice.
|
||||
|
||||
## Layout & Spacing
|
||||
|
||||
shadcn / Tailwind spacing scale inherited as-is (the 4-based scale: 4, 8, 12, 16, 20, 24, 32, 40, 48, 64). Maximum content width: `max-w-3xl` (768px) — Drift is not a wide-table product, and forcing one-column reading keeps the surface focused.
|
||||
|
||||
Single-column layout. Sidebar nav on `lg` (1024px+); on smaller viewports, the sidebar becomes a sheet triggered from the top bar.
|
||||
|
||||
## Elevation & Depth
|
||||
|
||||
Inherited from shadcn — subtle shadow on hover/active states, no elevation as a visual hierarchy device. Drift adds nothing on top of this; brand discipline is "shadcn's shadows are correct."
|
||||
|
||||
## Shapes
|
||||
|
||||
Tighter than shadcn defaults: `rounded/sm` (4px) for inputs, `rounded/md` (6px) for cards and buttons, `rounded/lg` (8px) for dialogs and the command palette. The crispness reads "tool" rather than "consumer app." Pill shapes (`rounded/full`) appear only on status badges.
|
||||
|
||||
## Components
|
||||
|
||||
Drift uses the following shadcn components as-is, unchanged: `Button`, `Card`, `Dialog`, `Sheet`, `Popover`, `DropdownMenu`, `Toast`, `Tabs`, `Avatar`, `Separator`. The contract: don't customize these.
|
||||
|
||||
Brand-layer-overridden components:
|
||||
|
||||
- **Button (primary variant)** — `{colors.primary}` fill, `{colors.primary-foreground}` text, `{rounded.md}` corner. Other variants (secondary, outline, ghost, destructive) inherit shadcn defaults.
|
||||
- **Focus card** — Custom Drift component. The "this is what you're working on now" card on Today and project detail. `{colors.accent}` fill, no border, slightly elevated. Appears at most once per surface.
|
||||
- **Command palette result (active)** — Override on shadcn's `Command` component: the highlighted/keyboard-selected result row uses `{colors.accent}` instead of shadcn's default `accent` token. Reinforces "this is what will fire if you hit Enter."
|
||||
|
||||
## Do's and Don'ts
|
||||
|
||||
| Do | Don't |
|
||||
|---|---|
|
||||
| Inherit shadcn defaults for everything not in the brand layer | Override shadcn's color tokens beyond `primary` and `accent` |
|
||||
| Use `{colors.accent}` only for "live / now / in-focus" | Use accent for state, chrome, or hover affordances |
|
||||
| `display` typography sparingly — empty states, hero greetings | Set body text in `display` to "make it pretty" |
|
||||
| Tighter corners than shadcn (4 / 6 / 8) | Use shadcn's default 6/8/12 (Drift reads sharper) |
|
||||
| Single-column layouts inside `max-w-3xl` | Wide multi-column tables (Drift is not a spreadsheet) |
|
||||
19
.agent/skills/bmad-ux/assets/excalidraw-wireframe.md
Normal file
19
.agent/skills/bmad-ux/assets/excalidraw-wireframe.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Excalidraw Wireframe Renderer
|
||||
|
||||
Subagent prompt. Produce one `.excalidraw` file at `.working/ia-{date}.excalidraw` (IA diagram) or `.working/flow-{name}-{date}.excalidraw` (flow wireframe).
|
||||
|
||||
## CRITICAL: two-character `index` fields only
|
||||
|
||||
Every element's `index` field must be **exactly two characters** (`a0`, `aZ`, `b3`, ...). Three-character indices cause a silent *"Error: invalid file"* with no diagnostic output. Assign sequentially across all elements; advance the leading letter when the trailing alphanumeric exhausts (`a0..a9, aA..aZ`, then `b0..`). Verify before writing.
|
||||
|
||||
## Shape
|
||||
|
||||
Valid Excalidraw file: `{type: "excalidraw", version: 2, source: "https://excalidraw.com", elements: [...], appState: {gridSize: null, viewBackgroundColor: "#ffffff"}, files: {}}`. Each element needs the standard Excalidraw element fields (`id, type, x, y, width, height, angle, strokeColor, backgroundColor, fillStyle, strokeWidth, strokeStyle, roughness, opacity, groupIds, frameId, roundness, seed, version, versionNonce, isDeleted, boundElements, updated, link, locked, index`). Text elements add `text, fontSize, fontFamily, textAlign, verticalAlign, baseline, containerId, originalText, lineHeight`.
|
||||
|
||||
## Content
|
||||
|
||||
**IA diagram:** boxes-and-arrows of auth stack, main app surfaces, modal routes, settings stack, cross-cutting affordances. Color sparingly to distinguish category. Layout for human legibility, not graph correctness.
|
||||
|
||||
**Flow wireframe:** screen-by-screen rectangles left-to-right, simple shapes inside (nav bar, CTA, content blocks) at low fidelity. Arrows labeled with the user action that causes transition. Annotations alongside for climax and edge-case beats.
|
||||
|
||||
Return to the parent: file path, kind, one-line subject, element count, confirmation that all indices are two-character. Do not dump JSON into parent context. Tell the user to open in Excalidraw desktop or excalidraw.com.
|
||||
112
.agent/skills/bmad-ux/assets/experience-example-mobile.md
Normal file
112
.agent/skills/bmad-ux/assets/experience-example-mobile.md
Normal file
@@ -0,0 +1,112 @@
|
||||
---
|
||||
name: Quill
|
||||
status: final
|
||||
sources:
|
||||
- {planning_artifacts}/prds/quill-2025-08-15/prd.md
|
||||
updated: 2025-09-02
|
||||
---
|
||||
|
||||
# Quill — Experience Spine
|
||||
|
||||
> Illustrative example. Single-surface mobile (iOS + Android parity). Consumer posture, calm by default. Paired with `design-example-mobile.md` (Quill DESIGN.md). Demonstrates: microcopy as gating discipline, Inspiration & Anti-patterns earning its place, Responsive & Platform omitted (single-surface).
|
||||
|
||||
## Foundation
|
||||
|
||||
Single-surface mobile, iOS + Android with parity. No UI system named — inherits platform conventions for navigation, system gestures, dynamic type. `DESIGN.md` is the visual identity reference; this spine is the experience. Dark mode is the default surface; light is a setting.
|
||||
|
||||
## Information Architecture
|
||||
|
||||
| Surface | Reached from | Purpose |
|
||||
|---|---|---|
|
||||
| Today | App open (cold) | Today's prompt + entry composer |
|
||||
| Library | Tab bar | Past entries, searchable |
|
||||
| Entry detail | Library row tap | Read / edit one entry |
|
||||
| Settings | Today header gear | Account, export, theme |
|
||||
|
||||
Bottom tab bar (Today / Library / Settings). No drawer. Modal stacks one level deep, never two.
|
||||
|
||||
→ Composition reference: `mockups/today-cold.html`, `mockups/composer.html`. Spine wins on conflict.
|
||||
|
||||
## Voice and Tone
|
||||
|
||||
Microcopy. Brand voice and aesthetic posture live in `DESIGN.md`.
|
||||
|
||||
| Do | Don't |
|
||||
|---|---|
|
||||
| "Today's prompt." | "Time to write!" |
|
||||
| "Saved." | "✓ Auto-saved successfully" |
|
||||
| "We couldn't reach the cloud — your work is on this device." | "Network error" |
|
||||
| Short, complete sentences. | Streak counters, encouragement, exclamation marks. |
|
||||
|
||||
## Component Patterns
|
||||
|
||||
Behavioral. Visual specs live in `DESIGN.md.Components`.
|
||||
|
||||
| Component | Use | Behavioral rules |
|
||||
|---|---|---|
|
||||
| Prompt card | Today | One per day. Tap opens composer. |
|
||||
| Composer | Today + entry detail | No formatting toolbar in v1. Autosave on pause ≥ 600ms. |
|
||||
| Entry row | Library list | Tap → entry detail. Long-press reserved for system text selection. |
|
||||
| Save indicator | Composer header | Cycles `Editing…` → `Saved.` (≥ 800ms visible). |
|
||||
| Settings row | Settings list | Tap → detail or toggle. |
|
||||
|
||||
## State Patterns
|
||||
|
||||
| State | Surface | Treatment |
|
||||
|---|---|---|
|
||||
| Cold open | Today | Show today's prompt (cached). If no cache, `Today's prompt is loading.` with skeleton. |
|
||||
| Empty library | Library | `No entries yet — Today's prompt is your first.` Link to Today. |
|
||||
| Search empty | Library search | `No matches.` No suggestions. |
|
||||
| Offline write | Composer | Save locally. No banner. Sync on next foreground. |
|
||||
| Sync error | Settings → Account | Surfaced here only. Never block writing. |
|
||||
| Focus | Composer | Native cursor + keyboard. No custom focus chrome. |
|
||||
|
||||
## Interaction Primitives
|
||||
|
||||
- Tap to act. Long-press reserved for system text selection.
|
||||
- Swipe-to-delete on entry rows (native pattern, confirm sheet).
|
||||
- Pull-to-refresh on Library only.
|
||||
- **Banned:** carousels, hero animations on open, badge counts, streaks, push-notification re-engagement.
|
||||
|
||||
## Accessibility Floor
|
||||
|
||||
Behavioral. Visual contrast lives in `DESIGN.md`.
|
||||
|
||||
- VoiceOver / TalkBack: every interactive element labeled with role + state. Save indicator announces `Saved` on transition.
|
||||
- Dynamic type honored through `DESIGN.md` typography tokens. UI must remain legible at largest setting — no truncated controls.
|
||||
- Reduce Motion: skip the save-indicator fade; show `Saved.` immediately.
|
||||
- Tap targets ≥ 44pt (iOS) / 48dp (Android).
|
||||
- Focus traversal follows reading order on every surface.
|
||||
|
||||
## Inspiration & Anti-patterns
|
||||
|
||||
- **Lifted from Day One:** the single daily entry framing — one prompt, one composer, no inbox.
|
||||
- **Lifted from iA Writer:** the no-toolbar composer; formatting is a settings-level decision, not a per-entry one.
|
||||
- **Rejected — Streaks (Duolingo, most habit apps):** streaks weaponize the user's calendar. Quill's value is showing up *today*, not punishing missed days.
|
||||
- **Rejected — AI prompt suggestions inside the composer:** the composer is for writing, not negotiating with a model. AI lives only in the daily prompt generation.
|
||||
|
||||
## Key Flows
|
||||
|
||||
### Flow 1 — Daily write (Mira, late evening, after work)
|
||||
|
||||
1. Mira opens app.
|
||||
2. Today surface shows today's prompt (cached if offline).
|
||||
3. She taps the composer entry point.
|
||||
4. Composer opens, keyboard active.
|
||||
5. She writes; autosave fires on pause.
|
||||
6. She taps Back.
|
||||
7. **Climax:** Today surface shows `Saved.` and the entry's first line below the prompt — proof the day is captured.
|
||||
|
||||
Failure: cold prompt fetch fails → composer still opens with cached generic prompt; banner on Today only after Mira returns.
|
||||
|
||||
### Flow 2 — Recall past entry (Mira, three weeks later, looking for what she wrote about her mother)
|
||||
|
||||
1. Mira taps Library.
|
||||
2. Scrolls or searches.
|
||||
3. Taps entry row.
|
||||
4. Entry detail opens in read mode.
|
||||
5. She taps anywhere to enter edit mode (cursor at tap point).
|
||||
6. Edits autosave.
|
||||
7. **Climax:** `Saved.` visible in entry header — the older self and the present self are in continuous conversation.
|
||||
|
||||
Empty state: no entries → message routes back to Today.
|
||||
133
.agent/skills/bmad-ux/assets/experience-example-shadcn.md
Normal file
133
.agent/skills/bmad-ux/assets/experience-example-shadcn.md
Normal file
@@ -0,0 +1,133 @@
|
||||
---
|
||||
name: Drift
|
||||
status: final
|
||||
sources:
|
||||
- {planning_artifacts}/prds/drift-2026-03-12/prd.md
|
||||
updated: 2026-04-02
|
||||
---
|
||||
|
||||
# Drift — Experience Spine
|
||||
|
||||
> Illustrative example. Single-surface responsive web. shadcn/ui on Next.js + Tailwind. Paired with `design-example-shadcn.md` (Drift DESIGN.md). Demonstrates: component-library inheritance, keyboard-first interaction primitives, the "shadcn + brand-layer" pattern that covers most modern web SaaS.
|
||||
|
||||
## Foundation
|
||||
|
||||
Single-surface responsive web. shadcn/ui on Next.js 15+ with Tailwind CSS. The component library does most of the work; brand discipline is "respect the defaults except where the brand layer overrides them." `DESIGN.md` is the visual identity reference and names the override surface; this spine is the experience. Single-tenant per project; users can belong to multiple projects but each project is a self-contained workspace.
|
||||
|
||||
## Information Architecture
|
||||
|
||||
| Surface | Reached from | Purpose |
|
||||
|---|---|---|
|
||||
| Today | App open / `g t` | Current focus, in-progress tasks pulled from all projects |
|
||||
| Projects | Sidebar / `g p` | List of active and archived projects |
|
||||
| Project detail | Projects row / `g 1`–`g 9` | Tasks in this project, organized by lane |
|
||||
| Search | `⌘K` / `Ctrl+K` | Command palette — surface, navigate, act |
|
||||
| Settings | Avatar menu | Account, theme, keyboard shortcuts, billing |
|
||||
|
||||
Sidebar collapses to icons on `md`; becomes a `Sheet` on `sm`. Modal stacks one level deep (e.g., open `Dialog` on top of a surface, never on top of another dialog).
|
||||
|
||||
→ Composition reference: `mockups/today.html`, `mockups/project-detail.html`, `mockups/command-palette.html`. Spine wins on conflict.
|
||||
|
||||
## Voice and Tone
|
||||
|
||||
Microcopy. Brand voice and aesthetic posture live in `DESIGN.md`.
|
||||
|
||||
| Do | Don't |
|
||||
|---|---|
|
||||
| "What are you working on?" | "Let's get productive! 🚀" |
|
||||
| "3 tasks in motion" | "You have 3 active items." |
|
||||
| "Closed. Nice work." | "Task completed successfully ✓" |
|
||||
| "Nothing in motion. Pick something." | "No active tasks. Click below to get started!" |
|
||||
| Manager-facing: counts and verbs. Employee-facing: same. | Different tone per audience — Drift talks to everyone the same way. |
|
||||
|
||||
## Component Patterns
|
||||
|
||||
Behavioral. Visual specs live in `DESIGN.md.Components` (or in shadcn defaults, when inherited).
|
||||
|
||||
| Component | Use | Behavioral rules |
|
||||
|---|---|---|
|
||||
| Task row | Projects, Today | Click anywhere on row opens edit dialog. Checkbox toggles done state with optimistic update. Hover reveals quick-actions (`focus`, `defer`, `archive`). |
|
||||
| Focus card | Today, Project detail | At most one focus card per surface — the task or project marked with `focus` state. `f` keyboard shortcut sets focus on the active row. |
|
||||
| Command palette | Global (⌘K) | Fuzzy search across all projects, tasks, and commands. `Enter` fires the highlighted result. `→` previews a result. Escape closes. |
|
||||
| Project header | Project detail | Inline-editable title (click to edit, blur to save). Status pill: active / archived / done. |
|
||||
| Empty state | Anywhere | shadcn's empty pattern + one Drift-specific sentence. `display-sm` for the headline, body text below, single primary action. |
|
||||
|
||||
## State Patterns
|
||||
|
||||
| State | Surface | Treatment |
|
||||
|---|---|---|
|
||||
| Cold app load | Today | shadcn `Skeleton` rows (4-6) match expected layout. Resolves on data. |
|
||||
| No focus | Today | `display-sm`: "Nothing in motion. Pick something." Below: list of in-progress tasks from all projects. |
|
||||
| Empty project | Project detail | `display-sm`: "{Project title} is empty." Body: "Add a first task to get going." Single primary button. |
|
||||
| Command palette no matches | ⌘K | "No matches. Start typing a task or project name, or pick an action below." Followed by 4-5 common commands. |
|
||||
| Offline | Global (status bar) | shadcn `Toast` once: "You're offline. Changes will sync when you reconnect." Local writes continue. |
|
||||
| Permission denied | Projects (others' private) | Surface hidden from sidebar. No "blocked" screen. |
|
||||
| Stale data | Project detail | If background refresh detects changes, shadcn `Toast`: "Updated by {user_name}. Refresh." Manual refresh, no auto. |
|
||||
|
||||
## Interaction Primitives
|
||||
|
||||
**Keyboard-first.** Drift's primary audience is developers and power users; the keyboard surface is the product, the mouse is fallback.
|
||||
|
||||
- `⌘K` / `Ctrl+K` — Command palette (universal)
|
||||
- `g t` / `g p` — Go to Today / Projects (vim-style)
|
||||
- `g 1`–`g 9` — Go to project by sidebar position
|
||||
- `f` — Set focus on highlighted task/project
|
||||
- `c` — Create new task (context-aware: in the active project)
|
||||
- `Esc` — Close dialogs, exit edit mode, clear command palette
|
||||
- `/` — Focus search in current surface
|
||||
|
||||
**Mouse:** click to act, drag deferred to v2. Hover reveals row actions on `md+` (touch users tap to reveal).
|
||||
|
||||
**Banned everywhere:** infinite scroll (pagination only), drag-to-reorder in v1, hover-only affordances on `sm` viewports, modal stacks > 1 level deep.
|
||||
|
||||
## Accessibility Floor
|
||||
|
||||
Behavioral. Visual contrast lives in `DESIGN.md` (inherits shadcn's WCAG AA-compliant defaults; brand overrides verified to maintain ratios).
|
||||
|
||||
- WCAG 2.2 AA across the responsive web surface.
|
||||
- Screen reader announces page surface on navigation: "Today, focus surface" / "Project: {name}, task list, {N} tasks."
|
||||
- Keyboard shortcuts available without modifier on most surfaces (vim-style `g t` etc.) — users with motor-control limitations get the same surface as power users.
|
||||
- `Tab` order matches reading order on every surface. `Esc` always closes the topmost modal/popover.
|
||||
- Command palette is fully keyboard-operable; results announce as they update via `aria-live`.
|
||||
- Focus rings inherit shadcn's `ring` token — visible at AA contrast against `background`.
|
||||
|
||||
## Responsive & Platform
|
||||
|
||||
| Breakpoint | Behavior |
|
||||
|---|---|
|
||||
| `≥ lg` (1024px+) | Sidebar visible. Today is a 2-column layout: focus + in-motion list. |
|
||||
| `md` (768–1023px) | Sidebar collapses to icons. Today stacks to single column. |
|
||||
| `< md` (`sm`) | Sidebar becomes a `Sheet` triggered from top bar. Command palette opens fullscreen. |
|
||||
|
||||
Drift is responsive web, not a native mobile app. The product works on phones for read + simple-edit, but the primary surface is desktop / laptop.
|
||||
|
||||
## Inspiration & Anti-patterns
|
||||
|
||||
- **Lifted from Linear:** the keyboard-first discipline. `⌘K` is the command center; vim-style nav (`g t`); no drag for primary navigation; status pill vocabulary.
|
||||
- **Lifted from Notion:** inline-editable titles. Click-to-edit on project header, blur to save. No edit/view mode toggle.
|
||||
- **Lifted from shadcn:** the entire surface vocabulary. Drift's brand is *what we add to shadcn*, not a from-scratch design system. This is a deliberate posture, not a shortcut.
|
||||
- **Rejected — Streaks, badges, achievement notifications:** Drift is a tool, not a habit app. Task closure is its own reward; no celebratory animation, no "🎉 5-day streak!" toast.
|
||||
- **Rejected — AI-suggested next tasks:** Drift surfaces what's in motion, doesn't tell the user what to work on. The user picks focus; the tool surfaces consequences.
|
||||
- **Rejected — Multi-column kanban as default project view:** lists are linear; kanban hides progress behind columns. Optional v2; not the default.
|
||||
|
||||
## Key Flows
|
||||
|
||||
### Flow 1 — Morning focus (Sarah, solo founder, 8:45am Tuesday)
|
||||
|
||||
1. Sarah opens Drift in a browser tab.
|
||||
2. App loads Today. `display-sm`: "Welcome back, Sarah." Focus card shows yesterday's marked task — "Finish landing page hero copy" — still in motion.
|
||||
3. She hits `⌘K`, types "ship hero", sees the matching task and presses Enter to open it.
|
||||
4. Inline edit: she updates the task description with two new bullets. Tab + Tab triggers save.
|
||||
5. **Climax:** Sarah closes the dialog. Today re-renders: focus card still shows the hero task, but now with the updated body text visible at a glance. She doesn't have to navigate anywhere — the surface that greeted her now reflects the work she just did. She picks up her coffee and starts writing.
|
||||
|
||||
Failure: data save fails → shadcn `Toast` (destructive variant): "Couldn't save. Trying again." Inline edit retained; another `Enter` retries.
|
||||
|
||||
### Flow 2 — Async handoff (Devon and Mara, small remote team, mid-afternoon)
|
||||
|
||||
1. Devon finishes wiring up the auth flow and marks the task `done`.
|
||||
2. Mara, time-zoned three hours ahead and online during overlap, opens Drift.
|
||||
3. Today loads; her focus is on her own front-end work, but the in-motion list shows Devon's auth task now marked done and one task below it newly assigned to her — "Wire up post-auth redirect" — that Devon set during checkout.
|
||||
4. She hits `f` on the row to mark it as her focus, then `Enter` to open it.
|
||||
5. **Climax:** The focus card swaps. Her surface now shows the post-auth redirect task as the live thing she's working on; the projects sidebar shows the Auth project highlighted; the command palette `⌘K` defaults its first result to "Go to Auth project." The state of the team's progress is *embedded in her surface* — no Slack thread to scroll, no status doc to read.
|
||||
|
||||
Failure: Devon hadn't actually assigned the follow-up — Mara mis-assigned to herself. She hits `Esc`, `f` again to unfocus, and reassigns to Devon. No "are you sure" dialog; Drift trusts the user.
|
||||
84
.agent/skills/bmad-ux/assets/headless-schemas.md
Normal file
84
.agent/skills/bmad-ux/assets/headless-schemas.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Headless Mode JSON Schemas
|
||||
|
||||
Every headless run ends with one of these payloads. Omit keys for artifacts not produced.
|
||||
|
||||
## Common fields
|
||||
|
||||
- `status` — `"complete"`, `"blocked"`, or `"partial"`
|
||||
- `intent` — `"create"`, `"update"`, or `"validate"` (matches the detected intent)
|
||||
- `reason` — required when `status` is `"blocked"`; one-sentence explanation
|
||||
- `assumptions` — array of inferred values that were not directly confirmed by inputs
|
||||
- `open_questions` — array of items that need a human decision before the artifact can be considered final
|
||||
|
||||
## Create
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "complete",
|
||||
"intent": "create",
|
||||
"design": "{doc_workspace}/DESIGN.md",
|
||||
"experience": "{doc_workspace}/EXPERIENCE.md",
|
||||
"memlog": "{doc_workspace}/.memlog.md",
|
||||
"working_artifacts": ["{doc_workspace}/.working/color-themes-1.html"],
|
||||
"promoted_artifacts": {
|
||||
"mockups": ["{doc_workspace}/mockups/direction-calm-sage.html"],
|
||||
"wireframes": ["{doc_workspace}/wireframes/ia-2026-05-19.excalidraw"]
|
||||
},
|
||||
"open_questions": [],
|
||||
"assumptions": [],
|
||||
"external_handoffs": [
|
||||
{"directive": "Confluence upload", "tool": "corp:confluence_upload", "url": "https://confluence.corp/DESIGN/123", "status": "ok"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The `working_artifacts` and `promoted_artifacts` keys are optional and omitted entirely when empty. Headless Create runs default to not enabling creative tools — both keys are typically absent in headless output unless the caller enabled them.
|
||||
|
||||
## Update
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "complete",
|
||||
"intent": "update",
|
||||
"design": "{doc_workspace}/DESIGN.md",
|
||||
"experience": "{doc_workspace}/EXPERIENCE.md",
|
||||
"memlog": "{doc_workspace}/.memlog.md",
|
||||
"changes_summary": "1-3 sentences describing what changed and why",
|
||||
"conflicts_with_prior_decisions": [],
|
||||
"open_questions": [],
|
||||
"external_handoffs": [
|
||||
{"directive": "Confluence upload", "tool": "corp:confluence_upload", "url": "https://confluence.corp/DESIGN/123", "status": "ok"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Validate
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "complete",
|
||||
"intent": "validate",
|
||||
"validation_report": "{doc_workspace}/validation-report.md",
|
||||
"findings_summary": {
|
||||
"critical": 0,
|
||||
"high": 0,
|
||||
"medium": 0,
|
||||
"low": 0
|
||||
},
|
||||
"offer_to_update": true
|
||||
}
|
||||
```
|
||||
|
||||
`validation_report` is always written for Validate intent — the path here is required, not optional.
|
||||
|
||||
## Blocked
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "blocked",
|
||||
"intent": "update",
|
||||
"reason": "Change signal ambiguous — could be a brand refresh or an accessibility audit response; no inferred direction"
|
||||
}
|
||||
```
|
||||
|
||||
Always include the intent (best-guess if not certain) and a one-sentence `reason`.
|
||||
29
.agent/skills/bmad-ux/assets/key-screens.md
Normal file
29
.agent/skills/bmad-ux/assets/key-screens.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Key Screens Renderer
|
||||
|
||||
Subagent prompt. Fired at Finalize (or during late Discovery once layout decisions firm up). Produces 1:1 HTML mocks of the load-bearing surfaces so the spine can link to them as visual reference. Spine remains the contract; mocks illustrate.
|
||||
|
||||
## Inputs
|
||||
|
||||
`.memlog.md`, the current drafts `DESIGN.md` and `EXPERIENCE.md`, `.working/` (especially the chosen color-theme and direction mocks), source PRD. The user names which surfaces to render — typically 2-4: the canonical entry surface, the most complex flow's hero screen, any load-bearing overlay/modal, and (when present) the Week / list / dashboard view.
|
||||
|
||||
## What to render
|
||||
|
||||
One HTML file per screen, at `.working/key-{slug}.html`. Each file: realistic device frame (phone or browser), real product content from the conversation (no lorem), every visible string voice-checked against `.memlog.md`, all decided tokens applied. Show one canonical state per screen; if a surface has a load-bearing alternate state (focus, error, crisis-card-present), render it as a second column or section in the same file.
|
||||
|
||||
Inline CSS, system fonts, no JS, no network. The mock must render fully offline. Comment block at the top of the `<style>` notes which spine sections govern this screen so a future reader knows what to check.
|
||||
|
||||
## What to return
|
||||
|
||||
A compact summary to the parent:
|
||||
- file path per screen
|
||||
- one-line caption per screen ("Today picker at rest; accent on Thought record")
|
||||
- which spine sections each mock illustrates (Component Patterns rows, State Patterns rows, Flow steps)
|
||||
|
||||
The parent, at Finalize "Promote working artifacts," uses this summary to insert inline `mockups/...` links into the relevant spine sections.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Do not invent layout — every composition decision must trace to a `.working/` artifact or a confirmation in `.memlog.md`. If a layout question is open, the mock is premature.
|
||||
- Do not show every screen of every flow — 2-4 load-bearing surfaces, not 14.
|
||||
- Do not stage marketing copy. Strings come from `.memlog.md` and voice rules.
|
||||
- Do not introduce a new pattern not in the spine's Component Patterns table. If you need one, log it and ask before rendering.
|
||||
319
.agent/skills/bmad-ux/assets/validation-report-template.html
Normal file
319
.agent/skills/bmad-ux/assets/validation-report-template.html
Normal file
@@ -0,0 +1,319 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
UX Design Validation Report — skeleton template.
|
||||
|
||||
This file is a starter the synthesis pass fills in directly. There is no
|
||||
substitution engine. The LLM:
|
||||
1. Reads {doc_workspace}/review-rubric.md and every review-{slug}.md from
|
||||
additional reviewers.
|
||||
2. Copies this skeleton.
|
||||
3. Replaces the placeholder content (everything between TEMPLATE markers)
|
||||
with the consolidated review, preserving the structure and CSS.
|
||||
4. Writes the result to {doc_workspace}/validation-report.html.
|
||||
5. Writes a markdown twin to {doc_workspace}/validation-report.md.
|
||||
|
||||
Visual rules the LLM must preserve:
|
||||
- The container width, the color tokens, the typography.
|
||||
- One dimension = one collapsible <section class="dimension">.
|
||||
- Verdict pill uses the verdict-* class matching its judgment.
|
||||
- Severity badge uses the badge-sev-* class matching its level.
|
||||
- Each extra reviewer (accessibility, adversarial, etc.) gets its own
|
||||
collapsible section below the rubric dimensions.
|
||||
- The footer always shows the artifact paths and timestamp.
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>UX Design Validation: TEMPLATE_UX_SPEC_NAME</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #fafaf9;
|
||||
--surface: #ffffff;
|
||||
--border: #e7e5e4;
|
||||
--text: #1c1917;
|
||||
--muted: #78716c;
|
||||
|
||||
--verdict-strong: #16a34a;
|
||||
--verdict-adequate: #65a30d;
|
||||
--verdict-thin: #d97706;
|
||||
--verdict-broken: #dc2626;
|
||||
|
||||
--sev-low: #64748b;
|
||||
--sev-medium: #ca8a04;
|
||||
--sev-high: #ea580c;
|
||||
--sev-critical: #dc2626;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html, body { margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.6;
|
||||
font-size: 15px;
|
||||
}
|
||||
.container { max-width: 960px; margin: 0 auto; padding: 32px 24px 64px; }
|
||||
|
||||
header.report-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.title h1 { margin: 0; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
||||
.title .subtitle { color: var(--muted); font-size: 13px; margin-top: 4px; font-family: ui-monospace, "SF Mono", Menlo, monospace; }
|
||||
|
||||
.synthesis {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--muted);
|
||||
border-radius: 8px;
|
||||
padding: 18px 22px;
|
||||
margin-bottom: 24px;
|
||||
font-size: 15.5px;
|
||||
}
|
||||
.synthesis p { margin: 0 0 10px; }
|
||||
.synthesis p:last-child { margin-bottom: 0; }
|
||||
|
||||
.dimension-summary {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 10px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.dim-card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 12px 14px;
|
||||
}
|
||||
.dim-card .dim-name { font-size: 13px; color: var(--muted); margin-bottom: 6px; }
|
||||
.dim-card .dim-verdict { font-size: 14px; font-weight: 600; }
|
||||
|
||||
section.dimension, section.reviewer-section { margin-bottom: 14px; }
|
||||
section.dimension details, section.reviewer-section details {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
section summary {
|
||||
padding: 14px 20px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
section summary::-webkit-details-marker { display: none; }
|
||||
section summary::before {
|
||||
content: "▸";
|
||||
display: inline-block;
|
||||
color: var(--muted);
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
section details[open] summary::before { transform: rotate(90deg); }
|
||||
section summary h2 {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.005em;
|
||||
flex: 1;
|
||||
}
|
||||
.verdict-pill {
|
||||
font-size: 11px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 999px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: white;
|
||||
}
|
||||
.verdict-strong { background: var(--verdict-strong); }
|
||||
.verdict-adequate { background: var(--verdict-adequate); }
|
||||
.verdict-thin { background: var(--verdict-thin); }
|
||||
.verdict-broken { background: var(--verdict-broken); }
|
||||
|
||||
.dim-body { padding: 4px 20px 18px; }
|
||||
.dim-judgment { color: var(--text); font-size: 14.5px; }
|
||||
.dim-judgment p { margin: 0 0 10px; }
|
||||
|
||||
.findings-list { padding: 0 20px 4px; }
|
||||
article.finding {
|
||||
padding: 14px 0;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
article.finding:first-child { border-top: none; }
|
||||
article.finding header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.badge {
|
||||
font-size: 10.5px;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.badge-sev-low { background: rgba(100, 116, 139, 0.12); color: var(--sev-low); }
|
||||
.badge-sev-medium { background: rgba(202, 138, 4, 0.14); color: var(--sev-medium); }
|
||||
.badge-sev-high { background: rgba(234, 88, 12, 0.14); color: var(--sev-high); }
|
||||
.badge-sev-critical { background: rgba(220, 38, 38, 0.14); color: var(--sev-critical); }
|
||||
.finding-title { margin: 0; font-size: 15px; font-weight: 500; flex: 1; min-width: 200px; }
|
||||
.finding-location { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12.5px; color: var(--muted); }
|
||||
.finding-note, .finding-fix { margin-top: 6px; font-size: 14px; }
|
||||
.finding-fix strong { color: var(--muted); font-weight: 500; }
|
||||
|
||||
.reviewer-source {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
||||
}
|
||||
|
||||
.mechanical {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 16px 20px;
|
||||
margin-top: 24px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.mechanical h3 { margin: 0 0 10px; font-size: 14px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
|
||||
.mechanical ul { margin: 0; padding-left: 20px; }
|
||||
.mechanical li { margin-bottom: 4px; color: var(--text); }
|
||||
|
||||
footer.report-footer {
|
||||
margin-top: 40px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--border);
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
||||
}
|
||||
footer .meta { display: flex; gap: 24px; flex-wrap: wrap; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<!-- TEMPLATE: header. Fill ux spec name and ux spec path. No overall grade —
|
||||
per-category verdicts and severity counts below carry the picture. -->
|
||||
<header class="report-header">
|
||||
<div class="title">
|
||||
<h1>TEMPLATE_UX_SPEC_NAME — UX Design Validation Report</h1>
|
||||
<div class="subtitle">TEMPLATE_UX_SPEC_PATH</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- TEMPLATE: overall synthesis paragraphs. Lift directly from
|
||||
review-rubric.md "Overall verdict" section; expand if extra reviewers
|
||||
(accessibility, adversarial, etc.) materially shift the picture.
|
||||
Wrap each paragraph in <p>. -->
|
||||
<div class="synthesis">
|
||||
<p>TEMPLATE_SYNTHESIS_PARAGRAPH</p>
|
||||
</div>
|
||||
|
||||
<!-- TEMPLATE: dimension summary cards. One per rubric category, in this
|
||||
canonical order (from references/validate.md):
|
||||
1. Flow coverage
|
||||
2. Token completeness
|
||||
3. Component coverage
|
||||
4. State coverage
|
||||
5. Visual reference coverage
|
||||
6. Bloat & overspecification
|
||||
7. Inheritance discipline
|
||||
8. Shape fit
|
||||
The dim-verdict text uses one of: strong | adequate | thin | broken. -->
|
||||
<div class="dimension-summary">
|
||||
<div class="dim-card">
|
||||
<div class="dim-name">TEMPLATE_CATEGORY_NAME</div>
|
||||
<div class="dim-verdict" style="color: var(--verdict-TEMPLATE_VERDICT)">TEMPLATE_VERDICT_TEXT</div>
|
||||
</div>
|
||||
<!-- repeat for each of the eight rubric categories -->
|
||||
</div>
|
||||
|
||||
<!-- TEMPLATE: one section per rubric category, same canonical order as the
|
||||
summary cards above. Skip a category entirely if the rubric review
|
||||
marked it n/a for this UX spec. Open the section by default if verdict
|
||||
is thin or broken. -->
|
||||
<section class="dimension">
|
||||
<details open>
|
||||
<summary>
|
||||
<h2>TEMPLATE_CATEGORY_NAME</h2>
|
||||
<span class="verdict-pill verdict-TEMPLATE_VERDICT">TEMPLATE_VERDICT_TEXT</span>
|
||||
</summary>
|
||||
<div class="dim-body">
|
||||
<div class="dim-judgment">
|
||||
<p>TEMPLATE_DIMENSION_JUDGMENT</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="findings-list">
|
||||
<!-- TEMPLATE: zero or more findings -->
|
||||
<article class="finding">
|
||||
<header>
|
||||
<span class="badge badge-sev-TEMPLATE_SEVERITY">TEMPLATE_SEVERITY</span>
|
||||
<h3 class="finding-title">TEMPLATE_FINDING_TITLE</h3>
|
||||
<span class="finding-location">TEMPLATE_LOCATION</span>
|
||||
</header>
|
||||
<div class="finding-note">TEMPLATE_FINDING_NOTE</div>
|
||||
<div class="finding-fix"><strong>Fix:</strong> TEMPLATE_SUGGESTED_FIX</div>
|
||||
</article>
|
||||
</div>
|
||||
</details>
|
||||
</section>
|
||||
|
||||
<!-- TEMPLATE: one section per extra reviewer that ran (accessibility,
|
||||
adversarial, brand-conformance, etc.). Skip this block entirely if
|
||||
only the rubric walker ran. -->
|
||||
<section class="reviewer-section">
|
||||
<details>
|
||||
<summary>
|
||||
<h2>Accessibility review</h2>
|
||||
<span class="reviewer-source">TEMPLATE_REVIEWER_SOURCE_FILE</span>
|
||||
</summary>
|
||||
<div class="dim-body">
|
||||
<div class="dim-judgment">
|
||||
<p>TEMPLATE_REVIEWER_PREAMBLE</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="findings-list">
|
||||
<article class="finding">
|
||||
<header>
|
||||
<span class="badge badge-sev-TEMPLATE_SEVERITY">TEMPLATE_SEVERITY</span>
|
||||
<h3 class="finding-title">TEMPLATE_FINDING_TITLE</h3>
|
||||
<span class="finding-location">TEMPLATE_LOCATION</span>
|
||||
</header>
|
||||
<div class="finding-note">TEMPLATE_FINDING_NOTE</div>
|
||||
<div class="finding-fix"><strong>Fix:</strong> TEMPLATE_SUGGESTED_FIX</div>
|
||||
</article>
|
||||
</div>
|
||||
</details>
|
||||
</section>
|
||||
|
||||
<!-- TEMPLATE: mechanical notes — short, bulleted. Skip if there are none. -->
|
||||
<div class="mechanical">
|
||||
<h3>Mechanical notes</h3>
|
||||
<ul>
|
||||
<li>TEMPLATE_MECHANICAL_NOTE</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<footer class="report-footer">
|
||||
<div class="meta">
|
||||
<span>Rubric: TEMPLATE_RUBRIC_PATH</span>
|
||||
<span>Generated: TEMPLATE_TIMESTAMP</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user