@radicool/throughline 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/adapters/codex/AGENTS.md +29 -0
- package/adapters/codex/codex-mcp.toml +4 -0
- package/adapters/codex/prompts/component-builder.md +272 -0
- package/adapters/codex/prompts/component-pipeline.md +81 -0
- package/adapters/codex/prompts/design-system-audit.md +122 -0
- package/adapters/codex/prompts/design-system-status.md +41 -0
- package/adapters/codex/prompts/figma-environment-setup.md +456 -0
- package/adapters/codex/prompts/icon-system-builder.md +268 -0
- package/adapters/codex/prompts/new-component.md +13 -0
- package/adapters/codex/prompts/repository-builder.md +163 -0
- package/adapters/codex/prompts/retrofit-planner.md +136 -0
- package/adapters/codex/prompts/start.md +22 -0
- package/adapters/codex/prompts/storybook-chromatic-builder.md +261 -0
- package/adapters/codex/prompts/sync-figma-tokens.md +22 -0
- package/adapters/codex/prompts/token-builder.md +361 -0
- package/adapters/codex/prompts/token-crosswalk-builder.md +120 -0
- package/adapters/codex/prompts/token-sheet-builder.md +162 -0
- package/adapters/codex/prompts/token-sync-layer.md +232 -0
- package/adapters/cursor/.cursor/commands/design-system-status.md +41 -0
- package/adapters/cursor/.cursor/commands/new-component.md +13 -0
- package/adapters/cursor/.cursor/commands/start.md +22 -0
- package/adapters/cursor/.cursor/commands/sync-figma-tokens.md +22 -0
- package/adapters/cursor/.cursor/mcp.json +14 -0
- package/adapters/cursor/.cursor/rules/component-builder.mdc +276 -0
- package/adapters/cursor/.cursor/rules/component-pipeline.mdc +85 -0
- package/adapters/cursor/.cursor/rules/design-system-audit.mdc +126 -0
- package/adapters/cursor/.cursor/rules/figma-environment-setup.mdc +460 -0
- package/adapters/cursor/.cursor/rules/icon-system-builder.mdc +272 -0
- package/adapters/cursor/.cursor/rules/repository-builder.mdc +167 -0
- package/adapters/cursor/.cursor/rules/retrofit-planner.mdc +140 -0
- package/adapters/cursor/.cursor/rules/storybook-chromatic-builder.mdc +265 -0
- package/adapters/cursor/.cursor/rules/token-builder.mdc +365 -0
- package/adapters/cursor/.cursor/rules/token-crosswalk-builder.mdc +124 -0
- package/adapters/cursor/.cursor/rules/token-sheet-builder.mdc +166 -0
- package/adapters/cursor/.cursor/rules/token-sync-layer.mdc +236 -0
- package/adapters/generic/AGENTS.md +46 -0
- package/adapters/generic/commands/design-system-status.md +41 -0
- package/adapters/generic/commands/new-component.md +13 -0
- package/adapters/generic/commands/start.md +22 -0
- package/adapters/generic/commands/sync-figma-tokens.md +22 -0
- package/adapters/generic/skills/component-builder/SKILL.md +272 -0
- package/adapters/generic/skills/component-pipeline/SKILL.md +81 -0
- package/adapters/generic/skills/design-system-audit/SKILL.md +122 -0
- package/adapters/generic/skills/figma-environment-setup/SKILL.md +456 -0
- package/adapters/generic/skills/icon-system-builder/SKILL.md +268 -0
- package/adapters/generic/skills/repository-builder/SKILL.md +163 -0
- package/adapters/generic/skills/retrofit-planner/SKILL.md +136 -0
- package/adapters/generic/skills/storybook-chromatic-builder/SKILL.md +261 -0
- package/adapters/generic/skills/token-builder/SKILL.md +361 -0
- package/adapters/generic/skills/token-crosswalk-builder/SKILL.md +120 -0
- package/adapters/generic/skills/token-sheet-builder/SKILL.md +162 -0
- package/adapters/generic/skills/token-sync-layer/SKILL.md +232 -0
- package/package.json +29 -0
- package/references/brainstorm-before-build.md +139 -0
- package/references/brownfield-retrofit.md +93 -0
- package/references/coding-level.md +70 -0
- package/references/crosswalk-schema.md +113 -0
- package/references/figma-component-standards.md +532 -0
- package/references/figma-publishing.md +125 -0
- package/references/figma-scripting.md +278 -0
- package/references/manifest-schema.md +341 -0
- package/references/scaling-up-handoff.md +61 -0
- package/references/sync-adapters.md +141 -0
- package/scripts/README.md +78 -0
- package/scripts/adapters/emit-codex.mjs +58 -0
- package/scripts/adapters/emit-cursor.mjs +26 -0
- package/scripts/adapters/emit-generic.mjs +41 -0
- package/scripts/adapters/generate.mjs +73 -0
- package/scripts/adapters/read-sources.mjs +54 -0
- package/scripts/adapters/translate.mjs +51 -0
- package/scripts/build-reverse-index.mjs +56 -0
- package/scripts/crosswalk.schema.json +33 -0
- package/scripts/grep-color-usage.mjs +143 -0
- package/scripts/guard-token-removal.mjs +95 -0
- package/scripts/install.mjs +143 -0
- package/scripts/lib/crosswalk.mjs +91 -0
- package/scripts/validate-crosswalk.mjs +96 -0
|
@@ -0,0 +1,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
|
+
```
|