@radicool/throughline 0.14.0 → 0.15.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 (36) hide show
  1. package/adapters/codex/AGENTS.md +10 -10
  2. package/adapters/codex/prompts/component-builder.md +59 -15
  3. package/adapters/codex/prompts/document-component.md +42 -10
  4. package/adapters/codex/prompts/storybook-chromatic-builder.md +52 -9
  5. package/adapters/cursor/.cursor/commands/document-component.md +42 -10
  6. package/adapters/cursor/.cursor/rules/component-builder.mdc +60 -16
  7. package/adapters/cursor/.cursor/rules/component-pipeline.mdc +1 -1
  8. package/adapters/cursor/.cursor/rules/design-system-audit.mdc +1 -1
  9. package/adapters/cursor/.cursor/rules/figma-environment-setup.mdc +1 -1
  10. package/adapters/cursor/.cursor/rules/icon-system-builder.mdc +1 -1
  11. package/adapters/cursor/.cursor/rules/repository-builder.mdc +1 -1
  12. package/adapters/cursor/.cursor/rules/retrofit-planner.mdc +1 -1
  13. package/adapters/cursor/.cursor/rules/storybook-chromatic-builder.mdc +53 -10
  14. package/adapters/cursor/.cursor/rules/token-builder.mdc +1 -1
  15. package/adapters/cursor/.cursor/rules/token-crosswalk-builder.mdc +1 -1
  16. package/adapters/cursor/.cursor/rules/token-sheet-builder.mdc +1 -1
  17. package/adapters/cursor/.cursor/rules/token-sync-layer.mdc +1 -1
  18. package/adapters/generic/AGENTS.md +10 -10
  19. package/adapters/generic/commands/document-component.md +42 -10
  20. package/adapters/generic/skills/component-builder/SKILL.md +59 -15
  21. package/adapters/generic/skills/storybook-chromatic-builder/SKILL.md +52 -9
  22. package/package.json +1 -1
  23. package/references/component-doc-archetypes.md +15 -11
  24. package/references/component-doc-schema.md +23 -5
  25. package/references/doc-card-builder.md +565 -0
  26. package/references/doc-writing-standard.md +144 -0
  27. package/references/figma-component-standards.md +63 -16
  28. package/references/guide-voice.md +96 -0
  29. package/references/manifest-schema.md +22 -4
  30. package/scripts/README.md +23 -0
  31. package/scripts/build-doc-card-builder.mjs +143 -0
  32. package/scripts/docs-check.mjs +18 -4
  33. package/scripts/docs-lint.mjs +163 -0
  34. package/scripts/install.mjs +13 -1
  35. package/scripts/lib/doc-card-plan.mjs +101 -0
  36. package/scripts/lib/doc-card-render.figma.js +371 -0
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Stand up Storybook in the monorepo, build code components matching the Figma design system (consuming the synced tokens and implementing the captured slot contracts), generate stories for every component, set up Chromatic for visual regression testing, and wire Code Connect when the user's Figma plan supports it. Use this when the user wants to set up Storybook, build component stories, add visual regression testing, set up Chromatic, connect Figma components to code, or build the code side of their design system. Also trigger after components and token sync exist, when moving the component library into code. Make sure to use this whenever someone wants their Figma components realized as documented, tested code."
2
+ description: "Stand up Storybook in the monorepo, build code components matching the Figma design system, generate stories for every component, set up Chromatic for visual regression testing, and wire Code Connect when the user's Figma plan supports it. Use this when the user wants to set up Storybook, build component stories, add visual regression testing, set up Chromatic, connect Figma components to code, or build the code side of their design system. Also trigger after components and token sync exist, when moving the component library into code."
3
3
  alwaysApply: false
4
4
  ---
5
5
  # Storybook + Chromatic builder
@@ -31,15 +31,16 @@ system). Wire it to consume `packages/tokens` output so stories render with the
31
31
  real design tokens (import the generated CSS/theme). Checkpoint: confirm
32
32
  Storybook runs and shows the token-themed canvas.
33
33
 
34
- Install the documentation scripts alongside the token scripts (copy from the
35
- plugin's `scripts/` `build-docs-digest.mjs`, `docs-check.mjs`, and
36
- `lib/doc-record.mjs` into the repo and register npm scripts):
37
-
38
- - `"docs:digest": "node scripts/build-docs-digest.mjs"`
39
- - `"docs:check": "node scripts/docs-check.mjs"`
34
+ Install the documentation scripts alongside the token scripts: copy the five
35
+ files and register the three npm scripts listed under **Documentation scripts —
36
+ install as a set** in `.throughline/scripts/README.md`. That table is
37
+ the single source of truth for what a consuming repo gets; do not restate the
38
+ list here.
40
39
 
41
40
  These are the documentation analog of `tokens:validate`; see
42
- `.throughline/scripts/README.md`.
41
+ `.throughline/scripts/README.md`. This copy is setup, not a forever-fork:
42
+ `/document-component` re-checks these files' freshness on every run and refreshes
43
+ them from the plugin when it has moved on.
43
44
 
44
45
  **pnpm build-script allowlist (first-run gotcha).** On pnpm workspaces, the
45
46
  `@storybook/react-vite` install pulls `esbuild`, whose postinstall is blocked by
@@ -163,6 +164,43 @@ Configure Chromatic to snapshot everything (do **not** set `onlyChanged`), and
163
164
  verify a token-only PR re-snapshots all stories — they should flip orange against
164
165
  the green baseline.
165
166
 
