@radicool/throughline 0.15.0 → 0.17.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/README.md +2 -1
- package/adapters/codex/prompts/token-crosswalk-builder.md +2 -0
- package/adapters/codex/prompts/token-sync-layer.md +64 -4
- package/adapters/cursor/.cursor/rules/token-crosswalk-builder.mdc +2 -0
- package/adapters/cursor/.cursor/rules/token-sync-layer.mdc +64 -4
- package/adapters/generic/skills/token-crosswalk-builder/SKILL.md +2 -0
- package/adapters/generic/skills/token-sync-layer/SKILL.md +64 -4
- package/package.json +1 -1
- package/references/manifest-schema.md +2 -2
- package/references/native-adapter-config.md +996 -0
- package/references/sync-adapters.md +104 -12
- package/scripts/README.md +14 -3
- package/scripts/build-native-adapter-config.mjs +284 -0
- package/scripts/install.mjs +3 -2
- package/scripts/lib/dtcg.mjs +203 -0
- package/scripts/lib/native-literal.mjs +205 -0
- package/scripts/lib/sd-native.mjs +832 -0
- package/scripts/validate-crosswalk.mjs +3 -29
- package/scripts/validate-token-output.mjs +376 -0
package/README.md
CHANGED
|
@@ -205,7 +205,8 @@ Future improvements and planned capabilities. Have a request? **[Open an issue](
|
|
|
205
205
|
- **Expanded component starters** — a larger foundational kit out of the box.
|
|
206
206
|
- **Richer status & auditing** — more from `/design-system-status`, including drift detection between Figma and code.
|
|
207
207
|
- **Built-in accessibility checks** — automatic a11y validation when tokens and components are created, so modes can't be built with poor color contrast and components can't ship with accessibility gaps. Catches issues at creation time rather than in review.
|
|
208
|
-
- **
|
|
208
|
+
- **Token fan-out to more platforms** — the DTCG token source is platform-neutral, and web targets are in daily use. Native targets are **validated per build, not assumed** — iOS/Swift is a curated adapter whose Style Dictionary configuration ships as tested code, and Android/Kotlin uses the same configuration through the Tier 2 protocol — `tokens:validate-output` checks generated native output against its source, because the stock transforms have been measured emitting wrong-but-compiling values.
|
|
209
|
+
- **Native component code generation** — producing a SwiftUI view or a Compose composable the way Storybook components are produced for React. This does not exist yet; it is a separate, larger effort than token fan-out, and the two were previously described as one roadmap item.
|
|
209
210
|
|
|
210
211
|
Versioning follows [Semantic Versioning](https://semver.org). The current version lives in [`.claude-plugin/plugin.json`](.claude-plugin/plugin.json); every release is recorded in [`CHANGELOG.md`](CHANGELOG.md).
|
|
211
212
|
|
|
@@ -65,6 +65,8 @@ Copy these from `.throughline/scripts/` into the user's repo **verbatim**
|
|
|
65
65
|
(they are zero-dependency and version with the user's repo so their CI can run them):
|
|
66
66
|
|
|
67
67
|
- `lib/crosswalk.mjs` → `packages/tokens/scripts/lib/crosswalk.mjs`
|
|
68
|
+
- `lib/dtcg.mjs` → `packages/tokens/scripts/lib/dtcg.mjs` (required by
|
|
69
|
+
`validate-crosswalk.mjs` — copying the validator without it breaks the gate at import)
|
|
68
70
|
- `validate-crosswalk.mjs` → `packages/tokens/scripts/validate-crosswalk.mjs`
|
|
69
71
|
- `build-reverse-index.mjs` → `packages/tokens/scripts/build-reverse-index.mjs`
|
|
70
72
|
- `guard-token-removal.mjs` → `packages/tokens/scripts/guard-token-removal.mjs`
|
|
@@ -44,8 +44,8 @@ Ask which platform(s) the user is building for. Read
|
|
|
44
44
|
- **Curated (Tier 1):** `shadcn`, `tailwind`, `mui`, `vanilla-css`, `ios-swift`.
|
|
45
45
|
Vetted presets — high confidence.
|
|
46
46
|
- **Generated (Tier 2):** any other framework (Ant Design, Chakra, HeroUI,
|
|
47
|
-
Android/Kotlin, Flutter, etc.). The skill generates an adapter and
|
|
48
|
-
against a real component before trusting it.
|
|
47
|
+
Android/Kotlin, Flutter, etc.). The skill generates an adapter and
|
|
48
|
+
verifies it against a real component before trusting it.
|
|
49
49
|
|
|
50
50
|
**Always tell the user which tier they're on.** If they name a curated one, say
|
|
51
51
|
it'll be solid. If they name anything else, be honest: "That's not one I have a
|
|
@@ -139,11 +139,53 @@ register the platform, transform group, format, and `outputReferences`
|
|
|
139
139
|
flattens). Web adapters emit `:root`/`.dark` (or `[data-theme]`); the shadcn
|
|
140
140
|
adapter also emits a Tailwind preset.
|
|
141
141
|
|
|
142
|
+
**Native targets import the shipped configuration; they do not transcribe it.**
|
|
143
|
+
Copy `.throughline/scripts/lib/sd-native.mjs` into
|
|
144
|
+
`packages/tokens/scripts/lib/` (see Step 4) and call it. The stock `ios-swift`
|
|
145
|
+
and `compose` transform groups emit every `px`-authored dimension at ×16 its
|
|
146
|
+
value — valid, compiling, silently wrong — and mishandle `color-mix()` and
|
|
147
|
+
dual-node DTCG the same way. Never build a native platform from a stock
|
|
148
|
+
`transformGroup`.
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
import StyleDictionary from 'style-dictionary';
|
|
152
|
+
import { registerNativeTransforms, nativePlatform, nativeSources }
|
|
153
|
+
from './scripts/lib/sd-native.mjs';
|
|
154
|
+
|
|
155
|
+
registerNativeTransforms(StyleDictionary);
|
|
156
|
+
|
|
157
|
+
for (const mode of MODES) { // e.g. ['light', 'dark']
|
|
158
|
+
const sd = new StyleDictionary({
|
|
159
|
+
source: nativeSources(sourcesFor(mode)), // guards against a mode collapse
|
|
160
|
+
preprocessors: ['dtcg/resolve-dual-node'],
|
|
161
|
+
platforms: {
|
|
162
|
+
ios: nativePlatform({ platform: 'ios-swift', buildPath: `ios/${mode}/` }),
|
|
163
|
+
// android also requires packageName:
|
|
164
|
+
// android: nativePlatform({ platform: 'android-kotlin',
|
|
165
|
+
// buildPath: `android/${mode}/`, packageName: 'com.example.tokens' }),
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
await sd.buildAllPlatforms();
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**One build per mode combination, and never a glob.** Style Dictionary dedupes
|
|
173
|
+
by dot-path, so a single build over the whole token directory collapses light
|
|
174
|
+
and dark into whichever file sorted last, silently dropping a mode. Passing each
|
|
175
|
+
mode's sources through `nativeSources` turns that into a thrown error naming the
|
|
176
|
+
colliding paths. The `dtcg/resolve-dual-node` preprocessor throws too, on its
|
|
177
|
+
own collision: a dual node's hoisted child renamed to a camel-joined name that
|
|
178
|
+
an existing sibling or an earlier hoist in the same pass already has. Then run
|
|
179
|
+
`tokens:validate-output` against each generated file with that same source
|
|
180
|
+
list. See `.throughline/references/native-adapter-config.md`.
|
|
181
|
+
|
|
142
182
|
**Execution model — subagent dispatch with model routing.** Generating each
|
|
143
183
|
platform's output is independent and verifiable. If your host supports subagent
|
|
144
184
|
dispatch, dispatch **one `code-executor` per adapter** — each produces its
|
|
145
|
-
platform's files and verifies them (the config builds, the expected
|
|
146
|
-
appear, references resolve for
|
|
185
|
+
platform's files and verifies them (for web: the config builds, the expected
|
|
186
|
+
files appear, references resolve; for native: `tokens:validate-output` passes —
|
|
187
|
+
"the config builds" is not verification, it is the condition under which all
|
|
188
|
+
four known native failure modes ship silently) — then a **`reviewer`**
|
|
147
189
|
to check each before combining. Choose each subagent's model from its role tier
|
|
148
190
|
per `.throughline/references/agent-routing.md` (`code-executor` → fast,
|
|
149
191
|
`reviewer` → balanced), and only dispatch once each adapter's spec is complete
|
|
@@ -159,6 +201,24 @@ as **build artifacts** — regenerated every sync, never hand-edited. Wire
|
|
|
159
201
|
`packages/tokens/package.json` to export them so the UI package, Storybook, and
|
|
160
202
|
any future app consume them.
|
|
161
203
|
|
|
204
|
+
**Install the native token toolkit — all four files, as a set.** Copy
|
|
205
|
+
`.throughline/scripts/validate-token-output.mjs` into
|
|
206
|
+
`packages/tokens/scripts/`, and
|
|
207
|
+
`.throughline/scripts/lib/dtcg.mjs`,
|
|
208
|
+
`.throughline/scripts/lib/native-literal.mjs`, and
|
|
209
|
+
`.throughline/scripts/lib/sd-native.mjs` into
|
|
210
|
+
`packages/tokens/scripts/lib/`. `sd-native.mjs` and the validator both import
|
|
211
|
+
`dtcg.mjs` and `native-literal.mjs`, so copying any of them without the others
|
|
212
|
+
breaks at import. Then register the gate so it stays live on every future sync:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
"tokens:validate-output": "node scripts/validate-token-output.mjs --min-match 1"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Invoke it once per native output file, passing the same `--source` list that
|
|
219
|
+
file's build used. `--min-match 1` is what makes it a gate: the flag defaults to
|
|
220
|
+
`0.5`, so without it a 60% match rate exits `0`.
|
|
221
|
+
|
|
162
222
|
## Step 4.5 — Icon code sync (install check + custom SVGR)
|
|
163
223
|
|
|
164
224
|
Icons reach code differently from tokens, so handle them here if the system has
|
|
@@ -69,6 +69,8 @@ Copy these from `.throughline/scripts/` into the user's repo **verbatim**
|
|
|
69
69
|
(they are zero-dependency and version with the user's repo so their CI can run them):
|
|
70
70
|
|
|
71
71
|
- `lib/crosswalk.mjs` → `packages/tokens/scripts/lib/crosswalk.mjs`
|
|
72
|
+
- `lib/dtcg.mjs` → `packages/tokens/scripts/lib/dtcg.mjs` (required by
|
|
73
|
+
`validate-crosswalk.mjs` — copying the validator without it breaks the gate at import)
|
|
72
74
|
- `validate-crosswalk.mjs` → `packages/tokens/scripts/validate-crosswalk.mjs`
|
|
73
75
|
- `build-reverse-index.mjs` → `packages/tokens/scripts/build-reverse-index.mjs`
|
|
74
76
|
- `guard-token-removal.mjs` → `packages/tokens/scripts/guard-token-removal.mjs`
|
|
@@ -48,8 +48,8 @@ Ask which platform(s) the user is building for. Read
|
|
|
48
48
|
- **Curated (Tier 1):** `shadcn`, `tailwind`, `mui`, `vanilla-css`, `ios-swift`.
|
|
49
49
|
Vetted presets — high confidence.
|
|
50
50
|
- **Generated (Tier 2):** any other framework (Ant Design, Chakra, HeroUI,
|
|
51
|
-
Android/Kotlin, Flutter, etc.). The skill generates an adapter and
|
|
52
|
-
against a real component before trusting it.
|
|
51
|
+
Android/Kotlin, Flutter, etc.). The skill generates an adapter and
|
|
52
|
+
verifies it against a real component before trusting it.
|
|
53
53
|
|
|
54
54
|
**Always tell the user which tier they're on.** If they name a curated one, say
|
|
55
55
|
it'll be solid. If they name anything else, be honest: "That's not one I have a
|
|
@@ -143,11 +143,53 @@ register the platform, transform group, format, and `outputReferences`
|
|
|
143
143
|
flattens). Web adapters emit `:root`/`.dark` (or `[data-theme]`); the shadcn
|
|
144
144
|
adapter also emits a Tailwind preset.
|
|
145
145
|
|
|
146
|
+
**Native targets import the shipped configuration; they do not transcribe it.**
|
|
147
|
+
Copy `.throughline/scripts/lib/sd-native.mjs` into
|
|
148
|
+
`packages/tokens/scripts/lib/` (see Step 4) and call it. The stock `ios-swift`
|
|
149
|
+
and `compose` transform groups emit every `px`-authored dimension at ×16 its
|
|
150
|
+
value — valid, compiling, silently wrong — and mishandle `color-mix()` and
|
|
151
|
+
dual-node DTCG the same way. Never build a native platform from a stock
|
|
152
|
+
`transformGroup`.
|
|
153
|
+
|
|
154
|
+
```js
|
|
155
|
+
import StyleDictionary from 'style-dictionary';
|
|
156
|
+
import { registerNativeTransforms, nativePlatform, nativeSources }
|
|
157
|
+
from './scripts/lib/sd-native.mjs';
|
|
158
|
+
|
|
159
|
+
registerNativeTransforms(StyleDictionary);
|
|
160
|
+
|
|
161
|
+
for (const mode of MODES) { // e.g. ['light', 'dark']
|
|
162
|
+
const sd = new StyleDictionary({
|
|
163
|
+
source: nativeSources(sourcesFor(mode)), // guards against a mode collapse
|
|
164
|
+
preprocessors: ['dtcg/resolve-dual-node'],
|
|
165
|
+
platforms: {
|
|
166
|
+
ios: nativePlatform({ platform: 'ios-swift', buildPath: `ios/${mode}/` }),
|
|
167
|
+
// android also requires packageName:
|
|
168
|
+
// android: nativePlatform({ platform: 'android-kotlin',
|
|
169
|
+
// buildPath: `android/${mode}/`, packageName: 'com.example.tokens' }),
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
await sd.buildAllPlatforms();
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**One build per mode combination, and never a glob.** Style Dictionary dedupes
|
|
177
|
+
by dot-path, so a single build over the whole token directory collapses light
|
|
178
|
+
and dark into whichever file sorted last, silently dropping a mode. Passing each
|
|
179
|
+
mode's sources through `nativeSources` turns that into a thrown error naming the
|
|
180
|
+
colliding paths. The `dtcg/resolve-dual-node` preprocessor throws too, on its
|
|
181
|
+
own collision: a dual node's hoisted child renamed to a camel-joined name that
|
|
182
|
+
an existing sibling or an earlier hoist in the same pass already has. Then run
|
|
183
|
+
`tokens:validate-output` against each generated file with that same source
|
|
184
|
+
list. See `.throughline/references/native-adapter-config.md`.
|
|
185
|
+
|
|
146
186
|
**Execution model — subagent dispatch with model routing.** Generating each
|
|
147
187
|
platform's output is independent and verifiable. If your host supports subagent
|
|
148
188
|
dispatch, dispatch **one `code-executor` per adapter** — each produces its
|
|
149
|
-
platform's files and verifies them (the config builds, the expected
|
|
150
|
-
appear, references resolve for
|
|
189
|
+
platform's files and verifies them (for web: the config builds, the expected
|
|
190
|
+
files appear, references resolve; for native: `tokens:validate-output` passes —
|
|
191
|
+
"the config builds" is not verification, it is the condition under which all
|
|
192
|
+
four known native failure modes ship silently) — then a **`reviewer`**
|
|
151
193
|
to check each before combining. Choose each subagent's model from its role tier
|
|
152
194
|
per `.throughline/references/agent-routing.md` (`code-executor` → fast,
|
|
153
195
|
`reviewer` → balanced), and only dispatch once each adapter's spec is complete
|
|
@@ -163,6 +205,24 @@ as **build artifacts** — regenerated every sync, never hand-edited. Wire
|
|
|
163
205
|
`packages/tokens/package.json` to export them so the UI package, Storybook, and
|
|
164
206
|
any future app consume them.
|
|
165
207
|
|
|
208
|
+
**Install the native token toolkit — all four files, as a set.** Copy
|
|
209
|
+
`.throughline/scripts/validate-token-output.mjs` into
|
|
210
|
+
`packages/tokens/scripts/`, and
|
|
211
|
+
`.throughline/scripts/lib/dtcg.mjs`,
|
|
212
|
+
`.throughline/scripts/lib/native-literal.mjs`, and
|
|
213
|
+
`.throughline/scripts/lib/sd-native.mjs` into
|
|
214
|
+
`packages/tokens/scripts/lib/`. `sd-native.mjs` and the validator both import
|
|
215
|
+
`dtcg.mjs` and `native-literal.mjs`, so copying any of them without the others
|
|
216
|
+
breaks at import. Then register the gate so it stays live on every future sync:
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
"tokens:validate-output": "node scripts/validate-token-output.mjs --min-match 1"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Invoke it once per native output file, passing the same `--source` list that
|
|
223
|
+
file's build used. `--min-match 1` is what makes it a gate: the flag defaults to
|
|
224
|
+
`0.5`, so without it a 60% match rate exits `0`.
|
|
225
|
+
|
|
166
226
|
## Step 4.5 — Icon code sync (install check + custom SVGR)
|
|
167
227
|
|
|
168
228
|
Icons reach code differently from tokens, so handle them here if the system has
|
|
@@ -65,6 +65,8 @@ Copy these from `.throughline/scripts/` into the user's repo **verbatim**
|
|
|
65
65
|
(they are zero-dependency and version with the user's repo so their CI can run them):
|
|
66
66
|
|
|
67
67
|
- `lib/crosswalk.mjs` → `packages/tokens/scripts/lib/crosswalk.mjs`
|
|
68
|
+
- `lib/dtcg.mjs` → `packages/tokens/scripts/lib/dtcg.mjs` (required by
|
|
69
|
+
`validate-crosswalk.mjs` — copying the validator without it breaks the gate at import)
|
|
68
70
|
- `validate-crosswalk.mjs` → `packages/tokens/scripts/validate-crosswalk.mjs`
|
|
69
71
|
- `build-reverse-index.mjs` → `packages/tokens/scripts/build-reverse-index.mjs`
|
|
70
72
|
- `guard-token-removal.mjs` → `packages/tokens/scripts/guard-token-removal.mjs`
|
|
@@ -44,8 +44,8 @@ Ask which platform(s) the user is building for. Read
|
|
|
44
44
|
- **Curated (Tier 1):** `shadcn`, `tailwind`, `mui`, `vanilla-css`, `ios-swift`.
|
|
45
45
|
Vetted presets — high confidence.
|
|
46
46
|
- **Generated (Tier 2):** any other framework (Ant Design, Chakra, HeroUI,
|
|
47
|
-
Android/Kotlin, Flutter, etc.). The skill generates an adapter and
|
|
48
|
-
against a real component before trusting it.
|
|
47
|
+
Android/Kotlin, Flutter, etc.). The skill generates an adapter and
|
|
48
|
+
verifies it against a real component before trusting it.
|
|
49
49
|
|
|
50
50
|
**Always tell the user which tier they're on.** If they name a curated one, say
|
|
51
51
|
it'll be solid. If they name anything else, be honest: "That's not one I have a
|
|
@@ -139,11 +139,53 @@ register the platform, transform group, format, and `outputReferences`
|
|
|
139
139
|
flattens). Web adapters emit `:root`/`.dark` (or `[data-theme]`); the shadcn
|
|
140
140
|
adapter also emits a Tailwind preset.
|
|
141
141
|
|
|
142
|
+
**Native targets import the shipped configuration; they do not transcribe it.**
|
|
143
|
+
Copy `.throughline/scripts/lib/sd-native.mjs` into
|
|
144
|
+
`packages/tokens/scripts/lib/` (see Step 4) and call it. The stock `ios-swift`
|
|
145
|
+
and `compose` transform groups emit every `px`-authored dimension at ×16 its
|
|
146
|
+
value — valid, compiling, silently wrong — and mishandle `color-mix()` and
|
|
147
|
+
dual-node DTCG the same way. Never build a native platform from a stock
|
|
148
|
+
`transformGroup`.
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
import StyleDictionary from 'style-dictionary';
|
|
152
|
+
import { registerNativeTransforms, nativePlatform, nativeSources }
|
|
153
|
+
from './scripts/lib/sd-native.mjs';
|
|
154
|
+
|
|
155
|
+
registerNativeTransforms(StyleDictionary);
|
|
156
|
+
|
|
157
|
+
for (const mode of MODES) { // e.g. ['light', 'dark']
|
|
158
|
+
const sd = new StyleDictionary({
|
|
159
|
+
source: nativeSources(sourcesFor(mode)), // guards against a mode collapse
|
|
160
|
+
preprocessors: ['dtcg/resolve-dual-node'],
|
|
161
|
+
platforms: {
|
|
162
|
+
ios: nativePlatform({ platform: 'ios-swift', buildPath: `ios/${mode}/` }),
|
|
163
|
+
// android also requires packageName:
|
|
164
|
+
// android: nativePlatform({ platform: 'android-kotlin',
|
|
165
|
+
// buildPath: `android/${mode}/`, packageName: 'com.example.tokens' }),
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
await sd.buildAllPlatforms();
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**One build per mode combination, and never a glob.** Style Dictionary dedupes
|
|
173
|
+
by dot-path, so a single build over the whole token directory collapses light
|
|
174
|
+
and dark into whichever file sorted last, silently dropping a mode. Passing each
|
|
175
|
+
mode's sources through `nativeSources` turns that into a thrown error naming the
|
|
176
|
+
colliding paths. The `dtcg/resolve-dual-node` preprocessor throws too, on its
|
|
177
|
+
own collision: a dual node's hoisted child renamed to a camel-joined name that
|
|
178
|
+
an existing sibling or an earlier hoist in the same pass already has. Then run
|
|
179
|
+
`tokens:validate-output` against each generated file with that same source
|
|
180
|
+
list. See `.throughline/references/native-adapter-config.md`.
|
|
181
|
+
|
|
142
182
|
**Execution model — subagent dispatch with model routing.** Generating each
|
|
143
183
|
platform's output is independent and verifiable. If your host supports subagent
|
|
144
184
|
dispatch, dispatch **one `code-executor` per adapter** — each produces its
|
|
145
|
-
platform's files and verifies them (the config builds, the expected
|
|
146
|
-
appear, references resolve for
|
|
185
|
+
platform's files and verifies them (for web: the config builds, the expected
|
|
186
|
+
files appear, references resolve; for native: `tokens:validate-output` passes —
|
|
187
|
+
"the config builds" is not verification, it is the condition under which all
|
|
188
|
+
four known native failure modes ship silently) — then a **`reviewer`**
|
|
147
189
|
to check each before combining. Choose each subagent's model from its role tier
|
|
148
190
|
per `.throughline/references/agent-routing.md` (`code-executor` → fast,
|
|
149
191
|
`reviewer` → balanced), and only dispatch once each adapter's spec is complete
|
|
@@ -159,6 +201,24 @@ as **build artifacts** — regenerated every sync, never hand-edited. Wire
|
|
|
159
201
|
`packages/tokens/package.json` to export them so the UI package, Storybook, and
|
|
160
202
|
any future app consume them.
|
|
161
203
|
|
|
204
|
+
**Install the native token toolkit — all four files, as a set.** Copy
|
|
205
|
+
`.throughline/scripts/validate-token-output.mjs` into
|
|
206
|
+
`packages/tokens/scripts/`, and
|
|
207
|
+
`.throughline/scripts/lib/dtcg.mjs`,
|
|
208
|
+
`.throughline/scripts/lib/native-literal.mjs`, and
|
|
209
|
+
`.throughline/scripts/lib/sd-native.mjs` into
|
|
210
|
+
`packages/tokens/scripts/lib/`. `sd-native.mjs` and the validator both import
|
|
211
|
+
`dtcg.mjs` and `native-literal.mjs`, so copying any of them without the others
|
|
212
|
+
breaks at import. Then register the gate so it stays live on every future sync:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
"tokens:validate-output": "node scripts/validate-token-output.mjs --min-match 1"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Invoke it once per native output file, passing the same `--source` list that
|
|
219
|
+
file's build used. `--min-match 1` is what makes it a gate: the flag defaults to
|
|
220
|
+
`0.5`, so without it a 60% match rate exits `0`.
|
|
221
|
+
|
|
162
222
|
## Step 4.5 — Icon code sync (install check + custom SVGR)
|
|
163
223
|
|
|
164
224
|
Icons reach code differently from tokens, so handle them here if the system has
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@radicool/throughline",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.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": {
|
|
@@ -291,8 +291,8 @@ bailing or running silently.
|
|
|
291
291
|
|
|
292
292
|
### `sync`
|
|
293
293
|
- `platforms` — array of adapter targets configured, e.g.
|
|
294
|
-
`["shadcn", "
|
|
295
|
-
name is a generated (Tier 2) adapter.
|
|
294
|
+
`["shadcn", "android-kotlin"]`. Curated adapters map to vetted presets; any
|
|
295
|
+
other name is a generated (Tier 2) adapter.
|
|
296
296
|
- `customAdapters` — names of validated generated adapters saved to
|
|
297
297
|
`packages/tokens/adapters/` for reuse, so future syncs don't regenerate them.
|
|
298
298
|
- `lastRun` — ISO timestamp the sync command last ran.
|