@orkastery/cli 0.5.3 → 0.5.6

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.
Files changed (212) hide show
  1. package/adapters/claude-code/README.md +158 -0
  2. package/adapters/claude-code/mods/autoridade.json +56 -0
  3. package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
  4. package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
  5. package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
  6. package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
  7. package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
  8. package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
  9. package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
  10. package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
  11. package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
  12. package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
  13. package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
  14. package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
  15. package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
  16. package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
  17. package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
  18. package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
  19. package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
  20. package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
  21. package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
  22. package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
  23. package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
  24. package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
  25. package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
  26. package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
  27. package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
  28. package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
  29. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +117 -0
  30. package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
  31. package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
  32. package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
  33. package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
  34. package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
  35. package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
  36. package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
  37. package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
  38. package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
  39. package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
  40. package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
  41. package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
  42. package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
  43. package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
  44. package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
  45. package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
  46. package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
  47. package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
  48. package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
  49. package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
  50. package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
  51. package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
  52. package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
  53. package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
  54. package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
  55. package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
  56. package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
  57. package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
  58. package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
  59. package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
  60. package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
  61. package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
  62. package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
  63. package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
  64. package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
  65. package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
  66. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
  67. package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
  68. package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
  69. package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
  70. package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
  71. package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
  72. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
  73. package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
  74. package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
  75. package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
  76. package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
  77. package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
  78. package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
  79. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +1 -1
  80. package/adapters/openclaw/README.md +2 -1
  81. package/adapters/openclaw/openclaw.plugin.json +1 -1
  82. package/adapters/openclaw/package.json +1 -1
  83. package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
  84. package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
  85. package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
  86. package/assets/docs-en/produto/README.md +14 -0
  87. package/assets/docs-en/produto/_modelo-feature.md +62 -0
  88. package/assets/docs-en/roadmap/README.md +14 -0
  89. package/assets/docs-en/roadmap/_modelo-item.md +75 -0
  90. package/dist/adapters/claude-bg.js +77 -13
  91. package/dist/adapters/codex.js +10 -1
  92. package/dist/agents-md.js +24 -15
  93. package/dist/auditrun.js +17 -2
  94. package/dist/board.js +4 -3
  95. package/dist/branch-de-estado.js +23 -1
  96. package/dist/catalogo.js +33 -0
  97. package/dist/ci.js +13 -7
  98. package/dist/claims-conferir.js +342 -0
  99. package/dist/claims.js +3 -1
  100. package/dist/company-brain-client.js +36 -1
  101. package/dist/company-brain-journal.js +2 -1
  102. package/dist/company-brain-migration.js +36 -1
  103. package/dist/conducao-sentinela.js +388 -0
  104. package/dist/conducao-texto.js +12 -18
  105. package/dist/conducao.js +122 -30
  106. package/dist/conhecimento.js +490 -0
  107. package/dist/docs.js +22 -8
  108. package/dist/doctor-pulse-cron.js +182 -27
  109. package/dist/doctor-rede.js +18 -17
  110. package/dist/doctor.js +115 -111
  111. package/dist/entrega-pr.js +22 -21
  112. package/dist/escopo-escrita.js +10 -1
  113. package/dist/estado-thread.js +23 -1
  114. package/dist/experiencia-instalacao.js +45 -25
  115. package/dist/fabrica-batida.js +310 -0
  116. package/dist/fabrica-estado.js +38 -8
  117. package/dist/fabrica-publicar.js +3 -1
  118. package/dist/fila-pesada.js +444 -0
  119. package/dist/fix.js +3 -2
  120. package/dist/forja.js +1 -1
  121. package/dist/gates.js +3 -28
  122. package/dist/handoff.js +10 -6
  123. package/dist/hitl-local-receipt.js +2 -0
  124. package/dist/hitl-resumo.js +29 -3
  125. package/dist/hitl-tempo-parado.js +4 -4
  126. package/dist/hitl.js +29 -33
  127. package/dist/horario.js +14 -7
  128. package/dist/hosts.js +52 -1
  129. package/dist/impedimento.js +108 -14
  130. package/dist/index.js +623 -521
  131. package/dist/indice.js +7 -1
  132. package/dist/init.js +43 -47
  133. package/dist/instabilidade.js +144 -0
  134. package/dist/integracoes-locais.js +2 -0
  135. package/dist/intelligence-graph-cli.js +92 -21
  136. package/dist/intelligence-graph-contexto.js +56 -17
  137. package/dist/intelligence-graph-contract.js +2 -1
  138. package/dist/intelligence-graph-extract-md.js +56 -4
  139. package/dist/intelligence-graph-extract-ts.js +71 -3
  140. package/dist/intelligence-graph-query.js +66 -19
  141. package/dist/ledger.js +15 -1
  142. package/dist/liveness.js +6 -3
  143. package/dist/locale-ajuda.js +761 -0
  144. package/dist/locale-gerados.js +160 -0
  145. package/dist/locale-master.js +99 -0
  146. package/dist/locale-onboarding.js +92 -0
  147. package/dist/locale-phase.js +151 -0
  148. package/dist/locale-pulse.js +211 -0
  149. package/dist/locale-retry.js +385 -0
  150. package/dist/locale-roadmap.js +102 -0
  151. package/dist/locale-ship.js +494 -0
  152. package/dist/locale-thread.js +277 -0
  153. package/dist/locale-verify.js +125 -0
  154. package/dist/locale.js +714 -0
  155. package/dist/manifest.js +129 -3
  156. package/dist/maquina.js +23 -4
  157. package/dist/master-digest.js +6 -1
  158. package/dist/master-nota.js +4 -6
  159. package/dist/master.js +21 -24
  160. package/dist/mcp-artifacts.js +11 -2
  161. package/dist/mcp-git.js +23 -6
  162. package/dist/mcp-grafo.js +7 -4
  163. package/dist/mcp-server.js +8 -2
  164. package/dist/mcp-ship.js +3 -1
  165. package/dist/mcp-verify.js +6 -1
  166. package/dist/modos.js +3 -6
  167. package/dist/network-roadmap.js +5 -2
  168. package/dist/noctum-arco.js +911 -0
  169. package/dist/noctum-capacidade.js +141 -0
  170. package/dist/noctum-envelope.js +810 -0
  171. package/dist/noctum-execucao.js +304 -0
  172. package/dist/noctum-fila.js +280 -0
  173. package/dist/ocupacao.js +29 -2
  174. package/dist/onboarding.js +40 -21
  175. package/dist/orkmind.js +9 -2
  176. package/dist/orquestracao.js +13 -12
  177. package/dist/parado-no-condutor.js +34 -9
  178. package/dist/phase.js +94 -39
  179. package/dist/policies.js +4 -4
  180. package/dist/portfolio.js +4 -2
  181. package/dist/postura-local.js +234 -0
  182. package/dist/preflight.js +11 -10
  183. package/dist/procedencia.js +225 -0
  184. package/dist/projeto-alvo.js +127 -4
  185. package/dist/prompts.js +6 -2
  186. package/dist/pulse-delivery.js +13 -2
  187. package/dist/pulse.js +52 -19
  188. package/dist/ratelimit.js +4 -2
  189. package/dist/redacao-saida.js +63 -0
  190. package/dist/rede-status.js +3 -2
  191. package/dist/retry.js +232 -148
  192. package/dist/roadmap-reservas.js +20 -3
  193. package/dist/roadmap-status.js +129 -33
  194. package/dist/runtime-context.js +181 -3
  195. package/dist/runtimes.js +2 -1
  196. package/dist/session-events.js +7 -3
  197. package/dist/session-watcher-claude.js +7 -1
  198. package/dist/session-watcher.js +185 -33
  199. package/dist/sessoes-contas.js +1 -1
  200. package/dist/ship-publicar.js +800 -0
  201. package/dist/ship.js +84 -81
  202. package/dist/steal.js +77 -0
  203. package/dist/thread-close.js +3 -2
  204. package/dist/thread.js +153 -82
  205. package/dist/util.js +8 -1
  206. package/dist/verify.js +141 -52
  207. package/dist/vida-da-thread.js +254 -0
  208. package/dist/worktree-local.js +165 -0
  209. package/dist/worktree.js +20 -0
  210. package/dist/yaml.js +27 -8
  211. package/package.json +1 -1
  212. package/schemas/code-artifact-graph.v1.schema.json +2 -1
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.ORIGENS_DO_PROJETO = exports.FORA_DA_CONSULTA = exports.OFERTA_DA_REDE = exports.ErroDeProjeto = exports.PADRAO_DO_NOME_DE_PROJETO = exports.SAIDA_DE_PROJETO = exports.ENV_PROJETO_EXPLICITO = exports.ENV_PROJETO = exports.CONTRATO_CONSULTA = exports.CONTRATO_PROJETOS = void 0;
36
+ exports.ORIGENS_DO_PROJETO = exports.FORA_DA_CONSULTA = exports.OFERTA_DA_REDE = exports.ErroDeProjeto = exports.PADRAO_DO_NOME_DE_PROJETO = exports.AMBIENTE_SEM_PROJETO_HERDADO = exports.SAIDA_DE_PROJETO = exports.ENV_PROJETO_EXPLICITO = exports.ENV_PROJETO = exports.CONTRATO_CONSULTA = exports.CONTRATO_PROJETOS = void 0;
37
37
  exports.caminhoDoRegistro = caminhoDoRegistro;