167
+ ### Usage & cost guardrails
168
+
169
+ The full-snapshot default above is the right call for catching regressions, and it
170
+ is also the **maximum-usage** choice: every story, every run. Chromatic bills per
171
+ snapshot, so name this cost shape to the user when you set Chromatic up, and put the
172
+ guardrails in *before* the first big token PR, not after the bill.
173
+
174
+ What Chromatic actually offers (re-verify the live numbers at
175
+ `chromatic.com/pricing` — they drift):
176
+
177
+ - **Free plan (~5,000 snapshots/month):** testing **auto-pauses** when the ceiling
178
+ is hit. No surprise bill, but visual-regression coverage silently *stops* until
179
+ the monthly reset or an upgrade. For a full-suite design system that ceiling
180
+ arrives fast — treat a *paused* build as a red flag, not a passing one.
181
+ - **Paid plans: no hard spending cap.** Overage snapshots auto-bill at month-end.
182
+ The only native guardrail is **usage alerts** — an email when consumption crosses
183
+ a threshold you set (e.g. 90%).
184
+
185
+ The math, so the user sizes the plan honestly: **snapshots ≈ stories × modes ×
186
+ builds.** One `/sync-figma-tokens` PR re-snapshots the *entire* suite × every mode
187
+ in a single build — e.g. 40 components × 2 modes = 80 snapshots per build, and a
188
+ handful of token PRs plus daily `main` builds clears a free tier in a week.
189
+
190
+ So the guardrails, all of them user-controlled (Chromatic will not cap you):
191
+
192
+ 1. **Set usage alerts** at ~80% on a paid plan so the bill cannot sneak up. On the
193
+ free plan, make sure the user knows testing *pauses* at the ceiling.
194
+ 2. **Scope the CI trigger.** Run Chromatic on **pull requests and `main` only** —
195
+ never on every branch push — path-filter out docs-only changes, and keep it to
196
+ one Chromatic build per commit (no duplicate runs).
197
+ 3. **Size the plan to the math** before the first token PR. A large story count is
198
+ also the *only* reason to revisit TurboSnap (see above), and even then treat
199
+ every token change as a full run.
200
+
201
+ Do not silently pick a plan or leave the trigger wide open. Name the tradeoff and
202
+ let the user choose with the numbers in front of them.
203
+
166
204
  ## Step 5 — Code Connect (plan-gated, skip gracefully)
167
205
 
168
206
  Code Connect ties Figma components to their code counterparts so Figma's dev
@@ -238,8 +276,10 @@ the `figma_execute` scripting gotchas — `getNodeByIdAsync` and an explicit
238
276
  re-render the affected surfaces so `docs:check` stays green.
239
277
  - If Figma is connected (per `figma.mechanism`), open the component's doc card and
240
278
  update the `Status Label` text to `stable`, re-bind the `Status` chip fill to
241
- the **success** semantic color variable (mode-aware, not a hardcoded hex), and
242
- set `Last Updated` to today's date then screenshot to confirm the chip
279
+ the **success** semantic color variable (mode-aware, not a hardcoded hex), then
280
+ re-run the canonical doc-card builder against the same card to refresh the
281
+ header date from the `record.updatedAt` already set above (it locates the date
282
+ node under either header shape) — then screenshot to confirm the chip
243
283
  recolored and the date changed.
244
284
  - If Figma isn't connected, still update the manifest and tell the user the card
245
285
  will reconcile next Figma session (or offer to reconnect and fix it now).
@@ -300,6 +340,9 @@ that may not exist.
300
340
  - Never rely on TurboSnap (`onlyChanged: true`) for a token-driven design system
301
341
  — its incremental model keeps missing global token changes. Default to full
302
342
  snapshots (every story, every run); revisit only at large story counts.
343
+ - Never leave Chromatic's cost shape unspoken or the CI trigger wide open — there
344
+ is no hard spend cap on paid plans, so set usage alerts, run it on PRs + `main`
345
+ only, and size the plan to stories × modes × builds before the first token PR.
303
346
  - Never use the sequential model for story-gen — parallelize via subagents.
304
347
  - Never capture the Chromatic baseline *after* a code retrofit — baseline before, so
305
348
  intended drift-fixes are distinguishable from regressions.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Build a two-tier (primitive + semantic) design token system as Figma variables — color ramps, spacing, type scale, radius, shadows — with light/dark or brand modes. IMPORTANT: this uses ONE COLLECTION PER CATEGORY PER TIER, never one giant Primitives collection + one giant Semantic collection. Each category (color, spacing, type, radius, border) gets its own primitive collection and its own semantic collection so that mode axes (Light/Dark, Desktop/Mobile) belong only to the categories that need them. Use this when the user wants to create design tokens, design variables, a color system, a type scale, a spacing system, or 'build my tokens' in Figma. Also trigger when the user mentions primitives and semantic tokens, variable collections, design system foundations, or modes/themes in Figma."
2
+ description: "Build a two-tier (primitive + semantic) design token system as Figma variables — color ramps, spacing, type scale, radius, shadows — with light/dark or brand modes, using one collection per category per tier. Use this when the user wants to create design tokens, design variables, a color system, a type scale, a spacing system, or 'build my tokens' in Figma. Also trigger when the user mentions primitives and semantic tokens, variable collections, design system foundations, or modes/themes in Figma."
3
3
  alwaysApply: false
4
4
  ---
5
5
  # Token builder
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Build the brownfield token crosswalk — a persistent three-way map between each new token, the old Figma variable, and the old code identifier(s) — as crosswalk.json, then install the vetted validator/reverse-index scripts into the monorepo and wire the tokens:validate CI gate. Use this when retrofitting a design system onto a mature codebase, when the user wants to map old tokens to new ones, build a crosswalk, set up tokens:validate, or generate a reverse index for SCSS/Tailwind swaps. Also trigger when retrofit-planner reaches the crosswalk stage, or after design-system-audit has sized the retrofit. Make sure to use this whenever someone needs the machine-readable backbone that drives a brownfield code retrofit and its validation gate."
2
+ description: "Build the brownfield token crosswalk — a persistent three-way map between each new token, the old Figma variable, and the old code identifier(s) — then wire the tokens:validate CI gate. Use this when retrofitting a design system onto a mature codebase, when the user wants to map old tokens to new ones, build a crosswalk, set up tokens:validate, or generate a reverse index for SCSS/Tailwind swaps. Also trigger when retrofit-planner reaches the crosswalk stage, or after design-system-audit has sized the retrofit."
3
3
  alwaysApply: false
