synthesisui 0.16.433 → 0.16.435

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.
@@ -56,7 +56,7 @@ import { consumersOf, outsideScope, } from "../outside-scope.js";
56
56
  import { phase, startProgress } from "../progress.js";
57
57
  import { repoStateOf } from "../repo-state.js";
58
58
  import { relatorioHtml, secoesDe } from "../report-html.js";
59
- import { abertura, aneis, historiaDeCor } from "../report-insight.js";
59
+ import { abertura, aneis, historiaDeCor, oQueMuda, passos, } from "../report-insight.js";
60
60
  import { runtimeDeclaredVars, runtimeDeclaredVarsIn } from "../runtime-vars.js";
61
61
  import { detectStack, resolveDeps, stackVersions } from "../stack.js";
62
62
  import { desligarCaptura, ligarCaptura } from "../transcript.js";
@@ -3787,6 +3787,13 @@ async function mostrarInspecao(c, root, transcrito) {
3787
3787
  abertura: abertura(c, c.measured?.repo ?? basename(root)),
3788
3788
  aneis: aneis(c),
3789
3789
  cor: historiaDeCor(c),
3790
+ /**
3791
+ * O COMANDO NO TOPO E NO FIM (dono, 18/09): quem decidiu adotar no meio da leitura nao
3792
+ * deveria ter que voltar ao terminal para descobrir o que digitar.
3793
+ */
3794
+ comando: "npx synthesisui@latest import",
3795
+ muda: oQueMuda(c),
3796
+ passos: passos(),
3790
3797
  });
3791
3798
  console.log(section("What came out of your files"));
