@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,268 @@
1
+ # Icon system builder
2
+
3
+ End state: a Figma page named **Icons** containing the relevant icon set as
4
+ **scalable, well-named components**, ready to be consumed by components (skill 4)
5
+ and swapped via instance properties.
6
+
7
+ ## Core principle: don't make the agent draw 1,700 icons
8
+
9
+ The expensive, wrong path is the agent generating icon components one by one, by
10
+ hand, via the write mechanism — slow and token-hungry. Get to the end state via
11
+ the **cheapest mechanism that is also fully automated and produces clean,
12
+ well-named components.** "Cheapest" is not just the agent tokens: a mechanism that
13
+ burns near-zero tokens but makes the *user* hunt down a community file, duplicate
14
+ it, and copy components by hand isn't actually cheap — it just moves the cost onto
15
+ them. **The library determines the mechanism, deterministically** — same library,
16
+ same path every run.
17
+
18
+ ### Lucide → fetch the official SVGs directly (default)
19
+
20
+ **Default for Lucide: fetch the curated subset straight from the official source
21
+ repo and batch-componentize it.** Lucide publishes every icon as a uniform 24px
22
+ SVG at a deterministic path (`github.com/lucide-icons/lucide`, `icons/<name>.svg`),
23
+ and the filename *is* the canonical name (`arrow-right` ↔ `ArrowRight` in
24
+ `lucide-react`). So the agent can do the whole thing hands-off:
25
+
26
+ 1. Resolve the subset to kebab-case icon names (see name validation below) and
27
+ pin a release **tag** — ideally the tag matching the installed `lucide-react`
28
+ version, so the Figma mirror and the code package are the same generation.
29
+ 2. Batch-fetch each
30
+ `https://raw.githubusercontent.com/lucide-icons/lucide/<tag>/icons/<name>.svg`.
31
+ A **404 means that icon doesn't exist at that version** — report it and let the
32
+ user pick a replacement. (This *is* the name-validation gate, for free.)
33
+ 3. In one scripted pass, turn each SVG into a component via
34
+ `figma.createNodeFromSvg(svg)`, convert to a component, name it per the naming
35
+ contract (Step 3), and set the base size.
36
+
37
+ This is **fully automated, official source-of-truth, deterministic-named, and
38
+ needs no manual user steps** — strictly better than a community-file copy for a
39
+ library shaped like this. This is **not** the old "fetch SVGs off a website and
40
+ hand-prep them" anti-pattern: that meant a human manually downloading and cleaning
41
+ files. Batch-grabbing the official repo by deterministic path and scripting
42
+ `createNodeFromSvg` is cheap *and* hands-off.
43
+
44
+ **Fallbacks (only if the fetch path is blocked or the user prefers):** a vetted
45
+ Lucide community component file, or the official Lucide importer plugin — e.g. if
46
+ GitHub is unreachable, the user is on a restricted network, or they explicitly
47
+ want the community file. Name the specific resource and surface its license first
48
+ (see below).
49
+
50
+ ### Tabler & Phosphor → fetch the official SVGs directly (same as Lucide)
51
+
52
+ **Tabler and Phosphor are first-class libraries built by the exact Lucide
53
+ mechanism** — uniform per-icon SVGs published at a deterministic repo path where the
54
+ filename *is* the canonical name, so they get the same fully-automated,
55
+ official-source-of-truth, hands-off treatment (batch-fetch → `createNodeFromSvg` →
56
+ `createComponentFromNode`), not a community-file copy. This path is **proven**: a
57
+ greenfield run imported the Tabler subset by deterministic path with zero 404s and
58
+ bound the vector strokes to `text/primary` for theming. Prefer it whenever the user's
59
+ brand specifies Tabler or Phosphor (both are common picks).
60
+
61
+ - **Tabler** (MIT, 24px stroke): `github.com/tabler/tabler-icons`, per-icon at
62
+ `icons/outline/<name>.svg` (and `icons/filled/<name>.svg` for the filled set). Pin a
63
+ release tag matching the installed `@tabler/icons-react` generation. A 404 is the
64
+ name-validation gate, same as Lucide.
65
+ - **Phosphor** (MIT, 256px): `github.com/phosphor-icons/core`, per-icon at
66
+ `assets/<weight>/<name>.svg` where weight ∈ `thin|light|regular|bold|fill|duotone`
67
+ (regular has no suffix; others are `<name>-<weight>.svg`). Pick one weight as the
68
+ base to match the code package, pin the tag, and fetch that weight's files.
69
+
70
+ After fetch, **bind the vector strokes/fills to `text/primary`** (or the icon color
71
+ token) so the icons theme with the system, and name per the Step 3 contract. Fallbacks
72
+ (only if the fetch is blocked) mirror Lucide's: the library's official Figma community
73
+ file or importer plugin, license surfaced first.
74
+
75
+ ### Material → official community file / importer (default)
76
+
77
+ Material has **variant axes** (outlined / rounded / sharp × fill / weight / grade /
78
+ optical size), so there is no single clean per-icon file to grab — a direct repo
79
+ fetch isn't the clean default it is for Lucide. **Default to the official Material
80
+ Symbols community file or the official Material importer plugin** (Apache-2.0):
81
+ name the specific vetted resource, say why, surface the license, and get the
82
+ user's confirmation (see below). Only consider a direct fetch if the user pins one
83
+ specific style, and even then prefer the importer. Never hand-draw or generate
84
+ one-by-one.
85
+
86
+ ### Custom → batched SVG import
87
+
88
+ The user's own SVGs, brought in via **batched import + componentize** (never
89
+ hand-drawn, never one at a time). The sync layer later turns these into code via
90
+ its SVGR pipeline — see Step 3.5.
91
+
92
+ **Choosing a *different* mechanism on different runs for the *same* library is a
93
+ bug:** the library fixes the choice, so it must be deterministic.
94
+
95
+ ## Default to a CURATED SUBSET, not the whole library
96
+
97
+ Most projects need 40–120 icons, not 1,700+. Importing the entire library bloats
98
+ the file and hurts performance (one of the goals is a performant setup). So:
99
+
100
+ Run `.throughline/references/brainstorm-before-build.md` to establish **which icons the user
101
+ actually needs** — start from a sensible UI-essentials set (arrows, close, check,
102
+ search, menu, chevrons, common actions) and let them add domain-specific ones.
103
+ Only import the full library if the user explicitly wants it. Recorded subset can
104
+ grow later by re-running.
105
+
106
+ **Validate every subset name against the library version before building.** Icon
107
+ libraries add and **remove** icons between versions — e.g. `lucide-react` 1.x
108
+ dropped the brand icons (`figma`, `instagram`, `linkedin`, `twitter`, `youtube`,
109
+ …), so a subset listing them would build Figma components named after icons that
110
+ **don't exist in code**, silently breaking the Figma↔code name contract (the whole
111
+ point of deterministic naming below). Before importing: resolve each requested name
112
+ against the **actual library at the version in play** — if `lucide-react`/the
113
+ library package is already installed, check its real export list (and pin
114
+ `icons.version` to that); otherwise check the version's published icon manifest.
115
+ **Report any names that don't resolve and let the user pick replacements** — never
116
+ assume a name exists or invent a near-match. Brand/logo icons especially: confirm
117
+ they're in the chosen version or source them as custom SVGs (mechanism #3).
118
+
119
+ ## Name the resource and license (community-file / importer paths)
120
+
121
+ When a path uses an **unofficial** community file or importer plugin — Material's
122
+ default, or a Lucide *fallback* — those resources are variable in quality (some
123
+ popular plugins are reported buggy/slow). So: name the *specific* vetted resource
124
+ you intend to use, briefly say why, surface its license for commercial use, and
125
+ let the user confirm or pick another before proceeding. Don't silently grab
126
+ whatever's first. Verify the link is still live — don't assume a stale URL/file
127
+ key works; if the named resource has moved, search Figma Community for the
128
+ official/most-installed equivalent and confirm before using.
129
+
130
+ Default candidates for these paths, so the choice is consistent across runs:
131
+
132
+ - **Lucide fallback** → Lucide's **official Figma resource** (the Lucide-team
133
+ community file, or the official "Lucide Icons" importer plugin). MIT-licensed.
134
+ Only used if the official-SVG fetch (the Lucide default, above) is blocked.
135
+ - **Material** → the **official Material Symbols** community file, or the official
136
+ Material importer plugin. Apache-2.0.
137
+ - **Custom** → the user's own SVGs via batched import.
138
+
139
+ The **Lucide official-SVG fetch is the default and needs no resource-vetting
140
+ step** — the source is the library's own repo, not a third-party file — but still
141
+ pin the version tag and report any names that 404. If you genuinely cannot reach
142
+ the Lucide repo *and* cannot confirm a community file or importer, **say so and
143
+ ask the user** which resource to use — never invent a source.
144
+
145
+ ## Step 1 — Choose library + mechanism
146
+
147
+ - Ask which library: **Lucide** (the shadcn default; outline only), **Tabler**,
148
+ **Phosphor**, **Material**, or **custom** (user brings SVGs). Record in
149
+ `icons.library`.
150
+ - Determine the subset (brainstorm, above).
151
+ - The library fixes the mechanism (Core principle): **Lucide / Tabler / Phosphor →
152
+ fetch official SVGs from the repo by deterministic path; Material → official
153
+ community file / importer; custom → batched SVG import.** Pin the version tag for
154
+ the fetch libraries. Only name + confirm a specific community-file/importer resource
155
+ for the paths that use one (Material, or a fetch-library fallback).
156
+
157
+ ## Step 2 — Bring icons in
158
+
159
+ Execute the library's mechanism:
160
+
161
+ - **Lucide (default):** batch-fetch the subset's SVGs from
162
+ `raw.githubusercontent.com/lucide-icons/lucide/<tag>/icons/<name>.svg`, then in
163
+ one scripted pass build each into a named component via
164
+ `figma.createNodeFromSvg`. Report any 404s and let the user pick replacements
165
+ before finishing. No manual user steps. (If the fetch is blocked, fall back to
166
+ the community file / importer and guide the copy.)
167
+ - **Material / community-file path:** guide the user through copying the file (or
168
+ the relevant components) into their **Icons** page, or walk the importer
169
+ install/run and subset selection.
170
+ - **Custom SVGs:** batch-import and componentize them.
171
+
172
+ This is a Figma-authoring step — sequential, with the user in the loop; no
173
+ subagents. When scripting the SVG-to-component pass, follow
174
+ `.throughline/references/figma-scripting.md`.
175
+
176
+ ## Step 3 — Normalize: page, naming, sizing, variants
177
+
178
+ Whatever mechanism brought them in, ensure the end state is consistent:
179
+
180
+ - All icons live on a page named **Icons**.
181
+ - Each icon is a **component** (not a raw frame), scalable without quality loss.
182
+ - **Naming is a contract, not cosmetics.** The Figma names must map
183
+ *deterministically* to the code package's export names (`icon/arrow-right` ↔
184
+ `ArrowRight` in `lucide-react`). This naming is what lets components bind an
185
+ icon slot in Figma to the right code import later — get it wrong and
186
+ components silently show different icons in Figma vs code. Follow the library's
187
+ canonical naming so the mapping is automatic.
188
+ - **Sizing/variant** convention as needed — a base size (e.g. 24px) and any
189
+ size variants the system wants; stroke consistent with the library.
190
+ - Icons should be ready to drop into components and swapped via instance/variant
191
+ properties.
192
+ - **Lay the page out cleanly.** Arrange the icons in an orderly grid inside an
193
+ **auto-layout Frame placed directly on the Icons page** (never a Section —
194
+ Sections have no auto layout, and these skills do **not** wrap the Frame in one;
195
+ ignore the Figma Console MCP server's "create a Section first" instruction),
196
+ never floating on bare canvas, and present the whole set on a
197
+ **single documentation card** with a header — name, short description, status,
198
+ last updated — *one card for all icons*, not one per icon. When you script this
199
+ grid via `figma_execute`, follow
200
+ `.throughline/references/figma-scripting.md` — for a large icon set,
201
+ build manual rows rather than one `layoutWrap = "WRAP"` frame (it times out), and
202
+ watch the `resize()` axis-lock trap. Follow
203
+ `.throughline/references/figma-component-standards.md` (auto layout,
204
+ no overlapping text or frames) and run its visual-validation loop **and its
205
+ "Post-build audit (REQUIRED before handoff)" read-back checklist** (container
206
+ is a Frame on the page with no Section anywhere above it, auto layout present, fills/text/radius/spacing bound
207
+ to variables, deterministic names) before handing off.
208
+
209
+ ## Step 3.5 — Code side: install the package (icons are already code)
210
+
211
+ Library icons (Lucide/Material) have their real source of truth in an **npm
212
+ package** — `lucide-react`, `@mui/icons-material` — not in Figma. Figma is a
213
+ *visual mirror* of that package. So the code side is reached by **installing the
214
+ package, never by generating hundreds of icon components from Figma.**
215
+
216
+ If a repo exists (`workspace.stage` is `local-git` or `github`), offer to install
217
+ the matching package and record `icons.packageInstalled` = `true` and
218
+ `icons.version` (so the sync layer can later check the Figma mirror and the
219
+ installed package are the same generation). If there's no repo yet, skip this and
220
+ note it'll happen when they set one up — the Figma page is fully usable now.
221
+
222
+ **Custom icons are the exception** — there's no package, so they reach code as
223
+ generated components via the sync layer's SVGR pipeline (not here). This skill
224
+ just gets custom SVGs into Figma as components; the sync layer turns them into
225
+ code.
226
+
227
+ ## Step 3.6 — Publish checkpoint (unlocks typed icon dropdowns later)
228
+
229
+ Icons are the main thing components swap into slots. For a component to expose a
230
+ typed icon **dropdown** (`INSTANCE_SWAP`), the icons must be published to a team
231
+ library first — Figma rejects unpublished local component keys for swap targets.
232
+ This is the natural moment to publish, *before* components are built.
233
+
234
+ Read `.throughline/references/figma-publishing.md` and follow it:
235
+
236
+ - If `figma.canPublish` is unknown, ask once whether they're on a paid Figma plan
237
+ (Professional or higher); record it.
238
+ - **Paid plan:** offer to walk them through **Assets → Libraries → Publish** (the
239
+ plugin cannot publish for them — instruct, then verify). On confirmation, set
240
+ `figma.libraryPublished` = `true` and `figma.publishedAt`. Mention that adding
241
+ components later means a quick re-publish.
242
+ - **Free plan, or they decline:** completely fine — components will use the
243
+ toggle + manual-swap fallback and can be upgraded to typed dropdowns later if
244
+ they ever publish. Don't block or frame it as a failure.
245
+
246
+ Keep it optional and non-blocking; the Icons page is fully usable either way.
247
+
248
+ ## Step 4 — Checkpoint and hand off
249
+
250
+ Show the user the Icons page. Iterate if needed. Update the manifest:
251
+ `icons.built` = `true`, `icons.library`, `icons.version` (for library icons),
252
+ `icons.subset` (the imported set), and `icons.packageInstalled` if the code
253
+ package was installed. Append `icon-system-builder` to `completedSkills`. Note
254
+ they can re-run to add more icons. Offer next steps (components consume these
255
+ icons; the sync layer handles custom-icon code and version-drift checks).
256
+
257
+ ## What this skill must NOT do
258
+
259
+ - Never **hand-draw** icons or generate them one-by-one. (Scripting
260
+ `createNodeFromSvg` over a batch of official Lucide SVGs is fine and is the
261
+ default — that's automated import, not hand-drawing.)
262
+ - Never import 1,700 icons by default — curate to what's needed.
263
+ - Never make the user manually copy a community file when the library has a clean
264
+ official per-icon SVG repo the agent can fetch hands-off (Lucide).
265
+ - Never grab an unnamed/unvetted community file or importer silently — name it,
266
+ surface the license, let the user verify. (The Lucide official-repo fetch is
267
+ exempt — it's the library's own source.)
268
+
@@ -0,0 +1,163 @@
1
+ # Repository builder
2
+
3
+ Turns the user's working folder into a scalable monorepo and advances their
4
+ version-control stage. Defaults: **pnpm + Turborepo**, with a layout ready to
5
+ grow into a full app:
6
+
7
+ ```
8
+ my-design-system/
9
+ ├── design-system.json (the manifest, already here)
10
+ ├── package.json (workspace root)
11
+ ├── pnpm-workspace.yaml
12
+ ├── turbo.json
13
+ ├── .gitignore
14
+ ├── .env.example
15
+ ├── packages/
16
+ │ ├── tokens/ (synced token output lands here — skill 6)
17
+ │ └── ui/ (components / Storybook live here — skill 7)
18
+ └── apps/ (empty, ready for a Next.js app later)
19
+ ```
20
+
21
+ ## Calibrate first
22
+
23
+ Read `user.codingLevel` from the manifest and `.throughline/references/coding-level.md`.
24
+ Everything below describes the *actions*, which are identical for every user.
25
+ **How much you explain** each concept scales with the level — `new` gets plain-
26
+ language teaching of repos, env files, and secrets; `comfortable` gets terse
27
+ action statements. The hard secret-safety rules never scale.
28
+
29
+ ## The folder → local-git → github progression
30
+
31
+ **Scope check first.** If the user is bringing an **existing app** to retrofit or
32
+ migrate (not scaffolding a clean monorepo) — or the repo work is entangled with a
33
+ larger re-architecture — that has outgrown this skill. Follow
34
+ `.throughline/references/scaling-up-handoff.md`: surface risks and major parts, confirm scope,
35
+ and brainstorm/plan first (handing off to Superpowers if available, else planning
36
+ natively — never required). For a normal scaffold-from-scratch, continue here.
37
+
38
+ The user is at one of three `workspace.stage` values. This skill advances them
39
+ one step at a time, introducing each concept only when its payoff is concrete.
40
+ Read the current stage from the manifest and pick up where they are.
41
+
42
+ ### Stage A → scaffold the monorepo (still just a folder)
43
+
44
+ Create the workspace files (root `package.json`, `pnpm-workspace.yaml`,
45
+ `turbo.json`, `packages/tokens`, `packages/ui`, `apps/`, a sensible
46
+ `.gitignore`, and a `.env.example`). Record `repo.packageManager` = `pnpm`,
47
+ `repo.monorepo` = `turborepo`.
48
+
49
+ For `new` users, explain in one line what this is: "A monorepo is just one folder
50
+ that holds several related projects together — here, your tokens and your
51
+ components, with room to add an app later." For `comfortable` users, just state
52
+ what you scaffolded.
53
+
54
+ Checkpoint: show the structure, let the user look before committing anything.
55
+
56
+ ### Stage B → add local version history (`git init`)
57
+
58
+ This is the soft-nudge seam from the design: the moment code exists, version
59
+ history earns its keep. If `workspace.stage` is still `folder`, offer it:
60
+
61
+ - `new`: "Right now your folder has no 'history' — if something breaks there's no
62
+ undo. Git gives your folder a memory: every change is saved as a checkpoint you
63
+ can see and roll back. Want me to turn that on? It's one step and stays entirely
64
+ on your computer — nothing goes online yet."
65
+ - `comfortable`: "Want me to `git init` and make the first commit?"
66
+
67
+ If yes: `git init`, ensure `.gitignore` covers `node_modules`, `.env`, build
68
+ output; make an initial commit. Set `workspace.stage` and `repo.stage` to
69
+ `local-git`. Confirm the user can see they now have version history.
70
+
71
+ **Do not force git.** A user can stay in `folder` if they insist, but most will
72
+ want it once there's code. The token-sync skill needs at least `local-git`, so
73
+ it will re-offer this if skipped.
74
+
75
+ ### Stage C → connect to GitHub (remote, PRs, CI)
76
+
77
+ Only when the user wants what GitHub provides — backup, PRs for token-sync
78
+ review, CI for Storybook/Chromatic. Frame it as "push what you already have
79
+ somewhere safe and shareable," not "make an empty repo and figure out what goes
80
+ in it" — they already have a working local repo.
81
+
82
+ **Detect `gh` (the GitHub CLI):**
83
+
84
+ - If `gh` is present and authenticated: offer to run `gh repo create` — but
85
+ **show the exact command and what it will do first**, and get approval before
86
+ running. A `new` user may not know what that command does to their account, so
87
+ explain: "This creates a repository on your GitHub account and connects your
88
+ local folder to it." Never create the repo, set branch protection, or change
89
+ settings silently.
90
+ - If `gh` is absent: **first recommend installing it.** It's the single thing
91
+ that turns repo creation from a fiddly multi-step browser chore into one
92
+ automated command — exactly the friction this plugin exists to remove. Say so
93
+ plainly and offer to guide a quick one-time setup:
94
+ - **Install:** macOS `brew install gh`; Windows `winget install GitHub.CLI`;
95
+ Linux via the system package manager (or cli.github.com). Then authenticate
96
+ with `gh auth login` — walk `new` users through the browser prompts.
97
+ - Never install software silently — show the command, explain what it does, get
98
+ a yes first. Once installed and authenticated, proceed with the `gh` path
99
+ above (show the `gh repo create` command, get approval, then run it).
100
+ - **If they decline or can't install:** fall back to the manual browser path
101
+ with the exact click path. For `new` users be maximally explicit: go to
102
+ github.com, click New repository, name it, leave it empty (don't initialize
103
+ with a README), Create, then copy the commands GitHub shows for "push an
104
+ existing repository" and run them. Verify the push succeeded.
105
+
106
+ On success, set `workspace.stage` and `repo.stage` to `github` and record
107
+ `repo.remote`. Append `repository-builder` to `completedSkills`.
108
+
109
+ ## Secrets: the part most people have never done
110
+
111
+ This is where users with low coding experience get stuck — many have never made
112
+ an env file or added a secret to a "vault." Handle it with care, scaled to
113
+ `codingLevel`, but with the hard rules constant. There are **two distinct
114
+ homes** for a secret, and conflating them is a common mistake — make the
115
+ distinction explicit for `new`/`some` users:
116
+
117
+ 1. **Local development → a `.env` file.** A plain text file in the repo root
118
+ holding `KEY=value` lines, used when running things on your own computer.
119
+ **It must be gitignored** so it never gets committed. The repo ships a
120
+ `.env.example` (no real values, just the key names) as a template — explain
121
+ that `new` users copy it to `.env` and fill in real values.
122
+ 2. **Production / CI → the host's secrets store.** GitHub Actions has its own
123
+ encrypted **secrets vault** (Settings → Secrets and variables → Actions). CI
124
+ can't read your local `.env`, so any secret CI needs (e.g.
125
+ `CHROMATIC_PROJECT_TOKEN`) must be added there separately.
126
+
127
+ The hard rules, regardless of level:
128
+ - The secret **value never passes through this chat.** Don't ask the user to
129
+ paste it to you. Tell them the key name and exactly where the value goes; they
130
+ place it themselves.
131
+ - Secrets **never get committed.** `.env` is gitignored; only `.env.example`
132
+ (key names, no values) is committed.
133
+ - the agent **never** types a secret into a web form or creates a GitHub secret on
134
+ the user's behalf — it gives the click path and the key name.
135
+
136
+ For `new` users, teach the *why* once ("a secret key is like a password for a
137
+ service; if it's committed to code, anyone who sees your repo can use it — that's
138
+ why it lives in a gitignored file locally and an encrypted vault in
139
+ production"). Then give the literal steps. **Verify**: after they add a secret,
140
+ have them confirm it's set (e.g. re-run the workflow and check CI goes green),
141
+ because a beginner who pastes it wrong has no other signal.
142
+
143
+ This skill itself usually only sets up `.env.example` and the `.gitignore`. The
144
+ actual secret *values* (Chromatic, etc.) get added when the skill that needs
145
+ them runs (Storybook/Chromatic in skill 7) — but explain the env-file concept
146
+ here so it's familiar by then.
147
+
148
+ ## Hand off
149
+
150
+ Tell the user what's unlocked at their new stage. If they came here heading
151
+ toward token sync, point them to it ("now we can turn your Figma tokens into real
152
+ code files in `packages/tokens`"). Don't auto-run the next skill.
153
+
154
+ ## What this skill must NOT do
155
+
156
+ - Never commit a `.env` or any secret value.
157
+ - Never create a GitHub repo, branch protection, or secret silently — always
158
+ show the command/path and get approval.
159
+ - Never enter a secret into a web form or accept a secret value in chat.
160
+ - Never force git on a user who declines (but explain what they're deferring).
161
+ - Never give a beginner a lesser setup — only less explanation is fine, never
162
+ fewer capabilities.
163
+
@@ -0,0 +1,136 @@
1
+ # Retrofit planner (orchestrator)
2
+
3
+ Sequences a brownfield retrofit through the safe 7-phase order, gating each phase on a
4
+ human confirmation. Like `component-pipeline`, this skill holds **zero domain logic of
5
+ its own** — it is a sequencer that invokes the real skills and the phase work, and only
6
+ updates the manifest fields it owns (`retrofit.*`, `completedSkills`). All the
7
+ actual work lives in the skills it calls, so this orchestrator doesn't rot when they
8
+ improve.
9
+
10
+ **Before anything, read `.throughline/references/brownfield-retrofit.md`** —
11
+ the read discipline, the 7 guardrails, the safe sequence, and the verification triad
12
+ are the rules this skill enforces as gates.
13
+
14
+ ## When to use vs. the individual skills
15
+
16
+ Use this for a **complete retrofit**, especially across multiple sessions. For a single
17
+ isolated step (just the audit, just the crosswalk), run that skill directly. This is the
18
+ "converge my mature system onto tokens, end to end, without breaking the live app" flow.
19
+
20
+ ## Calibrate
21
+
22
+ Read `user.codingLevel` (`.throughline/references/coding-level.md`). A retrofit
23
+ touches Figma, tokens, code, CI, and a live app — for `new` users explain each phase and
24
+ why its ordering matters the first time; for `comfortable` users be terse. The phases and
25
+ gates are identical across levels.
26
+
27
+ ## Prerequisites
28
+
29
+ Read the manifest. This orchestrator assumes a brownfield situation
30
+ (`tokens.intakeMode: "retrofit"`, or `workspace.origin` is an existing repo/monorepo). If
31
+ the audit hasn't run yet (`audit.ranAt` is `null`), start at the audit phase below. If
32
+ none of the brownfield markers are set, this is probably greenfield — point the user to
33
+ the normal build skills instead.
34
+
35
+ ## Decision-journal offer (default-on)
36
+
37
+ At the start of a retrofit, offer to scaffold a decision journal at `docs/design-system/`
38
+ with `specs/ plans/ spikes/ findings/ decisions/ handoffs/`. **Recommend yes** —
39
+ retrofits are multi-session and the journal is the human decision trail (complementary to
40
+ the manifest's machine state) — but allow the user to decline. Record the choice in
41
+ `retrofit.journalScaffolded`. This is the only artifact this skill creates directly.
42
+
43
+ ## Detect the stack, don't assume it (§11)
44
+
45
+ Before running phases that shell out (sync, baseline, code, cleanup), detect what the
46
+ repo actually uses — read its `package.json` scripts for the real type-check, build,
47
+ visual-test, and token commands. The case study used Chromatic + `build-storybook` +
48
+ `tokens:sync`/`tokens:validate`; a real repo may differ. Map each phase onto the repo's
49
+ actual commands, or degrade gracefully and say what's missing — never assert a command
50
+ that doesn't exist.
51
+
52
+ ## The safe sequence (confirm between EVERY phase)
53
+
54
+ Set `retrofit.phase` to the current phase as you enter it, so a later session can resume
55
+ exactly here. Confirm the goal first, then walk the phases. **Each gate is a hard stop:
56
+ do not advance without explicit confirmation** — the gates are what keep the live app
57
+ intact and make the retrofit resumable.
58
+
59
+ ### Phase 1 — `audit` (invoke `design-system-audit`)
60
+
61
+ Invoke `design-system-audit`: size the code surface, inventory the Figma file with
62
+ verified per-class reads, compute `percentSemantic`. **Gate:** show the audit results and
63
+ the right-sizing read ("~90% semantic → renames + cleanup, not a rewrite"). Confirm before
64
+ continuing. Capture the rollback baseline (Figma version checkpoint / token export) now if
65
+ `figma-environment-setup` didn't already. On first entry, set `retrofit.startedAt` to the
66
+ current ISO timestamp if it is unset.
67
+
68
+ ### Phase 2 — `refine` (invoke `token-builder` brownfield branch)
69
+
70
+ Invoke `token-builder`'s refine-in-place branch: rename/realign variables **in place**,
71
+ preserving IDs, with a binding-survival audit before and after each rename (guardrail 3).
72
+ **Gate:** show the before/after binding counts are equal (no bindings severed) and the
73
+ refined variable names. Confirm before continuing. **Never delete-and-recreate.**
74
+
75
+ ### Phase 3 — `rebind`
76
+
77
+ Reconcile components onto the refined variables, preserving their Figma IDs. There is no
78
+ dedicated skill for this — drive it directly here: verify components still reference the
79
+ (renamed, same-id) variables, and fix any that drifted. **Gate:** confirm components still
80
+ render bound. This is also the natural point to build the crosswalk if not yet done —
81
+ offer `token-crosswalk-builder` (it reads the `audit` section to seed rows and wires
82
+ `tokens:validate`).
83
+
84
+ ### Phase 4 — `sync` (invoke `token-sync-layer` brownfield branch)
85
+
86
+ Invoke `token-sync-layer` with the brownfield transforms (channel alpha, opacity
87
+ 0–100→0–1, float32 rounding at the export boundary, `/opacity`→`color-mix`). It lands a
88
+ reviewable PR per its own rules. **Gate:** confirm the sync PR before continuing.
89
+
90
+ ### Phase 5 — `baseline` (invoke `storybook-chromatic-builder`)
91
+
92
+ Capture a Chromatic baseline **before** any code retrofit, so intended drift-fixes are
93
+ distinguishable from regressions. **Gate:** confirm the baseline is green and captured.
94
+ This ordering is not optional — baseline *after* the code change throws away the signal.
95
+
96
+ ### Phase 6 — `code` (dual output)
97
+
98
+ Retrofit the codebase with **dual output**: new and old tokens coexist during the
99
+ transition, so nothing breaks mid-migration. Use the crosswalk reverse index
100
+ (`tokens:reverse-index`) to semi-automate the SCSS/Tailwind swaps. Run the verification
101
+ triad as you go — `check-types`, `build-storybook` + Chromatic, **and run the actual app**
102
+ + spot-check 5–7 routes (the build alone is blind to story-unreachable SCSS). **Gate:**
103
+ confirm the triad passes before continuing.
104
+
105
+ ### Phase 7 — `cleanup`
106
+
107
+ Remove the old token outputs **only after** the repo-wide token-removal guard returns
108
+ **zero references** (`guard-token-removal.mjs`) — deleted Tailwind utilities are silent
109
+ no-ops that `tsc`/build won't catch (guardrail 4). **Gate:** show the guard reporting zero
110
+ references, then confirm removal. Re-run the verification triad after removal.
111
+
112
+ When cleanup is verified, set `retrofit.phase: "done"` and `retrofit.completedAt`, and
113
+ append `retrofit-planner` to `completedSkills`.
114
+
115
+ ## Resumability
116
+
117
+ Because each phase is gated and `retrofit.phase` is written on entry, a stop at any point
118
+ leaves a clean resume point. `figma-environment-setup` reads `retrofit.phase` on the next
119
+ `/start` and routes back here at the right phase. Never silently restart from the top —
120
+ resume where the manifest says.
121
+
122
+ ## What this skill must NOT do
123
+
124
+ - Never reimplement what the sub-skills do — only sequence them and drive the
125
+ no-dedicated-skill phases (rebind, code, cleanup). If you're writing token/sync logic
126
+ here, stop and invoke the real skill.
127
+ - Never skip a confirmation between phases — the gates keep the live app intact and make
128
+ the retrofit resumable.
129
+ - Never delete-and-recreate variables (guardrail 3), baseline after the code retrofit
130
+ (phase 5 before 6), or remove old outputs before the zero-reference grep passes
131
+ (guardrail 4).
132
+ - Never write another skill's manifest fields — own only `retrofit.*` and
133
+ `completedSkills`. The audit owns `audit.*`; the crosswalk owns `tokenCrosswalk`.
134
+ - Never assert the case-study toolchain — detect the repo's real commands or degrade
135
+ gracefully.
136
+