4
4
  ---
5
5
  # Token crosswalk builder
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Build a beautiful, on-brand \"Foundations\" page in Figma that visually documents every variable collection and style — color ramps with swatches, the type scale, spacing, radius, shadows/elevations — with swatches live-bound to the actual variables where Figma allows. Use this when the user wants a visual stylesheet, a token reference page, a Foundations page, to document or showcase their design system, or to \"see all my tokens\" laid out. Also trigger after token-builder completes, when the user wants a visual artifact of their tokens. Make sure to use this when someone wants their tokens presented visually rather than just existing as variables."
2
+ description: "Build an on-brand \"Foundations\" page in Figma that visually documents every variable collection and style — color ramps with swatches, the type scale, spacing, radius, shadows/elevations. Use this when the user wants a visual stylesheet, a token reference page, a Foundations page, to document or showcase their design system, or to \"see all my tokens\" laid out. Also trigger after token-builder completes, when the user wants a visual artifact of their tokens."
3
3
  alwaysApply: false
4
4
  ---
5
5
  # Token sheet builder
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Sync Figma design variables into code-ready token files by extracting them to DTCG-format JSON, running them through Style Dictionary, and emitting framework-specific outputs via per-platform adapters (shadcn/Tailwind, MUI, vanilla CSS, iOS Swift, Android Kotlin, or custom). Sets up the reusable \"sync figma tokens\" command that re-runs the pipeline to catch updates and opens a PR for review. Use this when the user wants to turn Figma tokens into code, sync design tokens, generate tokens.css or a Tailwind config or tokens.swift, set up a token pipeline, or run \"sync figma tokens\". Also trigger when the user mentions Style Dictionary, design token export, or keeping code in sync with Figma. Make sure to use this whenever someone wants their Figma variables reflected in actual code files."
2
+ description: "Sync Figma design variables into code-ready token files via DTCG JSON and Style Dictionary, emitting framework-specific outputs (shadcn/Tailwind, MUI, vanilla CSS, iOS Swift, Android Kotlin, or custom), and set up the reusable \"sync figma tokens\" command. Use this when the user wants to turn Figma tokens into code, sync design tokens, generate tokens.css or a Tailwind config or tokens.swift, set up a token pipeline, or run \"sync figma tokens\". Also trigger when the user mentions Style Dictionary, design token export, or keeping code in sync with Figma."
3
3
  alwaysApply: false
4
4
  ---
5
5
  # Token sync layer
@@ -4,18 +4,18 @@ ThroughLine builds a design system end to end. Read the matching skill file for
4
4
 
5
5
  ## ThroughLine skills
6
6
 
7
- - `component-builder` — 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. → read `skills/component-builder/SKILL.md`.
7
+ - `component-builder` — Build Figma components — buttons, inputs, cards, badges, chips, modals, and more — with variant matrices (types, sizes, states) and icon/component/content slots bound to the design system's tokens and styles. → read `skills/component-builder/SKILL.md`.
8
8
  - `component-pipeline` — 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. → read `skills/component-pipeline/SKILL.md`.
9
- - `design-system-audit` — 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. → read `skills/design-system-audit/SKILL.md`.
9
+ - `design-system-audit` — Measure a pre-existing design system before retrofitting it onto tokens, so the retrofit is right-sized. → read `skills/design-system-audit/SKILL.md`.
10
10
  - `figma-environment-setup` — Set up the local working folder and connect the agent to Figma so the design-system skills can read and write variables, styles, and components. → read `skills/figma-environment-setup/SKILL.md`.
