synthesisui 0.16.449 → 0.16.451
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/dist/commands/hook.js +9 -1
- package/dist/commands/import.js +17 -1
- package/dist/doctor/components-scan.js +34 -0
- package/dist/doctor/shelf.js +91 -0
- package/package.json +1 -1
package/dist/commands/hook.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { readFile, stat, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join, relative, resolve } from "node:path";
|
|
3
3
|
import { changedSince } from "../changed-files.js";
|
|
4
|
-
import { emptyTally, internalSpecifiers, scanComponentsInto, tallyToInventory, } from "../doctor/components-scan.js";
|
|
4
|
+
import { emptyTally, exportedNames, internalSpecifiers, scanComponentsInto, tallyToInventory, } from "../doctor/components-scan.js";
|
|
5
5
|
import { checkContracts } from "../doctor/contract-check.js";
|
|
6
6
|
import { appendEvent, ledgerPath } from "../doctor/ledger.js";
|
|
7
7
|
import { diagnose, nameToWrite, scanSource } from "../doctor/scan.js";
|
|
8
|
+
import { declarados, falaDaPrateleira, naPrateleira } from "../doctor/shelf.js";
|
|
8
9
|
import { governs, ungovernedIn } from "../governed.js";
|
|
9
10
|
import { readMode } from "../mode.js";
|
|
10
11
|
import { namesRemoved, previousText, rulesTouchedBy, } from "../rule-touched.js";
|
|
@@ -361,7 +362,14 @@ async function report(root, filePath, mode) {
|
|
|
361
362
|
* parte do relatório que RECUSA, e uma recusa escondida embaixo de uma lista de valores é uma
|
|
362
363
|
* recusa que ninguém lê.
|
|
363
364
|
*/
|
|
365
|
+
/**
|
|
366
|
+
* A PRATELEIRA VEM ANTES DOS VALORES, e a ordem é o ponto: trocar um hex por
|
|
367
|
+
* um token num componente que não precisava existir é polir o que devia ser
|
|
368
|
+
* apagado. Se a peça já está no sistema, essa é a primeira coisa a saber.
|
|
369
|
+
*/
|
|
370
|
+
const prateleira = falaDaPrateleira(rel, naPrateleira(exportedNames(src), declarados(documents)), table.name ?? table.slug ?? "this system");
|
|
364
371
|
const lines = [
|
|
372
|
+
...(prateleira.length > 0 ? [...prateleira, ""] : []),
|
|
365
373
|
...(composed.length > 0 ? [...composed, ""] : []),
|
|
366
374
|
...(broke.length > 0 ? [...broke, ""] : []),
|
|
367
375
|
`${rel} - checked against ${table.name ?? table.slug}.`,
|
package/dist/commands/import.js
CHANGED
|
@@ -2417,7 +2417,23 @@ export async function takeCensus(root, opts) {
|
|
|
2417
2417
|
* e e' exatamente o caso que fazia o `canvas` ser escolhido por casamento de palavra.
|
|
2418
2418
|
* Ver `root-ground.ts` para a medicao do `codelevel` que motivou isto.
|
|
2419
2419
|
*/
|
|
2420
|
-
const rootGround = rootGroundOf(
|
|
2420
|
+
const rootGround = rootGroundOf(
|
|
2421
|
+
/**
|
|
2422
|
+
* SÓ AS FOLHAS DENTRO DO ESCOPO - corrigido em 21/09, na primeira corrida real.
|
|
2423
|
+
*
|
|
2424
|
+
* A versao de estreia leu TODAS as folhas colhidas e o `codelevel` respondeu com
|
|
2425
|
+
* `_local/bkp/scrollytelling/styles.css`: um backup morto, fora do escopo declarado
|
|
2426
|
+
* (`packages/ui`), que declara `html, body { background: var(--bg) }` com tokens que
|
|
2427
|
+
* o projeto de hoje nao tem. A regra certa estava tres arquivos ao lado e perdeu para
|
|
2428
|
+
* a ordem da varredura.
|
|
2429
|
+
*
|
|
2430
|
+
* `g.outside` ja existia e ja era contado logo acima, em `deForaDoEscopo` - eu e que
|
|
2431
|
+
* nao o usei. Um chao lido de codigo morto e pior que nenhum: ele tem a confianca de
|
|
2432
|
+
* uma medicao e a procedencia de um arquivo que ninguem executa.
|
|
2433
|
+
*/
|
|
2434
|
+
globalSheets
|
|
2435
|
+
.filter((g) => !g.outside)
|
|
2436
|
+
.map((g) => ({ file: g.file, css: g.body })));
|
|
2421
2437
|
const declaredSchemes = {
|
|
2422
2438
|
base: Object.fromEntries(schemes.base),
|
|
2423
2439
|
light: Object.fromEntries(schemes.light),
|
|
@@ -274,6 +274,40 @@ function importedNames(source, internal = []) {
|
|
|
274
274
|
*/
|
|
275
275
|
const BOUND = /(?:const|let|var|function|class)\s+([A-Z][A-Za-z0-9_]*)|[{,]\s*\w+\s*:\s*([A-Z][A-Za-z0-9_]*)\s*(?:=[^,}]*)?\s*[,}]/g;
|
|
276
276
|
const EXPORTED_NAME = /export\s+(?:default\s+)?(?:async\s+)?(?:function|class|const|let|var)\s+([A-Z][A-Za-z0-9_]*)|export\s+default\s+([A-Z][A-Za-z0-9_]*)|export\s*\{([^}]*)\}/g;
|
|
277
|
+
/**
|
|
278
|
+
* OS COMPONENTES QUE ESTE ARQUIVO EXPORTA - a metade que faltava para o hook
|
|
279
|
+
* enxergar a PRATELEIRA, e não só os valores.
|
|
280
|
+
*
|
|
281
|
+
* O hook já dizia "este valor tem nome no sistema". Ele nunca dizia "esta PEÇA
|
|
282
|
+
* tem recipe no sistema", e o agente do CodeLevel mediu o efeito disso em
|
|
283
|
+
* 22/09: escreveu cinco componentes do zero num dia, com pelo menos quatro
|
|
284
|
+
* deles já existindo no índice - *"a ferramenta estava ligada o dia inteiro e
|
|
285
|
+
* eu não fiz uma pergunta a ela"*.
|
|
286
|
+
*
|
|
287
|
+
* Reusa a mesma regex de `localOnlyNames`, que é quem já sabe ler as quatro
|
|
288
|
+
* formas de exportar. Duas leituras do mesmo formato discordariam um dia.
|
|
289
|
+
*/
|
|
290
|
+
export function exportedNames(source) {
|
|
291
|
+
const nomes = new Set();
|
|
292
|
+
EXPORTED_NAME.lastIndex = 0;
|
|
293
|
+
for (const m of source.matchAll(EXPORTED_NAME)) {
|
|
294
|
+
if (m[1])
|
|
295
|
+
nomes.add(m[1]);
|
|
296
|
+
if (m[2])
|
|
297
|
+
nomes.add(m[2]);
|
|
298
|
+
if (m[3]) {
|
|
299
|
+
for (const cru of m[3].split(",")) {
|
|
300
|
+
const nome = cru
|
|
301
|
+
.trim()
|
|
302
|
+
.split(/\s+as\s+/)[0]
|
|
303
|
+
?.trim();
|
|
304
|
+
if (nome && /^[A-Z]/.test(nome))
|
|
305
|
+
nomes.add(nome);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return nomes;
|
|
310
|
+
}
|
|
277
311
|
export function localOnlyNames(source) {
|
|
278
312
|
const exported = new Set();
|
|
279
313
|
EXPORTED_NAME.lastIndex = 0;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A PRATELEIRA - "esta peça já existe no sistema", dito sem ninguém perguntar.
|
|
3
|
+
*
|
|
4
|
+
* O PROBLEMA, medido em 22/09 no CodeLevel. O agente escreveu cinco componentes
|
|
5
|
+
* do zero num dia; pelo menos quatro já existiam no índice do sistema. Ele
|
|
6
|
+
* mesmo contou o porquê: *"o AGENTS.md manda consultar o índice antes de
|
|
7
|
+
* escrever UI (...) não consultei uma única vez. Também não chamei nenhuma das
|
|
8
|
+
* ferramentas dele"*. E fechou: *"a ferramenta estava ligada o dia inteiro e eu
|
|
9
|
+
* não fiz uma pergunta a ela"*.
|
|
10
|
+
*
|
|
11
|
+
* As duas metades do produto têm caminhos diferentes, e é isso que explica o
|
|
12
|
+
* resultado: a GUARDA roda no hook, sem pedir licença, e funcionou 209 de 209.
|
|
13
|
+
* A BIBLIOTECA é MCP - `list_components`, `describe_component` -, e MCP é PULL:
|
|
14
|
+
* só acontece se o agente resolver perguntar. Ele não resolveu nenhuma vez.
|
|
15
|
+
*
|
|
16
|
+
* Isto põe a biblioteca no caminho de push.
|
|
17
|
+
*
|
|
18
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
19
|
+
* A DISCIPLINA, e ela é a parte importante deste arquivo.
|
|
20
|
+
*
|
|
21
|
+
* Casar NOME é a família de defeito que este repositório já pagou caro: nome
|
|
22
|
+
* vencendo a leitura foi o erro do importador. Então aqui:
|
|
23
|
+
*
|
|
24
|
+
* IGUALDADE EXATA, depois de normalizar. Nada de substring, prefixo,
|
|
25
|
+
* distância de edição ou plural. `Card` casa com `card`; `CardHeader` não
|
|
26
|
+
* casa com `card`, e é melhor perder o aviso do que dar um errado.
|
|
27
|
+
*
|
|
28
|
+
* É PERGUNTA, NUNCA VEREDITO. O texto não diz "você errou": diz que os dois
|
|
29
|
+
* nomes coincidem e pergunta se são a mesma coisa.
|
|
30
|
+
*
|
|
31
|
+
* A CHECAGEM DECLARA A PRÓPRIA FRAQUEZA na saída. Quem lê é um agente, e um
|
|
32
|
+
* agente que recebe "isto já existe" como fato vai apagar trabalho certo.
|
|
33
|
+
*/
|
|
34
|
+
/** `StatCard` → `stat-card`; `DSCard` → `ds-card`. */
|
|
35
|
+
export function normalizar(nome) {
|
|
36
|
+
return nome
|
|
37
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
38
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
|
|
39
|
+
.toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
/** Os componentes que o sistema declara, de um documento de design system. */
|
|
42
|
+
export function declarados(documents) {
|
|
43
|
+
const nomes = new Set();
|
|
44
|
+
for (const doc of documents) {
|
|
45
|
+
const comps = doc?.components;
|
|
46
|
+
if (comps)
|
|
47
|
+
for (const k of Object.keys(comps))
|
|
48
|
+
nomes.add(normalizar(k));
|
|
49
|
+
const blocos = doc?.blocks;
|
|
50
|
+
if (blocos)
|
|
51
|
+
for (const k of Object.keys(blocos))
|
|
52
|
+
nomes.add(normalizar(k));
|
|
53
|
+
}
|
|
54
|
+
return nomes;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* O que este arquivo define E o sistema já declara. Vazio é a resposta normal.
|
|
58
|
+
*
|
|
59
|
+
* `ds-` some do nome declarado antes de comparar: o sistema guarda `card` e a
|
|
60
|
+
* classe emitida é `ds-card`, e um repositório que chama a peça dele de `DsCard`
|
|
61
|
+
* está falando do mesmo componente.
|
|
62
|
+
*/
|
|
63
|
+
export function naPrateleira(exportados, sistema) {
|
|
64
|
+
const achados = [];
|
|
65
|
+
for (const nome of exportados) {
|
|
66
|
+
const n = normalizar(nome);
|
|
67
|
+
const semPrefixo = n.startsWith("ds-") ? n.slice(3) : n;
|
|
68
|
+
if (sistema.has(n))
|
|
69
|
+
achados.push({ escrito: nome, declarado: n });
|
|
70
|
+
else if (sistema.has(semPrefixo))
|
|
71
|
+
achados.push({ escrito: nome, declarado: semPrefixo });
|
|
72
|
+
}
|
|
73
|
+
return achados;
|
|
74
|
+
}
|
|
75
|
+
/** O texto que o agente lê. Pergunta, com a fraqueza declarada. */
|
|
76
|
+
export function falaDaPrateleira(rel, achados, sistema) {
|
|
77
|
+
if (achados.length === 0)
|
|
78
|
+
return [];
|
|
79
|
+
return [
|
|
80
|
+
`${rel} - ${sistema} already declares ${achados.length === 1 ? "a component" : "components"} with ${achados.length === 1 ? "this name" : "these names"}:`,
|
|
81
|
+
...achados.map((a) => ` you wrote ${a.escrito} · the system has ${a.declarado}`),
|
|
82
|
+
"",
|
|
83
|
+
"If they are the same thing, materialize the system's instead of keeping yours - it arrives already wearing the tokens, and it stays in step when the system changes.",
|
|
84
|
+
/**
|
|
85
|
+
* A FRAQUEZA VAI JUNTO. Esta checagem compara NOME, e nome colide: um
|
|
86
|
+
* `Card` de dashboard e um `card` de baralho são palavras iguais e coisas
|
|
87
|
+
* diferentes. Sem esta linha, um agente obediente apaga trabalho certo.
|
|
88
|
+
*/
|
|
89
|
+
"This check compares NAMES only, and names collide. If yours is a different thing, keep it and say so in your summary.",
|
|
90
|
+
];
|
|
91
|
+
}
|
package/package.json
CHANGED