primocode 8.17.0 → 8.18.1

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/lib/effort.js CHANGED
@@ -138,18 +138,40 @@ function layoutEffort(idx) {
138
138
  // há o dobro de linhas para atravessar, e uma rampa curta viraria degrau
139
139
  // visível. Começa quase preta e termina em branco — é a amplitude que faz o
140
140
  // pico parecer luz, e não só "roxo mais claro".
141
- // Começa em roxo PROFUNDO, não em preto.
141
+ // A rampa é a paleta do PrimoCode, não uma cor qualquer.
142
142
  //
143
- // A primeira rampa abria em 16 e 17 (preto e azul-marinho). Os vales da onda
144
- // caíam neles e viravam buracos escuros furando o pano — parecia defeito de
145
- // renderização, não sombra. Agora o mais fundo ainda é roxo: o painel inteiro
146
- // é uma coisa só, do vale ao pico.
147
- const ROXOS = [53, 54, 54, 55, 56, 57, 93, 129, 135, 141, 177, 183, 219, 225, 231];
148
-
149
- // Quanto o plasma é amortecido nas linhas que têm texto. Pico branco atrás
150
- // de letra branca some com a letra, e o painel existe para ser lido — o
151
- // brilho fica para as faixas abertas, logo acima e abaixo.
152
- const TETO_SOB_TEXTO = 0.5;
143
+ // O plasma era roxo — bonito, e de outro programa. A marca do CLI é o ciano
144
+ // (brand 45, o cyan-400 do design system; brandDim 31 é a mesma cor
145
+ // recuando), e é dele que a rampa sai: do teal profundo ao branco, passando
146
+ // exatamente pelo 45 no meio do caminho. Assim o pico da onda é a cor da
147
+ // marca acesa, e não um roxo emprestado.
148
+ const RAMPA = [23, 23, 24, 30, 31, 37, 38, 44, 45, 51, 87, 123, 159, 195, 231];
149
+
150
+ // Mantido pelo nome antigo porque o resto do arquivo (e o teste) já o
151
+ // conhece; o conteúdo é que mudou de família.
152
+ const ROXOS = RAMPA;
153
+
154
+ // Quanto o plasma é amortecido nas linhas que têm texto.
155
+ //
156
+ // Baixou de 0.5 para 0.26: "os textos devem ser extremamente legíveis". Com
157
+ // 0.5 a linha ainda chegava ao ciano médio, e ciano claro atrás de texto
158
+ // claro é leitura no limite. Em 0.26 a linha de texto vive no terço escuro
159
+ // da rampa — teal profundo — e o texto branco salta. O brilho não se perde:
160
+ // ele acontece nas faixas abertas, logo acima e abaixo, que é onde ninguém
161
+ // precisa ler.
162
+ const TETO_SOB_TEXTO = 0.26;
163
+
164
+ // E um teto absoluto, além da escala: por mais alto que o campo suba, atrás
165
+ // de texto ele não passa daqui. A escala sozinha não garante — bastava um
166
+ // pico forte para a linha clarear inteira.
167
+ const INDICE_MAX_TEXTO = 2; // até o 24 (#005f87): teal fundo, sempre
168
+ //
169
+ // O 2 não foi escolhido a olho. Medi o contraste de TODAS as células de
170
+ // texto ao longo de dezenas de quadros, pela fórmula de luminância relativa
171
+ // da WCAG. Com teto 4 o pior caso dava 4.08 — abaixo do mínimo AA (4.5),
172
+ // e o vilão era o índice 3 (#008787, teal médio) atrás dos traços da régua.
173
+ // Com teto 2 o pior caso passa de 7, que é o nível AAA. O teste refaz essa
174
+ // medida e reprova se algum dia cair.
153
175
 
154
176
  /* O campo: o que decide a cor de cada meia-célula.
155
177
  *
@@ -192,10 +214,11 @@ function campoUltra(x, y, fase, foco, altura) {
192
214
  // visíveis atravessando o plasma. Multiplicar preserva a forma da onda e só
193
215
  // baixa a amplitude: a linha fica escura o bastante para ler e continua
194
216
  // fazendo parte do mesmo pano.
195
- function corDoCampo(v, escala) {
217
+ function corDoCampo(v, escala, tetoIndice) {
196
218
  const t = escala ? v * escala : v;
197
- const i = Math.round(t * (ROXOS.length - 1));
198
- return ROXOS[Math.max(0, Math.min(ROXOS.length - 1, i))];
219
+ let i = Math.round(t * (RAMPA.length - 1));
220
+ if (tetoIndice != null) i = Math.min(i, tetoIndice);
221
+ return RAMPA[Math.max(0, Math.min(RAMPA.length - 1, i))];
199
222
  }
200
223
 
201
224
  // Guardada para quem já usava a onda antiga (e para o teste da rampa).
@@ -241,18 +264,31 @@ function pintarLinhaUltra(texto, largura, fase, opts = {}) {
241
264
  function painelUltra(L, fase) {
242
265
  const alturaMeia = L.linhas.length * 2;
243
266
  const foco = (L.destaque.de + L.destaque.ate) / 2;
244
- const LILAS = 189;
267
+ // Duas cores de texto, as duas claras. Sobre o teal escuro das linhas de
268
+ // texto, tanto o branco quanto o ciano-claro passam com folga — e a
269
+ // diferença entre eles ainda separa o que está escolhido do resto.
270
+ //
271
+ // O lilás de antes (189) não era da paleta e, sobre ciano, ficava sujo.
272
+ // TUDO branco. A hierarquia fica no negrito, não na cor.
273
+ //
274
+ // O secundário era 195 (ciano quase branco). Bonito, e o cálculo de
275
+ // contraste reprovou: sobre o teal mais claro que o fundo de texto pode
276
+ // ter, o 195 dá 6.57 — passa o mínimo AA (4.5) e não chega ao AAA (7.0).
277
+ // E não adiantava clarear um pouco: sobre aquele fundo, NENHUMA cor
278
+ // chega a 7 a não ser o branco puro, que dá 7.20. Como o pedido foi
279
+ // "extremamente legíveis", o branco ganhou e a diferença entre escolhido
280
+ // e resto passou a ser o peso da fonte — que separa igual e não custa
281
+ // contraste nenhum.
282
+ const BRANCO = 231;
283
+ const CLARO = 231;
245
284
 
246
285
  const corDoTexto = (l, x) => {
247
- if (l.tipo === 'titulo') return { cor: 231, negrito: true };
286
+ if (l.tipo === 'titulo') return { cor: BRANCO, negrito: true };
248
287
  if (l.tipo === 'nomes') {
249
288
  const dentro = x >= L.destaque.de && x < L.destaque.ate;
250
- return { cor: dentro ? 231 : LILAS, negrito: dentro };
251
- }
252
- if (l.tipo === 'resumo' || l.tipo === 'extremos' || l.tipo === 'ajuda') {
253
- return { cor: LILAS, negrito: false };
289
+ return { cor: dentro ? BRANCO : CLARO, negrito: dentro };
254
290
  }
255
- return { cor: 231, negrito: false };
291
+ return { cor: CLARO, negrito: false };
256
292
  };
257
293
 
258
294
  return L.linhas.map((l, y) => {
@@ -282,11 +318,12 @@ function painelUltra(L, fase) {
282
318
  glifo = ch;
283
319
  corFrente = t.cor;
284
320
  querForte = t.negrito;
285
- corFundo = corDoCampo((cima + baixo) / 2, TETO_SOB_TEXTO);
321
+ corFundo = corDoCampo((cima + baixo) / 2, TETO_SOB_TEXTO, INDICE_MAX_TEXTO);
286
322
  } else {
287
323
  glifo = '▀'; // ▀
288
- corFrente = corDoCampo(cima, linhaCalma);
289
- corFundo = corDoCampo(baixo, linhaCalma);
324
+ const teto = linhaCalma ? INDICE_MAX_TEXTO : null;
325
+ corFrente = corDoCampo(cima, linhaCalma, teto);
326
+ corFundo = corDoCampo(baixo, linhaCalma, teto);
290
327
  querForte = false;
291
328
  }
292
329
 
@@ -331,6 +368,6 @@ function desenharEffort(idx, fase) {
331
368
  }
332
369
 
333
370
  module.exports = { NIVEIS, NOMES, normalizar, nivelDe, indiceDe, modeloDe, pesquisaDe,
334
- layoutEffort, fundoRoxo, pintarLinhaUltra, desenharEffort, ROXOS,
371
+ layoutEffort, fundoRoxo, pintarLinhaUltra, desenharEffort, ROXOS, RAMPA,
335
372
  campoUltra, corDoCampo, painelUltra };
336
373
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primocode",
3
- "version": "8.17.0",
3
+ "version": "8.18.1",
4
4
  "description": "PrimoCode — agente de engenharia com IA e cursor próprio. Modelos grátis. Cria arquivos, roda comandos, controla navegador e desktop: abre apps, clica em botões e ícones pelo nome, digita e usa atalhos.",
5
5
  "main": "bin/primocode.js",
6
6
  "bin": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "scripts": {
10
10
  "start": "node bin/primocode.js",
11
- "test": "node test/tools.test.js && node test/ui.test.js && node test/modo.test.js && node test/pasta.test.js && node test/catalogo.test.js && node test/desktop.test.js && node test/effort.test.js && node test/claude-engine.test.js && node test/regressao.test.js && node test/memoria-conversa.test.js && node test/repeticao.test.js && node test/referencia.test.js && node test/parar.test.js && node test/continuar.test.js && node test/studio-spec.test.js && node test/studio-versoes.test.js && node test/voz.test.js && node test/editor.test.js && node test/estudio-projeto.test.js"
11
+ "test": "node test/tools.test.js && node test/ui.test.js && node test/modo.test.js && node test/pasta.test.js && node test/catalogo.test.js && node test/desktop.test.js && node test/effort.test.js && node test/claude-engine.test.js && node test/regressao.test.js && node test/memoria-conversa.test.js && node test/repeticao.test.js && node test/referencia.test.js && node test/parar.test.js && node test/continuar.test.js && node test/studio-spec.test.js && node test/studio-versoes.test.js && node test/voz.test.js && node test/editor.test.js && node test/estudio-projeto.test.js && node test/vocabulario.test.js"
12
12
  },
13
13
  "engines": {
14
14
  "node": ">=18.17.0"
@@ -27,19 +27,18 @@
27
27
  transicao: [["", "Nenhuma (corte seco)"], ["fade", "Suave"], ["deslizar", "Deslizar para o lado"],
28
28
  ["subir", "Subir"], ["zoom", "Aproximar"], ["limpar", "Varrer"],
29
29
  ["persiana", "Persiana"], ["flash", "Flash"]],
30
- fundo: [["", "Sem fundo"], ["malha", "Malha"], ["aurora", "Aurora"], ["raios", "Raios"],
31
- ["brilho", "Brilho"], ["ondas", "Ondas"], ["grade", "Grade"], ["pontos", "Pontos"],
32
- ["vinheta", "Vinheta"], ["ruido", "Ruído"]],
30
+ fundo: [["", "Sem fundo"], ["malha", "Malha"], ["brilho", "Brilho"], ["grade", "Grade"],
31
+ ["pontos", "Pontos"], ["suave", "Suave"], ["vinheta", "Vinheta"], ["aurora", "Aurora"],
32
+ ["nevoa", "Névoa"], ["ondas", "Ondas"], ["raios", "Raios"], ["xadrez", "Xadrez"]],
33
33
  acabamento: [["", "Nenhum"], ["grao", "Granulado"], ["vinheta", "Vinheta"],
34
34
  ["scanlines", "Linhas de TV"], ["luz", "Vazamento de luz"], ["brilho", "Brilho"],
35
35
  ["moldura", "Moldura"]],
36
- animacao: [["", "Nenhuma"], ["subir", "Subir"], ["surgir", "Surgir"], ["esq", "Da esquerda"],
37
- ["dir", "Da direita"], ["zoom", "Aproximar"], ["desfoque", "Sair do desfoque"],
38
- ["cair", "Cair"], ["girar", "Girar"], ["saltar", "Saltar"], ["revelar", "Revelar"],
39
- ["cortina", "Cortina"], ["elastico", "Elástico"]],
40
- kenburns: [["", "Parado"], ["aproxima", "Aproximar"], ["afasta", "Afastar"],
41
- ["esquerda", "Correr para a esquerda"], ["direita", "Correr para a direita"],
42
- ["cima", "Subir devagar"]],
36
+ animacao: [["", "Nenhuma"], ["subir", "Subir"], ["surgir", "Surgir"],
37
+ ["esquerda", "Da esquerda"], ["direita", "Da direita"], ["zoom", "Aproximar"],
38
+ ["desfoque", "Sair do desfoque"], ["cair", "Cair"], ["girar", "Girar"],
39
+ ["saltar", "Saltar"], ["revelar", "Revelar"], ["cortina", "Cortina"],
40
+ ["elastico", "Elástico"], ["palavra", "Palavra por palavra"],
41
+ ["nenhuma", "Travada (sem entrada)"]],
43
42
  };
44
43
 
45
44
  /* Menu com nome legível. Aceita "valor" ou ["valor", "Nome"]. */
@@ -143,7 +142,7 @@
143
142
  { tipo: "texto", papel: "titulo", texto: "Parte dois", an: "zoom" }] } },