11
- - `icon-system-builder` — Build an icon system in Figma — a dedicated "Icons" page populated with the user's chosen icon library (Lucide, Material, or custom SVGs) as well-named, scalable components using the fastest, most-automated mechanism per library (for Lucide, batch-fetching the curated subset's official SVGs from the source repo and componentizing them hands-off; for Material, the official community file or importer plugin) rather than hand-generating icons or making the user copy components by hand. → read `skills/icon-system-builder/SKILL.md`.
12
- - `repository-builder` — Graduate the local design-system folder into a real monorepo — a pnpm + Turborepo workspace with packages for tokens and UI components and room for apps — and walk the user from a plain folder to local git to a GitHub remote with PRs and CI. → read `skills/repository-builder/SKILL.md`.
13
- - `retrofit-planner` — Orchestrate a full brownfield design-system retrofit end to end — audit, refine variables in place, rebind components, sync, capture a Chromatic baseline, retrofit the code with dual output, adopt existing documentation then fill gaps, then remove the old tokens only after a zero-reference grep — with a human confirmation gate between every phase. → read `skills/retrofit-planner/SKILL.md`.
14
- - `storybook-chromatic-builder` — Stand up Storybook in the monorepo, build code components matching the Figma design system (consuming the synced tokens and implementing the captured slot contracts), generate stories for every component, set up Chromatic for visual regression testing, and wire Code Connect when the user's Figma plan supports it. → read `skills/storybook-chromatic-builder/SKILL.md`.
15
- - `token-builder` — Build a two-tier (primitive + semantic) design token system as Figma variables — color ramps, spacing, type scale, radius, shadows — with light/dark or brand modes. → read `skills/token-builder/SKILL.md`.
16
- - `token-crosswalk-builder` — Build the brownfield token crosswalk — a persistent three-way map between each new token, the old Figma variable, and the old code identifier(s) — as crosswalk.json, then install the vetted validator/reverse-index scripts into the monorepo and wire the tokens:validate CI gate. → read `skills/token-crosswalk-builder/SKILL.md`.
17
- - `token-sheet-builder` — Build a beautiful, on-brand "Foundations" page in Figma that visually documents every variable collection and style — color ramps with swatches, the type scale, spacing, radius, shadows/elevations — with swatches live-bound to the actual variables where Figma allows. → read `skills/token-sheet-builder/SKILL.md`.
18
- - `token-sync-layer` — Sync Figma design variables into code-ready token files by extracting them to DTCG-format JSON, running them through Style Dictionary, and emitting framework-specific outputs via per-platform adapters (shadcn/Tailwind, MUI, vanilla CSS, iOS Swift, Android Kotlin, or custom). → read `skills/token-sync-layer/SKILL.md`.
11
+ - `icon-system-builder` — Build an icon system in Figma — a dedicated "Icons" page of well-named, scalable icon components from Lucide, Tabler, Phosphor, Material, or custom SVGs. → read `skills/icon-system-builder/SKILL.md`.
12
+ - `repository-builder` — Graduate the local design-system folder into a real monorepo — a pnpm + Turborepo workspace with packages for tokens and UI components — and walk the user from a plain folder to local git to a GitHub remote with PRs and CI. → read `skills/repository-builder/SKILL.md`.
13
+ - `retrofit-planner` — Orchestrate a full brownfield design-system retrofit end to end — audit, refine, rebind, sync, baseline, code, docs, cleanup — with a human confirmation gate between every phase. → read `skills/retrofit-planner/SKILL.md`.
14
+ - `storybook-chromatic-builder` — Stand up Storybook in the monorepo, build code components matching the Figma design system, generate stories for every component, set up Chromatic for visual regression testing, and wire Code Connect when the user's Figma plan supports it. → read `skills/storybook-chromatic-builder/SKILL.md`.
15
+ - `token-builder` — Build a two-tier (primitive + semantic) design token system as Figma variables — color ramps, spacing, type scale, radius, shadows — with light/dark or brand modes, using one collection per category per tier. → read `skills/token-builder/SKILL.md`.
16
+ - `token-crosswalk-builder` — Build the brownfield token crosswalk — a persistent three-way map between each new token, the old Figma variable, and the old code identifier(s) — then wire the tokens:validate CI gate. → read `skills/token-crosswalk-builder/SKILL.md`.
17
+ - `token-sheet-builder` — Build an on-brand "Foundations" page in Figma that visually documents every variable collection and style — color ramps with swatches, the type scale, spacing, radius, shadows/elevations. → read `skills/token-sheet-builder/SKILL.md`.
18
+ - `token-sync-layer` — Sync Figma design variables into code-ready token files via DTCG JSON and Style Dictionary, emitting framework-specific outputs (shadcn/Tailwind, MUI, vanilla CSS, iOS Swift, Android Kotlin, or custom), and set up the reusable "sync figma tokens" command. → read `skills/token-sync-layer/SKILL.md`.
19
19
 
20
20
  ## ThroughLine commands
21
21
 
@@ -8,17 +8,49 @@ Ask which component to document (e.g. "Button"), then:
8
8
  the `component-builder` skill's *Author the documentation record* step —
9
9
  ingest any existing docs first (brownfield), then infer → enrich (from
10
10
  `.throughline/references/component-doc-archetypes.md`) → specialize →
11
- interview. The user approves the drafted record; `imported`/`user` blocks are
12
- never overwritten.
11
+ interview. Authored prose follows
12
+ `.throughline/references/doc-writing-standard.md`. Set `updatedAt` to
13
+ today's date (ISO, `YYYY-MM-DD`) whenever the record is written or rewritten —
14
+ it is a projected field and the doc card's header renders it. Once the record is
15
+ written, run `node .throughline/scripts/docs-lint.mjs
16
+ design-system/docs/components/<Name>.doc.json` and fix its warnings. Do not
17
+ raise a separate confirmation for a warning on an `imported`/`user` block:
18
+ draft the rewrite and carry it into the approval gate below, shown as
19
+ before/after and labelled with the block's provenance, so one approval covers
20
+ the whole record. The user approves the drafted record before anything is
21
+ projected (Figma description, doc card, manifest). Blocks the user did not
22
+ clear keep their existing text; blocks the user did clear are stamped
23
+ `imported+user` so a later run neither re-asks nor rewrites them.
13
24
  2. **Project it.** Write `design-system/docs/components/<Name>.doc.json`, set the
