feat(composer): discovery-phase plugin from "I want an app that..." to tracker-loaded stories

Plugin pairs with Symphony — Composer's output (issues in the project's
tracker) is Symphony's input. State-aware /composer command walks the
user through 11 phases: concept, users (with workflow probing for hidden
actors), requirements/NFR/IA, design system, interaction design, flows,
mocks, architecture, stories, roadmap, load. Each phase produces a
reviewable artifact in docs/planning/ (or, for design and interaction,
a project-local skill — see below).

Architecture is intentionally LAST, after the spec is complete. Mocks
are JSX/TSX regardless of final stack and pass a "text feasibility"
audit — every visible string is categorized (static/computed/authored),
computed strings are traced to source data, and any string implying an
unspecified feature halts the commit.

Design system and interaction design are produced as PROJECT-LOCAL
SKILLS in .claude/skills/<slug>-design-system/ and
.claude/skills/<slug>-interaction-design/, not as docs in
docs/planning/. Skills auto-load via description matching whenever UI
work happens; a reference doc gets read once and drifts out of context.
The mocks skill imports tokens directly from the design-system skill
for a single source of truth across mocks and (eventually) real code.

ui-system is currently a PLACEHOLDER — captures the minimum needed for
mocks to proceed with <TBD: ...> markers as a return-pass worklist.
Full interview specification is the next pass.

Council touchpoints baked in: PM/skeptic/end-user after requirements,
end-user/a11y after mocks, full architecture council after architecture,
plus auto-additions (legal-triage on regulated data, privacy-advocate
on PII, finance-controller on money flows).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
movq
2026-04-29 21:03:40 -05:00
parent cd3032458c
commit 594fccc80a
25 changed files with 1595 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
---
name: <SLUG>-interaction-design
description: Interaction design for the <PROJECT NAME> project. State surfaces (modal vs inline vs drawer vs full-page), motion philosophy, input modes (touch/mouse/keyboard), breakpoints, i18n posture, empty/loading/error/offline state postures, time formatting, and keyboard policy. Load and apply whenever building UI behavior — modals, forms, navigation, transitions, gestures, error handling, async states, focus management. Pairs with <SLUG>-design-system.
---
# <PROJECT NAME> interaction design
> **Status: <draft | reviewed | locked>**
> Generated by Composer's `ui-system` phase. Re-running that phase
> updates this skill (with confirmation).
## How to use this skill
When building UI *behavior* — anything beyond static styling — read
this skill first. Don't invent new state-surface patterns, motion
durations, or empty-state postures. They're declared once here and
reused everywhere.
For visual tokens (color, type, spacing), see the paired
`<SLUG>-design-system` skill.
## Input modes
| Mode | Status |
|---|---|
| Touch | <TBD: primary | supported | not supported> |
| Mouse | <TBD> |
| Keyboard | <TBD> |
| Voice | <TBD: usually "not supported" in v1> |
## State surfaces
One pattern per action class. Used everywhere.
| Action class | Pattern | Notes |
|---|---|---|
| Quick edit (single field) | inline edit | <TBD> |
| Multi-field create / edit | <drawer | modal — pick one> | <TBD> |
| Confirm destructive | modal | always |
| Settings / configuration | full-page route | — |
| Top-level navigation | <sidebar | tab bar | header nav> | <TBD> |
| Detail-from-list | <full route | side panel> | <TBD> |
## Motion
- **Posture**: <minimal | restrained | expressive>
- **Default duration / easing**: see design-system tokens
- **Reduced motion**: respected via `prefers-reduced-motion` everywhere; fallbacks declared per pattern below
- **When things animate**:
- Page/route transitions: <yes/no, how>
- List item enter/exit: <yes/no, how>
- Modal/drawer open/close: <yes/no, how>
- State changes (toggle, expand): <yes/no, how>
## Breakpoints
| Breakpoint | Range | Primary? |
|---|---|---|
| Phone | < <px> | <TBD> |
| Tablet | <px> <px> | <TBD> |
| Desktop | ≥ <px> | <TBD> |
**Primary design target**: <which one — "mobile-first", "desktop-first", "fluid">
## i18n
- **Locales at launch**: <list — often just English in v1>
- **RTL support**: <yes | no | planned>
- **String length budget**: assume +30% over English for German/French translations
- **Pluralization**: <TBD: ICU MessageFormat / library / manual>
## State postures
One declared posture per state, used everywhere. No inventing on a per-screen basis.
### Empty
- **Visual**: <icon + heading + body + optional CTA>
- **Tone**: <encouraging | neutral | matter-of-fact>
- **CTA**: <when present, what kind of action>
### Loading
- **Default pattern**: <skeleton | spinner | blocking>
- **When to use which**: <criteria — "skeleton for list/card containers, spinner for inline buttons, blocking only for explicit user-initiated actions">
- **Threshold for showing loading at all**: <ms — usually 200300ms; below that, just let it pop>
### Error
- **Surface**: <inline | toast | dialog — by error class>
- **Recovery**: <retry button | clear path forward | "contact support" only as last resort>
- **Copy tone**: <plain language, name what happened, name what to do next>
### Offline
- **Behavior**: <feature subset that works | banner only | "go online to continue">
- **Sync semantics**: <when reconnected, what happens>
## Time formatting
- **Relative time** for events within: <threshold — e.g., < 7 days>
- **Absolute time** otherwise, format: <pattern — e.g., "MMM d, yyyy h:mm a">
- **Time zones**: <user-local | fixed (which?) | configurable>
- **Date-only vs date+time**: <when each is shown>
## Keyboard
- **Global shortcuts**: <list, or "none in v1">
- **Within-modal**: `Esc` closes; focus trap while open; restore focus on close
- **Tab order**: declared per-flow as needed; focus visible always (per design-system)
- **Forms**: `Enter` submits; `Esc` cancels destructive
- **Lists**: <arrow-key nav? | not in v1>
## TBD on return
- <TBD: anything the placeholder pass couldn't answer>