Files
claude-plugins/composer/skills/composer-mocks/SKILL.md
movq 20acf3ae9b chore(composer,symphony): align skills with skill-development spec
Validated against the plugin-dev:skill-development checklist and
applied conformance fixes:

Description style — all five skill descriptions now use the canonical
"This skill should be used when..." third-person form, with expanded
trigger-phrase coverage. Previously used imperative "Use when..." which
the spec calls out as wrong.

Writing voice — body prose changed from "You are the dispatcher / You
walk a user through..." to imperative "Act as the dispatcher / Walk
the user through...". Remaining "you" usage is confined to quoted
output text the agent prints to the user, which is correct usage.

Progressive disclosure — composer/skills/ui-system/SKILL.md was 2513
words (over the 2000-word ideal). Refactored to 1063 words by moving
detailed phase content into:

- references/design-interview.md (D1–D11 phase specifications)
- references/interaction-interview.md (I1–I11 phase specifications)
- references/inspiration-presets.md (Linear/Notion/Stripe/etc. table)

The SKILL.md now points at each reference as needed; agents load only
what's relevant for the current phase. Other four skills already
within the 1000–2000 word range, no refactor needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 22:10:14 -05:00

7.6 KiB

name, description
name description
composer-mocks Generates or revises high-fidelity JSX/TSX mocks for named user flows in a Composer project. Mocks reference the design system tokens and follow the patterns declared in the interaction-design skill. After generation, runs a text feasibility audit — every visible string is categorized (static/computed/authored) and traced to source data, so mocks don't lie about features the app can't yet generate. This skill should be used when the user runs /composer-mock, when the composer skill reaches phase 7, or when the user asks to "mock the X flow", "generate a mock for X", "draft a UI for X flow", or "wireframe the X screen".

Composer mocks

Generate high-fidelity, non-functional mocks in JSX/TSX. The final application may end up React, React Native, SwiftUI, Flutter, or a plain server-rendered template — JSX is just a fast, expressive way to encode layout, content, and component composition. The mock is a storyboard, not a build artifact.

Prerequisites (hard checks)

Before generating, verify all of:

  1. docs/planning/flows.md exists and contains the named flow.
  2. docs/planning/users.md exists.
  3. The design-system skill exists at .claude/skills/<slug>-design-system/, including its tokens.ts and components.md sidecars.
  4. The interaction-design skill exists at .claude/skills/<slug>-interaction-design/.

If any are missing, stop and tell the user which one — then point at the phase that should produce it. The skills (not docs) are the contract: they're what auto-load when UI work happens, so a missing skill means generated mocks will reference patterns that aren't in context.

The <slug> is resolved the same way the ui-system skill resolves it (package.json → git remote → directory name → ask).

Tokens are the skill's sidecar

The mock imports tokens directly from the design-system skill:

import { color, spacing, fontSize, radius, motion } from
  "../../.claude/skills/<slug>-design-system/tokens";

There is no separate mocks/tokens.ts. The design-system skill's tokens.ts IS the source of truth, and mocks import it directly. This keeps a single token file in scope whenever UI is being touched (mock or real code) — no duplication, no drift.

Generation

For a flow named <flow>:

  1. Read the flow's steps from flows.md.
  2. Read the relevant patterns from the interaction-design skill (state surface for this kind of action, motion policy, breakpoints, locale). The skill should already be in context via description match; read the SKILL.md explicitly if not.
  3. Read the relevant entities from ia.md so component names match the project's vocabulary.
  4. Read components.md from the design-system skill so any component referenced in the mock matches the declared anatomy.
  5. Draft docs/planning/mocks/<flow>.tsx as a single-file mock.
    • Use Tailwind classes referencing token values, or inline styles reading from tokens.ts — whichever the design system declares.
    • Components, not framework abstractions. No state, no effects, no fetchers — this is a still life.
    • Cover the empty/loading/error/offline states declared in interaction-design.md, even if just as commented-out variants.
  6. Run the text feasibility pass (below).
  7. Offer a council review (Marge + Maya).