38
38
  exports.lerRegistroDeProjetos = lerRegistroDeProjetos;
39
39
  exports.listarProjetos = listarProjetos;
@@ -51,7 +51,12 @@ exports.raizParaExibir = raizParaExibir;
51
51
  exports.outrosProjetosConhecidos = outrosProjetosConhecidos;
52
52
  exports.semRemoto = semRemoto;
53
53
  exports.consultaDoProjeto = consultaDoProjeto;
54
+ exports.linhaDoProjeto = linhaDoProjeto;
54
55
  exports.linhasDaConsulta = linhasDaConsulta;
56
+ exports.iniciarDeclaracaoDoProjeto = iniciarDeclaracaoDoProjeto;
57
+ exports.pedirDeclaracaoDoProjeto = pedirDeclaracaoDoProjeto;
58
+ exports.remotoParaExibir = remotoParaExibir;
59
+ exports.declaracaoQueFaltou = declaracaoQueFaltou;
55
60
  /**
56
61
  * RM-052: o projeto-alvo explicito.
57
62
  *
@@ -90,6 +95,18 @@ exports.ENV_PROJETO = 'ORK_PROJETO';
90
95
  exports.ENV_PROJETO_EXPLICITO = 'ORK_PROJETO_EXPLICITO';
91
96
  /** Codigo de saida da recusa de projeto-alvo no CLI (D3). */
92
97
  exports.SAIDA_DE_PROJETO = 4;
98
+ /**
99
+ * RM-052 (fatia 2, D2): o ambiente de quem o nucleo inicia ja dentro do projeto resolvido, a sessao
100
+ * despachada na worktree da thread e o filho `fabrica publicar`. O modo host e o `ORK_PROJETO` sao do
101
+ * gateway que pediu: herdados, recusavam todo `ork` da sessao com `projeto.escolha`, ou liam outro
102
+ * projeto. Valores neutros, e nao a ausencia das variaveis: o `claude --bg` entrega a sessao a um daemon
103
+ * que guarda o ambiente de quem o iniciou, e so o `env` do `--settings` vence o herdado. Com eles, o
104
+ * projeto da sessao e o do proprio cwd.
105
+ */
106
+ exports.AMBIENTE_SEM_PROJETO_HERDADO = Object.freeze({
107
+ [exports.ENV_PROJETO]: '',
108
+ [exports.ENV_PROJETO_EXPLICITO]: '0',
109
+ });
93
110
  const ARQUIVO = 'projetos.json';
94
111
  const TRAVA = 'projetos.json.lock';
95
112
  /** Nome ou abbrev de projeto: o mesmo alfabeto dos identificadores de thread, sem barra. */