14
- Figma component `description`, enrich the doc card, and (if the repo/code side
15
- exists) render MDX/JSDoc and run `docs:digest` per the
16
- `storybook-chromatic-builder` render step.
17
- 3. **Reconcile drift.** Run `docs:check`. For each drifted surface, offer a per-item
18
- choice **re-render** (canonical wins) or **pull-back** (fold the surface edit
19
- into the record) and land the result as a reviewable change. On a brownfield
20
- component's first pass, adopt existing content (`provenance: imported`) rather
21
- than overwriting it.
25
+ Figma component `description`, rebuild the doc card's `Usage` band with the
26
+ canonical builder (`.throughline/references/doc-card-builder.md`
27
+ verify its returned summary and stamp `surfaces.docCard.{src,render,renderer}`
28
+ from it), and (if the repo/code side exists) render MDX/JSDoc and run
29
+ `docs:digest` per the `storybook-chromatic-builder` render step.
30
+ 3. **Reconcile drift.** Before trusting `docs:check`, confirm the repo's copy of
31
+ the doc scripts is current: compare `DOC_CARD_RENDERER_VERSION` in the repo's
32
+ `scripts/lib/doc-card-plan.mjs` against the same constant in
33
+ `.throughline/scripts/lib/doc-card-plan.mjs`. If the repo file is
34
+ missing, or its version is lower, `docs:check` is reading stale rules and its
35
+ "no drift" is meaningless — say so plainly, and offer to refresh the repo's
36
+ doc scripts from the plugin copy. Refresh the whole set and re-check the npm
37
+ registrations, both per **Documentation scripts — install as a set** in
38
+ `.throughline/scripts/README.md` — a refreshed file whose script was
39
+ never registered is the same failure in a new place. Run `docs:check` (with the
40
+ refreshed scripts, if any). For each drifted surface, offer a per-item
41
+ choice — **re-render** (canonical wins) or **pull-back**
42
+ (fold the surface edit into the record) — and land the result as a reviewable
43
+ change. On a brownfield component's first pass, adopt existing content
44
+ (`provenance: imported`) rather than overwriting it.
45
+ `docs:check` may also report `layout-upgrade-available` (informational, never
46
+ failing): the card's layout predates the current builder. Offer to re-render
47
+ the `Usage` band now — rebuild happens on this touch, never unprompted.
48
+ 4. **Close the flow.** Hand back in the four-beat guide voice from
49
+ `.throughline/references/guide-voice.md`: the outcome, what you set
50
+ aside and why, one recommended next step, and at most one light alternative.
51
+ Read existing state to name what is actually outstanding rather than guessing —
52
+ a component at `status: "draft"` with no code surface in `meta[name].doc.surfaces`
53
+ means the code side is deferred. Do not close with a grid of co-equal options.
22
54
 
23
55
  See `.throughline/references/component-doc-schema.md` for the record schema,
24
56
  fingerprint contract, and projection mapping. If a component was never built in
@@ -236,7 +236,9 @@ Read `.throughline/references/component-doc-schema.md` for the exact JSON
236
236
  schema, the fingerprint algorithm, and the projection contract.
237
237
 
238
238
  **Run the generation pipeline (each layer only fills what it legitimately knows;
239
- stamp `provenance` per block):**
239
+ stamp `provenance` per block):** all authored prose follows
240
+ `.throughline/references/doc-writing-standard.md` — its plain
241
+ reference register, not this skill's guide voice.
240
242
 
241
243
  0. **Ingest existing docs — brownfield only, runs first.** If docs already exist
242
244
  for this component (code JSDoc/MDX/README, or a populated Figma component
@@ -255,32 +257,74 @@ stamp `provenance` per block):**
255
257
  accessibility idiom to the target framework (the same field you read for variant
256
258
  vocabulary). Provenance `framework`.
257
259
  4. **Interview for the non-inferable.** Ask the user for brand/product-specific
258
- do's & don'ts and intent. Provenance `user`. **Show the whole drafted record and
259
- get explicit approval before writing anything** — layers 1–4 only fill blocks the
260
- ingest step did not, and an `imported`/`user` block is never overwritten.
260
+ do's & don'ts and intent. Provenance `user`. Write the draft to
261
+ `design-system/docs/components/<Name>.doc.json`, run
262
+ `node .throughline/scripts/docs-lint.mjs design-system/docs/components/<Name>.doc.json`,
263
+ and fix the warnings it raises. Do not raise a separate confirmation for
264
+ a warning on an `imported`/`user` block: draft the rewrite and carry it
265
+ into the approval gate below, shown as before/after and labelled with the
266
+ block's provenance. **Show the whole drafted record and get explicit
267
+ approval before projecting it anywhere** (Figma description, doc card,
268
+ manifest) — one approval covers the whole record. Blocks the user did not
269
+ clear keep their existing text; blocks the user did clear are stamped
270
+ `imported+user` so a later run neither re-asks nor rewrites them.
261
271
 
262
272
  **Write the record and project it:**
263
273
 
264
274
  - Write `design-system/docs/components/<Name>.doc.json` (JSON; required fields
265
275
  `name`, `summary`, `description`).
266
276
  - **Figma component description.** Set the component's native `description` field
267
- (via `figma_set_description`) to a compact markdown rendering summary,
268
- when-to-use/not, do's/don'ts, and the a11y summary and append a fingerprint
269
- marker line `<!-- tl:doc <fp> -->` (this is the surface Dev Mode and Code Connect
270
- read).
271
- - **Doc card body.** Extend the existing doc card (name/short-desc/status/date, per
272
- `.throughline/references/figma-component-standards.md`) with a usage body:
273
- when-to-use, do's/don'ts, an a11y line, and a variant/state legend — all
274
- token-bound (no hardcoded hex/px). Add a metadata text node named
275
- `Doc Fingerprint` holding `<fp>`.
277
+ (via `figma_set_description`) from this exact templatethis is the surface
278
+ Dev Mode and Code Connect read, and it must be reproducible byte-for-byte by
279
+ any agent from the same record:
280
+
281
+ ```
282
+ <summary>
283
+
284
+ **When to use**
285
+ - <whenToUse[n]>
286
+
287
+ **When not to use**
288
+ - <whenNotToUse[n]>
289
+
290
+ **Do**
291
+ - <dos[n]>
292
+
293
+ **Don't**
294
+ - <donts[n]>
295
+
296
+ **Accessibility**
297
+ - <accessibility.keyboard[n]>
298
+ - <accessibility.notes[n]>
299
+
300
+ <!-- tl:doc <fp> -->
301
+ ```
302
+
303
+ Rules: every line is a record string **verbatim** — no re-wording, no added
304
+ connectives, no sentences that appear nowhere in the record. A block whose
305
+ source array is empty is omitted along with its bold label. The **Accessibility**
306
+ label is omitted only when both `accessibility.keyboard` and `accessibility.notes`
307
+ are empty; when one is empty its bullets are simply absent and the label stays.
308
+ Sections are separated by exactly one blank line, and the fingerprint marker is
309
+ always last.
310
+ - **Doc card body.** Render the card's `Usage` band with the canonical builder
311
+ snippet in `.throughline/references/doc-card-builder.md` (via
312
+ `figma_execute` with an explicit `timeout`, one card per call): fill the
313
+ RECORD/CANONICAL_FP slots, resolve the nine required semantic variables and
314
+ the `Body/Default` text style per that file's call contract, run it, and
315
+ verify the returned summary (`rowsRendered`, `blocksCreated`, `cardWidth`) —
316
+ not a screenshot. The builder creates the `Doc Fingerprint` node itself and
317
+ is the only thing that may build the usage body — never hand-assemble it.
276
318
  - Compute `<fp>` as the canonical fingerprint defined in the schema reference