3792
3799
  console.log(body(`${paint.strong(`${lidos} of ${total}`)} components came out with a blueprint${pct === null
@@ -82,7 +82,12 @@ ${layout()}
82
82
  <p class="kicker">Read by SynthesisUI</p>
83
83
  <p class="bar-repo">${escapar(cabecalho.repo)}</p>
84
84
  </div>
85
- <p class="meta">${escapar(quando)} &middot; CLI ${escapar(cabecalho.cli)} &middot; nothing left this machine</p>
85
+ <div class="bar-fim">
86
+ <p class="meta">${escapar(quando)} &middot; CLI ${escapar(cabecalho.cli)} &middot; nothing left this machine</p>${input.comando
87
+ ? `
88
+ <code class="comando">${escapar(input.comando)}</code>`
89
+ : ""}
90
+ </div>
86
91
  </div>
87
92
  </header>
88
93
 
@@ -107,6 +112,9 @@ ${desenharCor(input.cor)}
107
112
 
108
113
  ${corpo}
109
114
 
115
+ ${desenharMuda(input.muda ?? [], input.comando)}
116
+ ${desenharPassos(input.passos ?? [])}
117
+
110
118
  <footer>
111
119
  <p>Dressed by Halogen v${HALOGEN_VERSION}, a design system from the SynthesisUI gallery.</p>
112
120
  <p>This file lives in your project and was never sent anywhere. Re-run the command to refresh it.</p>
@@ -117,6 +125,50 @@ ${corpo}
117
125
  </html>
118
126
  `;
119
127
  }
128
+ /**
129
+ * O CAMINHO INTEIRO, numerado, com o que cada comando FAZ antes do que digitar.
130
+ *
131
+ * O botão no topo do bloco não é decoração: quem leu a conta e decidiu adotar tem um alvo único
132
+ * para o olho, e o passo a passo logo abaixo para quando ele perguntar "e depois?". Ele leva para a
133
+ * primeira linha - não para fora da página, porque a página não faz requisição nenhuma.
134
+ */
135
+ function desenharPassos(passos) {
136
+ if (passos.length === 0)
137
+ return "";
138
+ const itens = passos
139
+ .map((p, i) => ` <li>
140
+ <div class="passo-topo"><b>${i + 1}</b><h3>${escapar(p.titulo)}</h3></div>
141
+ <code class="comando grande">${escapar(p.comando)}</code>
142
+ <p>${escapar(p.porque)}</p>
143
+ </li>`)
144
+ .join("\n");
145
+ return ` <section class="chapter passos" style="--ordem:12">
146
+ <h2><span>How to install it, start to finish</span></h2>
147
+ <p class="callout">Three commands, in this order. Each one says what it does before it says what to type - a command without a stated consequence is somebody pasting into their terminal on faith.</p>
148
+ <a class="botao" href="#passo-1">Install SynthesisUI</a>
149
+ <ol class="lista-passos" id="passo-1">
150
+ ${itens}
151
+ </ol>
152
+ </section>`;
153
+ }
154
+ /**
155
+ * A ÚLTIMA COISA QUE ELA LÊ: a conta, e não mais um inventário.
156
+ *
157
+ * Um relatório que termina na décima sexta lista deixa a pessoa com o diagnóstico e sem o passo.
158
+ * Este capítulo diz o que muda COM OS NÚMEROS DELA e entrega o comando ao lado - a mesma linha que
159
+ * já está no topo, porque quem chegou até aqui não deveria ter que subir para achá-la.
160
+ */
161
+ function desenharMuda(linhas, comando) {
162
+ if (linhas.length === 0)
163
+ return "";
164
+ return ` <section class="chapter muda" style="--ordem:12">
165
+ <h2><span>What changes if you bring it in</span></h2>
166
+ ${linhas.map((l) => ` <p class="callout">${escapar(l)}</p>`).join("\n")}${comando
167
+ ? `
168
+ <code class="comando grande">${escapar(comando)}</code>`
169
+ : ""}
170
+ </section>`;
171
+ }
120
172
  /**
121
173
  * OS TRÊS ANÉIS DA NOSSA LEITURA DE TOKEN (pedido dele, 18/09) - e eles abrem a página porque são
122
174
  * a régua do produto: quanto já vem de token, quanto ela declara, e quanto a leitura entendeu.
@@ -367,17 +419,45 @@ body {
367
419
  background: var(--ds-color-semantic-raised, var(--ds-color-semantic-surface));
368
420
  border-bottom: 1px solid var(--ds-color-semantic-border);
369
421
  }
422
+ /* A BARRA ALINHA COM A COLUNA DO CONTEUDO: mesma largura maxima, mesma margem lateral. Antes ela
423
+ media 920px enquanto o corpo media 1200, entao o titulo do topo e o titulo da pagina comecavam em
424
+ colunas diferentes - a primeira coisa que o olho nota, e a mais facil de consertar. */
370
425
  .bar-in {
371
- max-width: 920px;
426
+ max-width: 1200px;
372
427
  margin-inline: auto;
373
- padding: 11px 24px;
428
+ padding: 0 24px;
429
+ min-height: 64px;
430
+ display: grid;
431
+ grid-template-columns: 230px minmax(0, 1fr);
432
+ gap: 40px;
433
+ align-items: center;
434
+ }
435
+ .bar-repo { margin: 2px 0 0; font-weight: 600; }
436
+ .bar-fim {
374
437
  display: flex;
438
+ align-items: center;
439
+ gap: 14px;
375
440
  flex-wrap: wrap;
376
- gap: 8px 24px;
377
- align-items: baseline;
378
441
  justify-content: space-between;
379
442
  }
380
- .bar-repo { margin: 2px 0 0; font-weight: 600; }
443
+
444
+ /* O COMANDO NO TOPO, sem rolar: quem decidiu adotar no meio da leitura nao volta para procura-lo. */
445
+ .comando {
446
+ font-family: ${mono};
447
+ font-size: 12px;
448
+ padding: 6px 12px;
449
+ border-radius: var(--ds-radius-sm, 8px);
450
+ border: 1px solid var(--ds-color-semantic-border);
451
+ background: var(--ds-color-semantic-canvas);
452
+ color: var(--ds-color-semantic-foreground);
453
+ user-select: all;
454
+ }
455
+ .comando.grande {
456
+ display: inline-block;
457
+ margin-top: 14px;
458
+ font-size: 14px;
459
+ padding: 12px 18px;
460
+ }
381
461
  .bar-id { min-width: 0; }
382
462
 
383
463
  .wrap {
@@ -385,7 +465,7 @@ body {
385
465
  margin-inline: auto;
386
466
  padding: 0 24px 96px;
387
467
  display: grid;
388
- grid-template-columns: 250px minmax(0, 1fr);
468
+ grid-template-columns: 230px minmax(0, 1fr);
389
469
  gap: 40px;
390
470
  align-items: start;
391
471
  }
@@ -453,7 +533,7 @@ h1 {
453
533
 
454
534
  nav { margin: 44px 0 8px; }
455
535
  nav ol {
456
- margin: 12px 0 0;
536
+ margin: 10px 0 0;
457
537
  padding: 0;
458
538
  list-style: none;
459
539
  counter-reset: capitulo;
@@ -465,10 +545,21 @@ nav li {
465
545
  counter-increment: capitulo;
466
546
  display: flex;
467
547
  align-items: baseline;
468
- gap: 12px;
469
- padding: 7px 10px;
548
+ gap: 10px;
549
+ padding: 5px 9px;
550
+ font-size: 13px;
551
+ line-height: 1.35;
552
+ border: 1px solid transparent;
470
553
  border-radius: var(--ds-radius-sm, 8px);
471
554
  }
555
+ /* O ITEM CLICADO FICA MARCADO: sem isto a lateral e uma lista de dezesseis iguais, e a pessoa perde
556
+ de onde veio no instante em que rola. O foco sobrevive ao clique, entao a marca tambem. */
557
+ nav li:has(a:focus),
558
+ nav li:has(a:focus-visible) {
559
+ border-color: var(--ds-color-semantic-accent);
560
+ background: var(--ds-color-semantic-surface);
561
+ }
562
+ nav li:has(a:focus) a { color: var(--ds-color-semantic-accent); }
472
563
  nav li:hover { background: var(--ds-color-semantic-surface); }
473
564
  nav li::before {
474
565
  content: counter(capitulo);
@@ -634,10 +725,45 @@ footer { margin-top: 40px; color: var(--ds-color-semantic-muted); font-size: 13p
634
725
  @keyframes girar { from { --fatia: 0%; } }
635
726
 
636
727
  @media (max-width: 900px) {
637
- .wrap { grid-template-columns: minmax(0, 1fr); gap: 0; }
728
+ .wrap, .bar-in { grid-template-columns: minmax(0, 1fr); gap: 8px; }
729
+ .bar-in { padding-block: 10px; }
638
730
  .lado { position: static; max-height: none; padding-bottom: 20px; }
639
731
  }
640
732
 
733
+ /* O BOTAO: um alvo unico para quem leu a conta e decidiu. Ele leva para o primeiro passo DENTRO da
734
+ pagina - sair para a internet contradiria o arquivo que nao faz requisicao nenhuma. */
735
+ .botao {
736
+ display: inline-block;
737
+ margin: 4px 0 20px;
738
+ padding: 12px 22px;
739
+ border-radius: var(--ds-radius-lg, 12px);
740
+ background: var(--ds-color-semantic-accent);
741
+ color: var(--ds-color-semantic-canvas);
742
+ font-weight: 600;
743
+ font-size: 14px;
744
+ text-decoration: none;
745
+ }
746
+ .botao:hover { opacity: 0.9; }
747
+
748
+ .lista-passos { list-style: none; margin: 0; padding: 0; display: grid; gap: 22px; }
749
+ .lista-passos li {
750
+ border-left: 2px solid var(--ds-color-semantic-border);
751
+ padding-left: 18px;
752
+ }
753
+ .passo-topo { display: flex; align-items: center; gap: 10px; }
754
+ .passo-topo b {
755
+ width: 22px;
756
+ height: 22px;
757
+ border-radius: 50%;
758
+ display: grid;
759
+ place-items: center;
760
+ font-size: 12px;
761
+ background: var(--ds-color-semantic-accent);
762
+ color: var(--ds-color-semantic-canvas);
763
+ }
764
+ .passo-topo h3 { margin: 0; font-size: 15px; }
765
+ .lista-passos p { margin: 10px 0 0; color: var(--ds-color-semantic-muted); font-size: 14px; }
766
+
641
767
  @media print {
642
768
  .bar { position: static; }
643
769
  nav { display: none; }
@@ -141,3 +141,64 @@ function colidem(valores) {
141
141
  }
142
142
  return n;
143
143
  }
144
+ /**
145
+ * O QUE MUDA SE ELA ADOTAR - com os números DELA, e sem uma promessa que a medição não sustente.
146
+ *
147
+ * O QUE O CLIENTE GANHA: a última coisa que ela lê não é mais um inventário, é a conta. Quantos dos
148
+ * valores que hoje ela repete à mão passam a ter um nome, e por que o problema para de voltar.
149
+ *
150
+ * E ELE NÃO PROMETE O QUE NÃO MEDIU: o número aqui é o que está escrito à mão HOJE, no repositório
151
+ * dela. Um texto que dissesse "seu design fica consistente" seria a mesma frase para todo mundo, e
152
+ * portanto verdade para ninguém.
153
+ */
154
+ export function oQueMuda(c) {
155
+ const observados = c.observed ?? [];
156
+ if (observados.length === 0)
157
+ return [];
158
+ const aMao = observados.filter((v) => !v.token);
159
+ if (aMao.length === 0)
160
+ return [
161
+ "Every design value in your code already comes from a token you declare. What SynthesisUI adds here is keeping it that way: the check runs after every file your agent writes, and a value that drifts off your own scale comes back to you as a decision instead of landing silently.",
162
+ ];
163
+ const repetidos = aMao.filter((v) => v.count > 1);
164
+ const usos = repetidos.reduce((n, v) => n + v.count, 0);
165
+ const linhas = [];
166
+ linhas.push(`${aMao.length} of your design values are written by hand today. Importing gives each one a name in your own vocabulary, so changing it later means changing it once instead of finding every copy.`);
167
+ if (repetidos.length > 0)
168
+ linhas.push(`${repetidos.length} of those are repeated - ${usos} uses across your files. Every copy is a place the next change can be forgotten, which is how two screens end up almost the same colour.`);
169
+ linhas.push("And it stops coming back: once the system is in the repository, the check runs after every file your agent writes and catches a value that drifts off your own scale, before it ships.");
170
+ return linhas;
171
+ }
172
+ /**
173
+ * O PASSO A PASSO INTEIRO, do login ao import (pedido dele, 18/09).
174
+ *
175
+ * O QUE O CLIENTE GANHA: ela termina a leitura sabendo exatamente o que digitar, na ordem, sem
176
+ * abrir documentação nenhuma. Cada passo diz o que FAZ antes de dizer o que digitar - um comando
177
+ * sem consequência declarada é uma pessoa colando algo no terminal dela por fé.
178
+ *
179
+ * A ORDEM NÃO É GOSTO, é a única que funciona: o `connect` instala hook, ferramentas e skills, e um
180
+ * agente só os enxerga numa sessão iniciada DEPOIS; e o `import` precisa do token que o `login`
181
+ * deixa nesta máquina - sem ele a leitura sobe e morre num 401 três passos adiante.
182
+ *
183
+ * ELE É FIXO PORQUE A ESTEIRA É FIXA: estes três comandos são os mesmos em qualquer projeto, e é
184
+ * exatamente por isso que eles podem ser escritos aqui sem medir nada do repositório dela.
185
+ */
186
+ export function passos() {
187
+ return [
188
+ {
189
+ comando: "npx synthesisui@latest login",
190
+ titulo: "Let this machine in",
191
+ porque: "Opens a page that already knows you and leaves a token in ~/.synthesisui/ on this computer. It is one click on a code - there is no account to fill in halfway through a terminal.",
192
+ },
193
+ {
194
+ comando: "npx synthesisui@latest connect",
195
+ titulo: "Wire your agent",
196
+ porque: "Installs the check that runs after every file your agent writes, the tools it can query, and the skills that know this pipeline. Nothing of your code is touched or sent. Run it before you open the agent - a session only picks these up when it starts.",
197
+ },
198
+ {
199
+ comando: "npx synthesisui@latest import",
200
+ titulo: "Turn your code into blueprints",
201
+ porque: "Reads the same values you saw above and writes them down as your design system, in your own vocabulary. From here your agent reads them before it writes anything, so consistency becomes something the project knows rather than something you remember.",
202
+ },
203
+ ];
204
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.433",
3
+ "version": "0.16.435",
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": {