@@ -532,6 +549,10 @@ exports.ORIGENS_DO_PROJETO = Object.freeze({
532
549
  * e nao revela os demais).
533
550
  */
534
551
  function consultaDoProjeto(carregado, opcoes) {
552
+ // Fatia 2 (D3): o comando monta o proprio cabecalho DO ALVO; a linha generica do fim nao se repete.
553
+ // A consulta de outro projeto (sugestao A3 do CHECK) nao apaga a declaracao pedida.
554
+ if (declaracao && mesmaRaiz(carregado.raiz, declaracao.alvo.raiz))
555
+ declaracao.feita = true;
535
556
  const alvo = projetoAlvoAtual();
536
557
  const origem = opcoes.origem ?? (alvo && path.resolve(alvo.raiz) === path.resolve(carregado.raiz) ? alvo.origem : 'cwd');
537
558
  const outros = opcoes.outrosProjetos === false ? 0 : outrosProjetosConhecidos(carregado.raiz);
@@ -540,16 +561,118 @@ function consultaDoProjeto(carregado, opcoes) {
540
561
  return {
541
562
  contrato: exports.CONTRATO_CONSULTA,
542
563
  projeto: { nome: carregado.manifesto.project.name, abbrev: carregado.manifesto.project.abbrev,
543
- raiz: raizParaExibir(carregado.raiz), remoto, origem },
564
+ raiz: raizParaExibir(carregado.raiz), remoto: remotoParaExibir(remoto), origem },
544
565
  lido: [...opcoes.lido],
545
566
  naoLido: [...opcoes.naoLido, ...(outros > 0 ? [`outros projetos desta máquina: ${outros} (ork projetos)`] : [])],
546
567
  };
547
568
  }
569
+ /** A linha do projeto consultado: a primeira do cabecalho e a que a declaracao da fatia 2 escreve. */
570
+ function linhaDoProjeto(p) {
571
+ return `Projeto consultado: ${p.nome} (${p.abbrev || '-'}) · ${p.raiz} · ${p.remoto ?? 'sem remoto'} · ${exports.ORIGENS_DO_PROJETO[p.origem]}`;
572
+ }
548
573
  /** As duas linhas do cabecalho em texto: o projeto consultado e o que nao foi lido. */
549
574
  function linhasDaConsulta(c) {
550
- const p = c.projeto;
551
575
  return [
552
- `Projeto consultado: ${p.nome} (${p.abbrev || '-'}) · ${p.raiz} · ${p.remoto ?? 'sem remoto'} · ${exports.ORIGENS_DO_PROJETO[p.origem]}`,
576
+ linhaDoProjeto(c.projeto),
553
577
  `Não lido: ${c.naoLido.length ? c.naoLido.join(' · ') : 'nada fora do projeto consultado'}`,
554
578
  ];
555
579
  }
580
+ // ---------------------------------------------------------------------------
581
+ // A declaracao do projeto consultado (fatia 2, D3).
582
+ // ---------------------------------------------------------------------------
583
+ /**
584
+ * Na fatia 1, so maestro, board, fabrica e roadmap status diziam qual projeto leram; dez das catorze
585
+ * tools de projeto do OpenClaw respondiam sem nomea-lo, e com um so projeto conhecido a resposta era a
586
+ * dele, sem aviso. Agora todo comando que le um projeto que o leitor nao tem como adivinhar termina com
587
+ * a linha `Projeto consultado: ...` no stderr: o OpenClaw junta stdout e stderr no texto da tool, e o
588
+ * JSON do stdout continua inteiro para quem o consome.
589
+ */
590
+ let declaracao = null;
591
+ /** Zera o pedido de declaracao do processo (os testes chamam `main` em serie no mesmo processo). */
592
+ function iniciarDeclaracaoDoProjeto() {
593
+ declaracao = null;
594
+ }
595
+ /**
596
+ * Pede a linha para o comando que vai ler `alvo`, so quando o leitor nao sabe qual projeto foi lido:
597
+ * no host (`ORK_PROJETO_EXPLICITO=1`), cuja resposta vai a um canal de conversa, ou quando o projeto nao
598
+ * e o do diretorio atual. No terminal, dentro do proprio projeto, nada muda (BR-030-02).
599
+ */
600
+ function pedirDeclaracaoDoProjeto(alvo, entrada = {}) {
601
+ declaracao = null;
602
+ if (!alvo)
603
+ return;
604
+ const ambiente = entrada.ambiente ?? process.env;
605
+ const host = (ambiente[exports.ENV_PROJETO_EXPLICITO] ?? '').trim() === '1';
606
+ if (!host && raizDoDiretorio(entrada.cwd ?? process.cwd()) === alvo.raiz)
607
+ return;
608
+ declaracao = { alvo, feita: false };
609
+ }
610
+ /** As duas raizes sao a mesma copia (caminho real; o resolvido quando o disco nao responde). */
611
+ function mesmaRaiz(a, b) {
612
+ const real = (p) => { try {
613
+ return fs.realpathSync(p);
614
+ }
615
+ catch {
616
+ return path.resolve(p);
617
+ } };
618
+ return real(a) === real(b);
619
+ }
620
+ /**
621
+ * Fatia 2 (sugestao S1 do CHECK): o remoto que vai a um canal de conversa. Ele ja chega sem usuario e
622
+ * senha (`remotoSemCredencial`); aqui sai tambem o que vem depois de `?` ou `#` na URL (token em query,
623
+ * como `?private_token=`), o caminho local mostra `~` no lugar da pasta da conta (D8) e o remoto que
624
+ * ainda parecer segredo sai omitido. So a exibicao muda: o registro guarda o remoto como sempre.
625
+ */
626
+ function remotoParaExibir(remoto) {
627
+ if (remoto === null)
628
+ return null;
629
+ let exibido = remoto;
630
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(exibido)) {
631
+ try {
632
+ const u = new URL(exibido);
633
+ u.search = '';
634
+ u.hash = '';
635
+ exibido = u.toString();
636
+ }
637
+ catch {
638
+ exibido = exibido.replace(/[?#].*$/, '');
639
+ }
640
+ }
641
+ else if (path.isAbsolute(exibido))
642
+ exibido = raizParaExibir(exibido);
643
+ return (0, policies_1.procurarSegredos)(exibido).length ? 'remoto omitido (parece carregar segredo)' : exibido;
644
+ }
645
+ /** A raiz do manifesto que o diretorio enxerga subindo, com caminho real; `null` fora de projeto. */
646
+ function raizDoDiretorio(cwd) {
647
+ const achada = (0, util_1.subirAte)(path.resolve(cwd), manifest_1.NOME_MANIFESTO) ?? (0, util_1.subirAte)(path.resolve(cwd), manifest_1.NOME_MANIFESTO_LEGADO);
648
+ if (!achada)
649
+ return null;
650
+ try {
651
+ return fs.realpathSync(achada);
652
+ }
653
+ catch {
654
+ return null;
655
+ }
656
+ }
657
+ /**
658
+ * A linha que faltou, e consome o pedido: `null` sem pedido, ou quando o comando montou o proprio
659
+ * cabecalho (`consultaDoProjeto`).
660
+ */
661
+ function declaracaoQueFaltou() {
662
+ const d = declaracao;
663
+ declaracao = null;
664
+ if (!d || d.feita)
665
+ return null;
666
+ let carregado;
667
+ try {
668
+ carregado = (0, manifest_1.carregarManifesto)(d.alvo.raiz);
669
+ }
670
+ catch {
671
+ return null;
672
+ }
673
+ if (!carregado)
674
+ return null;
675
+ const m = carregado.manifesto;
676
+ return linhaDoProjeto({ nome: m.project.name, abbrev: m.project.abbrev, raiz: raizParaExibir(carregado.raiz),
677
+ remoto: remotoParaExibir(remotoDoProjeto(carregado.raiz, m.fabrica?.remoto ?? 'origin')), origem: d.alvo.origem });
678
+ }
package/dist/prompts.js CHANGED
@@ -71,14 +71,18 @@ const policies_1 = require("./policies");
71
71
  const types_1 = require("./types");
72
72
  /** Limite duro de um template, o mesmo do manifesto: prosa longa nao vira prompt. */
73
73
  exports.LIMITE_TEMPLATE_BYTES = 16384;
74
- /** KG5 fatia 2: dica opt-in no pedido; desligada preserva o texto byte a byte. */
74
+ /**
75
+ * KG5 fatia 2: dica opt-in no pedido; desligada preserva o texto byte a byte. Fatia 5: a dica diz o que
76
+ * a marca `arvore: modificada` quer dizer na aresta.
77
+ */
75
78
  function pedidoComDicaDoGrafo(pedido, thread, ligado) {
76
79
  if (!ligado)
77
80
  return pedido;
78
81
  return pedido.trimEnd() + '\n\n## Contexto do grafo (opcional)\n'
79
82
  + `Consulte ork_grafo_contexto {threadId: "${thread}"} ou ork grafo contexto ${thread} --json para o pacote da thread com evidencias e teto em bytes.\n`
80
83
  + 'As tools ork_grafo_vizinhos, ork_grafo_chamadores, ork_grafo_importadores e ork_grafo_caminho permitem aprofundar. '
81
- + 'Sem indice do HEAD, rode ork grafo indexar. O grafo e parcial; com arvore modificada, descreve o HEAD.\n';
84
+ + 'Sem indice do HEAD, rode ork grafo indexar. O grafo e parcial e descreve o HEAD; '
85
+ + 'aresta com arvore: modificada vem de fonte que mudou depois dele: confira o arquivo antes de usar.\n';
82
86
  }
83
87
  /** Onde um projeto guarda os templates que sobrescrevem os embutidos. */
84
88
  function dirDeTemplates(raiz) {
@@ -50,6 +50,7 @@ const node_crypto_1 = require("node:crypto");
50
50
  const node_child_process_1 = require("node:child_process");
51
51
  const pulse_1 = require("./pulse");
52
52
  const estado_thread_1 = require("./estado-thread");
53
+ const procedencia_1 = require("./procedencia");
53
54
  const hitl_1 = require("./hitl");
54
55
  const horario_1 = require("./horario");
55
56
  const hitl_resumo_1 = require("./hitl-resumo");
@@ -212,6 +213,12 @@ function varrerPulse(opcoes) {
212
213
  const servidas = (0, pulse_resposta_1.threadsComPerguntaViva)(raiz, quando, dir);
213
214
  const jaServida = (i) => !!i.thread && servidas.has(i.thread);
214
215
  novas = itens.filter(i => vistas[i.id] !== assinaturaPulse(i) && !jaServida(i)).length;
216
+ // RM-055 (continuacao, D3): o impedimento que so o dono destrava vai no resumo com o comando de cada um,
217
+ // e o que ele ainda nao viu sai na hora, como pergunta nova: esperar a janela da cadencia deixava a
218
+ // fase parada sem ele saber. O ja avisado nao volta a tocar sozinho.
219
+ const impedimentos = itens.filter(i => i.impedimento && i.thread).map(i => ({ thread: i.thread, fase: i.fase,
220
+ comando: i.impedimento.comando, retry: i.impedimento.retry }));
221
+ const impedimentoNovo = itens.some(i => i.impedimento && vistas[i.id] !== assinaturaPulse(i) && !jaServida(i));
215
222
  for (const i of itens)
216
223
  if (jaServida(i))
217
224
  vistas[i.id] = assinaturaPulse(i);
@@ -220,6 +227,9 @@ function varrerPulse(opcoes) {
220
227
  if (opcoes.enviar)
221
228
  entregue = opcoes.enviar(mensagem);
222
229
  else {
230
+ // RM-047 (P2): o executavel do transporte so sai do arquivo local, nunca de um versionado no git.
231
+ if (!opcoes.transporte)
232
+ (0, procedencia_1.exigirHostLocal)(raiz, path.join(dir, 'pulse-host.json'));
223
233
  const config = opcoes.transporte ?? JSON.parse(fs.readFileSync(path.join(dir, 'pulse-host.json'), 'utf8'));
224
234
  if (typeof config.executavel !== 'string' || !config.executavel || !Array.isArray(config.argumentos) ||
225
235
  !config.argumentos.every(a => typeof a === 'string') || !config.argumentos.some(a => a.includes('{{mensagem}}'))) {
@@ -251,12 +261,13 @@ function varrerPulse(opcoes) {
251
261
  // cadencia do dono, e a novidade que esperou continua nao vista ate sair.
252
262
  const noPrazo = !opcoes.comCadencia || (0, pulse_cadencia_1.janelaAberta)(cadencia, (0, pulse_cadencia_1.lerUltimoResumo)(opcoes.raiz, dir), quando);
253
263
  const informacaoNova = novas > 0 || decisoesNovas.length > 0 || paradosNovos.length > 0;
254
- const adiada = !conjuntoNovo && !esperaNovaFora && informacaoNova && !noPrazo;
255
- if (conjuntoNovo || esperaNovaFora || (noPrazo && informacaoNova)) {
264
+ const adiada = !conjuntoNovo && !esperaNovaFora && !impedimentoNovo && informacaoNova && !noPrazo;
265
+ if (conjuntoNovo || esperaNovaFora || impedimentoNovo || (noPrazo && informacaoNova)) {
256
266
  const guardadas = anterior ? fila.candidatos.filter(c => anterior.candidatos.some(a => a.thread === c.thread)).length : 0;
257
267
  const resumo = (0, hitl_resumo_1.resumirHitl)(itens, { quando, janelaMin, prontas: fila.candidatos.length, acumuladas: guardadas,
258
268
  consertos: fila.consertos, atoDoItem: i => fila.atos.get(`${i.thread}|${i.fase}`),
259
269
  decisoes: decisoesNovas, acimaDoLimiar: pulse.acimaDoLimiar ?? [], outrasMaquinas: outras, paradosNoCondutor: parados,
270
+ impedimentosDoDono: impedimentos,
260
271
  // RM-057 (fatia 3): a linha so acompanha o resumo que ja sai; nao e novidade nem fura a cadencia.
261
272
  ...(pulse.hitlDeConducao ? { hitlDeConducao: pulse.hitlDeConducao } : {}) });
262
273
  // Pedir licenca para mandar zero perguntas era o defeito: sem pergunta, nao ha codigo.
package/dist/pulse.js CHANGED
@@ -4,6 +4,7 @@ exports.JANELA_DAS_DECISOES_MS = exports.CONTRATO_PULSE = void 0;
4
4
  exports.apresentacaoCurtaDoItem = apresentacaoCurtaDoItem;
5
5
  exports.comporPulse = comporPulse;
6
6
  exports.montarPulse = montarPulse;
7
+ exports.filaDoDono = filaDoDono;
7
8
  exports.textoDoPulse = textoDoPulse;
8
9
  const escopo_escrita_1 = require("./escopo-escrita");
9
10
  /** D4: uma fila para quem precisa de humano, com fontes e espera observada. */
@@ -20,6 +21,7 @@ const ledger_1 = require("./ledger");
20
21
  const types_1 = require("./types");
21
22
  const util_1 = require("./util");
22
23
  const horario_1 = require("./horario");
24
+ const locale_1 = require("./locale");
23
25
  const hitl_presentation_1 = require("./hitl-presentation");
24
26
  const hitl_contract_1 = require("./hitl-contract");
25
27
  const hitl_curto_1 = require("./hitl-curto");
@@ -173,12 +175,13 @@ function comporPulse(carregado, entrada) {
173
175
  fontes: ['monitor'], contextoLogs: [] };
174
176
  // RM-055: o impedimento do despacho sai no contrato curto, com o comando exato e o re-despacho depois.
175
177
  if (p.impedimento) {
178
+ item.impedimento = { motivo: p.motivo, comando: p.impedimento.comando, retry: `ork retry run ${l.thread}` };
176
179
  try {
177
180
  const curto = (0, impedimento_1.pedidoCurtoDoImpedimento)({ thread: l.thread, fase: p.fase, motivo: p.motivo, detalhe: p.detalhe,
178
181
  desdeEm: p.desdeEm, impedimento: p.impedimento }, quando);
179
182
  item.apresentacaoCurta = { telegram: (0, hitl_curto_1.textoDoPedidoCurto)(curto, 'telegram'), terminal: (0, hitl_curto_1.textoDoPedidoCurto)(curto, 'terminal') };
180
- item.opcoes = curto.alternativas.map(a => `${a.chave}. ${a.texto}`);
181
- item.comandoResposta = `ork retry run ${l.thread}`;
183
+ item.opcoes = curto.alternativas.map(a => (0, locale_1.textoDoCatalogo)((m) => `${a.chave}. ${m.pulse.alternativaDoImpedimento(a.texto)}`));
184
+ item.comandoResposta = item.impedimento.retry;
182
185
  }
183
186
  catch {
184
187
  item.evidencia.push('Pedido curto do impedimento indisponível; a correção acima vale.');
@@ -210,7 +213,7 @@ function comporPulse(carregado, entrada) {
210
213
  continue;
211
214
  const item = { id: `orfa:${o.thread}:${o.fase}:${o.sessionId}`, classe: o.classe, motivo: o.motivo,
212
215
  thread: o.thread, fase: o.fase, sessionId: o.sessionId, desdeEm: o.desdeEm, paradaHaMin: minutos(o.desdeEm, quando),
213
- impacto: impacto(o.fase), pergunta: `Fase ${o.fase} sem heartbeat desde ${o.ultimoHeartbeatEm}.`,
216
+ impacto: impacto(o.fase), pergunta: (0, locale_1.textoDoCatalogo)((m) => m.pulse.semHeartbeat(o.fase, o.ultimoHeartbeatEm)),
214
217
  opcoes: [], recomendacao: o.retry.razao,
215
218
  comandoResposta: o.retry.automatica ? `ork retry run ${o.thread} --motivo runtime.silencio --fase ${o.fase}` :
216
219
  `ork retry plan ${o.thread} --motivo runtime.silencio --fase ${o.fase}`,
@@ -261,11 +264,12 @@ function montarPulse(carregado, opcoes = {}) {
261
264
  const diagnosticos = [];
262
265
  const quando = opcoes.quando ?? (0, util_1.agora)();
263
266
  const consulta = opcoes.consulta ?? (opcoes.semRuntime
264
- ? { ok: false, sessoes: [], detalhe: 'runtime não consultado por --sem-runtime' } : (0, claude_bg_1.consultarSessoes)(undefined, true));
267
+ ? { ok: false, sessoes: [], detalhe: (0, locale_1.textoDoCatalogo)((m) => m.pulse.semRuntime) } : (0, claude_bg_1.consultarSessoes)(undefined, true));
265
268
  const estados = consulta.ok ? new Map(consulta.sessoes.map(s => [s.sessionId ?? '', (0, hitl_1.estadoBruto)(s)])) : null;
266
269
  const radar = (0, hitl_1.varrerSessoes)({ raiz: carregado.raiz, consulta, agora: quando, registrar: opcoes.registrar, escopo: opcoes.escopo, linhasLogs: opcoes.linhasLogs });
267
- if (radar.telasAdiadas)
268
- diagnosticos.push(`radar.orcamento: ${radar.telasAdiadas} tela(s) de sessão ficaram para a próxima varredura`);
270
+ const telasAdiadas = radar.telasAdiadas;
271
+ if (telasAdiadas)
272
+ diagnosticos.push((0, locale_1.textoDoCatalogo)((m) => m.pulse.telasAdiadas(telasAdiadas)));
269
273
  // Falha de observação não prova silêncio: Claude indisponível preserva sua guarda de HITL e Codex mantém sua coleta independente.
270
274
  const orfas = (0, liveness_1.detectarFasesOrfas)(carregado, { quando, registrar: opcoes.registrar, escopo: opcoes.escopo, diagnosticos,
271
275
  fontes: opcoes.fontes, estados: estados ?? undefined, runtimes: consulta.ok ? undefined : ['codex'] });
@@ -284,7 +288,7 @@ function montarPulse(carregado, opcoes = {}) {
284
288
  // retrato que o status do roadmap le sem rede. Falha de leitura e diagnostico, nunca "sem PR".
285
289
  let entregas;
286
290
  try {
287
- entregas = (0, parado_no_condutor_1.entregasDoProjeto)(carregado, { quando, sessoes: radar.sessoes, lerPrs: (candidatas) => {
291
+ entregas = (0, parado_no_condutor_1.entregasDoProjeto)(carregado, { quando, sessoes: radar.sessoes, lerPrs: opcoes.semForja ? () => null : (candidatas) => {
288
292
  const leitura = (0, parado_no_condutor_1.lerPrsDaForja)(carregado, { quando, executor: opcoes.executorDoGh, candidatas });
289
293
  if (leitura.ok) {
290
294
  try {
@@ -316,7 +320,9 @@ function montarPulse(carregado, opcoes = {}) {
316
320
  diagnosticos.push(`entregas.indisponiveis: ${e.message.slice(0, 120)}`);
317
321
  }
318
322
  const pulse = comporPulse(carregado, { radar, monitor, orfas, batch: (0, master_1.pendentesDeScore)(carregado.raiz), ...(entregas ? { entregas } : {}) });
319
- const conducoes = monitor.linhas.filter((l) => l.conducao).map((l) => ({ thread: l.thread, linha: (0, conducao_texto_1.linhaDeConducao)(l.conducao, { agora: quando }) }));
323
+ // RM-061 (F2b, G2): a linha de conducao e da familia `thread` e segue o locale ativo; o JSON a guarda em pt-BR.
324
+ const conducoes = monitor.linhas.filter((l) => l.conducao)
325
+ .map((l) => ({ thread: l.thread, linha: (0, locale_1.textoDoCatalogo)(() => (0, conducao_texto_1.linhaDeConducao)(l.conducao, { agora: quando })) }));
320
326
  if (conducoes.length > 0)
321
327
  pulse.conducoes = conducoes;
322
328
  // B4: a metade que presta contas. Leitura pura; falhar aqui nunca derruba a fila de atencao.
@@ -341,39 +347,66 @@ function montarPulse(carregado, opcoes = {}) {
341
347
  pulse.runtime.detalhe = [pulse.runtime.detalhe, ...diagnosticos].filter(Boolean).join('; ');
342
348
  return pulse;
343
349
  }
350
+ /**
351
+ * RM-063 (F2): a fila do dono que o `ork roadmap status` le, a MESMA do `ork pulse` (`precisaDeHumanoAgora`). Em 12/10/2026
352
+ * o status disse "Nada agora" com o pulse contando 3: as duas superficies montavam a fila cada uma do seu jeito. Sem
353
+ * forja e sem registrar; o texto de cada item sai numa linha, redigido.
354
+ */
355
+ function filaDoDono(carregado, opcoes = {}) {
356
+ const linha = (texto, teto) => {
357
+ const limpo = (0, hitl_1.redigirSegredos)(texto).replace(/[\p{Cc}\s]+/gu, ' ').trim();
358
+ return limpo.length > teto ? `${limpo.slice(0, teto - 3)}...` : limpo;
359
+ };
360
+ try {
361
+ const p = montarPulse(carregado, { quando: opcoes.quando, semForja: true });
362
+ // Sem o `claude` nesta maquina nao ha sessao dele a perder: a fila do monitor e do ledger esta inteira.
363
+ const lida = p.runtime.ok || !(0, util_1.noPath)('claude');
364
+ return { lida, detalhe: lida ? null : linha(p.runtime.detalhe, 160),
365
+ itens: p.precisaDeHumanoAgora.map(i => ({ id: i.id, thread: i.thread, sessionId: i.sessionId, fase: i.fase, classe: i.classe,
366
+ motivo: i.motivo, pergunta: linha(i.pergunta || i.motivo, 200), comando: linha(i.comandoResposta, 160), paradaHaMin: i.paradaHaMin })) };
367
+ }
368
+ catch (e) {
369
+ return { lida: false, detalhe: linha(e.message, 160), itens: [] };
370
+ }
371
+ }
344
372
  function textoDoPulse(p) {
373
+ const m = (0, locale_1.msg)().pulse;
345
374
  // I-35: o pulse guarda ISO; o texto ao dono sai no fuso dele, rotulado no cabeçalho.
346
- const local = (texto) => (0, horario_1.localizarTexto)(texto, { agora: p.consultadoEm });
347
- const linhas = [`Pulse (${p.contrato}) ${(0, horario_1.formatarDataHoraRotulada)(p.consultadoEm, { agora: p.consultadoEm })}`, `Precisa de humano agora: ${p.resumo.humanos}`, `${p.resumo.scores} entrega(s) sem nota, aceitas por padrão com registro`];
375
+ // RM-061 (F2b, G2): o que o pulse montou pelo catalogo sai remontado; o resto (pedido HITL, ledger) como veio.
376
+ const local = (texto) => (0, horario_1.localizarTexto)((0, locale_1.remontar)(texto), { agora: p.consultadoEm });
377
+ // O detalhe do runtime junta partes separadas por "; ": cada uma e remontada.
378
+ const detalhe = (texto) => (0, horario_1.localizarTexto)(texto.split('; ').map(locale_1.remontar).join('; '), { agora: p.consultadoEm });
379
+ const linhas = [m.cabecalho(p.contrato, (0, horario_1.formatarDataHoraRotulada)(p.consultadoEm, { agora: p.consultadoEm })), m.precisaDeHumano(p.resumo.humanos), m.semNota(p.resumo.scores)];
348
380
  // RM-037 (fatia 4): PR nao lido tambem e dito, para a falta de linha do condutor nao parecer "nada parado".
349
381
  if (p.runtime.ok && ['liveness.snapshot.invalid', 'prs.nao-lidos', 'prs.sem-leitura', 'entregas.indisponiveis'].some(d => p.runtime.detalhe.includes(d))) {
350
- linhas.push(`[diagnostico] ${local(p.runtime.detalhe)}`);
382
+ linhas.push(m.diagnostico(detalhe(p.runtime.detalhe)));
351
383
  }
352
384
  if (!p.runtime.ok)
353
- linhas.push(`[consulta incompleta] ${local(p.runtime.detalhe)}`);
385
+ linhas.push(m.consultaIncompleta(detalhe(p.runtime.detalhe)));
354
386
  for (const i of p.precisaDeHumanoAgora) {
355
- linhas.push('', `${i.thread ?? i.sessionId} [${i.classe}] ${i.paradaHaMin == null ? 'desconhecido' : i.paradaHaMin < 1 ? 'menos de 1' : i.paradaHaMin} min`, local(i.pergunta), ...i.opcoes.map(o => ` opção: ${o}`), `Recomendação: ${i.recomendacao}`, `Responder: ${i.comandoResposta}`, ...i.contextoLogs.map(l => ` log: ${l}`));
387
+ linhas.push('', m.item(String(i.thread ?? i.sessionId), m.classe(i.classe), i.paradaHaMin == null ? m.desconhecido : i.paradaHaMin < 1 ? m.menosDeUm : String(i.paradaHaMin)), local(i.pergunta), ...i.opcoes.map(o => m.opcao((0, locale_1.remontar)(o))), m.recomendacao((0, locale_1.remontar)(i.recomendacao)), m.responder((0, locale_1.remontar)(i.comandoResposta)), ...i.contextoLogs.map(l => m.log(l)));
356
388
  }
357
389
  if (p.conducoes?.length) {
358
- linhas.push('', `Conduzidas agora: ${p.conducoes.length}`);
390
+ linhas.push('', m.conduzidas(p.conducoes.length));
359
391
  for (const c of p.conducoes)
360
- linhas.push(`${c.thread}: ${c.linha}`);
392
+ linhas.push(m.conducao(c.thread, (0, locale_1.remontar)(c.linha)));
361
393
  }
362
394
  // RM-037 (fatia 4): o que espera o condutor, uma linha por thread; nao e pergunta ao dono.
363
395
  if (p.paradoNoCondutor?.length) {
364
- linhas.push('', `Parado no condutor: ${p.paradoNoCondutor.length}`);
396
+ linhas.push('', m.paradoNoCondutor(p.paradoNoCondutor.length));
365
397
  for (const x of p.paradoNoCondutor)
366
398
  linhas.push((0, hitl_resumo_1.linhaDoParadoNoCondutor)(x, { agora: p.consultadoEm }));
367
399
  }
368
400
  // RM-057 (fatia 3): quanto tempo cada pergunta de conducao aberta ja parou a thread, e a mediana da semana.
369
401
  if (p.hitlDeConducao) {
370
402
  const h = p.hitlDeConducao;
371
- linhas.push('', `HITL de condução: ${h.abertas.length} aberta(s); ${(0, hitl_tempo_parado_1.textoDaMediana)(h)}`);
403
+ linhas.push('', m.hitlDeConducao(h.abertas.length, (0, hitl_tempo_parado_1.textoDaMediana)(h)));
372
404
  for (const a of h.abertas)
373
405
  linhas.push((0, hitl_tempo_parado_1.linhaDaPerguntaParada)(a, { agora: p.consultadoEm }));
374
406
  }
375
- linhas.push('', `Ações automáticas pendentes: ${p.resumo.automaticas}`);
407
+ linhas.push('', m.automaticas(p.resumo.automaticas));
408
+ // RM-061 (F2b, D4): o item do radar sem tipo de HITL usa a classe como motivo; ela sai pelo id, o motivo tipado fica.
376
409
  for (const i of p.acoesAutomaticas)
377
- linhas.push(`${i.thread}: ${i.motivo}; ${i.comandoResposta}`);
410
+ linhas.push(m.automatica(String(i.thread), i.motivo === i.classe ? m.classe(i.motivo) : i.motivo, (0, locale_1.remontar)(i.comandoResposta)));
378
411
  return linhas.join('\n');
379
412
  }
package/dist/ratelimit.js CHANGED
@@ -73,6 +73,7 @@ const path = __importStar(require("node:path"));
73
73
  const manifest_1 = require("./manifest");
74
74
  const util_1 = require("./util");
75
75
  const horario_1 = require("./horario");
76
+ const locale_1 = require("./locale");
76
77
  const runtime_profiles_1 = require("./runtime-profiles");
77
78
  var claude_bg_1 = require("./adapters/claude-bg");
78
79
  Object.defineProperty(exports, "parseRateLimit", { enumerable: true, get: function () { return claude_bg_1.parseRateLimit; } });
@@ -204,10 +205,11 @@ function vencidos(raiz, quando = (0, util_1.agora)()) {
204
205
  /** Quanto falta para a janela de um pedido, em texto curto para o CLI. */
205
206
  function faltaPara(pedido, quando = (0, util_1.agora)()) {
206
207
  const ms = new Date(pedido.liberaEm).getTime() - new Date(quando).getTime();
208
+ const m = (0, locale_1.msg)().horario;
207
209
  if (ms <= 0)
208
- return 'ja liberou';
210
+ return m.jaLiberou;
209
211
  const min = Math.ceil(ms / 60000);
210
- return min < 60 ? `em ${min} min` : `em ${Math.floor(min / 60)}h${String(min % 60).padStart(2, '0')}`;
212
+ return min < 60 ? m.emMinutos(min) : m.emHoras(Math.floor(min / 60), String(min % 60).padStart(2, '0'));
211
213
  }
212
214
  /** Tabela de `ork retry list`. */
213
215
  function tabelaDaFila(raiz, quando = (0, util_1.agora)()) {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LIMITE_DE_TESTES = exports.LIMITE_DO_TRECHO = void 0;
4
4
  exports.redigirSaida = redigirSaida;
5
5
  exports.testesQueCairam = testesQueCairam;
6
+ exports.falhasDeTeste = falhasDeTeste;
6
7
  /**
7
8
  * I-37 (D9): a saida de um comando que falhou, pronta para ir ao ledger.
8
9
  *
@@ -41,5 +42,67 @@ function testesQueCairam(saida) {
41
42
  if (nomes.length === exports.LIMITE_DE_TESTES)
42
43
  break;
43
44
  }
45
+ // RM-037 (fatia 6): o reporter `spec`, o padrao do `node --test` 24 fora de TTY, nao imprime `not ok`;
46
+ // os nomes moram na secao "failing tests" do fim da saida.
47
+ if (nomes.length === 0)
48
+ return falhasDeTeste(saida).map((f) => f.nome).slice(0, exports.LIMITE_DE_TESTES);
44
49
  return nomes;
45
50
  }
51
+ /** As frases do `node --test` para a falha que e do relogio, e nao da asercao. */
52
+ const ASSINATURA_DE_RELOGIO = /test timed out after \d+ms|test did not finish before its parent and was cancelled/;
53
+ const TIPO_DE_RELOGIO = /failureType:\s*'(?:testTimeoutFailure|cancelledByParent)'/;
54
+ /** O teste que so agrega os filhos (subtestes ou arquivo) nao e uma falha por si. */
55
+ const TIPO_DE_AGREGADO = /failureType:\s*'subtestsFailed'/;
56
+ /**
57
+ * RM-037 (fatia 6): os testes reprovados, folha a folha, com a natureza da falha, para o verify saber
58
+ * se a reprovacao e so de relogio. Le o TAP do `node --test` (o bloco YAML depois do `not ok`, pulando
59
+ * o agregado `subtestsFailed`) e a secao "failing tests" do reporter `spec`. Outros runners (jest,
60
+ * vitest) nao dizem a natureza: os nomes saem com `relogio: false`, e nada e atenuado.
61
+ */
62
+ function falhasDeTeste(saida) {
63
+ const linhas = saida.split('\n');
64
+ const falhas = [];
65
+ const somar = (nome, relogio) => {
66
+ const limpo = nome.trim().slice(0, LIMITE_DO_NOME);
67
+ if (!limpo)
68
+ return;
69
+ const ja = falhas.find((f) => f.nome === limpo);
70
+ if (ja)
71
+ ja.relogio = ja.relogio && relogio;
72
+ else
73
+ falhas.push({ nome: limpo, relogio });
74
+ };
75
+ for (let i = 0; i < linhas.length; i++) {
76
+ const tap = /^\s*not ok \d+ - (.+?)\s*(?:#.*)?$/.exec(linhas[i]);
77
+ if (!tap)
78
+ continue;
79
+ const bloco = [];
80
+ for (let j = i + 1; j < linhas.length && !/^\s*(?:not )?ok \d+ /.test(linhas[j]); j++)
81
+ bloco.push(linhas[j]);
82
+ const texto = bloco.join('\n');
83
+ if (TIPO_DE_AGREGADO.test(texto))
84
+ continue;
85
+ somar(tap[1], TIPO_DE_RELOGIO.test(texto) || ASSINATURA_DE_RELOGIO.test(texto));
86
+ }
87
+ const inicio = linhas.findIndex((l) => /^\s*✖ failing tests:\s*$/.test(l));
88
+ if (inicio >= 0) {
89
+ for (let i = inicio + 1; i < linhas.length; i++) {
90
+ const cabeca = /^✖ (.+?)(?: \([\d.]+m?s\))?\s*$/.exec(linhas[i]);
91
+ if (!cabeca)
92
+ continue;
93
+ const corpo = [];
94
+ for (let j = i + 1; j < linhas.length && !/^(?:✖ |test at )/.test(linhas[j]); j++)
95
+ corpo.push(linhas[j]);
96
+ const primeira = corpo.find((l) => l.trim() !== '') ?? '';
97
+ somar(cabeca[1], ASSINATURA_DE_RELOGIO.test(primeira));
98
+ }
99
+ }
100
+ if (falhas.length === 0) {
101
+ for (const linha of linhas) {
102
+ const fail = /^\s*(?:FAIL|✕|×)\s+(\S.*?)\s*$/.exec(linha);
103
+ if (fail)
104
+ somar(fail[1], false);
105
+ }
106
+ }
107
+ return falhas;
108
+ }
@@ -55,6 +55,7 @@ const path = __importStar(require("node:path"));
55
55
  const branch_de_estado_1 = require("./branch-de-estado");
56
56
  const fabrica_estado_1 = require("./fabrica-estado");
57
57
  const horario_1 = require("./horario");
58
+ const locale_1 = require("./locale");
58
59
  const manifest_1 = require("./manifest");
59
60
  const maquina_1 = require("./maquina");
60
61
  const rede_1 = require("./rede");
@@ -261,10 +262,10 @@ function lerRede(o = {}) {
261
262
  }
262
263
  function duracao(ms) {
263
264
  if (!Number.isFinite(ms))
264
- return 'tempo desconhecido';
265
+ return (0, locale_1.msg)().horario.duracaoDesconhecida;
265
266
  const min = Math.round(ms / 60000);
266
267
  if (min < 1)
267
- return 'menos de 1 min';
268
+ return (0, locale_1.msg)().horario.menosDeUmMin;
268
269
  if (min < 120)
269
270
  return `${min} min`;
270
271
  const h = Math.round(ms / 3600000);