277
319
  (sha256 of the projected record without `provenance`, first 16 hex chars).
278
320
 
279
321
  **Update the manifest (fields this skill owns):** set
280
322
  `components.meta[<Name>].doc` to `{ path, fingerprint: <fp>, surfaces: {
281
323
  figmaDescription: { src: <fp>, render: <hash of the description text> }, docCard: {
282
- src: <fp>, render: <hash of the card body content> } } }`. The code surfaces
283
- (`storybookMdx`) are added later by `storybook-chromatic-builder`.
324
+ src: <fp>, render: <summary.renderHash>, renderer: <summary.rendererVersion> } } }`
325
+ the docCard entry is stamped from the builder's returned summary, never by
326
+ re-reading the card. The code surfaces (`storybookMdx`) are added later by
327
+ `storybook-chromatic-builder`.
284
328
 
285
329
  Run the standard doc-card visual-validation + post-build audit
286
330
  (`.throughline/references/figma-component-standards.md`) after enriching
@@ -27,15 +27,16 @@ system). Wire it to consume `packages/tokens` output so stories render with the
27
27
  real design tokens (import the generated CSS/theme). Checkpoint: confirm
28
28
  Storybook runs and shows the token-themed canvas.
29
29
 
30
- Install the documentation scripts alongside the token scripts (copy from the
31
- plugin's `scripts/` `build-docs-digest.mjs`, `docs-check.mjs`, and
32
- `lib/doc-record.mjs` into the repo and register npm scripts):
33
-
34
- - `"docs:digest": "node scripts/build-docs-digest.mjs"`
35
- - `"docs:check": "node scripts/docs-check.mjs"`
30
+ Install the documentation scripts alongside the token scripts: copy the five
31
+ files and register the three npm scripts listed under **Documentation scripts —
32
+ install as a set** in `.throughline/scripts/README.md`. That table is
33
+ the single source of truth for what a consuming repo gets; do not restate the
34
+ list here.
36
35
 
37
36
  These are the documentation analog of `tokens:validate`; see
38
- `.throughline/scripts/README.md`.
37
+ `.throughline/scripts/README.md`. This copy is setup, not a forever-fork:
38
+ `/document-component` re-checks these files' freshness on every run and refreshes
39
+ them from the plugin when it has moved on.
39
40
 
40
41
  **pnpm build-script allowlist (first-run gotcha).** On pnpm workspaces, the
41
42
  `@storybook/react-vite` install pulls `esbuild`, whose postinstall is blocked by
@@ -159,6 +160,43 @@ Configure Chromatic to snapshot everything (do **not** set `onlyChanged`), and
159
160
  verify a token-only PR re-snapshots all stories — they should flip orange against
160
161
  the green baseline.
161
162
 
163
+ ### Usage & cost guardrails
164
+
165
+ The full-snapshot default above is the right call for catching regressions, and it
166
+ is also the **maximum-usage** choice: every story, every run. Chromatic bills per
167
+ snapshot, so name this cost shape to the user when you set Chromatic up, and put the
168
+ guardrails in *before* the first big token PR, not after the bill.
169
+
170
+ What Chromatic actually offers (re-verify the live numbers at
171
+ `chromatic.com/pricing` — they drift):
172
+
173
+ - **Free plan (~5,000 snapshots/month):** testing **auto-pauses** when the ceiling
174
+ is hit. No surprise bill, but visual-regression coverage silently *stops* until
175
+ the monthly reset or an upgrade. For a full-suite design system that ceiling
176
+ arrives fast — treat a *paused* build as a red flag, not a passing one.
177
+ - **Paid plans: no hard spending cap.** Overage snapshots auto-bill at month-end.
178
+ The only native guardrail is **usage alerts** — an email when consumption crosses
179
+ a threshold you set (e.g. 90%).
180
+
181
+ The math, so the user sizes the plan honestly: **snapshots ≈ stories × modes ×
182
+ builds.** One `/sync-figma-tokens` PR re-snapshots the *entire* suite × every mode
183
+ in a single build — e.g. 40 components × 2 modes = 80 snapshots per build, and a
184
+ handful of token PRs plus daily `main` builds clears a free tier in a week.
185
+
186
+ So the guardrails, all of them user-controlled (Chromatic will not cap you):
187
+
188
+ 1. **Set usage alerts** at ~80% on a paid plan so the bill cannot sneak up. On the
189
+ free plan, make sure the user knows testing *pauses* at the ceiling.
190
+ 2. **Scope the CI trigger.** Run Chromatic on **pull requests and `main` only** —
191
+ never on every branch push — path-filter out docs-only changes, and keep it to
192
+ one Chromatic build per commit (no duplicate runs).
193
+ 3. **Size the plan to the math** before the first token PR. A large story count is
194
+ also the *only* reason to revisit TurboSnap (see above), and even then treat
195
+ every token change as a full run.
196
+
197
+ Do not silently pick a plan or leave the trigger wide open. Name the tradeoff and
198
+ let the user choose with the numbers in front of them.
199
+
162
200
  ## Step 5 — Code Connect (plan-gated, skip gracefully)
163
201
 
164
202
  Code Connect ties Figma components to their code counterparts so Figma's dev
@@ -234,8 +272,10 @@ the `figma_execute` scripting gotchas — `getNodeByIdAsync` and an explicit
234
272
  re-render the affected surfaces so `docs:check` stays green.
235
273
  - If Figma is connected (per `figma.mechanism`), open the component's doc card and
236
274
  update the `Status Label` text to `stable`, re-bind the `Status` chip fill to
237
- the **success** semantic color variable (mode-aware, not a hardcoded hex), and
238
- set `Last Updated` to today's date then screenshot to confirm the chip
275
+ the **success** semantic color variable (mode-aware, not a hardcoded hex), then
276
+ re-run the canonical doc-card builder against the same card to refresh the
277
+ header date from the `record.updatedAt` already set above (it locates the date
278
+ node under either header shape) — then screenshot to confirm the chip
239
279
  recolored and the date changed.
240
280
  - If Figma isn't connected, still update the manifest and tell the user the card
241
281
  will reconcile next Figma session (or offer to reconnect and fix it now).
@@ -296,6 +336,9 @@ that may not exist.
296
336
  - Never rely on TurboSnap (`onlyChanged: true`) for a token-driven design system
297
337
  — its incremental model keeps missing global token changes. Default to full
298
338
  snapshots (every story, every run); revisit only at large story counts.
339
+ - Never leave Chromatic's cost shape unspoken or the CI trigger wide open — there
340
+ is no hard spend cap on paid plans, so set usage alerts, run it on PRs + `main`
341
+ only, and size the plan to stories × modes × builds before the first token PR.
299
342
  - Never use the sequential model for story-gen — parallelize via subagents.
300
343
  - Never capture the Chromatic baseline *after* a code retrofit — baseline before, so
301
344
  intended drift-fixes are distinguishable from regressions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radicool/throughline",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Build a complete design system end to end — author in Figma, sync tokens to code, generate Storybook. Usable from Claude Code, Cursor, Codex, or any AGENTS.md agent.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,14 +12,16 @@ These are **seeds, not gospel** — the user's approval and the actual built
12
12
  component override them. Sources: W3C ARIA Authoring Practices Guide (roles +
13
13
  keyboard), Material 3, Shopify Polaris (content/usage), IBM Carbon (usage).
14
14
 
15
+ Seeds are clause-style shorthand; the authoring pipeline expands them into full sentences per references/doc-writing-standard.md before they enter a record.
16
+
15
17
  ## Button
16
18
 
17
19
  - **whenToUse:** trigger an action or event (submit, confirm, open a dialog).
18
- - **whenNotToUse:** navigation between pages/URLs use a Link.
20
+ - **whenNotToUse:** navigation between pages/URLs (use a Link).
19
21
  - **dos:** lead the label with a verb; keep one primary (highest-emphasis) button
20
22
  per view; keep labels short (≤ ~3 words).
21
- - **donts:** don't use a button for navigation; don't stack multiple primary
22
- buttons; don't disable without telling the user why.
23
+ - **donts:** don't use a button for navigation (use a Link); don't stack multiple
24
+ primary buttons (keep one per view); don't disable without telling the user why.
23
25
  - **accessibility (w3c-apg):** role `button`; Enter and Space activate; an
24
26
  icon-only button needs an `aria-label`; disabled buttons are not focusable.
25
27
 
@@ -30,8 +32,8 @@ keyboard), Material 3, Shopify Polaris (content/usage), IBM Carbon (usage).
30
32
  text (use Textarea).
31
33
  - **dos:** always pair with a visible label; show format hints as helper text;
32
34
  reserve space for error text to avoid layout shift.
33
- - **donts:** don't use placeholder text as the only label; don't validate on every
34
- keystroke before first blur.
35
+ - **donts:** don't use placeholder text as the only label (pair with a visible
36
+ label); don't validate on every keystroke before first blur.
35
37
  - **accessibility (w3c-apg):** every input has a programmatically associated
36
38
  `<label>`; error state sets `aria-invalid` and links the message via
37
39
  `aria-describedby`.
@@ -42,8 +44,8 @@ keyboard), Material 3, Shopify Polaris (content/usage), IBM Carbon (usage).
42
44
  - **whenNotToUse:** a single either/or action that takes effect immediately with no
43
45
  save (prefer a toggle) vs. a form choice (prefer radio/checkbox).
44
46
  - **dos:** label the control, not just the group; make the label clickable.
45
- - **donts:** don't use a radio group for multi-select; don't use a toggle for
46
- choices that only apply after a separate Save.
47
+ - **donts:** don't use a radio group for multi-select (use checkboxes); don't use
48
+ a toggle for choices needing a separate Save (use radio/checkbox).
47
49
  - **accessibility (w3c-apg):** roles `checkbox` / `radio` / `switch`; Space
48
50
  toggles; radio groups navigate with arrow keys; state exposed via
49
51
  `aria-checked`.
@@ -51,7 +53,8 @@ keyboard), Material 3, Shopify Polaris (content/usage), IBM Carbon (usage).
51
53
  ## Card
52
54
 
53
55
  - **whenToUse:** group related content and actions about a single subject.
54
- - **whenNotToUse:** primary page layout scaffolding; a bare list of text.
56
+ - **whenNotToUse:** primary page layout scaffolding (use a layout/grid component); a
57
+ bare list of text (use a List).
55
58
  - **dos:** make the primary action obvious; keep one main call-to-action per card.
56
59
  - **donts:** don't nest cards more than one level; don't make the whole card AND an
57
60
  inner button separately clickable in conflicting ways.
@@ -71,10 +74,11 @@ keyboard), Material 3, Shopify Polaris (content/usage), IBM Carbon (usage).
71
74
  ## Badge / chip / tag
72
75
 
73
76
  - **whenToUse:** short status, count, or category label (badge); a removable/
74
- selectable token (chip).
77
+ selectable item (chip).
75
78
  - **whenNotToUse:** interactive primary actions (use a Button).
76
- - **dos:** keep text to a word or two; bind color to a semantic tone token.
77
- - **donts:** don't rely on color alone to convey status — include text/icon.
79
+ - **dos:** keep text to a word or two; match badge color to its semantic meaning
80
+ (success, warning, error).
81
+ - **donts:** don't rely on color alone to convey status (include text or an icon).
78
82
  - **accessibility:** a removable chip's remove control needs an accessible name
79
83
  (e.g. "Remove <label>"); status conveyed with text, not color only (WCAG 1.4.1).
80
84
 
@@ -58,9 +58,17 @@ deterministically. JSON is equally machine-legible for AI consumers.
58
58
  - **Lifecycle:** `status` (`draft`|`beta`|`stable`|`deprecated`), `updatedAt` (ISO date).
59
59
  - **`provenance`** — per-block author source, one of `imported`, `ai-inferred`,
60
60
  `best-practice`, `w3c-apg`, `framework`, `user`, or a `+`-joined combination
61
- (e.g. `best-practice+user`). Regeneration re-infers `ai-inferred`/`framework`
62
- blocks and **never overwrites** a block whose provenance includes `user` or
63
- `imported`.
61
+ (e.g. `best-practice+user`). Regeneration **re-infers** a block whose
62
+ provenance includes `ai-inferred`, `framework`, `best-practice`, or `w3c-apg`,
63
+ and **never overwrites** one whose provenance includes `user` or `imported`.
64
+ Every value is assigned to exactly one of those two tiers: generated content is
65
+ re-inferred, human input (`user`) and pre-existing external content
66
+ (`imported`) are protected. Protection takes precedence: a combination that
67
+ contains both — `best-practice+user`, say — is protected. A block is
68
+ re-inferred only when it carries no `user` or `imported` marker at all. A
69
+ protected block may still be rewritten when the user approves the rewrite at
70
+ the record-approval gate; the result is stamped `imported+user`, which is
71
+ protected from then on and never re-proposed.
64
72
 
65
73
  Deferred to a later version (do not emit in v1): `anatomy`, `content` (writing
66
74
  guidelines), `examples`.
@@ -84,7 +92,7 @@ Figma-connected skill computing the identical hash over the description content.
84
92
  |---|---|---|---|---|
85
93
  | summary, description | ✔ | ✔ | ✔ | ✔ |
86
94
  | whenToUse / whenNotToUse | ✔ | ✔ | ✔ | ✔ |
87
- | variants, states (meanings) | compact | ✔ legend | ✔ argTypes | ✔ |
95
+ | variants, states (meanings) | | ✔ legend | ✔ argTypes | ✔ |
88
96
  | dos / donts | ✔ | ✔ | ✔ | ✔ |
89
97
  | accessibility | ✔ | ✔ | ✔ | ✔ |
90
98
  | tokensUsed | — | — | ✔ | ✔ |
@@ -105,7 +113,7 @@ The manifest stores pointers + per-surface fingerprints, never content:
105
113
  "fingerprint": "<canonical fingerprint at last render>",
106
114
  "surfaces": {
107
115
  "figmaDescription": { "src": "<fp>", "render": "<hash of description text>" },
108
- "docCard": { "src": "<fp>", "render": "<hash of card content>" },
116
+ "docCard": { "src": "<fp>", "render": "<hash of card content>", "renderer": "4" },
109
117
  "storybookMdx": { "src": "<fp>", "render": "<hash of mdx file>", "file": "packages/ui/src/Button/Button.mdx" }
110
118
  }
111
119
  }
@@ -116,6 +124,11 @@ The manifest stores pointers + per-surface fingerprints, never content:
116
124
  - `render` — a hash of the surface's rendered content at render time (detects
117
125
  **edited**, for surfaces the tooling can re-read).
118
126
  - `file` — repo-relative path for code surfaces so `docs:check` can re-read them.
127
+ - `renderer` — (docCard only) the layout version of the builder that last
128
+ rendered the card: `DOC_CARD_RENDERER_VERSION` in `scripts/lib/doc-card-plan.mjs`,
129
+ currently `"4"`. Additive and optional — absence means the card predates the
130
+ versioned builder. Stamped from the builder's returned summary, never by
131
+ re-reading the card.
119
132
 
120
133
  ## Drift + reconciliation contract
121
134
 
@@ -123,6 +136,11 @@ The manifest stores pointers + per-surface fingerprints, never content:
123
136
  - **canonical-changed** — the `.doc.json` fingerprint ≠ `doc.fingerprint`.
124
137
  - **stale** — `surface.src` ≠ current canonical fingerprint.
125
138
  - **edited** — a re-readable surface's current content hash ≠ `surface.render`.
139
+ - **layout-upgrade-available** — informational, never failing, docCard only:
140
+ `surfaces.docCard.renderer` is missing or lower than the current
141
+ `DOC_CARD_RENDERER_VERSION`. The card's content is not in drift — its layout
142
+ predates the current builder. Re-render on next touch (no unprompted Figma
143
+ writes; untouched brownfield cards must not generate a standing warning wall).
126
144
  - **missing-surface** — a repo surface that declares a `file` which is now gone.
127
145
  Failing, and distinct from `edit-unverified`: the surface *was* re-readable and
128
146
  its rendered output has been deleted, not merely unreadable this run.