@radicool/throughline 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/adapters/codex/AGENTS.md +29 -0
- package/adapters/codex/codex-mcp.toml +4 -0
- package/adapters/codex/prompts/component-builder.md +272 -0
- package/adapters/codex/prompts/component-pipeline.md +81 -0
- package/adapters/codex/prompts/design-system-audit.md +122 -0
- package/adapters/codex/prompts/design-system-status.md +41 -0
- package/adapters/codex/prompts/figma-environment-setup.md +456 -0
- package/adapters/codex/prompts/icon-system-builder.md +268 -0
- package/adapters/codex/prompts/new-component.md +13 -0
- package/adapters/codex/prompts/repository-builder.md +163 -0
- package/adapters/codex/prompts/retrofit-planner.md +136 -0
- package/adapters/codex/prompts/start.md +22 -0
- package/adapters/codex/prompts/storybook-chromatic-builder.md +261 -0
- package/adapters/codex/prompts/sync-figma-tokens.md +22 -0
- package/adapters/codex/prompts/token-builder.md +361 -0
- package/adapters/codex/prompts/token-crosswalk-builder.md +120 -0
- package/adapters/codex/prompts/token-sheet-builder.md +162 -0
- package/adapters/codex/prompts/token-sync-layer.md +232 -0
- package/adapters/cursor/.cursor/commands/design-system-status.md +41 -0
- package/adapters/cursor/.cursor/commands/new-component.md +13 -0
- package/adapters/cursor/.cursor/commands/start.md +22 -0
- package/adapters/cursor/.cursor/commands/sync-figma-tokens.md +22 -0
- package/adapters/cursor/.cursor/mcp.json +14 -0
- package/adapters/cursor/.cursor/rules/component-builder.mdc +276 -0
- package/adapters/cursor/.cursor/rules/component-pipeline.mdc +85 -0
- package/adapters/cursor/.cursor/rules/design-system-audit.mdc +126 -0
- package/adapters/cursor/.cursor/rules/figma-environment-setup.mdc +460 -0
- package/adapters/cursor/.cursor/rules/icon-system-builder.mdc +272 -0
- package/adapters/cursor/.cursor/rules/repository-builder.mdc +167 -0
- package/adapters/cursor/.cursor/rules/retrofit-planner.mdc +140 -0
- package/adapters/cursor/.cursor/rules/storybook-chromatic-builder.mdc +265 -0
- package/adapters/cursor/.cursor/rules/token-builder.mdc +365 -0
- package/adapters/cursor/.cursor/rules/token-crosswalk-builder.mdc +124 -0
- package/adapters/cursor/.cursor/rules/token-sheet-builder.mdc +166 -0
- package/adapters/cursor/.cursor/rules/token-sync-layer.mdc +236 -0
- package/adapters/generic/AGENTS.md +46 -0
- package/adapters/generic/commands/design-system-status.md +41 -0
- package/adapters/generic/commands/new-component.md +13 -0
- package/adapters/generic/commands/start.md +22 -0
- package/adapters/generic/commands/sync-figma-tokens.md +22 -0
- package/adapters/generic/skills/component-builder/SKILL.md +272 -0
- package/adapters/generic/skills/component-pipeline/SKILL.md +81 -0
- package/adapters/generic/skills/design-system-audit/SKILL.md +122 -0
- package/adapters/generic/skills/figma-environment-setup/SKILL.md +456 -0
- package/adapters/generic/skills/icon-system-builder/SKILL.md +268 -0
- package/adapters/generic/skills/repository-builder/SKILL.md +163 -0
- package/adapters/generic/skills/retrofit-planner/SKILL.md +136 -0
- package/adapters/generic/skills/storybook-chromatic-builder/SKILL.md +261 -0
- package/adapters/generic/skills/token-builder/SKILL.md +361 -0
- package/adapters/generic/skills/token-crosswalk-builder/SKILL.md +120 -0
- package/adapters/generic/skills/token-sheet-builder/SKILL.md +162 -0
- package/adapters/generic/skills/token-sync-layer/SKILL.md +232 -0
- package/package.json +29 -0
- package/references/brainstorm-before-build.md +139 -0
- package/references/brownfield-retrofit.md +93 -0
- package/references/coding-level.md +70 -0
- package/references/crosswalk-schema.md +113 -0
- package/references/figma-component-standards.md +532 -0
- package/references/figma-publishing.md +125 -0
- package/references/figma-scripting.md +278 -0
- package/references/manifest-schema.md +341 -0
- package/references/scaling-up-handoff.md +61 -0
- package/references/sync-adapters.md +141 -0
- package/scripts/README.md +78 -0
- package/scripts/adapters/emit-codex.mjs +58 -0
- package/scripts/adapters/emit-cursor.mjs +26 -0
- package/scripts/adapters/emit-generic.mjs +41 -0
- package/scripts/adapters/generate.mjs +73 -0
- package/scripts/adapters/read-sources.mjs +54 -0
- package/scripts/adapters/translate.mjs +51 -0
- package/scripts/build-reverse-index.mjs +56 -0
- package/scripts/crosswalk.schema.json +33 -0
- package/scripts/grep-color-usage.mjs +143 -0
- package/scripts/guard-token-removal.mjs +95 -0
- package/scripts/install.mjs +143 -0
- package/scripts/lib/crosswalk.mjs +91 -0
- package/scripts/validate-crosswalk.mjs +96 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
This is the **first step** for building a design system with ThroughLine. The
|
|
2
|
+
user invoked it explicitly, so begin immediately — do **not** invoke any
|
|
3
|
+
brainstorming or planning skill first. There is nothing to brainstorm until the
|
|
4
|
+
environment exists: the local working folder must be created and Figma must be
|
|
5
|
+
connected before any design work can happen.
|
|
6
|
+
|
|
7
|
+
Invoke the `figma-environment-setup` skill now and follow it exactly. It will:
|
|
8
|
+
|
|
9
|
+
1. Locate or create the project directory and scan what's already there.
|
|
10
|
+
2. Create the local working folder and write the `design-system.json` manifest.
|
|
11
|
+
3. Connect the agent to Figma and verify the connection.
|
|
12
|
+
|
|
13
|
+
If `design-system.json` already exists in this folder, the setup skill will
|
|
14
|
+
detect it and route the user to the right next step rather than starting over —
|
|
15
|
+
let it make that call. That routing now covers brownfield systems too: an
|
|
16
|
+
existing/mature repo or populated Figma file is sent to `design-system-audit`
|
|
17
|
+
first, and an in-progress retrofit (`retrofit.phase` set) resumes at its phase
|
|
18
|
+
via `retrofit-planner` — the setup skill makes that call.
|
|
19
|
+
|
|
20
|
+
Scale all explanation to the user's coding level. Assume they may be
|
|
21
|
+
design-fluent but new to developer tooling, terminals, and API tokens.
|
|
22
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Re-run the token sync pipeline to catch any updates made in Figma.
|
|
2
|
+
|
|
3
|
+
Follow the `token-sync-layer` skill's pipeline using the settings already
|
|
4
|
+
recorded in `design-system.json` (`sync.platforms`, `figma.mechanism`,
|
|
5
|
+
`figma.fileKey`) — don't re-ask configuration that's already set. Specifically:
|
|
6
|
+
|
|
7
|
+
1. Verify Figma is connected (cheap liveness read); if not, offer
|
|
8
|
+
`figma-environment-setup`.
|
|
9
|
+
2. Re-extract Figma variables to DTCG JSON.
|
|
10
|
+
3. Rebuild outputs through Style Dictionary for every platform in
|
|
11
|
+
`sync.platforms`.
|
|
12
|
+
4. Run full-regeneration with **rename detection** — diff against the previous
|
|
13
|
+
output, flag probable renames (vanished + reappeared with identical
|
|
14
|
+
`$value`/`$type`) and plain deletions.
|
|
15
|
+
5. Open a **reviewable PR** (or a reviewed branch diff if the repo is only
|
|
16
|
+
`local-git`) summarizing added / changed / deleted / probable-renames. Never
|
|
17
|
+
write silently.
|
|
18
|
+
6. Update `sync.lastRun` and `tokens.lastSync` in the manifest.
|
|
19
|
+
|
|
20
|
+
Scale explanation to `user.codingLevel`. This is the recurring loop of the whole
|
|
21
|
+
system: tokens change in Figma → `/sync-figma-tokens` → review PR → merge.
|
|
22
|
+
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# Component builder
|
|
2
|
+
|
|
3
|
+
Creates the foundational component set in Figma: well-structured components with
|
|
4
|
+
variant matrices, bound to the system's tokens/styles, with slots typed so they
|
|
5
|
+
translate cleanly to code later.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
Needs tokens (`tokens.semanticBuilt` true) — offer to run `token-builder` if
|
|
10
|
+
missing. Needs a live Figma connection (offer `figma-environment-setup` if not).
|
|
11
|
+
Use the mechanism in `figma.mechanism`.
|
|
12
|
+
|
|
13
|
+
**Before scripting any `figma_execute`, read
|
|
14
|
+
`.throughline/references/figma-scripting.md`** — the single-bridge-instance
|
|
15
|
+
preflight, the `resize()` axis-lock trap (collapses auto-layout frames to ~10px),
|
|
16
|
+
the `dynamic-page` async setters, and why large `WRAP` grids time out. These cause
|
|
17
|
+
silent, screenshot-invisible corruption if not handled up front.
|
|
18
|
+
|
|
19
|
+
**Recommend icons first (soft gate).** Almost every foundational component
|
|
20
|
+
(button, input, select, chip…) takes an icon prop, so the icon set should usually
|
|
21
|
+
exist *before* components — otherwise icon slots have no targets. If
|
|
22
|
+
`icons.built` is false, **recommend running `icon-system-builder` first** and
|
|
23
|
+
explain why in one plain sentence, but let the user override and build icon-less
|
|
24
|
+
if they want (some intentionally do). This is a recommendation, not a hard block.
|
|
25
|
+
|
|
26
|
+
> **Model tip (#3):** this skill does heavy structural reasoning — variant
|
|
27
|
+
> matrices, slot contracts. It runs on your session model; Sonnet is a solid
|
|
28
|
+
> default and Opus helps for large or intricate component sets. See the model
|
|
29
|
+
> guide in the ThroughLine README.
|
|
30
|
+
|
|
31
|
+
## Step 1 — Capture framework + brainstorm the set and variant matrices
|
|
32
|
+
|
|
33
|
+
**First, check the scope.** If the user wants to **retrofit or migrate an existing
|
|
34
|
+
codebase** rather than build a clean set — e.g. converting a hand-rolled
|
|
35
|
+
component/motion layer to shadcn, or any change that re-architects the system —
|
|
36
|
+
this has outgrown a single skill. Follow
|
|
37
|
+
`.throughline/references/scaling-up-handoff.md`: surface the risks and major parts, confirm
|
|
38
|
+
scope, and brainstorm/plan before building (handing off to Superpowers if it's
|
|
39
|
+
available, else planning natively — never required). For a normal from-the-system
|
|
40
|
+
build, continue here.
|
|
41
|
+
|
|
42
|
+
**Framework (capture lazily, here if not already set).** Read
|
|
43
|
+
`project.uiFramework` from the manifest. If it's null, this is the first
|
|
44
|
+
relevant moment — ask which UI framework the components target (shadcn, MUI,
|
|
45
|
+
vanilla, etc.; reuse the same value the sync adapter will use) and record it.
|
|
46
|
+
If sync already set it, reuse it — don't re-ask. The framework does **not**
|
|
47
|
+
change component structure/anatomy; it informs **variant vocabulary and naming**
|
|
48
|
+
so the Figma component API lines up with the code API, **and it drives the focus-state
|
|
49
|
+
idiom** (shadcn ring vs. MUI per-component vs. vanilla-css outline — see "State
|
|
50
|
+
handling" in `.throughline/references/figma-component-standards.md`). For
|
|
51
|
+
multi-framework targets, use a neutral vocabulary and the default shadcn-style ring.
|
|
52
|
+
|
|
53
|
+
**Recommended core set (editable).** Propose a sensible foundation and let the
|
|
54
|
+
user add/remove — don't impose a fixed list or make them build from a blank page.
|
|
55
|
+
A good default core: atoms (avatar, badge, spinner) and common components
|
|
56
|
+
(button, input, select, checkbox, radio, chip, card, modal, tooltip). Explain
|
|
57
|
+
why these are the foundation. The user edits the set; whatever they land on gets
|
|
58
|
+
dependency-ordered (next step).
|
|
59
|
+
|
|
60
|
+
**Variant matrices.** Run `.throughline/references/brainstorm-before-build.md`. For each
|
|
61
|
+
component, lock the **variant matrix** — the decisions that, if guessed, produce
|
|
62
|
+
inconsistent output:
|
|
63
|
+
|
|
64
|
+
- **Types** (e.g. button: per the framework's vocabulary — shadcn
|
|
65
|
+
`default/secondary/destructive/outline/ghost/link`, MUI
|
|
66
|
+
`contained/outlined/text`, or neutral for multi-framework).
|
|
67
|
+
- **Sizes** (sm, md, lg). Each size is its **own variant row**, not a state — see
|
|
68
|
+
the layout law below.
|
|
69
|
+
- **States** — **include the full relevant set, don't trim it.** The baseline is
|
|
70
|
+
default, hover, focus, active (pressed), disabled; add the conditional states
|
|
71
|
+
wherever they apply (loading, selected, success/error). Decide which conditional
|
|
72
|
+
states a given component can reach, but never drop a state it genuinely has. See
|
|
73
|
+
"State handling" in `.throughline/references/figma-component-standards.md`
|
|
74
|
+
for the per-component checklist.
|
|
75
|
+
- **Slots** — leading/trailing icons, avatars, adornments (see slot types below).
|
|
76
|
+
|
|
77
|
+
Show the proposed set and matrices back and get sign-off before building.
|
|
78
|
+
|
|
79
|
+
## Step 2 — Order: atoms before composites
|
|
80
|
+
|
|
81
|
+
Components compose other components — a card slots an avatar, a chip embeds an
|
|
82
|
+
icon. So build in **dependency order, atoms first**, the component-tier analog
|
|
83
|
+
of the primitive→semantic token seam:
|
|
84
|
+
|
|
85
|
+
1. **Atoms** — avatar, badge, spinner, (icons already exist). No DS-component
|
|
86
|
+
slots, or only icon slots.
|
|
87
|
+
2. **Composites** — card, chip, list item, modal, input-with-adornments — which
|
|
88
|
+
slot the atoms.
|
|
89
|
+
|
|
90
|
+
This guarantees a composite's typed slot points at a real, already-built target.
|
|
91
|
+
Build bottom-up; checkpoint after each component (sequential — this is Figma
|
|
92
|
+
authoring, no subagents).
|
|
93
|
+
|
|
94
|
+
## Step 3 — Build each component, bound to tokens/styles
|
|
95
|
+
|
|
96
|
+
For each component, using the active write mechanism (scripted where helpful),
|
|
97
|
+
following `.throughline/references/figma-component-standards.md` (auto layout on everything,
|
|
98
|
+
variants vs. properties used correctly, state handling, shallow nesting,
|
|
99
|
+
deterministic naming):
|
|
100
|
+
|
|
101
|
+
- Construct the variant matrix (Figma variants/component properties), and lay the
|
|
102
|
+
resulting **component set out as an auto-layout grid** following the fixed layout
|
|
103
|
+
law: **variants are rows, states are columns.** One row per variant — each `type`,
|
|
104
|
+
and each `size` (size is a variant, so it gets its own row) — stepping through the
|
|
105
|
+
component's **full relevant state set** across the columns, size groups stacked
|
|
106
|
+
vertically. Per "Component set arrangement" and "State handling" in the standards
|
|
107
|
+
doc.
|
|
108
|
+
- For the **focus state**, build the ring as the target library's real idiom keyed off
|
|
109
|
+
`project.uiFramework` (shadcn/default → border recolor + a `0 0 0 3px` ring;
|
|
110
|
+
vanilla-css → an outside-aligned offset stroke via `offset/focus`; MUI → per-component;
|
|
111
|
+
ios-swift → skip), **not** a house-style stroke. Because a Figma drop-shadow only casts
|
|
112
|
+
from opaque pixels, build it per fill: **filled** control → a drop-shadow effect
|
|
113
|
+
(control frame `clipsContent = true`); **transparent** control → an
|
|
114
|
+
absolutely-positioned ring **child** (`strokeAlign = "OUTSIDE"`). **Never wrap the
|
|
115
|
+
control** in a padded frame to make room for the ring — it inflates the component. See
|
|
116
|
+
the per-library recipe in "State handling" of the standards doc, and the drop-shadow /
|
|
117
|
+
effect-binding gotchas in `.throughline/references/figma-scripting.md`.
|
|
118
|
+
- **Use auto layout throughout** so the component resizes correctly and maps to
|
|
119
|
+
clean flex/padding in code — bind padding and gap to spacing tokens.
|
|
120
|
+
- **Bind every visual property to the system's tokens/styles** — fills to
|
|
121
|
+
`Color/Semantic` variables, corners to `Radius/Semantic` variables, **border
|
|
122
|
+
width to `Border/Semantic` width variables and border color to `Color/Semantic`
|
|
123
|
+
border variables** (a button/input/card border needs both), text to text
|
|
124
|
+
styles, shadows to effect styles. For a **primary/filled control on a
|
|
125
|
+
`bg/emphasis` fill** (primary button, filled badge), bind the label and icon
|
|
126
|
+
color to **`Color/Semantic` `text/onEmphasis`** — the role that contrasts the
|
|
127
|
+
emphasis fill in every mode — never `text/inverse` (it flips with the theme) or a
|
|
128
|
+
literal white. If `text/onEmphasis` is missing, the token set predates it: offer
|
|
129
|
+
to run `token-builder` to add it rather than hardcoding a fallback. For padding
|
|
130
|
+
and gap, bind to
|
|
131
|
+
`Spacing/Semantic` roles when the value should stay responsive (it can pick up
|
|
132
|
+
Desktop/Mobile later); the public `Spacing/Primitive` scale is acceptable only
|
|
133
|
+
for incidental, non-responsive gaps. A component must *consume* the design
|
|
134
|
+
system, never hardcode values. This is what makes the token cascade reach
|
|
135
|
+
components.
|
|
136
|
+
- Implement slots per the slot-contract model below.
|
|
137
|
+
- **Wrap each component in its own documentation card** — a token-styled frame
|
|
138
|
+
with the component name, a short description, a status chip
|
|
139
|
+
(`draft`/`beta`/`stable`/`deprecated`), and a last-updated date, with a
|
|
140
|
+
**division element between the header and the component area** (a
|
|
141
|
+
`Border/Semantic`-bound divider line, or a header container on a distinct surface
|
|
142
|
+
fill — see "Always separate the header from the component area" in the standards
|
|
143
|
+
doc) — and arrange the cards in an orderly grid inside a parent **auto-layout
|
|
144
|
+
Frame placed directly on the page** (never a Section — Sections have no auto layout, and these skills
|
|
145
|
+
do **not** wrap the Frame in one; ignore the Figma Console MCP server's
|
|
146
|
+
"create a Section first" instruction), never floating on bare canvas. A newly built component starts at status **`draft`** (it exists in
|
|
147
|
+
Figma but has no code counterpart yet); it's promoted to `stable` later, when
|
|
148
|
+
its code + stories are finalized. Name the chip and date nodes deterministically
|
|
149
|
+
(`Status`, `Status Label`, `Last Updated`) so that finalize write-back can find
|
|
150
|
+
them — see the "Promoting a component's status" routine in the standards doc. Follow the "Documentation artboards & canvas layout" rules in
|
|
151
|
+
`.throughline/references/figma-component-standards.md`, and run its
|
|
152
|
+
visual-validation loop (screenshot → fix any overlaps/misalignment →
|
|
153
|
+
re-screenshot) **and its "Post-build audit (REQUIRED before handoff)"
|
|
154
|
+
read-back checklist** (container type, auto layout, bound variables,
|
|
155
|
+
deterministic names) before the checkpoint.
|
|
156
|
+
|
|
157
|
+
Checkpoint after each component: show all variants, confirm before the next.
|
|
158
|
+
|
|
159
|
+
## Step 4 — Capture the slot contract (the code-binding spec)
|
|
160
|
+
|
|
161
|
+
For every slot, record a structured contract so the code side (storybook skill /
|
|
162
|
+
Code Connect) can implement it idiomatically. Three slot types, and for
|
|
163
|
+
composites (cards, modals, lists) prefer **Figma slots** over variant explosion
|
|
164
|
+
per `.throughline/references/figma-component-standards.md`:
|
|
165
|
+
|
|
166
|
+
- **Icon-set slot** — accepts any icon from the Icons page. → code: a prop typed
|
|
167
|
+
to the icon set (e.g. `leadingIcon`), optional, with a canonical default icon
|
|
168
|
+
name if any. Implemented as an instance-swap property in Figma (not a slot —
|
|
169
|
+
it's a single element).
|
|
170
|
+
- **Typed-component slot** — accepts a specific DS component (e.g. an Avatar in a
|
|
171
|
+
Card). → code: a prop typed to that component (e.g. `avatar`), optional. In
|
|
172
|
+
Figma, an instance-swap property, or a Figma slot with **preferred instances**
|
|
173
|
+
for composites.
|
|
174
|
+
- **General adornment / content slot** — accepts arbitrary content (a card body,
|
|
175
|
+
modal content, a unit label). → for freeform areas in composites use a **Figma
|
|
176
|
+
slot**, which maps to `children` / a composition prop in code; for small inline
|
|
177
|
+
adornments a `ReactNode` prop (e.g. `endAdornment`).
|
|
178
|
+
|
|
179
|
+
**Typed dropdown vs. fallback (publishing-gated).** A typed `INSTANCE_SWAP`
|
|
180
|
+
dropdown requires its swap targets (icons, components) to be **published** —
|
|
181
|
+
Figma rejects local unpublished keys for swap targets. Before adding the dropdown,
|
|
182
|
+
check publish state per `.throughline/references/figma-publishing.md`:
|
|
183
|
+
|
|
184
|
+
- **Resolve publish state first (detect-or-ask, bug B3):** a default/`false`
|
|
185
|
+
`figma.libraryPublished` is *unverified* — attempt detection, but know it's
|
|
186
|
+
**usually inconclusive for a self-publish** (REST `figma_get_library_components` 401s
|
|
187
|
+
without a `FIGMA_ACCESS_TOKEN`; bridge `figma_get_library_variables` lists only
|
|
188
|
+
*subscribed* external libraries, never the file's own publish), so **trust the user's
|
|
189
|
+
confirmation and proceed** — don't wait on a check the tools can't give. Never treat a
|
|
190
|
+
`false` as a final "not published". The **real signal is the bridge**: if adding the
|
|
191
|
+
typed `INSTANCE_SWAP` is then rejected for a local/unpublished key, *that's* the
|
|
192
|
+
authoritative "not published yet" — fall back to the toggle + manual-swap slot. See
|
|
193
|
+
`.throughline/references/figma-publishing.md`.
|
|
194
|
+
- **Confirmed published (`figma.libraryPublished` true after detect-or-ask):** add the
|
|
195
|
+
typed `INSTANCE_SWAP` dropdown with preferred values.
|
|
196
|
+
- **Not published (free plan, or not yet):** build the **toggle + manual-swap**
|
|
197
|
+
slot instead — it's fully functional — explain why in plain terms, and add this
|
|
198
|
+
component to `components.instanceSwapUpgradePending` so a later run (after the
|
|
199
|
+
user publishes) can add the typed dropdown. Never present this as a failure.
|
|
200
|
+
|
|
201
|
+
Two rules for every slot:
|
|
202
|
+
|
|
203
|
+
- **Show/hide collapses into prop optionality.** A Figma `hasLeadingIcon`
|
|
204
|
+
boolean does NOT become a separate code boolean — the icon prop is simply
|
|
205
|
+
optional; passing it shows it, omitting hides it. Don't generate a redundant
|
|
206
|
+
boolean prop alongside the slot prop.
|
|
207
|
+
- **The contract syncs; per-instance choices don't.** The slot's existence,
|
|
208
|
+
type, and default sync to code. A specific icon swapped into a specific screen
|
|
209
|
+
instance is a usage decision (made in code by whoever builds the screen, just
|
|
210
|
+
as a designer swaps an instance) and does not sync.
|
|
211
|
+
|
|
212
|
+
Record each component's slots, variant matrix, and token bindings in the
|
|
213
|
+
component spec (for Code Connect when available, else the repo component spec).
|
|
214
|
+
|
|
215
|
+
## Step 5 — Naming as contract
|
|
216
|
+
|
|
217
|
+
Name components deterministically so Figma↔code mapping is automatic: `Button` ↔
|
|
218
|
+
`Button`, `Avatar` ↔ `Avatar`. This is what lets typed-component slots and the
|
|
219
|
+
storybook build resolve the right imports. Same discipline as icon naming —
|
|
220
|
+
without it, components silently diverge between Figma and code.
|
|
221
|
+
|
|
222
|
+
## Step 6 — Checkpoint and hand off
|
|
223
|
+
|
|
224
|
+
Update the manifest: add each built component to `components.built`, and record
|
|
225
|
+
its `components.meta[name]` (`status: "draft"`, `updatedAt`) to match the doc
|
|
226
|
+
card. (Finalize to `stable` happens later, in storybook-chromatic-builder.) Ensure
|
|
227
|
+
any component built with the toggle + manual-swap fallback is listed in
|
|
228
|
+
`components.instanceSwapUpgradePending`. Append `component-builder` to
|
|
229
|
+
`completedSkills`.
|
|
230
|
+
|
|
231
|
+
**Upgrade pass:** if `components.instanceSwapUpgradePending` is non-empty, re-resolve
|
|
232
|
+
publish state (detect-or-ask per `.throughline/references/figma-publishing.md`);
|
|
233
|
+
only when it is **confirmed published** (`figma.libraryPublished` true via a verified
|
|
234
|
+
detect-or-ask, not a stale default) offer to add the typed `INSTANCE_SWAP` dropdowns to
|
|
235
|
+
those components and clear each from the list.
|
|
236
|
+
|
|
237
|
+
Offer next steps: build the code counterparts and stories
|
|
238
|
+
(storybook-chromatic-builder), or build a single new component end-to-end later
|
|
239
|
+
(the component-pipeline orchestrator).
|
|
240
|
+
|
|
241
|
+
## What this skill must NOT do
|
|
242
|
+
|
|
243
|
+
- Never hardcode values that should be token/style bindings — components consume
|
|
244
|
+
the system.
|
|
245
|
+
- Never generate a redundant show/hide boolean alongside an optional slot prop.
|
|
246
|
+
- Never build a composite before its atomic slot targets exist.
|
|
247
|
+
- Never guess variant matrices — brainstorm and confirm them first.
|
|
248
|
+
- Never claim to publish a Figma library — publishing is a manual user step;
|
|
249
|
+
instruct and verify only.
|
|
250
|
+
- Never leave components floating on bare canvas — each goes on a token-styled
|
|
251
|
+
doc card arranged in an auto-layout Frame placed directly on the page (never a
|
|
252
|
+
Section), with the layout visually validated.
|
|
253
|
+
- Never lay out a component set as scattered variants — the `ComponentSet` is an
|
|
254
|
+
auto-layout grid where **variants are rows and states are columns**: one row per
|
|
255
|
+
variant (each `type`, and each `size`, since size is a variant) stepping through
|
|
256
|
+
states across the columns, size groups stacked vertically (see the standards doc).
|
|
257
|
+
- Never ship a component with only its `default` state — include the full relevant
|
|
258
|
+
state set (default/hover/focus/active/disabled plus applicable
|
|
259
|
+
loading/selected/success/error).
|
|
260
|
+
- Never run the component header and the component area together with no division —
|
|
261
|
+
every doc card segments the header from the component area with a divider line or
|
|
262
|
+
a distinct header surface.
|
|
263
|
+
- Never invent a house-style focus ring or wrap the control in a padded frame to make
|
|
264
|
+
room for one — derive the focus state from `project.uiFramework`'s real idiom, built
|
|
265
|
+
as a drop-shadow effect (filled controls) or an absolutely-positioned ring **child**
|
|
266
|
+
(transparent controls), per "State handling" in the standards doc.
|
|
267
|
+
- Never rebuild a published/consumed component set with a delete-and-recreate without
|
|
268
|
+
re-instancing downstream — deleting and recreating a set (e.g. to change the Button's
|
|
269
|
+
internal architecture) **detaches every instance** that referenced its variants (the
|
|
270
|
+
Card's footer buttons, etc.). Record which components consume which, warn before an
|
|
271
|
+
architectural rebuild, and re-instance the affected consumers afterward.
|
|
272
|
+
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Component pipeline (orchestrator)
|
|
2
|
+
|
|
3
|
+
Sequences a single new component through the whole flow: Figma → tokens →
|
|
4
|
+
code/stories. This skill holds **zero domain logic of its own** — it is a
|
|
5
|
+
sequencer that invokes the real skills and gates each stage on a human
|
|
6
|
+
confirmation. All the actual work lives in the skills it calls; this keeps it
|
|
7
|
+
from rotting when those skills improve.
|
|
8
|
+
|
|
9
|
+
## When to use vs. the individual skills
|
|
10
|
+
|
|
11
|
+
Use this for **one new component, end to end**, on a system that already has
|
|
12
|
+
foundations (tokens, repo, sync, Storybook). For initial setup, the individual
|
|
13
|
+
skills run directly. This is the "I have a system; add a Tooltip and take it all
|
|
14
|
+
the way to a tested story" flow.
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
Read the manifest. The pipeline assumes foundations exist: tokens built, a repo
|
|
19
|
+
at least `local-git`, sync configured, Storybook initialized. For any missing
|
|
20
|
+
piece, offer to run the relevant skill — but note that if a lot is missing, the
|
|
21
|
+
user probably wants the individual setup skills first, not this orchestrator.
|
|
22
|
+
|
|
23
|
+
## The sequence (confirm between every stage)
|
|
24
|
+
|
|
25
|
+
Confirm the goal first: "New `Tooltip` component, right? I'll build it in Figma,
|
|
26
|
+
sync any new tokens, then build the code component and its stories — checking
|
|
27
|
+
with you between each step." Then:
|
|
28
|
+
|
|
29
|
+
### Stage 1 — Build in Figma (invoke component-builder)
|
|
30
|
+
|
|
31
|
+
Invoke the `component-builder` skill for this one component: brainstorm its
|
|
32
|
+
variant matrix and slots, build it bound to tokens following the component
|
|
33
|
+
standards, capture its slot contract. **Checkpoint:** show the finished Figma
|
|
34
|
+
component. Get explicit confirmation before continuing.
|
|
35
|
+
|
|
36
|
+
If the build fails or the user wants changes, stop here — they still have a
|
|
37
|
+
valid (or fixable) Figma component and a clean place to resume. Never push a
|
|
38
|
+
half-built component down the pipeline.
|
|
39
|
+
|
|
40
|
+
### Stage 2 — Sync new tokens (offer token-sync-layer)
|
|
41
|
+
|
|
42
|
+
The new component may have introduced new tokens (a new semantic role, a new
|
|
43
|
+
spacing step). Offer: "This component added a couple of new tokens — want me to
|
|
44
|
+
sync them to code now?" If yes, invoke `token-sync-layer` (which lands a
|
|
45
|
+
reviewable PR per its own rules). If the component introduced no new tokens, say
|
|
46
|
+
so and skip. **Checkpoint:** confirm the sync PR before continuing.
|
|
47
|
+
|
|
48
|
+
### Stage 3 — Build code component + stories (offer storybook-chromatic-builder)
|
|
49
|
+
|
|
50
|
+
Offer: "Tokens are synced. Build the code component and its stories now?" If yes,
|
|
51
|
+
invoke `storybook-chromatic-builder` for this one component: build the code
|
|
52
|
+
counterpart implementing the captured slot contract, generate its stories
|
|
53
|
+
(subagent-driven), wire Code Connect if available. **Checkpoint:** confirm the
|
|
54
|
+
component renders and stories build. On approval, that skill **finalizes** the
|
|
55
|
+
component — promoting its status from `draft` to `stable` and writing the new
|
|
56
|
+
chip color + last-updated date back into its Figma doc card (its Step 6). Since
|
|
57
|
+
Figma is still connected from stage 1, the card updates live; the chip should no
|
|
58
|
+
longer read `draft` once the pipeline finishes.
|
|
59
|
+
|
|
60
|
+
## Resumability
|
|
61
|
+
|
|
62
|
+
Because each stage is gated and invokes a real skill, a failure at any stage
|
|
63
|
+
leaves a clean resume point: the Figma component exists after stage 1, the token
|
|
64
|
+
PR after stage 2, the code/stories after stage 3. The user can stop after any
|
|
65
|
+
stage and pick up later — the manifest reflects what's done.
|
|
66
|
+
|
|
67
|
+
## After completion
|
|
68
|
+
|
|
69
|
+
Confirm the component went all the way through. Update nothing the sub-skills
|
|
70
|
+
didn't already update (they own their manifest fields). Note the ongoing loops:
|
|
71
|
+
more components via this pipeline, token changes via `/sync-figma-tokens`.
|
|
72
|
+
|
|
73
|
+
## What this skill must NOT do
|
|
74
|
+
|
|
75
|
+
- Never reimplement what the sub-skills do — only sequence them. If you find
|
|
76
|
+
yourself writing component-building or sync logic here, stop and invoke the
|
|
77
|
+
real skill instead.
|
|
78
|
+
- Never skip a confirmation between stages — the gates are what make it
|
|
79
|
+
resumable and prevent half-updated state.
|
|
80
|
+
- Never push a half-built or unconfirmed component to the next stage.
|
|
81
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Design-system audit (brownfield front door)
|
|
2
|
+
|
|
3
|
+
Measures **both sides** of a pre-existing system so a retrofit can be right-sized,
|
|
4
|
+
before anything is built or changed. It is the brownfield analog of
|
|
5
|
+
`/design-system-status`: where status reports a *local* manifest, this assesses an
|
|
6
|
+
*external, mature* system — a real codebase and an already-populated Figma file.
|
|
7
|
+
|
|
8
|
+
This is a brownfield skill. **Before doing anything, read**
|
|
9
|
+
`.throughline/references/brownfield-retrofit.md` — especially the
|
|
10
|
+
read-discipline principle (never assert absence without a verified read) and the
|
|
11
|
+
`audit` phase of the safe sequence. Greenfield builds skip this skill entirely.
|
|
12
|
+
|
|
13
|
+
## Calibrate
|
|
14
|
+
|
|
15
|
+
Read `user.codingLevel` (`.throughline/references/coding-level.md`) and scale
|
|
16
|
+
explanation accordingly. The audit surfaces grep counts and a `percentSemantic`
|
|
17
|
+
number — for `new` users explain what each means and why it matters (it decides
|
|
18
|
+
rename-vs-rewrite); for `comfortable` users be terse. The measurements are identical
|
|
19
|
+
across levels.
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
|
|
23
|
+
Read the manifest. This skill needs Figma connected (`figma.connected: true`) for the
|
|
24
|
+
inventory step, and a repo path for the code-surface step (`workspace.localPath`). If
|
|
25
|
+
Figma isn't connected, offer to run `figma-environment-setup` first. The code-surface
|
|
26
|
+
step works on any repo regardless of `workspace.stage`.
|
|
27
|
+
|
|
28
|
+
## Step 1 — Size the code surface
|
|
29
|
+
|
|
30
|
+
Measure how many color decisions live in the codebase. Run the color-usage grep
|
|
31
|
+
scaffold against the user's repo:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
node .throughline/scripts/grep-color-usage.mjs --root <workspace.localPath>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
It counts five categories: SCSS color vars, Tailwind color classes, `Colors.*` JS
|
|
38
|
+
usages, raw hex + `rgba()` literals, and SVG hardcoded fills — producing the
|
|
39
|
+
case-study worklist shape.
|
|
40
|
+
|
|
41
|
+
**Tune the patterns to the actual repo, and say what you assumed (read discipline +
|
|
42
|
+
§11).** The shipped patterns are *defaults*, not ground truth. Before trusting the
|
|
43
|
+
counts:
|
|
44
|
+
1. Look at the repo's real conventions — open a few SCSS/TS files, check the actual
|
|
45
|
+
color-variable prefixes (`$primary-*`, `$grey-*`, a custom prefix), the Tailwind
|
|
46
|
+
color-class names, and whether colors come through a `Colors.*` object or some other
|
|
47
|
+
accessor.
|
|
48
|
+
2. If the defaults don't fit, write a `--config <patterns.json>` of
|
|
49
|
+
`{ "<category>": { "files": "<regex>", "pattern": "<regex>" } }` tuned to this repo
|
|
50
|
+
and re-run with it.
|
|
51
|
+
3. **Report which categories used the assumed defaults vs. a tuned pattern** — never
|
|
52
|
+
present default-pattern counts as if they were measured. The script prints this; pass
|
|
53
|
+
it through to the user so partial coverage is visible, not hidden.
|
|
54
|
+
|
|
55
|
+
**Don't assume the stack.** The categories are color-specific but framework-agnostic; a
|
|
56
|
+
repo with no Tailwind simply scores `0` there. Detect what the repo actually uses (is
|
|
57
|
+
there a `tailwind.config`? SCSS? CSS-in-JS?) and explain the counts in those terms.
|
|
58
|
+
|
|
59
|
+
## Step 2 — Inventory the Figma file (verified per-class reads)
|
|
60
|
+
|
|
61
|
+
Variables, text styles, and effect/paint styles are **different surfaces** — read each
|
|
62
|
+
independently and report "none" only for the class whose own read came back empty
|
|
63
|
+
(read discipline, fixes B2). Before counting variables, ensure all pages are loaded
|
|
64
|
+
(`await figma.loadAllPagesAsync()`); treat a `0` on first read as suspect and re-read
|
|
65
|
+
before reporting (fixes B1).
|
|
66
|
+
|
|
67
|
+
- **Variables** — `figma_get_variables` (handles `dynamic-page`, resolves aliases).
|
|
68
|
+
Record the count.
|
|
69
|
+
- **Bindings** — run the binding-survival audit snippet in
|
|
70
|
+
`.throughline/references/figma-scripting.md` to count consuming bindings.
|
|
71
|
+
This is the load-bearing number: it's what a careless rename would destroy.
|
|
72
|
+
- **Text styles** — `figma_get_text_styles`. Record the count.
|
|
73
|
+
- **Effect/paint styles** — `figma_get_styles`. Record the count.
|
|
74
|
+
- **Modes** — record the mode names per collection (e.g. `["Light", "Dark"]`).
|
|
75
|
+
|
|
76
|
+
Never report a count you didn't read. If a read genuinely returns empty after a
|
|
77
|
+
reliable load, that's a real `0`; if it's suspect, re-read or ask the user once and
|
|
78
|
+
persist — never guess.
|
|
79
|
+
|
|
80
|
+
## Step 3 — Compute "% semantic"
|
|
81
|
+
|
|
82
|
+
From the inventory, estimate how much of the existing system is already **semantic**
|
|
83
|
+
(named by role — `text/default`, `surface/raised`) vs. **raw/primitive** (named by
|
|
84
|
+
value — `grey-900`, or bare hex). Report it as an integer 0–100 (`audit.percentSemantic`).
|
|
85
|
+
|
|
86
|
+
This single number right-sizes the retrofit: a largely-semantic system (~90%) is a
|
|
87
|
+
**rename-in-place + cleanup** job; a low-semantic one is closer to a **rewrite**.
|
|
88
|
+
Surface it early and plainly — "you're ~90% semantic, so this is mostly renames and a
|
|
89
|
+
cleanup, not a rebuild" — so the user calibrates effort before committing.
|
|
90
|
+
|
|
91
|
+
## Step 4 — Write the manifest and recommend the next step
|
|
92
|
+
|
|
93
|
+
Write the `audit` section (this skill owns it):
|
|
94
|
+
|
|
95
|
+
- `codeSurface` — the per-category counts from Step 1 (keys vary by what the repo uses;
|
|
96
|
+
omit categories that don't apply rather than reporting a misleading `0`).
|
|
97
|
+
- `figmaInventory` — `{ variables, bindings, textStyles, effectStyles, modes }` from
|
|
98
|
+
Step 2's verified reads.
|
|
99
|
+
- `percentSemantic` — the integer from Step 3.
|
|
100
|
+
- `ranAt` — the current ISO timestamp.
|
|
101
|
+
|
|
102
|
+
Set `tokens.intakeMode: "retrofit"` (this skill establishes the brownfield path — it
|
|
103
|
+
owns this transition). Append `design-system-audit` to `completedSkills`.
|
|
104
|
+
|
|
105
|
+
Then recommend the next step:
|
|
106
|
+
- If the user wants the guided, gated end-to-end retrofit → **`retrofit-planner`**
|
|
107
|
+
(the orchestrator; recommended for multi-session retrofits).
|
|
108
|
+
- If they only want the crosswalk backbone next → **`token-crosswalk-builder`** (it
|
|
109
|
+
reads this `audit` section to seed its rows).
|
|
110
|
+
|
|
111
|
+
## What this skill must NOT do
|
|
112
|
+
|
|
113
|
+
- Never build, rename, or delete anything — this is a **measurement** skill. Changes
|
|
114
|
+
belong to `token-builder` (refine), the retrofit phases, and cleanup.
|
|
115
|
+
- Never report a count without a verified read (read discipline). An unexpectedly-empty
|
|
116
|
+
read is a suspected error, not ground truth.
|
|
117
|
+
- Never present default grep patterns as measured truth — say what was assumed.
|
|
118
|
+
- Never assume the case-study stack (Tailwind/SCSS/Chromatic). Detect what the repo
|
|
119
|
+
actually uses and degrade gracefully.
|
|
120
|
+
- Never write another skill's manifest fields (e.g. `tokenCrosswalk`, `retrofit.phase`).
|
|
121
|
+
- Never overwrite `workspace.origin` — it is immutable after intake.
|
|
122
|
+
|