synthesisui 0.16.4 → 0.16.6

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.
@@ -264,6 +264,53 @@ function verdict(d, hasSystem, overruled, conflicts) {
264
264
  }
265
265
  return lines;
266
266
  }
267
+ /**
268
+ * Wiring is a property of the PROJECT, never of the scope being read.
269
+ *
270
+ * This ran inside the scoped walk, so `doctor app/login` read only that folder
271
+ * - and the import lives in `app/globals.css`. It concluded "installed, but not
272
+ * wired up yet" about a project that was perfectly wired (my-test4, 27/07).
273
+ *
274
+ * Which would be a mild annoyance, except the managed block now tells the agent
275
+ * to run `doctor <the file you just wrote>` after every edit. The false alarm
276
+ * fires on every loop, and an agent that believes the system is unwired starts
277
+ * repairing wiring that was already correct - editing the one file we most need
278
+ * it to leave alone.
279
+ *
280
+ * The system itself was always resolved from the root. So is this now.
281
+ */
282
+ async function readWiring(root, slug) {
283
+ const w = {
284
+ imported: false,
285
+ scoped: false,
286
+ /** `init` wrote a fonts file for this project (Next targets only). */
287
+ fontsWritten: false,
288
+ /** …and the stylesheet actually maps it onto the system's type tokens. */
289
+ fontsMapped: false,
290
+ };
291
+ if (!slug)
292
+ return w;
293
+ for await (const file of walk(root)) {
294
+ const src = await readFile(file, "utf8").catch(() => "");
295
+ if (!src)
296
+ continue;
297
+ if (src.includes(`_synthesisui/ds/${slug}/tokens.css`))
298
+ w.imported = true;
299
+ if (src.includes(`data-ds="${slug}"`))
300
+ w.scoped = true;
301
+ // The requirement that stayed invisible. `init` writes a fonts file and
302
+ // asks for two more edits; an agent told to check only the first two did
303
+ // exactly that, stopped, and left the project rendering in the framework's
304
+ // default face (my-test2, 27/07). What the checker checks is what gets done.
305
+ if (src.includes("--font-ds-") && /next\/font/.test(src))
306
+ w.fontsWritten = true;
307
+ if (/--ds-typography-families-\w+\s*:\s*var\(\s*--font-ds-/.test(src))
308
+ w.fontsMapped = true;
309
+ if (w.imported && w.scoped && w.fontsMapped)
310
+ break;
311
+ }
312
+ return w;
313
+ }
267
314
  export async function doctor(opts) {
268
315
  const root = resolve(opts.dir ?? process.cwd());
269
316
  const scopes = (opts.scopes ?? []).map((s) => resolve(root, s));
@@ -292,20 +339,12 @@ export async function doctor(opts) {
292
339
  *
293
340
  * Nobody debugs from 0%. They conclude the product does not work.
294
341
  */
295
- const wiring = { imported: false, scoped: false };
342
+ const wiring = await readWiring(root, table.slug);
296
343
  for await (const file of scopes.length > 0 ? walkAll(scopes) : walk(root)) {
297
344
  const src = await readFile(file, "utf8").catch(() => "");
298
345
  if (!src)
299
346
  continue;
300
347
  const rel = relative(root, file);
301
- // The two facts that decide whether an installed system reaches the
302
- // browser at all. Free: these files are already open and in memory.
303
- if (table.slug) {
304
- if (src.includes(`_synthesisui/ds/${table.slug}/tokens.css`))
305
- wiring.imported = true;
306
- if (src.includes(`data-ds="${table.slug}"`))
307
- wiring.scoped = true;
308
- }
309
348
  reports.push(scanSource(rel, src, table));
310
349
  if (recipes.size > 0) {
311
350
  for (const o of findOverrides(src, recipes))
@@ -378,7 +417,11 @@ export async function doctor(opts) {
378
417
  // Before the number, because the number is the thing that misleads. An
379
418
  // installed-but-unwired system reads 0%, and 0% reads as "broken product"
380
419
  // rather than "one import missing".
381
- const unwired = table.source === "installed" && (!wiring.imported || !wiring.scoped);
420
+ // Fonts only count as missing when `init` actually wrote the file - a
421
+ // non-Next project has no fonts.ts and must not be nagged about one.
422
+ const fontsPending = wiring.fontsWritten && !wiring.fontsMapped;
423
+ const unwired = table.source === "installed" &&
424
+ (!wiring.imported || !wiring.scoped || fontsPending);
382
425
  if (unwired) {
383
426
  console.log("");
384
427
  console.log(body(`${table.name ?? table.slug} is installed - but not wired up yet.`));
@@ -389,9 +432,28 @@ export async function doctor(opts) {
389
432
  console.log(body(wiring.scoped
390
433
  ? ` ✓ data-ds="${table.slug}" found`
391
434
  : ` ✗ no element carries data-ds="${table.slug}"`));
435
+ if (wiring.fontsWritten) {
436
+ console.log(body(wiring.fontsMapped
437
+ ? " ✓ the type from fonts.ts is mapped onto the system"
438
+ : " ✗ fonts.ts exists but nothing maps it - the system's type is not being used"));
439
+ }
392
440
  console.log("");
393
- console.log(body(`Until both are true, none of the ${table.byName.size} tokens reach the browser`));
394
- console.log(body("and the number below cannot mean anything."));
441
+ // Three requirements now, and they fail differently. Missing the import or
442
+ // the scope means NOTHING reaches the browser and the number below is
443
+ // noise. Missing only the type mapping means colour and spacing are
444
+ // working and the faces are not - saying "nothing reaches the browser"
445
+ // there would be false, and a report that overstates is one nobody trusts
446
+ // the next time.
447
+ const blocked = !wiring.imported || !wiring.scoped;
448
+ if (blocked) {
449
+ console.log(body(`Until the first two are true, none of the ${table.byName.size} tokens reach the`));
450
+ console.log(body("browser and the number below cannot mean anything."));
451
+ }
452
+ else {
453
+ console.log(body("Colour and spacing are working. Type is not: the system's faces"));
454
+ console.log(body("are declared and nothing points at them, so the page renders in"));
455
+ console.log(body("whatever the framework picked."));
456
+ }
395
457
  console.log(body("The exact snippets are in the output of `init`."));
396
458
  }
397
459
  if (hasSystem && measurable) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.4",
3
+ "version": "0.16.6",
4
4
  "description": "Bring SynthesisUI design systems into any project - tokens, typed components, whole pages and an agent-ready CLAUDE.md manifest.",
5
5
  "type": "module",
6
6
  "bin": {