@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,139 @@
1
+ # Brainstorm before build
2
+
3
+ A shared protocol that every Figma **authoring** skill (token-builder,
4
+ token-sheet-builder, icon-system-builder, component-builder) runs *before*
5
+ generating anything in Figma. Its job is to lock the spec with the user while
6
+ changes are still free — i.e. in conversation, not in the Figma file after
7
+ tokens have been burned creating the wrong thing.
8
+
9
+ This is distinct from the checkpoint gates that come *after* generation
10
+ ("here's what I built, approve it?"). Brainstorming happens *before*: "what are
11
+ we even building?" For a design-fluent, code-unsure user, this is where their
12
+ expertise drives the machine — they can't read the generation script, but they
13
+ can absolutely answer "should buttons have a loading state?"
14
+
15
+ ## The protocol
16
+
17
+ 1. **Don't jump to generating.** When the user asks for something ("build my
18
+ tokens", "make a button"), resist producing Figma output immediately. First
19
+ surface the decisions that shape it.
20
+
21
+ 2. **Ask in small, readable chunks.** Present choices a few at a time, in plain
22
+ language, with a recommended default for each so the user has something to
23
+ react to rather than a blank page. Prefer concrete either/or framings over
24
+ open questions. Use the question-asking UI (tappable options) when available
25
+ — it's much easier for the user than typing.
26
+
27
+ 3. **Show the proposed spec back before building.** Once decisions are made,
28
+ restate the full spec in a short, digestible form the user can sign off on:
29
+ "Here's what I'll create: [the spec]. Good to go?" This is the gate between
30
+ brainstorm and generation.
31
+
32
+ 4. **Only then generate.** After explicit sign-off, proceed to the skill's
33
+ generation step (and its own post-generation checkpoints).
34
+
35
+ ## Intake mode (token-builder runs this FIRST)
36
+
37
+ Before brainstorming structure, the token-builder must establish **which
38
+ starting point the user is at**, because the three modes are genuinely different
39
+ behaviors. Ask this first, route accordingly:
40
+
41
+ - **Generative** — the user gives a seed (e.g. one brand color, one font) and
42
+ wants AI to expand it into a full system: a complete tonal ramp from the brand
43
+ color, supporting/semantic color families (success/warning/danger derived to
44
+ harmonize), complementary font pairings, and full spacing/type/radius scales.
45
+ Here you generate the most; confirm the seed and the aesthetic direction, then
46
+ propose the expanded system for sign-off.
47
+ - **Descriptive** — the user gives aesthetic direction (words like simple,
48
+ rounded, modern, dense, comfortable) and/or a reference image/URL, but not
49
+ exact values. Derive concrete scales and ramps from the description, mapping
50
+ adjectives to decisions (e.g. "rounded" → larger radius scale, "dense" →
51
+ tighter spacing base). Propose values back for sign-off.
52
+ - **Import** — the user already has a token set (a JSON file, a list, an
53
+ existing system, or source like a marketing site + brand guide) and wants it
54
+ ingested and organized into the per-category Figma structure. Import has **two
55
+ distinct responsibilities — keep them separate so they don't fight each other**:
56
+ *(1)* preserve and organize what they gave, and *(2)* run a completeness pass
57
+ that recommends what a fuller system adds. Preserve their actual values and
58
+ names exactly — never overwrite or silently invent values **in place**. But do
59
+ not stop at a 1:1 transcription: a brand guide or website is almost always a
60
+ *partial* system (a few brand colors, two fonts, ad-hoc paddings), so a faithful
61
+ import alone produces a thin, rigid token set. The completeness pass below is
62
+ what turns it into a flexible one.
63
+
64
+ **Completeness pass (gap analysis — the high-value step).** After organizing,
65
+ diff what they gave against the reference model of a full, flexible system (the
66
+ checklist below). Then **proactively propose the missing pieces, derived from
67
+ their existing values so they harmonize** — e.g. extend a single brand color
68
+ into a full 50–900 tonal ramp, add a neutral/gray ramp, derive success/warning/
69
+ danger/info families tuned to their palette, add dark-mode values, an elevation/
70
+ shadow scale, a radius scale, and the semantic role layer (bg/surface/text/
71
+ border roles). This is **preserve-first and opt-in**, which is how it coexists
72
+ with "don't invent values": you are not overwriting their brand or inventing
73
+ silently — you surface a derived, clearly-labeled upgrade menu and let them
74
+ choose. Present it grouped by category: *"Here's what you have (kept as-is).
75
+ Here's what a fuller system adds, and what I'd derive for each — accept all, pick
76
+ some, or skip."* Nothing recommended is created until the user accepts. Keep it
77
+ proportional (see "Keep it proportional" below): lead with the high-impact gaps
78
+ (tonal ramps, neutral ramp, state colors, dark mode, semantic roles), offer the
79
+ rest lightly.
80
+
81
+ **What a full, flexible system includes (the reference model to diff against):**
82
+ - **Color** — a neutral/gray ramp (~10 steps); each brand/accent as a full
83
+ tonal ramp (50–900), not just its base; state families (success, warning,
84
+ danger, info) as ramps; a semantic role layer (bg/surface layers, text
85
+ hierarchy: primary/secondary/muted/disabled, border/divider, interactive
86
+ states: hover/active/focus/selected/disabled); **dark mode** values.
87
+ - **Typography** — a full size ramp with line-heights, weights, and
88
+ letter-spacing; semantic roles (display, heading h1–h6, body, label, caption,
89
+ code); responsive (Desktop/Mobile) sizing where relevant.
90
+ - **Spacing** — a consistent base-unit scale (replacing ad-hoc one-off
91
+ paddings), spanning tight insets up to large layout steps.
92
+ - **Radius / border-width / elevation(shadow)** — each a real scale
93
+ (none→full, hairline→thick, sm→xl) rather than one hardcoded value;
94
+ elevation should be dark-mode-aware.
95
+ - **Often-absent optional layers** — opacity scale, z-index/layer tokens,
96
+ motion (duration + easing). Mention these exist; don't force them.
97
+ - **Modes** — note which axes are missing (dark mode, density, brand) since
98
+ a partial import usually has none.
99
+
100
+ **Organize into per-category collections.** While ingesting, map their values
101
+ onto the structural-consistency model (see token-builder Step 1): one
102
+ primitive and one semantic collection per category, split so each category owns
103
+ its own mode axis. Passthrough dimensional semantics (e.g. border-width
104
+ semantics that alias a single primitive) are **expected and kept** — they exist
105
+ to carry a future mode axis — so do not collapse them. The only thing to flag
106
+ is a genuine naming problem: a "semantic" token that's just a renamed primitive
107
+ step with no real role (`space-12` rather than `inset/md`). Surface those:
108
+ "A few of your semantic names mirror primitive steps rather than naming a role
109
+ — want me to rename them to usage roles, or keep them as-is?" Let the user
110
+ choose. Keep structure; fix only fake roles.
111
+
112
+ Many users are a blend (e.g. "here's my 2 brand colors and a font, fill in the
113
+ rest" is generative with seeds). Identify the dominant mode, confirm it, and
114
+ proceed. The rest of the token brainstorm (below) then runs within that mode.
115
+
116
+ ## What each skill brainstorms
117
+
118
+ - **token-builder** — after intake mode, the structure of the scales: which
119
+ color ramps and how many steps, the spacing scale, the type scale,
120
+ radius/border/shadow scales, and which modes exist (light/dark, brand
121
+ variants, density). Critically, the primitive naming convention, since the
122
+ semantic tier aliases onto it. Also: whether a third (component) tier is
123
+ warranted — default two-tier; only raise three-tier if the user signals
124
+ multi-brand, white-labeling, or a very large component library.
125
+ - **token-sheet-builder** — layout and grouping of the visual stylesheets; which
126
+ collections get their own artboard; how much per-token detail to show.
127
+ - **icon-system-builder** — which icon library (lucide / material / custom),
128
+ which subset of icons, the naming convention, and sizing/grid conventions.
129
+ - **component-builder** — the variant matrix for each component: types, sizes,
130
+ states (hover/focus/disabled/loading), icon slots, and which tokens each
131
+ variant binds to.
132
+
133
+ ## Keep it proportional
134
+
135
+ Brainstorming should be thorough for high-impact, hard-to-undo decisions (the
136
+ primitive naming convention, the mode structure) and light for low-stakes ones.
137
+ Don't interrogate the user about trivia — the goal is to prevent expensive
138
+ regeneration, not to slow them down. If a decision is cheap to change later, note
139
+ the default and move on.
@@ -0,0 +1,93 @@
1
+ # Brownfield retrofit — read discipline, guardrails, safe sequence
2
+
3
+ Canonical reference for retrofitting a design system onto a **mature codebase and
4
+ an already-populated Figma file** (the brownfield path), as opposed to building
5
+ greenfield. Read this before running `design-system-audit`, `token-crosswalk-builder`,
6
+ `retrofit-planner`, or any brownfield branch of `token-builder`, `token-sync-layer`,
7
+ or `storybook-chromatic-builder`.
8
+
9
+ ## The read-discipline principle (fixes bugs B1–B4)
10
+
11
+ **Never assert that something is absent, empty, unpublished, or stale without an
12
+ explicit, completed read that returned that result.** "I didn't find X" must mean
13
+ "I queried for X and the result was empty (after the file and all pages fully
14
+ loaded)," never "I assumed X from Y." When a result is genuinely undetectable, ask
15
+ the user once and persist the answer in the manifest — never guess.
16
+
17
+ Concrete applications:
18
+
19
+ - **Variables (B1).** Before counting variables, `await figma.loadAllPagesAsync()`.
20
+ Treat a `0` count on a first read as suspect — re-read before reporting. An
21
+ unexpectedly-empty result is a possible read/cache error, not ground truth. Prefer
22
+ the dedicated `figma_get_variables` tool over a hand-written probe.
23
+ - **Styles vs. variables (B2).** Text styles, effect/paint styles, and variables are
24
+ **different surfaces**. Absence of variables says nothing about styles. Query each
25
+ independently — variables (`figma_get_variables`), text styles
26
+ (`figma_get_text_styles`), effect/paint styles (`figma_get_styles`) — and only
27
+ report "none" for the specific class whose own read returned empty.
28
+ - **Publish state (B3).** Treat a default/`false` `figma.libraryPublished` as
29
+ _unverified_. Attempt detection first (`figma_get_library_components` /
30
+ `figma_get_library_variables`, library component keys). If inconclusive, ask once
31
+ ("Is this library published to a team library?") and persist to
32
+ `figma.libraryPublished` / `figma.canPublish`. Frame the unpublished path as a
33
+ graceful choice, not a failure.
34
+ - **Bridge ports (B4).** Distinguish *live* concurrent bridge instances from
35
+ *dead/stale* entries. Only block on genuinely live ones; reap or offer one-click
36
+ cleanup for stale ones. See the bridge-instance preflight in
37
+ `${CLAUDE_PLUGIN_ROOT}/references/figma-scripting.md`.
38
+
39
+ ## The 7 guardrails (hard "DON'T" rules)
40
+
41
+ Each cost real debugging time on a live retrofit. Treat each as a hard rule.
42
+
43
+ 1. **Don't bind line-height / letter-spacing variables to text styles.** Figma stores
44
+ them as PERCENT; a unitless ratio var (`1.6`) rebinds as `1.6px` — catastrophic.
45
+ **Font-size binding only** (px→px is safe).
46
+ 2. **Don't normalize float32 in Figma** — it is a no-op (Figma re-quantizes to float32
47
+ on store). Normalize at the export boundary instead (`Math.round(v*100)/100`).
48
+ 3. **Don't delete-and-recreate variables to rename** — it unbinds everything. Rename
49
+ in place to preserve Figma IDs (and therefore every existing binding).
50
+ 4. **Don't trust `tsc` / build to catch Tailwind color-utility removal** — deleted
51
+ utilities become *silent no-ops*. Guard repo-wide across all `.tsx`/`.ts` files
52
+ except generated and test files, and let Chromatic be the net.
53
+ 5. **Don't assume `build-storybook` exercises all SCSS** — story-unreachable modules
54
+ (and a dead `@import` of a deleted partial) only fail when the real app renders.
55
+ Run the app and spot-check 5–7 routes before declaring an SCSS change done.
56
+ 6. **Don't carry `/opacity` modifiers onto var-based tokens** — convert to
57
+ `color-mix(in srgb, var(--…) NN%, transparent)` or channel-based alpha.
58
+ 7. **Don't hand-edit generated files** — change the source and re-run `tokens:sync`.
59
+
60
+ ## The safe retrofit sequence
61
+
62
+ Run these phases in order; `retrofit-planner` gates each one with a human
63
+ confirmation. The ordering rules are not arbitrary — each prevents a specific class
64
+ of damage.
65
+
66
+ 1. **audit** — measure both sides (`design-system-audit`). Size the code surface and
67
+ inventory the Figma file with verified per-class reads. Compute `percentSemantic`
68
+ (manifest `audit.percentSemantic`): a system that is already largely semantic is a
69
+ **rename-in-place + cleanup** job; a low-semantic one is closer to a **rewrite**.
70
+ The higher the percentage, the lighter the retrofit — let it right-size the effort.
71
+ 2. **refine** — rename/realign variables **in place** (`token-builder` brownfield
72
+ branch). Never delete-and-recreate (guardrail 3); run a binding-survival audit.
73
+ 3. **rebind** — reconcile components onto the refined variables, preserving IDs. No
74
+ dedicated tool — the `retrofit-planner` orchestrator drives this step directly.
75
+ 4. **sync** — run the sync layer with the brownfield transforms (alpha channels,
76
+ opacity 0–100→0–1, float32 rounding at the export boundary).
77
+ 5. **baseline** — capture a Chromatic baseline **before** any code retrofit, so
78
+ intended drift-fixes are distinguishable from regressions.
79
+ 6. **code** — retrofit the codebase with **dual output**: new and old tokens coexist
80
+ during the transition.
81
+ 7. **cleanup** — remove old outputs **only** after a zero-reference grep passes (the
82
+ repo-wide token-removal guard).
83
+
84
+ ## The verification triad
85
+
86
+ No single check catches everything; all three are necessary on every retrofit:
87
+
88
+ 1. **`check-types`** (TypeScript) — blind to Tailwind silent no-ops.
89
+ 2. **`build-storybook` + Chromatic snapshots** — the visual-regression net; blind to
90
+ story-unreachable code. **Chromatic, not `tsc`/build, is the source of truth** for
91
+ color-utility removal.
92
+ 3. **Run the actual app** + spot-check real routes — the only thing that exercises
93
+ story-unreachable SCSS.
@@ -0,0 +1,70 @@
1
+ # Coding level — calibrating how much to explain
2
+
3
+ The user has a `user.codingLevel` recorded in the manifest. It governs **how
4
+ much code/git/terminal concepts are explained** in the code-touching skills
5
+ (repository-builder, token-sync-layer, storybook-chromatic-builder, and the
6
+ orchestrator). It is set once in `figma-environment-setup` (skill 0) and can be
7
+ changed anytime the user asks.
8
+
9
+ ## Critical principle: level changes EXPLANATION, never CAPABILITY
10
+
11
+ A `new` user and a `comfortable` user get the **exact same repo, the exact same
12
+ secrets setup, the exact same outputs.** The only thing that changes is how much
13
+ the skill narrates concepts along the way. Never give a beginner a lesser
14
+ system; never withhold a step. Same destination, different amount of teaching.
15
+
16
+ The **hard safety rules never scale** with level. Regardless of level:
17
+ - A secret value (token, key, password) never passes through the chat.
18
+ - Secrets never get committed to code; env files holding them are gitignored.
19
+ - Claude never enters credentials into web forms or creates secrets on the
20
+ user's behalf — it tells the user exactly where to put them.
21
+
22
+ Only the *explanation* of these rules scales, not the rules themselves.
23
+
24
+ ## The three levels
25
+
26
+ - **`new`** — has never set up a GitHub repo, made an env file, or used a
27
+ terminal much. **Default if unsure.** Explain every concept the first time it
28
+ appears, in one plain sentence: what a repo is, what an env file is, why
29
+ secrets are gitignored, what a "secrets vault" / GitHub Actions secret is.
30
+ Give exact click paths for anything outside the chat. Verify each step worked
31
+ before moving on (e.g. confirm CI went green after they add a secret). Be warm
32
+ and patient; assume zero terminal fluency beyond what you walk them through.
33
+
34
+ - **`some`** — has used git/GitHub and run commands, but isn't an expert. Brief
35
+ reminders, not full lessons. Skip "what is a token" but still confirm the
36
+ specific click path or command, and still verify the important steps. Assume
37
+ they can run a command you give them without hand-holding, but don't assume
38
+ they remember exactly where GitHub's secrets settings live.
39
+
40
+ - **`comfortable`** — fluent with git, env files, CI, and secrets. Terse and
41
+ direct. Name the action and move on: "Scaffold pnpm+Turborepo, add
42
+ `.env.example`, gitignore `.env`. Put `CHROMATIC_PROJECT_TOKEN` in `.env` and
43
+ as a repo Actions secret." No concept-teaching, no click paths unless asked.
44
+ Assume terminal fluency.
45
+
46
+ ## How to determine the level (skill 0)
47
+
48
+ Don't ask "are you technical?" — self-assessment is unreliable and people
49
+ over- or under-claim. Anchor to **concrete, recognizable experiences** and infer
50
+ the level from the answers:
51
+
52
+ - "Have you set up a GitHub repository before?"
53
+ - "Have you used a command line / terminal before?"
54
+ - "Have you worked with environment variables or `.env` files?"
55
+
56
+ Map roughly: no to most → `new`; yes to some, hesitant on others → `some`; yes
57
+ and casual about all → `comfortable`. Confirm the inferred level in plain terms
58
+ ("Sounds like you're comfortable with the code side — I'll keep things brief and
59
+ skip the basics. Tell me if you want more detail anytime.") and record it.
60
+
61
+ When in doubt, choose the **lower** level — over-explaining is recoverable
62
+ (the user says "you can skip that"), under-explaining can strand a beginner.
63
+
64
+ ## Applying it
65
+
66
+ Every code-touching skill reads `user.codingLevel` at the start and calibrates
67
+ its prose accordingly. The skill's *actions* are identical across levels; only
68
+ the surrounding explanation differs. If the user seems mismatched to their
69
+ recorded level mid-task (a `comfortable` user asking what an env file is, or a
70
+ `new` user breezing ahead), gently offer to adjust it.
@@ -0,0 +1,113 @@
1
+ # Crosswalk schema — `crosswalk.json`
2
+
3
+ The crosswalk is the backbone artifact of a brownfield retrofit: a persistent,
4
+ machine-readable **three-way map** between the new token, the old Figma variable,
5
+ and the old code identifier(s). It drives the code retrofit and the
6
+ `tokens:validate` CI gate. Built by the `token-crosswalk-builder` skill; consumed
7
+ by the validator and reverse-index scripts (`scripts/`). The machine contract is
8
+ `${CLAUDE_PLUGIN_ROOT}/scripts/crosswalk.schema.json`; this doc is its prose home.
9
+
10
+ ## Where it lives
11
+
12
+ `packages/tokens/crosswalk.json`, beside the DTCG intermediate
13
+ `packages/tokens/dtcg/tokens.json` that `token-sync-layer` emits. The manifest's
14
+ `tokenCrosswalk.path` records the actual path. (Spec §8 shows `tokens/crosswalk.json`
15
+ illustratively; the standard monorepo path is `packages/tokens/crosswalk.json`.)
16
+
17
+ ## Top-level shape
18
+
19
+ ```jsonc
20
+ {
21
+ "$schema": "./crosswalk.schema.json",
22
+ "version": 1,
23
+ "tokens": [ /* rows */ ]
24
+ }
25
+ ```
26
+
27
+ `$schema` is optional but recommended — editors use it to validate the file against `crosswalk.schema.json` inline.
28
+
29
+ ## Row columns
30
+
31
+ | Field | Type | Meaning |
32
+ | --- | --- | --- |
33
+ | `newToken` | string | DTCG dot-path, exactly as `token-sync-layer` emits it (`color.text.primary`). This is the key the validator resolves against the DTCG tokens. |
34
+ | `newValue` | string | The **resolved leaf value** — aliases followed to a literal. For a semantic token whose `$value` is `{color.gray.900}`, this is the primitive literal (`#111827`), never the `{…}` reference. |
35
+ | `tier` | `"primitive"` \| `"semantic"` | Which tier the new token belongs to. |
36
+ | `figmaOld` | string \| null | The old Figma variable name/path being reconciled, or `null` for an `added` token with no prior Figma variable. |
37
+ | `codeTokens` | string[] | Old code identifiers this token replaces (`$primary-red`, `bg-primary-red`, `Colors.primaryRed`, `--primary-red`). May be `[]`. Drives the reverse index. |
38
+ | `status` | enum | The reconciliation status — see below. |
39
+ | `recommendedSemantic` | string \| null | An optional suggested semantic token to migrate a raw/primitive usage toward. |
40
+
41
+ ## `status` enum
42
+
43
+ Kebab-case, from the Sweet case study (151 renamed, 42 added, 12 aligned,
44
+ 3 mapped-nearest, 2 drift-fix):
45
+
46
+ | `status` | Meaning |
47
+ | --- | --- |
48
+ | `aligned` | New token already matches the old one in name and value — no change needed. |
49
+ | `renamed` | Same value, new name. The bulk of a ~90%-semantic retrofit. |
50
+ | `drift-fix` | The old value was wrong/inconsistent; the new value intentionally differs (a deliberate fix, distinguishable from a regression via the Chromatic baseline). |
51
+ | `added` | A new token with no prior Figma variable (`figmaOld: null`). |
52
+ | `mapped-nearest` | No exact old equivalent; mapped to the nearest new token (a judgment call worth review). |
53
+
54
+ ## Status-count rollup (kebab → camelCase)
55
+
56
+ The manifest's `tokenCrosswalk.statusCounts` uses camelCase keys. The validator
57
+ emits the rollup in this shape so the skill can copy it straight into the manifest:
58
+
59
+ | Row `status` | `statusCounts` key |
60
+ | --- | --- |
61
+ | `aligned` | `aligned` |
62
+ | `renamed` | `renamed` |
63
+ | `drift-fix` | `driftFix` |
64
+ | `added` | `added` |
65
+ | `mapped-nearest` | `mappedNearest` |
66
+
67
+ ## The validation gate
68
+
69
+ `tokens:validate` resolves every `newToken` against `packages/tokens/dtcg/tokens.json`
70
+ (following `{…}` alias chains to a leaf) and asserts the resolved value equals the
71
+ row's `newValue`, for **every** row (the N/N gate — Sweet passed 210/210). Value
72
+ comparison is case-insensitive and trimmed, so `#EF4444` and `#ef4444` are equal. A
73
+ token present in the crosswalk but absent from the DTCG source is a failure
74
+ (reported as *missing*), never silently skipped — this honors the read-discipline
75
+ principle in `${CLAUDE_PLUGIN_ROOT}/references/brownfield-retrofit.md`.
76
+
77
+ ## Worked example
78
+
79
+ ```jsonc
80
+ {
81
+ "$schema": "./crosswalk.schema.json",
82
+ "version": 1,
83
+ "tokens": [
84
+ {
85
+ "newToken": "color.gray.900",
86
+ "newValue": "#111827",
87
+ "tier": "primitive",
88
+ "figmaOld": "grey/900",
89
+ "codeTokens": ["$grey-900"],
90
+ "status": "renamed",
91
+ "recommendedSemantic": "color.text.primary"
92
+ },
93
+ {
94
+ "newToken": "color.text.primary",
95
+ "newValue": "#111827",
96
+ "tier": "semantic",
97
+ "figmaOld": "Text/Default",
98
+ "codeTokens": ["$text-default", "text-grey-900"],
99
+ "status": "renamed",
100
+ "recommendedSemantic": null
101
+ },
102
+ {
103
+ "newToken": "color.surface.raised",
104
+ "newValue": "#ffffff",
105
+ "tier": "semantic",
106
+ "figmaOld": null,
107
+ "codeTokens": [],
108
+ "status": "added",
109
+ "recommendedSemantic": null
110
+ }
111
+ ]
112
+ }
113
+ ```