synthesisui 0.16.471 → 0.16.472

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.
@@ -48,6 +48,8 @@ const IGNORED = [
48
48
  ".ledger-sent",
49
49
  /** O que a última medição viu, para a próxima dizer o que mudou - descreve ESTE clone. */
50
50
  ".last-sync.json",
51
+ /** O que o sync destacado mandou, esperando o fim do turno seguinte dizer - ver `what-grew.ts` (28/09). */
52
+ ".last-growth.json",
51
53
  "not-expressed.md",
52
54
  /**
53
55
  * O RELATÓRIO QUE O `inspect` ESCREVE - a leitura inteira com forma, para ele abrir no navegador.
@@ -11,6 +11,7 @@ import { governs, ungovernedIn } from "../governed.js";
11
11
  import { readMode } from "../mode.js";
12
12
  import { namesRemoved, previousText, rulesTouchedBy, } from "../rule-touched.js";
13
13
  import { loadSystem } from "./doctor.js";
14
+ import { takeGrowthNote } from "../what-grew.js";
14
15
  const pass = () => ({ continue: true });
15
16
  const speak = (context) => ({
16
17
  continue: true,
@@ -664,6 +665,10 @@ async function endOfTurn(root, input) {
664
665
  const { said } = changed.length > 0
665
666
  ? await checkChanged(root, changed, mode, "turn")
666
667
  : { said: [] };
668
+ /** O que o sync destacado do turno anterior mandou para o rascunho - dito uma vez (re-rodada, 28/09). */
669
+ const grown = await takeGrowthNote(root).catch(() => null);
670
+ if (grown)
671
+ said.push(grown);
667
672
  await moveTurnClock(root);
668
673
  out(said.length === 0
669
674
  ? pass()
@@ -4983,8 +4983,10 @@ export async function runImport(opts) {
4983
4983
  census.scheme = scheme;
4984
4984
  if (!scheme && mustNotGuessPolarity(census)) {
4985
4985
  console.log("");
4986
- console.log(body("Your stylesheet does not say which face this project opens in, and nothing here declares a light or a dark scheme on its own. Nothing was guessed: the measurement is complete and the default stays yours to pick."));
4987
- console.log(body(`Name it with ${paint.strong("--scheme dark")} or ${paint.strong("--scheme light")}, or answer the question this command asks at a terminal.`));
4986
+ console.log(body(
4987
+ /** Desde a "(b)" do dono (28/09): as cores entram como a face única, e a escolha é um clique na tela. */
4988
+ "Your stylesheet does not say which face this project opens in, and nothing here declares a light or a dark scheme on its own. Nothing was guessed: your colours came in as the system's one face."));
4989
+ console.log(body(`Next, if you like: say light or dark on the system's page - one click - or run this with ${paint.strong("--scheme dark")} or ${paint.strong("--scheme light")}.`));
4988
4990
  }
4989
4991
  // The file on disk has to say what we sent, or the next person to read it is
4990
4992
  // reading a different import than the one that happened.
@@ -13,7 +13,7 @@ import { measuredScope, rememberScope } from "../measured-scope.js";
13
13
  import { fromCensus } from "../memory/observation.js";
14
14
  import { reportMeasurement } from "../memory/report.js";
15
15
  import { mergeCensus } from "../merge-census.js";
16
- import { describeGrowth, whatGrew } from "../what-grew.js";
16
+ import { describeGrowth, recordGrowthForTurn, whatGrew } from "../what-grew.js";
17
17
  import { body, paint, section, snippet } from "../output.js";
18
18
  import { repoStateOf } from "../repo-state.js";
19
19
  import { reportWhatIsLeft } from "./align.js";
@@ -617,6 +617,9 @@ export async function remeasure(args) {
617
617
  console.log(section("What your code grew"));
618
618
  for (const l of growth)
619
619
  console.log(body(l));
620
+ /** Sem terminal (o fim do turno), a lista fica para o turno seguinte dizer - ver `recordGrowthForTurn`. */
621
+ if (!process.stdin.isTTY || !process.stdout.isTTY)
622
+ await recordGrowthForTurn(root, growth);
620
623
  if (!(await askToSendGrowth())) {
621
624
  console.log(body("Nothing was sent. Your draft is untouched - run `npx synthesisui sync` again when you want them in."));
622
625
  return null;
@@ -295,7 +295,12 @@
295
295
  * escrita como a função dele (`color("brand")`), nunca `$semantic-brand` (rodada 14 do refinamento). Um
296
296
  * componente escrito antes num projeto desses está sem estilo.
297
297
  */
298
- export const MATERIALISER_SINCE = "0.16.471";
298
+ /**
299
+ * 0.16.471 -> 0.16.472 em 28/09, e o passo 1 dá **SIM**: o `.gitignore` da pasta passa a cobrir `.last-growth.json`, o que
300
+ * o sync destacado deixa para o fim do turno dizer (re-rodada depois do #1631). Uma pasta escrita antes deixaria esse
301
+ * arquivo local entrar num commit.
302
+ */
303
+ export const MATERIALISER_SINCE = "0.16.472";
299
304
  /**
300
305
  * A ÚLTIMA VERSÃO EM QUE O QUE O HOOK RODA MUDOU.
301
306
  *
@@ -467,7 +472,11 @@ export const COUNTED_DIFFERENTLY = "this run counts a value as named only when Y
467
472
  * (`$palette`, `color("brand")`) - rodada 14 do refinamento. Um hook anterior acusa como valor à mão toda cor
468
473
  * que o projeto guarda num mapa.
469
474
  */
470
- export const CHECKER_SINCE = "0.16.471";
475
+ /**
476
+ * 0.16.471 -> 0.16.472 em 28/09, e o passo 1 dá **SIM**: o fim do turno entrega ao agente o que o sync destacado do turno
477
+ * anterior mandou para o rascunho (re-rodada, f12). Um hook anterior deixa esses componentes entrarem calados.
478
+ */
479
+ export const CHECKER_SINCE = "0.16.472";
471
480
  /**
472
481
  * A ÚLTIMA VERSÃO EM QUE OS LEITORES PASSARAM A PRODUZIR UM CENSO DIFERENTE.
473
482
  *
package/dist/what-grew.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
- import { join, relative } from "node:path";
2
+ import { dirname, join, relative } from "node:path";
3
+ import { readStyleSheet } from "./doctor/scss-lens.js";
3
4
  import { loadSystem, walkAll } from "./commands/doctor.js";
4
5
  import { diagnose, scanSource } from "./doctor/scan.js";
5
6
  export async function whatGrew(root, census,
@@ -26,6 +27,9 @@ before) {
26
27
  context.push(report);
27
28
  }
28
29
  }
30
+ /** Os componentes dele que um arquivo monta, cada um uma vez - fora ele mesmo. */
31
+ const own = new Set(now.filter((c) => typeof c.api?.file === "string").map((c) => c.name));
32
+ const composed = (src, self) => new Set([...src.matchAll(/<([A-Z][A-Za-z0-9]*)\b/g)].map((m) => m[1]).filter((n) => n !== self && own.has(n))).size;
29
33
  const born = [];
30
34
  for (const c of fresh) {
31
35
  const file = c.api?.file;
@@ -34,13 +38,29 @@ before) {
34
38
  born.push({ name: c.name, file, fromSystem: 0, of: 0, byHand: [] });
35
39
  continue;
36
40
  }
37
- const d = diagnose([scanSource(file, src, table)], context);
41
+ /**
42
+ * E A FOLHA QUE ELE IMPORTA - relato 15, 28/09: "Landing - no colour or spacing of its own to measure", com os
43
+ * valores no `Landing.module.css` ao lado. O componente é o `.tsx` MAIS o estilo que ele puxa.
44
+ */
45
+ const reports = [scanSource(file, src, table)];
46
+ for (const m of src.matchAll(/^\s*import\s+(?:[\w{}\s,*]+\s+from\s+)?["'](\.{1,2}\/[^"']+\.(?:css|scss|sass|less))["']/gm)) {
47
+ const sheet = join(dirname(file), m[1]);
48
+ const css = await readStyleSheet(join(root, sheet)).catch(() => "");
49
+ if (css)
50
+ reports.push(scanSource(sheet, css, table));
51
+ }
52
+ const d = diagnose(reports, context);
53
+ /** Classes utilitárias numa string qualquer do arquivo - `className="…"`, `cn("…")`, `cva("…")` (f11, 28/09). */
54
+ const utilities = !d.reach.measured &&
55
+ /["'`][^"'`\n]*(?<![\w-])(bg|text|border|p[xytrbl]?|m[xytrbl]?|gap|rounded|shadow)-[a-z0-9][^"'`\n]*["'`]/.test(src);
38
56
  born.push({
39
57
  name: c.name,
40
58
  file,
41
59
  fromSystem: d.reach.measured ? d.reach.uses : 0,
42
60
  of: d.reach.measured ? d.reach.of : 0,
43
61
  byHand: [...new Set(d.findings.map((f) => f.literal))],
62
+ ...(utilities ? { utilities: true } : {}),
63
+ ...(composed(src, c.name) >= 3 ? { composes: composed(src, c.name) } : {}),
44
64
  });
45
65
  }
46
66
  return { born, gone };
@@ -50,9 +70,50 @@ export function describeGrowth(grown) {
50
70
  const out = [];
51
71
  for (const b of grown.born)
52
72
  out.push(b.of === 0
53
- ? `${b.name} (${b.file}) - no colour or spacing of its own to measure`
73
+ ? b.utilities
74
+ ? `${b.name} (${b.file}) - styled with utility classes; \`npx synthesisui doctor\` measures those`
75
+ : `${b.name} (${b.file}) - no colour or spacing of its own to measure`
54
76
  : `${b.name} (${b.file}) - ${b.fromSystem} of ${b.of} values from your system${b.byHand.length > 0 ? `; by hand: ${b.byHand.slice(0, 4).join(", ")}${b.byHand.length > 4 ? ", …" : ""}` : ""}`);
77
+ /** A tela que mora na pasta de componentes: a linha pergunta, e quem responde decide. */
78
+ for (const [i, b] of grown.born.entries())
79
+ if (b.composes)
80
+ out[i] = `${out[i]} - it composes ${b.composes} of your components - a screen?`;
55
81
  for (const g of grown.gone)
56
82
  out.push(`${g} is no longer in your code - it leaves the draft with this send`);
57
83
  return out;
58
84
  }
85
+ /**
86
+ * O QUE O SYNC DESTACADO MANDOU, PARA O FIM DO TURNO SEGUINTE DIZER - re-rodada, f12 (28/09).
87
+ *
88
+ * Pelo agente, o `sync` roda destacado do fim do turno (`auto-sync.ts`), com a saída descartada: o bloco "What your
89
+ * code grew" não chegava a ninguém, e o componente entrava no rascunho calado - o contrário da decisão do dono. A
90
+ * lista fica ao lado, e o fim do turno seguinte a entrega ao agente UMA vez, para ele contar à pessoa.
91
+ */
92
+ const GROWTH_FILE = ".last-growth.json";
93
+ export async function recordGrowthForTurn(root, lines) {
94
+ if (lines.length === 0)
95
+ return;
96
+ const { writeFile } = await import("node:fs/promises");
97
+ await writeFile(join(root, "_synthesisui", GROWTH_FILE), JSON.stringify({ at: new Date().toISOString(), lines }), "utf8").catch(() => { });
98
+ }
99
+ export async function takeGrowthNote(root) {
100
+ const { rm } = await import("node:fs/promises");
101
+ const path = join(root, "_synthesisui", GROWTH_FILE);
102
+ const raw = await readFile(path, "utf8").catch(() => null);
103
+ if (raw == null)
104
+ return null;
105
+ await rm(path, { force: true }).catch(() => { });
106
+ try {
107
+ const { lines } = JSON.parse(raw);
108
+ if (!lines?.length)
109
+ return null;
110
+ return [
111
+ "The last sync sent to your system's draft (the person has not seen this yet - tell the person, in one line each):",
112
+ ...lines.map((l) => ` ${l}`),
113
+ "Each one can stay out of the system on its page before the draft is published.",
114
+ ].join("\n");
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.471",
3
+ "version": "0.16.472",
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": {