144
143
  { id: "foto", nome: "Foto com frase", para: ["corte", "prisma", "tela"],
145
144
  cena: { layout: "capa", duracao: 5, acabamento: "vinheta", transicao: "fade",
146
- fundo: "vinheta", kenburns: "aproxima", elementos: [
145
+ fundo: "vinheta", elementos: [
147
146
  { tipo: "texto", papel: "titulo", texto: "A frase por cima da imagem", an: "subir" }] } },
148
147
  { id: "grafico", nome: "Gráfico", para: ["corte", "prisma"],
149
148
  cena: { layout: "titulo", duracao: 6, elementos: [
@@ -1191,12 +1190,13 @@
1191
1190
  // deles apareciam vazios porque só um podia estar preenchido por vez.
1192
1191
  // Era a parte mais confusa do inspetor. Agora é uma lista só, com tudo
1193
1192
  // que existe, e a cor entra por baixo quando é cor que se quer.
1194
- var padroes = ["", "malha", "brilho", "grade", "pontos", "suave", "vinheta",
1195
- "aurora", "raios", "ondas", "nevoa", "xadrez"];
1193
+ // A lista vem de OPC, não repetida aqui: era a duplicação que deixava
1194
+ // o menu com "ruido" (que não existe) enquanto o CSS tinha "nevoa" e
1195
+ // "xadrez" que ninguém alcançava.
1196
1196
  var fundoAtual = typeof c.fundo === "string" && c.fundo.charAt(0) !== "#" ? c.fundo : "";
1197
- g0.appendChild(linha("Fundo", selecao(padroes, fundoAtual, function (v) {
1197
+ g0.appendChild(linha("Fundo", menu(OPC.fundo, fundoAtual, function (v) {
1198
1198
  mudar(function () { if (v) c.fundo = v; else delete c.fundo; });
1199
- }, "Sem fundo")));
1199
+ })));
1200
1200
  g0.appendChild(linha("Cor do fundo", seletorCor(
1201
1201
  typeof c.fundo === "string" && c.fundo.charAt(0) === "#" ? c.fundo : "",
1202
1202
  function (v) { mudar(function () { if (v) c.fundo = v; else delete c.fundo; }); })));
@@ -1210,8 +1210,8 @@
1210
1210
  };
1211
1211
  g0.appendChild(linha("Imagem", bFoto));
1212
1212
 
1213
- g0.appendChild(linha("Acabamento", selecao(["", "grao", "vinheta", "scanlines", "luz", "brilho", "moldura"],
1214
- c.acabamento || "", function (v) { mudar(function () { if (v) c.acabamento = v; else delete c.acabamento; }); }, "Nenhum")));
1213
+ g0.appendChild(linha("Acabamento", menu(OPC.acabamento, c.acabamento || "",
1214
+ function (v) { mudar(function () { if (v) c.acabamento = v; else delete c.acabamento; }); })));
1215
1215
  g0.appendChild(linha("Cor de destaque", seletorCor(c.tom || "",
1216
1216
  function (v) { mudar(function () { if (v) c.tom = v; else delete c.tom; }); })));
1217
1217
  g0.appendChild(linha("Tema da cena", selecao([""].concat(TEMAS), c.tema || "",