synthesisui 0.16.485 → 0.16.487

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.
@@ -5,6 +5,7 @@ import { readAutoSync, startSync } from "../auto-sync.js";
5
5
  import { changedSince } from "../changed-files.js";
6
6
  import { emptyTally, exportedNames, internalSpecifiers, scanComponentsInto, tallyToInventory, } from "../doctor/components-scan.js";
7
7
  import { checkContracts } from "../doctor/contract-check.js";
8
+ import { componentOf } from "../doctor/component-of.js";
8
9
  import { appendEvent, ledgerPath } from "../doctor/ledger.js";
9
10
  import { describeOffScale, diagnose, nameToWrite, scanSource } from "../doctor/scan.js";
10
11
  import { declarados, falaDaPrateleira, naPrateleira } from "../doctor/shelf.js";
@@ -317,12 +318,16 @@ async function report(root, filePath, mode) {
317
318
  // just flagged is the evidence the agent read the report and acted. Without
318
319
  // the clean lines the record could only ever say "found", never "fixed",
319
320
  // which is the half we could not answer when asked (28/07).
321
+ const component = componentOf(rel, documents);
320
322
  await appendEvent(root, {
321
323
  kind: "hook",
322
324
  at: new Date().toISOString(),
323
325
  file: rel,
324
326
  named: named.length,
325
327
  phantoms: phantoms.length,
328
+ unnamed: unnamed.length,
329
+ offScale: d.files.reduce((n, f) => n + (f.offScale?.length ?? 0), 0),
330
+ ...(component ? { component } : {}),
326
331
  });
327
332
  /** O bloqueio de CONSUMIR é a única saída que recusa, e ele acompanha o relatório seja qual for. */
328
333
  const block = mode === "consume" && composed.length > 0;
@@ -0,0 +1,68 @@
1
+ import { basename, dirname } from "node:path";
2
+ /**
3
+ * DE QUAL COMPONENTE É ESTE ARQUIVO - a ponte que o documento já tem, e nenhuma outra (E01, 30/09).
4
+ *
5
+ * A receita diz onde o componente mora (`components.<Nome>.source.file`), escrito pela leitura do
6
+ * import. O arquivo que a checagem olha pode ser esse mesmo, ou o estilo ao lado dele:
7
+ * `components/Card.module.css` é do `Card` cujo arquivo é `components/Card.tsx` - mesma pasta, mesmo
8
+ * nome antes do primeiro ponto.
9
+ *
10
+ * E A PASTA DO COMPONENTE É DELE (medido no `codelevel` em 30/09, na E03): `packages/ui/src/CourseCover/motion.ts` é
11
+ * do `course-cover`, porque a pasta tem o nome do arquivo do componente. `components/`, que é de todos, não vira de
12
+ * ninguém: ali só o arquivo e o estilo com o mesmo nome.
13
+ *
14
+ * DUAS RECEITAS NO MESMO ARQUIVO: fica a que tem o nome dele. O `codelevel` tem `course-cover` e `covers` em
15
+ * `CourseCover.tsx`, e a regra antiga ("duas reclamam, nenhuma") deixava sem componente as 21 checagens do
16
+ * componente mais checado do sistema. Se nenhuma tem o nome, continua nenhuma.
17
+ *
18
+ * SEM RECEITA, SEM COMPONENTE. Um `app/page.module.css` que nenhuma receita reclama não vira "Page":
19
+ * o palpite pelo nome contaria checagens para um componente que não existe no sistema dele, e é
20
+ * dessa contagem que os degraus do jogo vão sair. E se duas receitas diferentes reclamam o mesmo
21
+ * arquivo, também não há resposta - escolher uma seria o mesmo palpite com outra roupa.
22
+ */
23
+ export function componentOf(file, documents) {
24
+ const exact = new Map();
25
+ const sibling = new Map();
26
+ const folder = new Map();
27
+ const dir = dirname(file);
28
+ const stem = stemOf(file);
29
+ for (const doc of documents) {
30
+ const components = doc?.components;
31
+ if (!components || typeof components !== "object")
32
+ continue;
33
+ for (const [name, recipe] of Object.entries(components)) {
34
+ const at = recipe?.source
35
+ ?.file;
36
+ if (typeof at !== "string" || at === "")
37
+ continue;
38
+ if (at === file)
39
+ exact.set(name, at);
40
+ else if (dirname(at) !== dir)
41
+ continue;
42
+ else if (stemOf(at) === stem)
43
+ sibling.set(name, at);
44
+ else if (basename(dir) === stemOf(at))
45
+ folder.set(name, at);
46
+ }
47
+ }
48
+ const found = [exact, sibling, folder].find((m) => m.size > 0);
49
+ if (!found)
50
+ return undefined;
51
+ if (found.size === 1)
52
+ return [...found.keys()][0];
53
+ const named = [...found].filter(([name, at]) => name === kebab(stemOf(at)));
54
+ return named.length === 1 ? named[0]?.[0] : undefined;
55
+ }
56
+ /**
57
+ * `CourseCover` -> `course-cover`: a chave que a plataforma dá à receita - cópia de `contractName`
58
+ * (apps/web/src/lib/ds/exclusive-contract.ts), porque o CLI é publicado sozinho e não importa de lá.
59
+ */
60
+ const kebab = (name) => name
61
+ .split(".")
62
+ .join("-")
63
+ .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
64
+ .toLowerCase()
65
+ .replace(/[^a-z0-9-]/g, "-")
66
+ .replace(/-+/g, "-")
67
+ .replace(/^-|-$/g, "");
68
+ const stemOf = (path) => basename(path).split(".")[0] ?? "";
@@ -515,7 +515,19 @@ export const COUNTED_DIFFERENTLY = "this run counts a value as named only when Y
515
515
  * de propósito, avisa a grade que divide a altura da tela no celular, propõe os nomes numa pergunta só e termina pedindo
516
516
  * o resumo por último. Um hook anterior diz outra coisa sobre o mesmo turno.
517
517
  */
518
- export const CHECKER_SINCE = "0.16.485";
518
+ /**
519
+ * 0.16.485 -> 0.16.486 em 30/09, e o passo 1 dá **SIM** (o jogo dos envios, E01): a linha que o hook grava no ledger
520
+ * passa a dizer quantos valores sem nome e quantos fora da escala a checagem achou, e de qual componente é o arquivo. Um
521
+ * hook anterior grava "limpo" sobre o arquivo que acabou de acusar, e é dessas linhas que os degraus de cada componente
522
+ * vão ser contados - quem está atrás vê o componente amadurecer com checagens que não foram limpas.
523
+ */
524
+ /**
525
+ * 0.16.486 -> 0.16.487 em 30/09, e o passo 1 dá **SIM** (o jogo dos envios, E03): a ponte arquivo -> componente passa a
526
+ * dar dono ao arquivo da pasta do componente (`CourseCover/motion.ts`) e, quando duas receitas reclamam o mesmo arquivo,
527
+ * à que tem o nome dele. Medido no `codelevel`: 33 checagens do componente mais checado chegavam sem componente. Um
528
+ * hook anterior continua mandando essas checagens sem dono, e elas não contam para o degrau.
529
+ */
530
+ export const CHECKER_SINCE = "0.16.487";
519
531
  /**
520
532
  * A ÚLTIMA VERSÃO EM QUE OS LEITORES PASSARAM A PRODUZIR UM CENSO DIFERENTE.
521
533
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.485",
3
+ "version": "0.16.487",
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": {