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