synthesisui 0.16.354 → 0.16.356

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.
@@ -150,10 +150,38 @@ const BECAUSE = {
150
150
  * look, e reter as duas cópias é o que dobraria o censo.
151
151
  */
152
152
  /**
153
- * TETO DE FORMAS POR GRUPO. Medido: as 706 folhas do app inteiro comprimem 18 473 declarações em
154
- * 194 formas - 64 por grupo cobre as populações reais com folga e segura o patológico.
153
+ * TETO DE FORMAS POR GRUPO - o MESMO número do texto, e a razão de serem iguais é a razão de os dois
154
+ * existirem: proteger contra um censo patológico, não escolher quanto do repositório dele viaja.
155
+ *
156
+ * ERA 64, sobre uma medição que não era a deste campo: *"as 706 folhas do app inteiro comprimem
157
+ * 18 473 declarações em 194 formas - 64 por grupo cobre as populações reais com folga"*. As 194 são
158
+ * do APP INTEIRO; o teto é POR GRUPO, e um grupo concentra muito mais. Remedido em 03/09, com o
159
+ * teto solto, o maior grupo de cada população:
160
+ *
161
+ * web-subscribe css/component-not-admitted 1 480 formas
162
+ * wellcell-official-app css/shape-not-read 752
163
+ * frontend-hub/dashboard css/component-not-admitted 245
164
+ * web-onboarding css/shape-not-read 15
165
+ *
166
+ * Com 64, o que chegava era 424 de 2 481 formas no `web-subscribe` (17%), 124 de 812 no `wellcell`
167
+ * (15%) e 230 de 411 no `frontend-hub` (56%).
168
+ *
169
+ * POR QUE A FORMA E NÃO O TEXTO, que é a escolha que este número representa. Subir `DISTINCT_CAP`
170
+ * para cobrir os textos do `web-subscribe` custaria **+1,12 MB** num censo de 1,50 MB (+75%), e
171
+ * levaria o texto-fonte dele de 67% para 81% do arquivo - 18 426 declarações verbatim, que é o CSS
172
+ * dele praticamente inteiro. Cobrir todas as FORMAS custa **+93 KB** (+6%), doze vezes menos, e
173
+ * entrega o que um leitor novo precisa: `form-identity` existe porque *"quem ensina a ler
174
+ * `text-<word>-<n>` ensinou as centenas de uma vez"*.
175
+ *
176
+ * E A FORMA TEM OS VALORES ABSTRAÍDOS - `background: <gradient>`, `text-<word>-<n>` -, então
177
+ * carregá-la inteira não muda a resposta que a gente dá quando um cliente pergunta se guardamos o
178
+ * código dele. Carregar o texto inteiro mudaria.
179
+ *
180
+ * O TETO CONTINUA EXISTINDO, e `formsTotal` continua dizendo quando ele corta (`INV-COB-14`): 4 096
181
+ * é 2,7x o maior grupo medido, o que segura o patológico sem dimensionar pela amostra - que foi
182
+ * exatamente o erro que escolheu 4096 para o texto em 24/08 e 64 para a forma.
155
183
  */
156
- const FORM_CAP = 64;
184
+ const FORM_CAP = DISTINCT_CAP;
157
185
  export function buildLedger(cli, seen,
158
186
  /**
159
187
  * OS NOMES QUE ELE DECLARA - para a contagem de `withTheirTokens`.
@@ -185,6 +213,7 @@ declared) {
185
213
  seenFiles: new Set(),
186
214
  withTheirTokens: 0,
187
215
  formTally: new Map(),
216
+ distinctTexts: new Set(),
188
217
  };
189
218
  group.uses += 1;
190
219
  group.seenFiles.add(f.file);
@@ -218,30 +247,57 @@ declared) {
218
247
  /**
219
248
  * SÓ O QUE UM LEITOR ALCANÇA, E SÓ TEXTO DISTINTO - as duas restrições vieram de medir.
220
249
  *
221
- * `value-not-read` diz que a forma FOI lida e o valor está fora das escalas deles - texto não
222
- * ensina nada a leitor nenhum. `computed` é montado em runtime e não existe na fonte.
223
- * `component-not-admitted` é o portão, não a leitura. Sobram os dois de `A_READER_REACHES`.
250
+ * SOBRA O QUE `A_READER_REACHES` NOMEIA, e o que ele nomeia mudou duas vezes - este comentário
251
+ * ficou parado na primeira. Ele dizia *"`value-not-read` … texto não ensina nada a leitor
252
+ * nenhum … `component-not-admitted` é o portão, não a leitura. Sobram os DOIS"*, e os dois
253
+ * excluídos ali entraram no conjunto depois (11/08 e 24/08), somando quatro. Quem lesse isto
254
+ * concluiria que o maior grupo de todos - 96% do volume não interpretado - não carrega texto,
255
+ * quando ele carrega. O conjunto é a fonte única; esta frase não repete os nomes de propósito.
256
+ *
257
+ * `computed` continua fora, e por uma razão que não envelhece: é montado em runtime e não
258
+ * existe na fonte, então não há texto para guardar.
224
259
  *
225
260
  * E TEXTO DISTINTO, porque a primeira versão disto reprovou no spec do repo vivo: guardar todo
226
261
  * fragmento deu 723 215 bytes no dashboard dele, contra um teto de 65 536. Oito mil cópias da
227
262
  * mesma string não ensinam mais que uma - o que um leitor precisa é da variedade de FORMAS.
228
263
  *
229
- * O TETO SUBIU PARA 4096 EM 24/08, e o número saiu de uma medição e não de um palpite: a
230
- * variedade real do `frontend-hub` é de ~1 500 textos distintos sobre 10 825 usos, então 4096
231
- * cabe a população inteira daquele repositório com folga e continua sendo um teto de verdade
232
- * para um caso patológico.
264
+ * O TETO SUBIU PARA 4096 EM 24/08 sobre uma medição que EXTRAPOLOU: *"a variedade real do
265
+ * `frontend-hub` é de ~1 500 textos distintos sobre 10 825 usos"*, contada nos 400 primeiros
266
+ * arquivos de module. Remedida em 03/09 no repositório inteiro, com o teto solto, ela é 6 394 -
267
+ * quatro vezes o estimado. O teto corta, e corta a maior parte:
268
+ *
269
+ * web-subscribe css/component-not-admitted 9 722 distintos, 4 096 viajam
270
+ * web-subscribe css/shape-not-read 8 016 distintos, 4 096 viajam
271
+ * frontend-hub/dashboard css/component-not-admitted 6 394 distintos, 4 096 viajam
272
+ *
273
+ * A FRASE QUE ESTAVA AQUI DIZIA QUE ISSO ERA VISÍVEL: *"`uses` continua contando tudo, então a
274
+ * diferença entre o contado e o que viajou permanece visível em vez de silenciosa"*. Não é.
275
+ * `uses` conta ocorrências e `unreadable` guarda distintos, então aquela diferença existe
276
+ * sempre, por repetição, e não muda de forma quando o teto entra. Quem paga é a
277
+ * re-interpretação, que roda sobre o censo guardado prometendo alcançar quem já importou sem
278
+ * re-medir: ela processa 4 096 de 9 722 e relata sucesso.
233
279
  *
234
- * `uses` continua contando tudo, então a diferença entre o contado e o que viajou permanece
235
- * visível em vez de silenciosa - e é ela que a tela mostra quando o teto corta.
280
+ * QUEM DECLARA O CORTE AGORA É `distinct`, escrito na linha de baixo e sempre presente. ESTE
281
+ * NÚMERO NÃO É O CONSERTO DO TETO - subir 4096 é uma decisão de tamanho de censo, medida e
282
+ * entregue à parte. Declarar vem primeiro; ampliar vem depois, e as duas são separadas porque
283
+ * uma é honestidade e a outra é custo.
236
284
  */
237
- if (A_READER_REACHES.has(reason) &&
238
- group.unreadable.length < DISTINCT_CAP &&
239
- !group.unreadable.some((u) => u.text === f.text))
240
- group.unreadable.push({
241
- file: f.file,
242
- line: f.line,
243
- text: f.text.replace(/\s+/g, " ").trim().slice(0, 400),
244
- });
285
+ if (A_READER_REACHES.has(reason) && !group.distinctTexts.has(f.text)) {
286
+ /**
287
+ * CONTAR VEM ANTES DE CABER, e essa ordem é a correção inteira.
288
+ *
289
+ * O texto entra no conjunto mesmo quando o teto já fechou: é assim que `distinct` sabe
290
+ * dizer 9 722 enquanto `unreadable` carrega 4 096, e é a única diferença entre um teto
291
+ * declarado e um teto silencioso. Inverter as duas linhas devolve o defeito.
292
+ */
293
+ group.distinctTexts.add(f.text);
294
+ if (group.unreadable.length < DISTINCT_CAP)
295
+ group.unreadable.push({
296
+ file: f.file,
297
+ line: f.line,
298
+ text: f.text.replace(/\s+/g, " ").trim().slice(0, 400),
299
+ });
300
+ }
245
301
  groups.set(key, group);
246
302
  }
247
303
  return {
@@ -250,18 +306,36 @@ declared) {
250
306
  counted,
251
307
  interpreted,
252
308
  unread: [...groups.values()]
253
- .map(({ seenFiles, withTheirTokens, formTally, ...group }) => ({
309
+ .map(({ seenFiles, withTheirTokens, formTally, distinctTexts, ...group }) => ({
254
310
  ...group,
255
311
  files: seenFiles.size,
312
+ /**
313
+ * QUANTOS TEXTOS DISTINTOS EXISTEM - incondicional, e é isso que o torna legível.
314
+ *
315
+ * Os outros campos deste objeto somem quando são zero, porque um zero repetido em todo
316
+ * grupo é ruído. Este não pode: quem lê precisa separar "o censo mediu e deu zero" de "o
317
+ * censo é anterior a este campo", e um campo que desaparece funde os dois casos. O tipo o
318
+ * declara opcional pela segunda razão, nunca pela primeira.
319
+ */
320
+ distinct: distinctTexts.size,
256
321
  /** Ausente quando é zero: um campo zerado em todo grupo é ruído em cada relatório. */
257
- ...(withTheirTokens && withTheirTokens > 0 ? { withTheirTokens } : {}),
322
+ ...(withTheirTokens && withTheirTokens > 0
323
+ ? { withTheirTokens }
324
+ : {}),
258
325
  /**
259
326
  * AS FORMAS DESTE GRUPO, com os usos de cada uma - ver `form-identity.ts` (item 12).
260
- * Ordenadas por uso: a primeira é a pergunta que mais vale a pena fazer. O teto corta o
261
- * patológico, e `uses` do grupo continua contando tudo - o corte fica visível.
327
+ * Ordenadas por uso: a primeira é a pergunta que mais vale a pena fazer.
328
+ *
329
+ * `formsTotal` existe pela MESMA razão que `distinct`, e o comentário que estava aqui
330
+ * afirmava o contrário: *"o teto corta o patológico, e `uses` do grupo continua contando
331
+ * tudo - o corte fica visível"*. `uses` conta OCORRÊNCIAS e o teto corta FORMAS, então
332
+ * `uses` alto convive com qualquer número de formas e não denuncia corte nenhum. Medido em
333
+ * 03/09: cinco grupos em três populações relatam exatamente 64 formas, que é o teto - e
334
+ * nenhum deles diz quantas ficaram de fora.
262
335
  */
263
336
  ...(formTally.size > 0
264
337
  ? {
338
+ formsTotal: formTally.size,
265
339
  forms: [...formTally.entries()]
266
340
  .sort((a, b) => b[1] - a[1])
267
341
  .slice(0, FORM_CAP)
@@ -328,6 +402,22 @@ values) {
328
402
  ? ` — and ${g.withTheirTokens} of them already wear a token you declare, so their value is in the system`
329
403
  : "";
330
404
  lines.push(` ${g.uses} ${g.shape}${g.uses === 1 ? "" : "s"} in ${g.files} file${g.files === 1 ? "" : "s"} - ${g.because}${theirs}`);
405
+ /**
406
+ * A TERCEIRA FRASE, QUANDO O TETO CORTOU - e ela existe para não deixar o cliente descobrir
407
+ * sozinho (lei 8: lacuna declarada é confiança, lacuna calada é bug).
408
+ *
409
+ * Ela só aparece quando corta, ao contrário do campo `distinct`, e a assimetria é de propósito:
410
+ * um campo ausente no censo é ambíguo para quem lê JSON e precisa do valor incondicional; uma
411
+ * linha a mais em TODO grupo de um relatório de 108 linhas é ruído que treina a pessoa a rolar
412
+ * sem ler (dono, 09/08).
413
+ *
414
+ * O QUE ELA NÃO FAZ é prometer o desfecho - mesma correção que `shape-not-read` recebeu em
415
+ * 24/08. Ela diz quantos textos viajam e o que isso significa para um leitor que a gente
416
+ * publique depois; para onde vai o resto depende de uma decisão de tamanho de censo que não é
417
+ * do cliente e ainda não foi tomada.
418
+ */
419
+ if (g.distinct !== undefined && g.distinct > g.unreadable.length)
420
+ lines.push(` of ${g.distinct} distinct texts here, ${g.unreadable.length} travel with the census - a reader we publish later reaches those without you re-measuring, and the remaining ${g.distinct - g.unreadable.length} need this scan run again`);
331
421
  for (const e of g.examples)
332
422
  lines.push(` ${e.file}:${e.line} ${e.text.slice(0, 80)}`);
333
423
  }
@@ -616,7 +616,24 @@ export const CHECKER_SINCE = "0.16.308";
616
616
  * QUEM NÃO É AFETADO: quem não escreve `rotate-x`, `skew-x/y` ou `scale-x/y`. As formas SEM eixo -
617
617
  * `rotate-180`, `scale-95` - não se movem, e há asserção disso.
618
618
  */
619
- export const READER_SINCE = "0.16.354";
619
+ /**
620
+ * 0.16.355 -> 0.16.356 em 03/09 (`INV-COB-14`): a FORMA de cada declaração não lida passa a viajar
621
+ * inteira, e é a decisão 24 no seu outro lado - declarar não move a marca, AMPLIAR move.
622
+ *
623
+ * O QUE ELE GANHA COM O `sync`: o teto de formas por grupo era 64, sobre uma medição do app inteiro
624
+ * (194 formas) aplicada a um limite POR GRUPO. Remedido em 03/09, o maior grupo do `web-subscribe`
625
+ * tem 1 480 formas - então chegavam 424 de 2 481 (17%), 124 de 812 no `wellcell` (15%) e 230 de 411
626
+ * no `frontend-hub` (56%). Um leitor novo escrito sobre o censo guardado alcançava um sexto do que
627
+ * existe no repositório dele, e o censo não tinha como dizer isso até `formsTotal` existir.
628
+ *
629
+ * POR QUE A FORMA E NÃO O TEXTO: cobrir os textos do `web-subscribe` custava +1,12 MB num censo de
630
+ * 1,50 MB (+75%), levando o texto-fonte dele a 81% do arquivo. Cobrir as formas custa +93 KB (+6%),
631
+ * e a forma tem os valores abstraídos - ela ensina o leitor sem guardar o código dele.
632
+ *
633
+ * QUEM NÃO É AFETADO: quem tem menos de 4 096 formas em todo grupo - `web-onboarding` já chegava
634
+ * com 39 de 39. O `sync` daquele repositório não muda um byte.
635
+ */
636
+ export const READER_SINCE = "0.16.356";
620
637
  /**
621
638
  * O QUE ESTÁ INSTALADO AQUI FICOU PARA TRÁS - e as DUAS condições que fazem isso ser verdade.
622
639
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.354",
3
+ "version": "0.16.356",
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": {