synthesisui 0.16.204 → 0.16.207
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/align.js +51 -12
- package/dist/doctor/fragments.js +33 -1
- package/dist/install-marks.js +92 -0
- package/dist/reader-version.js +17 -1
- package/package.json +1 -1
package/dist/commands/align.js
CHANGED
|
@@ -2,23 +2,30 @@ import { readdir, readFile } from "node:fs/promises";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { pinnedHookVersion } from "../agent-wiring.js";
|
|
5
|
+
import { isOlderCli } from "../cli-version.js";
|
|
5
6
|
import { readToken, resolveRegistry } from "../config.js";
|
|
6
7
|
import { unsentEvents } from "../doctor/ledger.js";
|
|
8
|
+
import { CHECKER_SINCE, MATERIALISER_SINCE, READER_SINCE, } from "../install-marks.js";
|
|
7
9
|
import { measuredScope } from "../measured-scope.js";
|
|
8
|
-
import { READER } from "../reader-version.js";
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
+
* QUAL CLI MEDIU O CENSO EM DISCO - e era o `reader`, um inteiro, até 11/08.
|
|
11
12
|
*
|
|
12
|
-
* `
|
|
13
|
-
*
|
|
13
|
+
* O carimbo `ledger.reader` existe e continua sendo gravado, mas ele não serve para responder esta
|
|
14
|
+
* pergunta: ficou parado em 1 enquanto os leitores mudavam, então censos de julho e de ontem levam
|
|
15
|
+
* o mesmo número e nada os separa. A versão que mediu separa - ver `READER_SINCE`.
|
|
16
|
+
*
|
|
17
|
+
* `null` para censo que não diz quem o mediu: um censo assim não prova nada, e supor que ele é
|
|
18
|
+
* velho faria toda pessoa que ainda não re-mediu ver o aviso para sempre.
|
|
14
19
|
*/
|
|
15
|
-
async function
|
|
20
|
+
async function censusMeasuredBy(root) {
|
|
16
21
|
const raw = await readFile(join(root, "_synthesisui", "census.json"), "utf8").catch(() => null);
|
|
17
22
|
if (!raw)
|
|
18
23
|
return null;
|
|
19
24
|
try {
|
|
20
25
|
const c = JSON.parse(raw);
|
|
21
|
-
return typeof c.ledger?.
|
|
26
|
+
return typeof c.ledger?.cli === "string" && c.ledger.cli
|
|
27
|
+
? c.ledger.cli
|
|
28
|
+
: null;
|
|
22
29
|
}
|
|
23
30
|
catch {
|
|
24
31
|
return null;
|
|
@@ -59,6 +66,28 @@ async function credentials(home) {
|
|
|
59
66
|
*
|
|
60
67
|
* Separada de propósito: ela é a que sempre roda, e é testável sem servidor nenhum.
|
|
61
68
|
*/
|
|
69
|
+
/**
|
|
70
|
+
* O QUE ESTÁ INSTALADO AQUI FICOU PARA TRÁS - e as DUAS condições que fazem isso ser verdade.
|
|
71
|
+
*
|
|
72
|
+
* `installed` é a versão que escreveu a coisa (a pasta, ou o pin do hook); `running` é o CLI de hoje;
|
|
73
|
+
* `since` é a última versão em que aquilo mudou de verdade - ver `install-marks.ts`.
|
|
74
|
+
*
|
|
75
|
+
* As duas condições, e nenhuma delas basta sozinha:
|
|
76
|
+
*
|
|
77
|
+
* o que está instalado é ANTERIOR à última mudança senão `upgrade` reescreve bytes idênticos
|
|
78
|
+
* o CLI de hoje já ALCANÇOU essa mudança senão `upgrade` escreve a mesma coisa velha
|
|
79
|
+
*
|
|
80
|
+
* A segunda é a que quase escapou: quem roda um CLI antigo com uma pasta da mesma época não ganha
|
|
81
|
+
* nada com `upgrade` - o comando usa o CLI que ela tem. Mandar rodar ali é gastar a atenção dela num
|
|
82
|
+
* comando que não pode mudar nada, e o caminho de verdade é outro (`connect`).
|
|
83
|
+
*/
|
|
84
|
+
function behind(installed, running, since) {
|
|
85
|
+
if (!installed || !running)
|
|
86
|
+
return null;
|
|
87
|
+
if (!isOlderCli(installed, since))
|
|
88
|
+
return null;
|
|
89
|
+
return isOlderCli(running, since) ? null : installed;
|
|
90
|
+
}
|
|
62
91
|
export async function localMisalignments(root,
|
|
63
92
|
/**
|
|
64
93
|
* `home` é injetável porque a SESSÃO mora nele e não no repo - e uma verificação que lê o home da
|
|
@@ -97,11 +126,13 @@ opts = {}) {
|
|
|
97
126
|
* leitura de antes e NENHUMA re-interpretação nossa alcança isso. Só uma medição nova alcança, e
|
|
98
127
|
* ela é um comando que ninguém tinha motivo para rodar.
|
|
99
128
|
*
|
|
100
|
-
* Compara `
|
|
101
|
-
* leitor - pedir re-medição em cada bump faria a pessoa parar de ler estas
|
|
129
|
+
* Compara contra `READER_SINCE`, e não contra a string do CLI: em 07/08 o CLI subiu quatro vezes e
|
|
130
|
+
* nenhuma delas mudou um leitor - pedir re-medição em cada bump faria a pessoa parar de ler estas
|
|
131
|
+
* linhas. E não contra o carimbo `reader`, que ficou parado em 1 enquanto os leitores andavam:
|
|
132
|
+
* medido em 11/08, 12 de 36 componentes têm árvore diferente entre o leitor de 07/08 e o de hoje.
|
|
102
133
|
*/
|
|
103
|
-
const
|
|
104
|
-
if (
|
|
134
|
+
const measuredBy = await censusMeasuredBy(root);
|
|
135
|
+
if (behind(measuredBy, cli, READER_SINCE))
|
|
105
136
|
out.push({
|
|
106
137
|
says: `the measurement stored in this repo was read by an older reader, so what the platform knows about your components is what that reader could see. A re-measure is the only thing that reaches it - the fix lives on this machine, not on the server.`,
|
|
107
138
|
run: "npx synthesisui sync",
|
|
@@ -147,8 +178,12 @@ opts = {}) {
|
|
|
147
178
|
* O `upgrade` conserta, e esta linha existe para quem ainda não rodou: a verificação de abertura é
|
|
148
179
|
* o único lugar que fala sem ser perguntado. Apontava `connect` até 07/08, quando o dono nomeou a
|
|
149
180
|
* incoerência - a palavra que significa atualizar era a única que não atualizava.
|
|
181
|
+
*
|
|
182
|
+
* COMPARA `MATERIALISER_SINCE`, E NÃO A STRING DO CLI - a mesma correção que o `READER` recebeu do
|
|
183
|
+
* lado da medição, e que este lado não tinha. Medido: de 79 bumps, 10 mudaram o que vai para esta
|
|
184
|
+
* pasta. Os outros 69 mandavam rodar `upgrade` para reescrever bytes idênticos.
|
|
150
185
|
*/
|
|
151
|
-
const folderBehind =
|
|
186
|
+
const folderBehind = behind(lock.cli, cli, MATERIALISER_SINCE);
|
|
152
187
|
/**
|
|
153
188
|
* O HOOK, MEDIDO NELE MESMO - e não pelo `.lock`, que é um proxy que se move sozinho.
|
|
154
189
|
*
|
|
@@ -159,9 +194,13 @@ opts = {}) {
|
|
|
159
194
|
*
|
|
160
195
|
* `pinnedHookVersion` devolve `null` numa instalação local, onde o hook segue o `node_modules` e
|
|
161
196
|
* nunca está atrás por si.
|
|
197
|
+
*
|
|
198
|
+
* E COMPARA `CHECKER_SINCE` pelo mesmo motivo da linha acima: o hook estar pinado numa versão
|
|
199
|
+
* anterior só importa quando o checador de hoje veria algo que o pinado não vê. De 79 bumps, 34
|
|
200
|
+
* mudaram o checador - nos outros 45 esta linha acusava um pin que se comporta igual.
|
|
162
201
|
*/
|
|
163
202
|
const pinned = await pinnedHookVersion(root).catch(() => null);
|
|
164
|
-
const hookBehind =
|
|
203
|
+
const hookBehind = behind(pinned, cli, CHECKER_SINCE);
|
|
165
204
|
/**
|
|
166
205
|
* UMA CAUSA, UMA LINHA - e as duas metades nomeadas dentro dela.
|
|
167
206
|
*
|
package/dist/doctor/fragments.js
CHANGED
|
@@ -58,6 +58,36 @@ const MODULE_REF = /\$\{\s*[A-Za-z_$][\w$]*\.[A-Za-z_$][\w$]*\s*\}/g;
|
|
|
58
58
|
* que nenhum leitor cobre (`sx`, `styled`, `runtime`) já saem com o motivo, porque nesses casos o
|
|
59
59
|
* motivo é a própria forma e não depende de leitura.
|
|
60
60
|
*/
|
|
61
|
+
/**
|
|
62
|
+
* O QUE ESTÁ DENTRO DE UM `cn(...)` E NÃO É CLASSE - e por que isto vira número na tela dele.
|
|
63
|
+
*
|
|
64
|
+
* O corpo da chamada é varrido por literal, e todo literal virava um fragmento de estilo. Dois deles
|
|
65
|
+
* nunca foram estilo, e a esteira estava dizendo ao cliente que não conseguia ler o que ele nem
|
|
66
|
+
* escreveu:
|
|
67
|
+
*
|
|
68
|
+
* status === "success" ? "bg-success-500" : ... "success" é OPERANDO da comparação
|
|
69
|
+
* // ... to prevent the "short width" issue "short width" está num COMENTÁRIO
|
|
70
|
+
*
|
|
71
|
+
* MEDIDO EM 11/08 no repo real, sobre as 26 declarações que o censo listava como `value-not-read`:
|
|
72
|
+
*
|
|
73
|
+
* 8 (31%) operando de === Card, RadioCard x4, SelectionCard x2
|
|
74
|
+
* 2 (8%) comentário Input, Tag
|
|
75
|
+
* 16 (61%) classe de verdade sr-only, flex flex-col, data-[side=top]:top-full, ...
|
|
76
|
+
*
|
|
77
|
+
* Ou seja: 10 das 26 eram acusação NOSSA. E a lei 8 é explícita - lacuna declarada é confiança,
|
|
78
|
+
* mas lacuna FALSA custa o mesmo que a escondida: ela manda a pessoa procurar um problema que não
|
|
79
|
+
* existe no código dela, e gasta a credibilidade do número que está certo.
|
|
80
|
+
*/
|
|
81
|
+
/** Apaga comentários preservando o COMPRIMENTO, senão todo índice depois deles aponta para a linha errada. */
|
|
82
|
+
function blankComments(body) {
|
|
83
|
+
return body
|
|
84
|
+
.replace(/\/\*[\s\S]*?\*\//g, (m) => " ".repeat(m.length))
|
|
85
|
+
.replace(/\/\/[^\n]*/g, (m) => " ".repeat(m.length));
|
|
86
|
+
}
|
|
87
|
+
/** `size === "md"`: o literal é o que está sendo COMPARADO, e comparar não é vestir. */
|
|
88
|
+
function isComparedTo(body, index) {
|
|
89
|
+
return /(?:===|!==|==|!=)\s*$/.test(body.slice(0, index));
|
|
90
|
+
}
|
|
61
91
|
export function fragmentsOfSource(file, source) {
|
|
62
92
|
const out = [];
|
|
63
93
|
const at = (index) => source.slice(0, index).split("\n").length;
|
|
@@ -93,12 +123,14 @@ export function fragmentsOfSource(file, source) {
|
|
|
93
123
|
* classe escrita à mão - a forma mais comum do repo dele (113 arquivos).
|
|
94
124
|
*/
|
|
95
125
|
for (const call of source.matchAll(CALL_LITERAL)) {
|
|
96
|
-
const body = call[1] ?? "";
|
|
126
|
+
const body = blankComments(call[1] ?? "");
|
|
97
127
|
const base = (call.index ?? 0) + (call[0].length - body.length - 1);
|
|
98
128
|
for (const s of body.matchAll(STRING_IN_CALL)) {
|
|
99
129
|
const text = s[1] ?? s[2] ?? "";
|
|
100
130
|
if (!LOOKS_LIKE_CLASS.test(text))
|
|
101
131
|
continue;
|
|
132
|
+
if (isComparedTo(body, s.index ?? 0))
|
|
133
|
+
continue;
|
|
102
134
|
push("class", base + (s.index ?? 0), text);
|
|
103
135
|
}
|
|
104
136
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QUANDO O QUE ESTÁ INSTALADO NESTA MÁQUINA FICOU PARA TRÁS DE VERDADE.
|
|
3
|
+
*
|
|
4
|
+
* Duas coisas do CLI vivem no repositório de quem usa e NÃO se atualizam sozinhas: os arquivos que o
|
|
5
|
+
* `add` escreve em `_synthesisui/ds/<slug>`, e o hook que roda depois de cada escrita do agente - que
|
|
6
|
+
* fica pinado de propósito, porque comportamento que muda sob você é indebugável.
|
|
7
|
+
*
|
|
8
|
+
* O `align` avisava sobre as duas comparando a STRING DA VERSÃO do CLI. É a mesma armadilha que o
|
|
9
|
+
* `READER` já tinha resolvido do lado da medição, e que ninguém tinha aplicado aqui. Medido em 11/08
|
|
10
|
+
* sobre os 79 últimos bumps deste repositório:
|
|
11
|
+
*
|
|
12
|
+
* mudaram o que o `upgrade` ESCREVE 20 (25%)
|
|
13
|
+
* mudaram o que o HOOK roda 34 (43%)
|
|
14
|
+
* não mudaram NENHUM dos dois 27 (34%)
|
|
15
|
+
*
|
|
16
|
+
* Um terço dos bumps mandava a pessoa rodar `upgrade` por absolutamente nada, com as DUAS linhas na
|
|
17
|
+
* tela. E o custo não é o incômodo: um alarme que toca quando está tudo certo é o alarme que ela
|
|
18
|
+
* aprende a pular no dia em que ele estiver dizendo a verdade.
|
|
19
|
+
*
|
|
20
|
+
* O dono nomeou isso em 11/08 pela pergunta certa - *"por que foi necessário atualizar o CLI dessa
|
|
21
|
+
* vez?"* - sobre um bump que mexeu no `clean` e numa frase, e não tocou a pasta de ninguém.
|
|
22
|
+
*
|
|
23
|
+
* ESTAS MARCAS SÃO VERSÕES, e não números de série, por um motivo prático: elas comparam contra o que
|
|
24
|
+
* já está gravado no `.lock` e no hook dos installs QUE JÁ EXISTEM. Um contador novo precisaria ser
|
|
25
|
+
* escrito primeiro, e o primeiro contato com ele acusaria todo mundo uma vez - exatamente o alarme à
|
|
26
|
+
* toa que isto remove.
|
|
27
|
+
*
|
|
28
|
+
* A família inteira, e o que cada uma alcança:
|
|
29
|
+
*
|
|
30
|
+
* READER a medição na máquina dela -> npx synthesisui sync
|
|
31
|
+
* COMPILER o CSS de uma versão já instalada -> npx synthesisui connect
|
|
32
|
+
* INTERPRETATION a nossa metade, no servidor -> sem comando
|
|
33
|
+
* MATERIALISER_SINCE os arquivos da pasta dele -> npx synthesisui upgrade
|
|
34
|
+
* CHECKER_SINCE o hook que lê o que o agente faz -> npx synthesisui upgrade
|
|
35
|
+
*
|
|
36
|
+
* COMO SE MEXE NELAS: não se lembra, o spec cobra. `install-marks.spec.ts` guarda o fingerprint dos
|
|
37
|
+
* arquivos que decidem cada marca e fica vermelho quando eles mudam sem a marca acompanhar. O
|
|
38
|
+
* `READER` nasceu sem esse portão em 07/08 e a disciplina falhou na primeira oportunidade que teve:
|
|
39
|
+
* `d90260cb` acrescentou 47 linhas a `anatomy-from-sketch.ts` - uma mudança que muda o censo dos
|
|
40
|
+
* mesmos arquivos - e o `READER` continua em 1 até hoje. Uma marca mantida à mão sem portão é uma
|
|
41
|
+
* marca errada esperando a hora.
|
|
42
|
+
*/
|
|
43
|
+
/**
|
|
44
|
+
* A ÚLTIMA VERSÃO EM QUE O QUE O `upgrade` ESCREVE NO REPO DELE MUDOU.
|
|
45
|
+
*
|
|
46
|
+
* Um install escrito por um CLI ANTERIOR a esta está velho de verdade; escrito por qualquer versão a
|
|
47
|
+
* partir daqui, tem exatamente os mesmos bytes que o `upgrade` de hoje escreveria.
|
|
48
|
+
*
|
|
49
|
+
* CONJUNTO COMPLETO, e a primeira tentativa errou por incompleta: `add.ts` chama `claude-md.ts`,
|
|
50
|
+
* `fonts.ts`, `rule-filter.ts` e `stack.ts`, e o `upgrade.ts` escreve o `UPGRADE.md` por conta
|
|
51
|
+
* própria. Deixar qualquer um de fora produz FALSO NEGATIVO - a marca fica parada enquanto o
|
|
52
|
+
* conteúdo anda, e o alarme cala no dia em que ele é verdade. Foi exatamente o que quase aconteceu:
|
|
53
|
+
* o `claude-md.ts` mudou em 0.16.204 e o conjunto de quatro arquivos não via.
|
|
54
|
+
*
|
|
55
|
+
* O resto da pasta vem do servidor e já é coberto pela versão do DS.
|
|
56
|
+
*/
|
|
57
|
+
export const MATERIALISER_SINCE = "0.16.204";
|
|
58
|
+
/**
|
|
59
|
+
* A ÚLTIMA VERSÃO EM QUE O QUE O HOOK RODA MUDOU.
|
|
60
|
+
*
|
|
61
|
+
* O hook fica pinado, então ele só anda quando alguém roda `upgrade`. Isso é de propósito - mas só
|
|
62
|
+
* vale a pena dizer quando o checador de hoje veria algo que o pinado não vê.
|
|
63
|
+
*
|
|
64
|
+
* Os arquivos que decidem: `doctor/` inteiro e `commands/hook.ts`.
|
|
65
|
+
*/
|
|
66
|
+
export const CHECKER_SINCE = "0.16.202";
|
|
67
|
+
/**
|
|
68
|
+
* A ÚLTIMA VERSÃO EM QUE OS LEITORES PASSARAM A PRODUZIR UM CENSO DIFERENTE.
|
|
69
|
+
*
|
|
70
|
+
* A terceira do mesmo bolo, e a que tinha o desenho MAIS antigo e mais errado. O `READER` era um
|
|
71
|
+
* inteiro carimbado no censo na hora da medição, e a comparação era `carimbo !== READER`. O defeito
|
|
72
|
+
* disso não é ruído, é PERDA DE INFORMAÇÃO: com o número parado em 1 desde 07/08, um censo medido
|
|
73
|
+
* ontem e um medido em julho carregam o mesmo `1` e nada os separa. Subir o número para 2 chamaria
|
|
74
|
+
* os dois para re-medir - inclusive quem já está em dia.
|
|
75
|
+
*
|
|
76
|
+
* Uma versão não perde nada, porque o censo já grava QUEM mediu (`StyleLedger.cli`).
|
|
77
|
+
*
|
|
78
|
+
* MEDIDO EM 11/08, rodando o leitor de 07/08 e o de hoje sobre os mesmos 35 componentes do repo
|
|
79
|
+
* real, e comparando o censo canônico:
|
|
80
|
+
*
|
|
81
|
+
* 12 de 36 componentes com ÁRVORE diferente - 10 lendo mais (LineChart +556 bytes)
|
|
82
|
+
* 8 de 36 com FRONTEIRA diferente - Tooltip, Menu, Modal, Select, ColorPicker, ...
|
|
83
|
+
* 2 custom properties que eram descartadas: --loader-color, --color-track
|
|
84
|
+
*
|
|
85
|
+
* Ou seja, o `READER` estava errado e ninguém tinha sido avisado. A marca nasceu em `0.16.202`,
|
|
86
|
+
* bisseccionada: o censo de 0.16.201 difere do de então, o de 0.16.202 é byte a byte igual.
|
|
87
|
+
*
|
|
88
|
+
* ANDOU PARA `0.16.207` no mesmo dia, e desta vez o portão é que mandou. `fragmentsOfSource` parou
|
|
89
|
+
* de tomar operando de `===` e texto de comentário por classe - 11 das 26 declarações que o censo
|
|
90
|
+
* dele listava como ilegíveis eram acusação NOSSA. Um censo medido antes disto carrega as onze.
|
|
91
|
+
*/
|
|
92
|
+
export const READER_SINCE = "0.16.207";
|
package/dist/reader-version.js
CHANGED
|
@@ -20,5 +20,21 @@
|
|
|
20
20
|
* READER a medição na máquina dela -> npx synthesisui sync
|
|
21
21
|
* COMPILER o CSS de uma versão já instalada -> npx synthesisui connect
|
|
22
22
|
* INTERPRETATION a nossa metade, sobre censos já guardados -> roda no servidor, sem comando
|
|
23
|
+
*
|
|
24
|
+
* A DECISÃO SAIU DAQUI EM 11/08, e este número virou só um carimbo.
|
|
25
|
+
*
|
|
26
|
+
* O desenho acima está certo na intenção e errado no formato: um inteiro gravado no censo NO
|
|
27
|
+
* MOMENTO DA MEDIÇÃO só separa duas medições se ele tiver subido entre elas. Ele não subiu - ficou
|
|
28
|
+
* em 1 desde 07/08 - enquanto os leitores andavam. Medido rodando o leitor daquele dia e o de hoje
|
|
29
|
+
* sobre os mesmos 35 componentes do repo real: 12 de 36 componentes com ÁRVORE diferente, 8 com
|
|
30
|
+
* FRONTEIRA diferente, e 2 custom properties que eram descartadas. Todos esses censos carregam `1`,
|
|
31
|
+
* e a informação para separá-los não existe mais.
|
|
32
|
+
*
|
|
33
|
+
* Subir para 2 agora chamaria para re-medir também quem já está em dia. Então quem responde
|
|
34
|
+
* *"este censo está velho?"* passou a ser `READER_SINCE`, em `install-marks.ts`, comparado contra a
|
|
35
|
+
* VERSÃO que mediu (`StyleLedger.cli`) - que o censo sempre gravou e nunca se perde.
|
|
36
|
+
*
|
|
37
|
+
* O carimbo continua sendo escrito porque ele é barato e é registro; ele só não decide mais nada.
|
|
38
|
+
* Sobe para 2 aqui por honestidade com o que foi medido.
|
|
23
39
|
*/
|
|
24
|
-
export const READER =
|
|
40
|
+
export const READER = 2;
|
package/package.json
CHANGED