Text feasibility pass

This is the headline pass. Every visible string in the generated mock is categorized:

Category Definition Mock shows…
STATIC UI label, button text, fixed copy The literal string
COMPUTED Derived from data via a transform A representative example + annotation comment
AUTHORED Free text the user types in A placeholder + clear "user-authored" marker

For every COMPUTED string, document:

  • Source: which entity / field. Must trace back to an entity declared in ia.md or a state declared in users.md.
  • Transform: what produces the string from the source.
  • Status: source exists / ⚠️ source not yet specified / implies an unstated feature.

Output the audit to the user before committing the mock to disk (if the source is incomplete) or alongside the mock (if everything traces).

Audit format

log-feeding.tsx — text feasibility audit

14 strings. STATIC: 9, COMPUTED: 4, AUTHORED: 1.

COMPUTED:

  ┌─ "Last fed 6 hours ago"
  │  Source:     starter.feedings[-1].timestamp
  │  Transform:  relative-time formatter, locale-aware
  │  Status:     ✅ source field exists in ia.md
  │  Note:       interaction-design.md should declare relative-time
  │              policy (when do we switch to absolute?)
  │
  ├─ "Activity score: 7.2"
  │  Source:     starter.activityScore
  │  Transform:  format(score, 1 decimal)
  │  Status:     ❌ activityScore not in ia.md — implies a feature
  │              we have not specified
  │  Action:     either add activityScore (with its computation) to
  │              the model and to requirements.md, or remove this
  │              element from the mock
  │
  ├─ "Will peak around 4:30 PM today"
  │  Source:     prediction.peakTime
  │  Transform:  format(peakTime, "around h:mm a")
  │  Status:     ⚠️  prediction is in requirements.md as soft —
  │              call out that "peak prediction" is a real subproject,
  │              not a label
  │
  └─ "3 active starters"
     Source:     count(starters where status='active')
     Transform:  pluralize("active starter", n)
     Status:     ✅ trivial

Halt-vs-warn

  • status in any string → halt. Do not commit the mock until the user resolves: spec the feature properly, or remove the element. Lying mocks anchor stakeholders to capabilities the team has not agreed to build.
  • ⚠️ statuswarn. Commit the mock, but add a comment in the file flagging the implication, and surface it in the post-generation report.
  • everywhere → commit cleanly.

Naming and file shape

docs/planning/mocks/<flow>.tsx. One mock per flow. State variants (empty / loading / error) live in the same file as commented sections or as additional named exports — whichever the user prefers.

Header comment of every mock:

/**
 * Mock: <flow name>
 * Source: docs/planning/flows.md § <flow>
 * Generated: <date>
 * Status: <draft | reviewed | stale>
 *
 * This is a non-functional mock. No state, no fetchers, no logic.
 * Strings are annotated for source/transform per text feasibility pass.
 */

Re-running on an existing mock

If the mock file exists:

  • Compare flows.md § mod-time to the mock file. If flow is newer, regenerate; if mock is newer, ask the user before overwriting.
  • Always re-run the text feasibility pass after changes.
  • Preserve the user's hand-edits where possible: diff before write.

Council review

After a clean text pass, offer:

Mock committed. Summon Marge (end-user) and Maya (a11y) for review? [Y/n]

The review reads the mock and interaction-design.md and produces the standard council output. Save to docs/planning/reviews/mock-<flow>-<date>.md.

Hard rules

  • No mock without a clean (or warned) text feasibility audit. A mock that implies an unspecified feature is a mock that has lied to its viewer.
  • No tokens hardcoded. Everything visual comes from the design-system skill's tokens.ts. Import directly; do not copy.
  • No state, no effects, no async. This is a still life. If the mock needs interaction to communicate, write a second mock for the next state.
  • Match the vocabulary in ia.md. Don't introduce new terms in mocks that the rest of the planning doesn't use.