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,137 @@
---
name: ui-system
description: Interview the user and produce two project-local skills — a design-system skill and an interaction-design skill — that auto-load whenever UI work is in progress. Output goes to .claude/skills/<slug>-design-system/ and .claude/skills/<slug>-interaction-design/, NOT docs/planning/. The skills load themselves into context when anyone codes UI (mock or real); a plain reference doc would not. Currently a placeholder skill that captures the minimum needed for downstream phases to proceed; planned for a fuller specification pass. Use when the composer skill reaches phase 4 or 5, or when the user asks to "set up the design system" or "specify interaction patterns."
---
# UI system (placeholder)
> **Status: PLACEHOLDER.** This skill currently captures the minimum
> design-system and interaction-design content needed for the mocks
> phase to proceed. A fuller specification pass is planned. When the
> user returns to flesh this out, expand the interview sections below
> and the SKILL.md / sidecar templates.
## Why this is a skill, not a doc
A reference document at `docs/planning/design-system.md` gets read once
and then drifts out of context as the conversation grows. UI work that
happens later — generating a mock, writing a component, picking a color —
won't have it loaded.
A **skill** with a description that triggers on UI work is loaded
automatically every time the trigger matches. That's the whole point of
the skill mechanism. The design system and interaction design must be
skills.
## What this skill produces
Two project-local skills, plus their sidecar data files:
```
.claude/skills/<slug>-design-system/
├── SKILL.md ← the skill itself; auto-loads on UI work
├── tokens.ts ← machine-readable color / type / spacing / motion tokens
└── components.md ← component vocabulary with anatomy
.claude/skills/<slug>-interaction-design/
└── SKILL.md ← interaction patterns, state surfaces, input modes, i18n
```
And two stub pointer files in `docs/planning/` so the planning index
finds them:
```
docs/planning/design-system.md ← pointer; tells humans where the skill lives
docs/planning/interaction-design.md ← pointer
```
## Slug
The skills need a project slug for their `name:` frontmatter, so they
don't collide with skills from other projects on the same machine.
Resolution order:
1. If `package.json` has a `name`, slugify it.
2. Else if a git remote exists, slugify the repo name.
3. Else ask the user. Default to the directory name.
Slug rule: lowercase, hyphenated, kebab-case, ASCII only. Example:
`SourdoughTracker``sourdough-tracker` → skill `sourdough-tracker-design-system`.
## design-system interview (placeholder pass)
Ask the user, in order, with sensible defaults:
1. **Existing material?** Brand assets, mood boards, screenshots,
"make it look like Linear/Notion/Stripe", or nothing. If material
exists, ingest it before asking the rest.
2. **Color**: brand color(s), neutral scale (warm/cool/true), dark mode
(yes/no/system). Offer to generate accessible contrast pairs.
3. **Typography**: one family or two (display + body), size scale base
and ratio, line-height policy.
4. **Spacing**: scale base (4px / 8px), key spacing tokens.
5. **Radii**: tight / medium / pillowy.
6. **Shadows**: flat / subtle / generous.
7. **Visual motion**: default duration, default easing.
8. **Components**: confirm vocabulary against `ia.md`.
Mark unanswered with `<TBD: ...>` so the return pass has a worklist.
### Write phase — design-system
1. Write `.claude/skills/<slug>-design-system/SKILL.md` from
`templates/design-system/SKILL.md`. Substitute the slug into the
`name:` field and the project name into the `description:`.
2. Write `.claude/skills/<slug>-design-system/tokens.ts` from
`templates/design-system/tokens.ts`. Fill in the values gathered in
the interview; `<TBD>` for unanswered.
3. Write `.claude/skills/<slug>-design-system/components.md` from
`templates/design-system/components.md`.
4. Write `docs/planning/design-system.md` from the pointer template —
one paragraph saying where the skill lives.
## interaction-design interview (placeholder pass)
Ask, in order:
1. **Primary input**: touch / mouse / keyboard / mixed. Primary, supported, not supported.
2. **State surfaces**: pick one pattern per action class.
3. **Motion**: minimal / restrained / expressive. `prefers-reduced-motion` always honored.
4. **Breakpoints**: count, primary design target.
5. **i18n**: locales planned, RTL, string-length budget.
6. **Empty/loading/error/offline**: one declared posture each.
7. **Time formatting**: relative threshold, absolute format.
8. **Keyboard**: global shortcuts, escape behavior.
### Write phase — interaction-design
1. Write `.claude/skills/<slug>-interaction-design/SKILL.md` from
`templates/interaction-design/SKILL.md`.
2. Write `docs/planning/interaction-design.md` pointer.
## Re-entry
When the user returns to flesh this out fully:
- Expand the interviews above.
- Expand the SKILL.md and sidecar templates.
- Both skills are version-controlled in `.claude/skills/` — re-running
this phase shows the user a diff before overwriting.
The downstream contract is: `composer-mocks` reads the **skills**, not
the planning pointer files. That contract does not change as the
templates grow.
## Hard rules even in placeholder mode
- **Always produce both skills with sidecars.** Mocks can't proceed without them.
- **Always slug-namespace** so projects on the same machine don't collide.
- **Mark unknowns with `<TBD: ...>`** rather than inventing — TBDs are the return-pass worklist.
- **Don't pretend.** If the user has nothing and no opinions, say so in the SKILL.md: "No design direction set; defaults applied. Revisit before mocks are committed."
- **Tell the user what just happened.** After write, print:
```
Wrote two project skills:
.claude/skills/<slug>-design-system/SKILL.md
.claude/skills/<slug>-interaction-design/SKILL.md
These auto-load whenever UI work is happening. Verify after restart
with /agents (they should appear as project-local skills).
```