synthesisui 0.16.466 → 0.16.468
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/add.js +7 -2
- package/dist/commands/hook.js +15 -0
- package/dist/commands/import.js +13 -2
- package/dist/commands/init.js +1 -0
- package/dist/component-codegen.js +14 -1
- package/dist/doctor/architecture.js +30 -3
- package/dist/guide.js +16 -17
- package/dist/install-marks.js +19 -3
- package/dist/never-measured.js +21 -0
- package/package.json +1 -1
package/dist/commands/add.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { neverMeasured } from "../never-measured.js";
|
|
1
2
|
import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
3
|
import { join } from "node:path";
|
|
3
4
|
import { agentsToMaintain } from "../agents-chosen.js";
|
|
@@ -347,7 +348,11 @@ export async function add(slug, opts) {
|
|
|
347
348
|
registry: base,
|
|
348
349
|
...(opts.cli ? { cli: opts.cli } : {}),
|
|
349
350
|
/** O que o `sync` aprendeu sobre a leitura não se perde no próximo `connect` (27/09). */
|
|
350
|
-
|
|
351
|
+
/**
|
|
352
|
+
* E O SISTEMA QUE NUNCA FOI MEDIDO NUM CÓDIGO já nasce assim - ver `neverMeasured` (rodada 5, 27/09):
|
|
353
|
+
* o fork do leigo-5 terminava o `connect` mandando rodar `sync` para uma pasta que não existe.
|
|
354
|
+
*/
|
|
355
|
+
...(prev?.reading === "none" || neverMeasured(payload.document) ? { reading: "none" } : {}),
|
|
351
356
|
/** Ver `RegistryPayload.compiler`: é o que faz um conserto de CSS chegar a um install. */
|
|
352
357
|
...(payload.compiler != null ? { compiler: payload.compiler } : {}),
|
|
353
358
|
...(payload.rulesStamp ? { rules: payload.rulesStamp } : {}),
|
|
@@ -586,7 +591,7 @@ export async function add(slug, opts) {
|
|
|
586
591
|
* A linha diz quantos utilitários do Tailwind ficaram apontando para a decisão dele e quantos
|
|
587
592
|
* saíram por serem nossos, com os primeiros nomes. Quem lê pode discordar de qualquer um.
|
|
588
593
|
*/
|
|
589
|
-
if (aligned.dropped.length > 0 || aligned.own.length > 0) {
|
|
594
|
+
if (!opts.themeFollows && (aligned.dropped.length > 0 || aligned.own.length > 0)) {
|
|
590
595
|
console.log(line(
|
|
591
596
|
/**
|
|
592
597
|
* A LINHA DIZ QUE FICARAM DE FORA - e nao AFIRMA por que, porque ela nao sabe.
|
package/dist/commands/hook.js
CHANGED
|
@@ -528,6 +528,21 @@ round) {
|
|
|
528
528
|
* pelo nome é o que transforma uma perda silenciosa numa lacuna declarada (lei 8).
|
|
529
529
|
*/
|
|
530
530
|
const rest = changed.slice(AT_MOST);
|
|
531
|
+
/**
|
|
532
|
+
* NO FIM DO TURNO, O REGISTRO É DO TURNO INTEIRO - rodada 5 do refinamento, 27/09.
|
|
533
|
+
*
|
|
534
|
+
* O relatório para em três, e a linha do ledger só nascia dentro dele: o agente do leigo-5 escreveu
|
|
535
|
+
* sete arquivos do dashboard num turno, o ledger ficou com três linhas `hook` e o envio com
|
|
536
|
+
* `count: 3`. O `connect` promete "every file (...) is checked at the end of each agent turn", e o
|
|
537
|
+
* painel contava três. Os demais agora são checados e registrados em silêncio; o texto continua em
|
|
538
|
+
* três, com o resto pelo nome logo abaixo.
|
|
539
|
+
*
|
|
540
|
+
* Só no turno: um comando de shell continua como era, porque ali o corte existe para um `git
|
|
541
|
+
* checkout` que muda a árvore inteira não virar trinta checagens a cada comando.
|
|
542
|
+
*/
|
|
543
|
+
if (round === "turn")
|
|
544
|
+
for (const { rel } of rest.slice(0, REFUSAL_CEILING))
|
|
545
|
+
await report(root, join(root, rel), mode).catch(() => null);
|
|
531
546
|
/**
|
|
532
547
|
* E EM CONSUMIR, O TETO DO RELATÓRIO NÃO É O TETO DA RECUSA - achado da revisão de QA no fecho,
|
|
533
548
|
* e ele falsificava a invariante inteira.
|
package/dist/commands/import.js
CHANGED
|
@@ -1488,8 +1488,19 @@ export async function takeCensus(root, opts) {
|
|
|
1488
1488
|
* `app/` and no `pages/`, so there is nothing to count and the count would be zero for
|
|
1489
1489
|
* everything. An app has them, and then the number means something.
|
|
1490
1490
|
*/
|
|
1491
|
-
const
|
|
1492
|
-
|
|
1491
|
+
const appScreens = new Set([...screensOf.values()].flatMap((at) => [...at].filter((s) => s.startsWith("app/") || s.startsWith("pages/"))));
|
|
1492
|
+
const hasScreens = appScreens.size > 0;
|
|
1493
|
+
/**
|
|
1494
|
+
* E MENOS TELAS DO QUE A LINHA TAMBÉM NÃO É TESTE - rodadas 6 a 10 do refinamento, 27/09.
|
|
1495
|
+
*
|
|
1496
|
+
* A pergunta da regra é "duas telas compartilham isto?", e num app de UMA tela ela não tem como ser
|
|
1497
|
+
* respondida: todo componente sai "composed on one screen only". Nos cinco estilos das rodadas
|
|
1498
|
+
* (Tailwind, variáveis CSS, CSS Modules, atômico, SCSS) o import tirou assim os componentes do
|
|
1499
|
+
* usuário, e o sistema nascia sem nenhum dele. É o mesmo raciocínio da biblioteca logo acima, do outro
|
|
1500
|
+
* lado: sem telas bastantes para comparar, não há compartilhamento para medir.
|
|
1501
|
+
*/
|
|
1502
|
+
const measurable = appScreens.size >= SCREENS_FOR_SYSTEM;
|
|
1503
|
+
if (hasScreens && measurable) {
|
|
1493
1504
|
const keep = [];
|
|
1494
1505
|
for (const d of defined) {
|
|
1495
1506
|
/**
|
package/dist/commands/init.js
CHANGED
|
@@ -672,9 +672,22 @@ const preferFor = (prop) => (prop.startsWith("border") ? "border" : null);
|
|
|
672
672
|
const namedInside = (prop, value, themeVars) => {
|
|
673
673
|
if (themeVars === null)
|
|
674
674
|
return value;
|
|
675
|
-
return value
|
|
675
|
+
return value
|
|
676
|
+
.replace(/\{color\.[a-zA-Z0-9.-]+\}/g, (ref) => {
|
|
676
677
|
const key = theirColorKey(ref, themeVars, preferFor(prop));
|
|
677
678
|
return key ? `var(--color-${key})` : ref;
|
|
679
|
+
})
|
|
680
|
+
/**
|
|
681
|
+
* E A CURVA - rodada 5, 27/09: o `card` do Zephyr saía com `cubic-bezier(0.2, 0.7, 0.2, 1)` escrito
|
|
682
|
+
* dentro da `transition`, com `--ease-lumina` declarado pelo `init`. Mesma regra: o nome dele vale
|
|
683
|
+
* quando o valor bate.
|
|
684
|
+
*/
|
|
685
|
+
.replace(/\{motion\.easings\.([a-zA-Z0-9-]+)\}/g, (ref, name) => {
|
|
686
|
+
const key = kebab(name);
|
|
687
|
+
const ok = themeVars instanceof ThemeVocab
|
|
688
|
+
? themeVars.nameFor(ref, "ease", key) === key
|
|
689
|
+
: minted(themeVars, `--ease-${key}`);
|
|
690
|
+
return ok ? `var(--ease-${key})` : ref;
|
|
678
691
|
});
|
|
679
692
|
};
|
|
680
693
|
/** One declaration → Tailwind classes (pretty when mappable, arbitrary-property
|
|
@@ -18,6 +18,18 @@
|
|
|
18
18
|
* so this returns all of them and the person picks which one has PRIORITY. That word is
|
|
19
19
|
* theirs and it is the right one: the others are still true, they just do not decide.
|
|
20
20
|
*/
|
|
21
|
+
/**
|
|
22
|
+
* A PASTA DA FORMA `flat` - ela casa no lugar que TEM uma `components/`, e as peças moram DENTRO dela. Dizer
|
|
23
|
+
* "directly under `.`" num Next mandava o agente para a raiz (rodadas 6 a 10, 27/09). Quando o caminho já
|
|
24
|
+
* termina na pasta, ele é a resposta.
|
|
25
|
+
*/
|
|
26
|
+
function flatFolder(where, folder) {
|
|
27
|
+
if (!folder)
|
|
28
|
+
return where;
|
|
29
|
+
if (where === "." || where === "")
|
|
30
|
+
return folder;
|
|
31
|
+
return where === folder || where.endsWith(`/${folder}`) ? where : `${where}/${folder}`;
|
|
32
|
+
}
|
|
21
33
|
const SHAPES = [
|
|
22
34
|
{
|
|
23
35
|
kind: "atomic",
|
|
@@ -49,7 +61,7 @@ const SHAPES = [
|
|
|
49
61
|
{
|
|
50
62
|
kind: "flat",
|
|
51
63
|
needs: [["components"]],
|
|
52
|
-
describe: (
|
|
64
|
+
describe: (a, where) => `Every component sits directly under \`${flatFolder(where, a.evidence[0])}\`, one folder deep. It is the shape that stays legible longest while a system is small, and the one to revisit when the folder passes about forty names.`,
|
|
53
65
|
},
|
|
54
66
|
];
|
|
55
67
|
/**
|
|
@@ -203,7 +215,14 @@ function explains(other, shape) {
|
|
|
203
215
|
return other.kind === shape.kind || shape.kind === "flat";
|
|
204
216
|
return (pathKey(other.root) === pathKey(shape.root) &&
|
|
205
217
|
shape.kind === "flat" &&
|
|
206
|
-
other.kind !== "flat"
|
|
218
|
+
other.kind !== "flat" &&
|
|
219
|
+
/**
|
|
220
|
+
* `colocated` NÃO EXPLICA A PASTA COMPARTILHADA - rodadas 6 a 10 do refinamento, 27/09. Num Next, a
|
|
221
|
+
* raiz tem `app/` e `components/`, as duas formas casam ali, e a `flat` sumia: o import dizia "BESIDE
|
|
222
|
+
* THE ROUTE" nos cinco estilos, com os componentes todos em `components/`. `colocated` diz onde moram
|
|
223
|
+
* as rotas; `flat` diz onde moram as peças que elas compartilham.
|
|
224
|
+
*/
|
|
225
|
+
other.kind !== "colocated");
|
|
207
226
|
}
|
|
208
227
|
/**
|
|
209
228
|
* O CAMINHO COMPARÁVEL - a raiz do escopo é escrita `.` pela caminhada, e comparada com `""` ela é
|
|
@@ -395,7 +414,15 @@ entries, scope) {
|
|
|
395
414
|
const hasSrc = entries.some((e) => e.path === "src" ||
|
|
396
415
|
e.path.startsWith("src/") ||
|
|
397
416
|
(isRoot(e.path) && e.dirs.includes("src")));
|
|
398
|
-
|
|
417
|
+
/**
|
|
418
|
+
* O ESCOPO QUE JÁ É A PASTA DE COMPONENTES não ganha outra dentro dele - rodadas 6 e 8, 27/09: a
|
|
419
|
+
* sugestão saía `components/ui/components/{atoms, molecules, organisms}` e `components/components/…`, e o
|
|
420
|
+
* agente da rodada 8 chamou de "a slip in the tool".
|
|
421
|
+
*/
|
|
422
|
+
const insideComponents = /(^|\/)components(\/|$)/.test(base);
|
|
423
|
+
const trunk = insideComponents
|
|
424
|
+
? base
|
|
425
|
+
: `${base ? `${base}/` : ""}${hasSrc ? "src/components" : "components"}`;
|
|
399
426
|
const fresh = `${trunk}/{atoms, molecules, organisms}`;
|
|
400
427
|
/** Se a proposta é o que já existe, ela não é uma pasta nova - e oferecê-la seria repetir a opção 1. */
|
|
401
428
|
return found.some((a) => componentHome(a, scope) === fresh) ? null : fresh;
|
package/dist/guide.js
CHANGED
|
@@ -461,7 +461,17 @@ ${depLines.join("\n")}
|
|
|
461
461
|
Object.keys(foundations.color.semanticAlt).length > 0;
|
|
462
462
|
const altScheme = meta.scheme === "light" ? "dark" : "light";
|
|
463
463
|
const hasTailwind = "theme.css" in payload.artifacts;
|
|
464
|
-
|
|
464
|
+
/**
|
|
465
|
+
* O EXEMPLO DE PEÇA COM PARTES SAI DE UMA QUE O SISTEMA TEM - rodada 5, 27/09. Era sempre uma tabela
|
|
466
|
+
* (`.ds-table`, `.ds-table-head`…), bastando QUALQUER peça ter partes: o Zephyr tem `streak`, `xp-bar` e
|
|
467
|
+
* `join-field`, nenhuma tabela, e o agente dele foi procurar classes que não existem. A tabela só é o
|
|
468
|
+
* exemplo quando o sistema a tem.
|
|
469
|
+
*/
|
|
470
|
+
const withParts = Object.entries(components).filter(([, r]) => r.parts && Object.keys(r.parts).length > 0);
|
|
471
|
+
const picked = withParts.find(([n]) => n === "table") ?? withParts[0];
|
|
472
|
+
const multiPart = picked
|
|
473
|
+
? { name: kebab(picked[0]), parts: Object.keys(picked[1].parts ?? {}).map(kebab) }
|
|
474
|
+
: null;
|
|
465
475
|
const componentLines = Object.entries(components).map(([cname, recipe]) => componentEntry(cname, recipe));
|
|
466
476
|
/**
|
|
467
477
|
* O CORTE SÓ ACONTECE QUANDO ELE DE FATO CORTA - e este é o único jeito honesto de prometê-lo.
|
|
@@ -739,26 +749,15 @@ The system defines the scale; these are sensible defaults for spending it:
|
|
|
739
749
|
- **Section gaps:** \`lg\` (or the nearest large step). **Card/panel padding:** \`md\`.
|
|
740
750
|
- **Field / tight gaps:** \`2xs\`/\`3xs\`.
|
|
741
751
|
- The system imposes no content max-width - cap long-form/text columns yourself for readability.
|
|
742
|
-
${
|
|
752
|
+
${multiPart
|
|
743
753
|
? `
|
|
744
754
|
### Multi-part components
|
|
745
755
|
Components that have **parts** compile to \`.ds-<name>-<part>\` classes you nest yourself; the exact
|
|
746
|
-
part classes and their \`data-*\` are listed per component below. Example -
|
|
756
|
+
part classes and their \`data-*\` are listed per component below. Example - ${multiPart.name}:
|
|
747
757
|
\`\`\`tsx
|
|
748
|
-
<
|
|
749
|
-
<
|
|
750
|
-
|
|
751
|
-
<th className="ds-table-cell-head">Name</th>
|
|
752
|
-
<th className="ds-table-cell-head" data-align="end">Updated</th>
|
|
753
|
-
</tr>
|
|
754
|
-
</thead>
|
|
755
|
-
<tbody>
|
|
756
|
-
<tr className="ds-table-row">
|
|
757
|
-
<td className="ds-table-cell">Halogen</td>
|
|
758
|
-
<td className="ds-table-cell" data-align="end">2h ago</td>
|
|
759
|
-
</tr>
|
|
760
|
-
</tbody>
|
|
761
|
-
</table>
|
|
758
|
+
<div className="ds-${multiPart.name}">
|
|
759
|
+
${multiPart.parts.map((p) => ` <div className="ds-${multiPart.name}-${p}">…</div>`).join("\n")}
|
|
760
|
+
</div>
|
|
762
761
|
\`\`\`
|
|
763
762
|
`
|
|
764
763
|
: ""}
|
package/dist/install-marks.js
CHANGED
|
@@ -275,7 +275,13 @@
|
|
|
275
275
|
* `--color-accent` e `--color-primary` declarados - e a desempatar pela palavra da propriedade numa borda
|
|
276
276
|
* (rodada 4 do refinamento).
|
|
277
277
|
*/
|
|
278
|
-
|
|
278
|
+
/**
|
|
279
|
+
* 0.16.464 -> 0.16.467 em 27/09, e o passo 1 dá **SIM**: o gerador que o `upgrade` usa passa a escrever a
|
|
280
|
+
* curva de uma `transition` pelo nome dele (`var(--ease-lumina)`), o `GUIDE.md` deixa de ensinar uma tabela
|
|
281
|
+
* que o sistema não tem, e o `.lock` de um sistema nunca medido num código nasce com `reading: "none"` -
|
|
282
|
+
* rodada 5 do refinamento. Uma pasta escrita antes ensina `.ds-table` ao agente.
|
|
283
|
+
*/
|
|
284
|
+
export const MATERIALISER_SINCE = "0.16.467";
|
|
279
285
|
/**
|
|
280
286
|
* A ÚLTIMA VERSÃO EM QUE O QUE O HOOK RODA MUDOU.
|
|
281
287
|
*
|
|
@@ -437,7 +443,12 @@ export const COUNTED_DIFFERENTLY = "this run counts a value as named only when Y
|
|
|
437
443
|
* rodada 3 do refinamento: o dashboard do leigo-3 inteiro nunca foi checado. Um hook anterior segue calado
|
|
438
444
|
* nos dois casos.
|
|
439
445
|
*/
|
|
440
|
-
|
|
446
|
+
/**
|
|
447
|
+
* 0.16.463 -> 0.16.467 em 27/09, e o passo 1 dá **SIM**: o fim do turno passa a registrar no ledger TODOS os
|
|
448
|
+
* arquivos do turno, e não só os três que relata - rodada 5: o leigo-5 escreveu sete e o painel recebeu
|
|
449
|
+
* três. Um hook anterior segue mandando ao painel um turno pela metade.
|
|
450
|
+
*/
|
|
451
|
+
export const CHECKER_SINCE = "0.16.467";
|
|
441
452
|
/**
|
|
442
453
|
* A ÚLTIMA VERSÃO EM QUE OS LEITORES PASSARAM A PRODUZIR UM CENSO DIFERENTE.
|
|
443
454
|
*
|
|
@@ -886,7 +897,12 @@ export const CHECKER_SINCE = "0.16.463";
|
|
|
886
897
|
* deveriam estar lá. Quem tem censo gravado precisa de um `sync` para a fila de trabalho dele ser a
|
|
887
898
|
* real; ver o livro-razão de `corpus.spec.ts`.
|
|
888
899
|
*/
|
|
889
|
-
|
|
900
|
+
/**
|
|
901
|
+
* 0.16.440 -> 0.16.468 em 27/09, e o passo 1 dá **SIM**: num app de uma tela só a regra de duas telas deixa
|
|
902
|
+
* de tirar os componentes dele - rodadas 6 a 10 do refinamento, nos cinco estilos o sistema nascia sem
|
|
903
|
+
* nenhum componente do usuário. Um censo lido antes guardou essa lista vazia, e só remedir a enche.
|
|
904
|
+
*/
|
|
905
|
+
export const READER_SINCE = "0.16.468";
|
|
890
906
|
/**
|
|
891
907
|
* O QUE ESTÁ INSTALADO AQUI FICOU PARA TRÁS - e as DUAS condições que fazem isso ser verdade.
|
|
892
908
|
*
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* O SISTEMA NUNCA FOI MEDIDO NUM CÓDIGO - rodada 5 do refinamento, 27/09.
|
|
3
|
+
*
|
|
4
|
+
* O `connect` do leigo-5 terminou com "Still out of alignment: \"zephyr\" does not record where it was
|
|
5
|
+
* measured (...) npx synthesisui sync". O aviso só se calava com `reading: "none"` no `.lock`, e isso só
|
|
6
|
+
* era gravado depois de um `sync` que perguntava. Só que o documento já responde: cada fundação carrega
|
|
7
|
+
* quem a escreveu (`foundations.source`, os `FoundationAuthor` da plataforma), e num fork nascido na
|
|
8
|
+
* plataforma todas são `seed`. Não existe pasta de onde ele veio, e não há o que remedir.
|
|
9
|
+
*
|
|
10
|
+
* OS AUTORES QUE LERAM UM CÓDIGO são `import`, `sync`, `reground` e `reinterpret`. Um deles basta para o
|
|
11
|
+
* sistema ter origem num repositório, e aí a pergunta do `sync` continua valendo. Sem `source` nenhum, o
|
|
12
|
+
* documento não diz - e o silêncio não vira afirmação.
|
|
13
|
+
*/
|
|
14
|
+
const FROM_CODE = new Set(["import", "sync", "reground", "reinterpret"]);
|
|
15
|
+
export function neverMeasured(doc) {
|
|
16
|
+
const source = doc?.foundations?.source;
|
|
17
|
+
if (!source || typeof source !== "object")
|
|
18
|
+
return false;
|
|
19
|
+
const authors = Object.values(source);
|
|
20
|
+
return authors.length > 0 && !authors.some((a) => FROM_CODE.has(String(a)));
|
|
21
|
+
}
|
package/package.json
CHANGED