@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
package/dist/locale.js ADDED
@@ -0,0 +1,714 @@
1
+ "use strict";
2
+ /**
3
+ * CLI em ingles e pt-BR (RM-061): F1 com `doctor` e `init`, F2a com o caminho da primeira experiencia.
4
+ *
5
+ * Um catalogo de mensagens por locale, sem dependencia nova: pt-BR e o padrao e a fonte; `en` e a
6
+ * alternativa. O catalogo ingles e tipado pelo portugues (`typeof PT_BR`), entao chave faltando ou
7
+ * assinatura diferente nao compila.
8
+ *
9
+ * Quem decide o locale, nesta ordem:
10
+ * 1. `owner.language` do manifesto, a escolha do onboarding (etapa maestro);
11
+ * 2. `LC_ALL`, `LC_MESSAGES` e `LANG`, a primeira nao vazia (a ordem do POSIX);
12
+ * 3. pt-BR.
13
+ * So `en*` vira ingles; qualquer outra lingua (es, fr, C, POSIX) fica no pt-BR, a lingua do CLI.
14
+ *
15
+ * O locale so vale nos comandos que o CLI ativa por `ativarLocale` (`COMANDOS_COM_LOCALE`, no texto;
16
+ * o `--json` e contrato e nao passa por aqui). Sem ativacao, tudo segue pt-BR: nenhum outro comando
17
+ * muda de lingua pela metade.
18
+ *
19
+ * F2a (D1 e D6 da thread ork-rm061f2a): o catalogo traduz o texto que o comando monta para a pessoa.
20
+ * Dado gravado (ledger, `thread.json`, prompt, estado do onboarding, recusa registrada, policy
21
+ * avaliada) e montado dentro de `comLocale('pt-BR', ...)` e sai como foi gravado. Valor que e dado,
22
+ * como o nome de um check ou o `pausaSobre` de um bloco, so e traduzido na impressao.
23
+ *
24
+ * D14: o erro que o catalogo monta e que nasce no escopo pt-BR da gravacao (`ErroDoCatalogo`: manifesto
25
+ * ausente, os erros de argumento de `thread new`, `--runtime` e o modelo ao trocar de runtime no `phase run`)
26
+ * e remontado no locale do comando pela entrada do CLI. Seguem como o modulo dono escreve, ate a familia dele migrar: o validador
27
+ * do manifesto (fora os avisos de preferencia da experiencia, traduzidos na impressao), o regime de
28
+ * memoria, o erro de estado durante a gravacao e, na F2b, a recusa `ship.remoto-invalido` do `exigirRemoto`
29
+ * (`branch-de-estado.ts`, modulo compartilhado com a fabrica e a rede). O cabecalho `Projeto consultado:` e `Não lido:` e
30
+ * contrato do RM-052 com os hosts e fica igual nas duas linguas.
31
+ *
32
+ * F2b (G2 e D1 da thread ork-rm061f2b): o texto que o proprio comando monta e que tambem vai ao ledger ou
33
+ * ao `--json` (o detalhe de uma claim reexecutada, o bloqueio do ship, a razao do retry) nasce em pt-BR por
34
+ * `textoDoCatalogo`, dentro do escopo da gravacao, e a impressao o remonta no locale ativo por `remontar`.
35
+ * O registro dos montadores so existe nos comandos cobertos (`ligarRemontagem`); o servidor MCP e o cron
36
+ * nunca o ligam. O que outro processo gravou, a policy avaliada e a saida de ferramenta externa saem como
37
+ * vieram, e tambem (G5) o proximo passo e o estado da entrega de uma thread parada no condutor
38
+ * (`parado-no-condutor.ts`, a familia de entregas), ate a F3. Motivo tipado, acao e bloqueio do retry, codigo,
39
+ * comando e sha saem iguais nas duas linguas (G4); valor de estado mostrado em tabela ou entre parenteses (a
40
+ * acao do `registrar-pr`, o tipo da autorizacao do ship, o status da thread, o veredito e a cobertura do
41
+ * CHECK-REVERIFY, o titulo do grupo do roadmap, a classe do item do pulse) e dado do `--json` e so se traduz
42
+ * na impressao, pelo id (D4).
43
+ *
44
+ * F3a (D1 a D3 da thread ork-rm061f3a): o que o CLI escreve em arquivo para pessoas e agentes lerem (os comentarios
45
+ * do `orkastery.yaml`, o bloco do `AGENTS.md`, o bloco da experiencia no `CLAUDE.md` e os modelos do `ork docs init`)
46
+ * nasce na lingua do dono no momento da geracao, pela familia `gerados` e por `core/assets/docs-en/`.
47
+ * O gerador recebe o locale por parametro, com pt-BR por omissao, e so a entrada do CLI passa a lingua do dono: o
48
+ * locale ativo nunca escolhe a lingua de um arquivo. Chave, valor e marcador do arquivo nao mudam com a lingua.
49
+ *
50
+ * Ingles (D8): curto, no imperativo onde e instrucao, com os mesmos termos em todo o CLI (`thread`,
51
+ * `phase`, `claim`, `verify`, `ship`, `pulse`, `lease`, `ledger`, `worktree`, `slug`). Comando, flag
52
+ * e identificador dentro de frase vao entre crases; valor que e so um comando (a linha `fix:`) fica nu.
53
+ */
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.ErroDoCatalogo = exports.COMANDOS_COM_LOCALE = exports.LOCALE_PADRAO = void 0;
56
+ exports.chaveDoLocale = chaveDoLocale;
57
+ exports.cobreLocale = cobreLocale;
58
+ exports.localeDe = localeDe;
59
+ exports.resolverLocale = resolverLocale;
60
+ exports.ativarLocale = ativarLocale;
61
+ exports.localeAtivo = localeAtivo;
62
+ exports.comLocale = comLocale;
63
+ exports.msg = msg;
64
+ exports.mensagemDoErro = mensagemDoErro;
65
+ exports.ligarRemontagem = ligarRemontagem;
66
+ exports.textoDoCatalogo = textoDoCatalogo;
67
+ exports.remontar = remontar;
68
+ exports.nomeDoCheck = nomeDoCheck;
69
+ const locale_onboarding_1 = require("./locale-onboarding");
70
+ const locale_thread_1 = require("./locale-thread");
71
+ const locale_phase_1 = require("./locale-phase");
72
+ const locale_ajuda_1 = require("./locale-ajuda");
73
+ const locale_verify_1 = require("./locale-verify");
74
+ const locale_ship_1 = require("./locale-ship");
75
+ const locale_retry_1 = require("./locale-retry");
76
+ const locale_master_1 = require("./locale-master");
77
+ const locale_pulse_1 = require("./locale-pulse");
78
+ const locale_roadmap_1 = require("./locale-roadmap");
79
+ const locale_gerados_1 = require("./locale-gerados");
80
+ exports.LOCALE_PADRAO = 'pt-BR';
81
+ /**
82
+ * Comandos cujo texto ja sai pelo catalogo, por `comando` ou por `comando subcomando`; `comando ?` e o
83
+ * subcomando desconhecido (o erro de uso e do proprio comando). Os demais seguem em pt-BR. Ficam de
84
+ * fora por decisao (D2 da F2a): `doctor --modo`, `thread new --from-finding`, `onboarding sync`,
85
+ * `experiencia uninstall` e `thread list|close|entrega`. A F2b (G3) acrescenta `verify` (com `--baseline`),
86
+ * `ship`, `ship registrar-pr`, `retry plan`, `retry run`, `master` (o indice), `master aceitar-omissao` e
87
+ * `master pedir`, `pulse` (sem `responder` nem `cadencia`) e `roadmap status`. A F3a (D5) acrescenta `docs init`;
88
+ * `docs verificar` e `docs sincronizar` seguem em pt-BR.
89
+ */
90
+ exports.COMANDOS_COM_LOCALE = ['doctor', 'init', 'onboarding show', 'onboarding set', 'onboarding reset',
91
+ 'onboarding ?', 'experiencia show', 'experiencia ?', 'thread new', 'thread status', 'thread ?',
92
+ 'phase list', 'phase run', 'phase ?', 'verify', 'ship', 'ship registrar-pr', 'retry plan', 'retry run',
93
+ 'master', 'master aceitar-omissao', 'master pedir', 'pulse', 'roadmap status', 'docs init'];
94
+ /** Os comandos com subcomando: o padrao (sem subcomando) e os conhecidos; o resto vira `?`. */
95
+ const FAMILIAS = new Map([
96
+ ['onboarding', { padrao: 'show', conhecidos: ['show', 'set', 'reset', 'sync'] }],
97
+ ['experiencia', { padrao: 'show', conhecidos: ['show', 'uninstall'] }],
98
+ ['thread', { padrao: 'list', conhecidos: ['new', 'list', 'status', 'close', 'entrega'] }],
99
+ ['phase', { padrao: null, conhecidos: ['run', 'list'] }],
100
+ ['retry', { padrao: null, conhecidos: ['plan', 'run', 'policy', 'parse', 'list', 'resume', 'cancel'] }],
101
+ ['roadmap', { padrao: 'reservas', conhecidos: ['reservas', 'status', 'feat', 'pegar', 'soltar'] }],
102
+ ['docs', { padrao: 'verificar', conhecidos: ['verificar', 'sincronizar', 'init'] }],
103
+ ]);
104
+ /** A entrada de `COMANDOS_COM_LOCALE` que a linha de comando pede, com o subcomando padrao de cada um. */
105
+ function chaveDoLocale(posicionais, opcoes) {
106
+ const [comando = '', bruto] = posicionais;
107
+ // F2b (D2): `ork ship <thread>` tem a thread no lugar do subcomando; so `registrar-pr` e rota propria.
108
+ if (comando === 'ship')
109
+ return bruto === 'registrar-pr' ? 'ship registrar-pr' : 'ship';
110
+ if (comando === 'master')
111
+ return chaveDoMaster(bruto, opcoes);
112
+ // `ork pulse` le qualquer posicional como o pulse de sempre; `responder` e `cadencia` sao rotas proprias.
113
+ if (comando === 'pulse')
114
+ return bruto === 'responder' || bruto === 'cadencia' ? `pulse ${bruto}` : 'pulse';
115
+ const familia = FAMILIAS.get(comando);
116
+ if (!familia)
117
+ return comando;
118
+ const sub = comando === 'onboarding' && 'reset' in opcoes ? 'reset' : bruto ?? familia.padrao;
119
+ return `${comando} ${sub !== null && familia.conhecidos.includes(sub) ? sub : '?'}`;
120
+ }
121
+ /** Os subcomandos do `ork master` que nao seguem o locale (G3 da F2b): cada um e rota propria. */
122
+ const SUBCOMANDOS_DO_MASTER = ['audit', 'digest', 'migrar', 'classes', 'ratificar', 'batch', 'propor'];
123
+ /**
124
+ * A rota do `ork master`, na mesma ordem em que o comando a decide: `pedir` (nunca com `--formato json`),
125
+ * os subcomandos proprios, `--batch`, o aceite por omissao e, sem nada, o indice. A thread sozinha e a nota
126
+ * (`--score`), que segue em pt-BR.
127
+ */
128
+ function chaveDoMaster(bruto, opcoes) {
129
+ if (bruto === 'pedir')
130
+ return opcoes.formato === 'json' ? 'master pedir json' : 'master pedir';
131
+ if (bruto !== undefined && SUBCOMANDOS_DO_MASTER.includes(bruto))
132
+ return `master ${bruto}`;
133
+ if (opcoes.batch !== undefined)
134
+ return 'master batch';
135
+ if (opcoes['aceitar-omissao'] !== undefined)
136
+ return 'master aceitar-omissao';
137
+ return bruto === undefined ? 'master' : 'master <thread>';
138
+ }
139
+ /** O comando pede o texto pelo locale? Nunca com `--json`, nem nos recortes da D2. */
140
+ function cobreLocale(posicionais, opcoes) {
141
+ if (opcoes.json !== undefined)
142
+ return false;
143
+ if (posicionais[0] === 'doctor' && opcoes.modo !== undefined)
144
+ return false;
145
+ if (opcoes['from-finding'] !== undefined || opcoes['do-achado'] !== undefined)
146
+ return false;
147
+ return exports.COMANDOS_COM_LOCALE.includes(chaveDoLocale(posicionais, opcoes));
148
+ }
149
+ /** `en_US.UTF-8`, `en-GB`, `en` viram `en`; `pt_BR.UTF-8`, `pt` viram pt-BR; o resto, undefined. */
150
+ function localeDe(valor) {
151
+ if (typeof valor !== 'string')
152
+ return undefined;
153
+ const lingua = valor.trim().split(/[.@]/)[0].replace(/_/g, '-').split('-')[0].toLowerCase();
154
+ if (lingua === 'en')
155
+ return 'en';
156
+ if (lingua === 'pt')
157
+ return 'pt-BR';
158
+ return undefined;
159
+ }
160
+ /** O locale do processo: a escolha do onboarding vence o ambiente; sem nenhum, pt-BR. */
161
+ function resolverLocale(ownerLanguage, env = process.env) {
162
+ if (typeof ownerLanguage === 'string' && ownerLanguage.trim()) {
163
+ return { locale: localeDe(ownerLanguage) ?? exports.LOCALE_PADRAO, origem: 'manifesto' };
164
+ }
165
+ for (const nome of ['LC_ALL', 'LC_MESSAGES', 'LANG']) {
166
+ const v = env[nome];
167
+ if (v && v.trim())
168
+ return { locale: localeDe(v) ?? exports.LOCALE_PADRAO, origem: nome };
169
+ }
170
+ return { locale: exports.LOCALE_PADRAO, origem: 'padrao' };
171
+ }
172
+ let ativo = exports.LOCALE_PADRAO;
173
+ /** Fixa o locale do processo (o CLI, nos comandos de `COMANDOS_COM_LOCALE`; os testes). */
174
+ function ativarLocale(locale) {
175
+ ativo = locale ?? exports.LOCALE_PADRAO;
176
+ }
177
+ function localeAtivo() {
178
+ return ativo;
179
+ }
180
+ /**
181
+ * Roda `fn` no locale pedido e volta ao anterior, mesmo com erro. Nos comandos cobertos, o que grava
182
+ * estado roda em `comLocale('pt-BR', ...)`: o texto sai em ingles, o dado gravado nao muda (D1, D6).
183
+ */
184
+ function comLocale(locale, fn) {
185
+ const anterior = ativo;
186
+ ativo = locale;
187
+ try {
188
+ return fn();
189
+ }
190
+ finally {
191
+ ativo = anterior;
192
+ }
193
+ }
194
+ // ---------------------------------------------------------------------------
195
+ // Catalogo
196
+ // ---------------------------------------------------------------------------
197
+ const PT_BR = {
198
+ cli: {
199
+ /** Prefixo do erro que a entrada do CLI imprime (D11). */
200
+ erro: (mensagem) => `erro: ${mensagem}`,
201
+ subcomandoDesconhecido: (comando, sub) => `subcomando desconhecido: ${comando} ${sub}`,
202
+ /** `exigirManifesto` fora de um projeto: o primeiro erro de quem chega (D14). */
203
+ manifestoNaoEncontrado: (nome, dir) => `manifesto ${nome} nao encontrado a partir de ${dir}. Rode: ork init`,
204
+ },
205
+ horario: {
206
+ brasilia: 'horário de Brasília',
207
+ legendaBrasilia: 'Horários de Brasília.',
208
+ legenda: (rotulo) => `Horários em ${rotulo}.`,
209
+ duracaoDesconhecida: 'tempo desconhecido',
210
+ menosDeUmMin: 'menos de 1 min',
211
+ /** `faltaPara` (ratelimit.ts): quanto falta para o pedido da fila liberar. */
212
+ jaLiberou: 'ja liberou',
213
+ emMinutos: (n) => `em ${n} min`,
214
+ emHoras: (h, mm) => `em ${h}h${mm}`,
215
+ },
216
+ doctor: {
217
+ titulo: 'ork doctor: o que vale nesta maquina agora',
218
+ correcao: 'correcao',
219
+ bloqueado: (falhas, avisos) => `Veredito: BLOQUEADO (${falhas} fail, ${avisos} warn). Corrija os itens acima antes de despachar fase.`,
220
+ pronto: (avisos) => `Veredito: PRONTO (${avisos} warn). Despacho de fase liberado por \`ork phase run\`.`,
221
+ /** Nome de cada check como aparece no texto; o `Check.nome` gravado nao muda. */
222
+ nomes: {},
223
+ instaleNode: 'instale Node 20 ou superior',
224
+ gitAusente: 'nao encontrado no PATH',
225
+ instaleGit: 'instale o git',
226
+ branch: (branch, semCommit) => `branch ${branch}${semCommit ? ' (sem commit)' : ''}`,
227
+ foraDeRepo: 'fora de um repositorio git',
228
+ rodeDentroDeRepo: 'rode o ork dentro de um repositorio git',
229
+ versaoDesconhecida: 'versao desconhecida',
230
+ codexAusenteUsado: 'binario `codex` fora do PATH (o projeto despacha por ele: veja despacho pelo codex)',
231
+ codexAusenteOpcional: 'binario `codex` fora do PATH (opcional: claude-bg e o runtime padrao)',
232
+ instaleCodex: 'para despachar pelo codex, instale o Codex CLI e autentique com `codex login`',
233
+ sandboxOk: '`codex sandbox true` executa nesta maquina',
234
+ sandboxFalhou: (detalhe) => `sonda \`codex sandbox true\` falhou: ${detalhe}`,
235
+ sandboxCorrecao: (confirmar) => 'instale o pacote bubblewrap do sistema (o bwrap embutido nao cria user namespace ' +
236
+ `nesta maquina) ou declare runtime.sandbox: danger-full-access ciente do risco e confirme nesta maquina com ${confirmar}`,
237
+ manifestoAusente: (nome, dir) => `${nome} nao encontrado a partir de ${dir}`,
238
+ rodeInit: 'ork init',
239
+ entreNoRepoEInit: 'entre no repositorio do projeto (ou crie um com git init e o primeiro commit) e rode ork init',
240
+ corrijaManifesto: 'corrija o manifesto e rode ork doctor de novo',
241
+ abbrevOk: (abbrev) => `"${abbrev}" (parte 1 do slug de sessao)`,
242
+ abbrevCorrecao: 'defina project.abbrev com ate 3 caracteres [a-z0-9]',
243
+ modos: (padrao, permitidos) => `padrao ${padrao}; permitidos ${permitidos}`,
244
+ fusoDoManifesto: (fuso, chave, rotulo) => `${fuso} (${chave}); horarios para pessoas em ${rotulo}`,
245
+ fusoDoSistema: (fuso, chave) => `${fuso} (fuso do sistema; ${chave} nao configurado)`,
246
+ fusoCorrecao: (chave) => `corrija ${chave} com um nome IANA`,
247
+ filaVazia: 'vazia: nenhuma fase morreu por limite de uso neste projeto',
248
+ filaResumo: (esperando, escalados) => `${esperando} aguardando janela, ${escalados} escalado(s) para humano`,
249
+ filaProxima: (quando) => `; proxima janela em ${quando}`,
250
+ estadoOk: (dir, qtd) => `${dir} (${qtd} thread(s))`,
251
+ estadoAusente: (dir) => `${dir} ausente`,
252
+ estadoCorrecao: 'ork init cria o diretorio de estado',
253
+ claudeSemLogin: (detalhe, auth) => `${detalhe}; ${auth}: o despacho pelo claude-bg falharia`,
254
+ claudeLoginPago: 'faca o login de assinatura (claude.ai) no `claude`, sem API key nem provider de nuvem',
255
+ claudeLogin: 'rode `claude` uma vez, faca o login de assinatura (/login) e aceite a confianca no diretorio do projeto; ' +
256
+ 'ou crie um perfil com ork accounts add <id> --runtime claude-bg --dir <pasta>',
257
+ onboardingPendente: (n, etapas) => `${n} etapa(s) pendente(s): ${etapas}`,
258
+ onboardingCompleto: '9 etapas respondidas',
259
+ foraDaRede: 'fora da rede; ork network entrar poe esta maquina na rede da pessoa',
260
+ manifestoOk: (caminho, bytes, limite) => `${caminho} (${bytes} B de ${limite})`,
261
+ politicaViolada: (politica, envs) => `politica ${politica} violada: ${envs} redireciona o despacho do claude`,
262
+ politicaComPaga: (politica, envs) => `politica ${politica}; despacho segue na assinatura local, mas ha credencial paga no ambiente: ${envs}`,
263
+ politicaLimpa: (politica) => `politica ${politica}; nenhuma variavel de provider pago ativa`,
264
+ removaDoAmbiente: (envs) => `remova do ambiente: ${envs} (o despacho usa a assinatura Claude local)`,
265
+ nuncaDespachePorPaga: (envs) => `nenhuma acao obrigatoria; nunca despache fase por ${envs}`,
266
+ providersAtivos: (nomes) => `nomes ativos: ${nomes}`,
267
+ nenhumProvider: 'nenhum nome da lista de provider ativo',
268
+ memoriaFiles: 'files (fallback honesto: handoff por arquivos, ponteiro path#ancora)',
269
+ embeddingNone: 'memory.embedding com provider none: busca por significado desligada',
270
+ semPerfis: 'nenhum perfil configurado: cada runtime despacha pelo ambiente do processo',
271
+ // F2a: o resto do doctor.
272
+ manifestoForaDoRepo: (nome, caminho, topo) => `o ${nome} lido fica fora deste repositorio (${caminho}): o ork conduz o projeto daquela pasta, nao o de ${topo}`,
273
+ manifestoForaDoRepoCorrecao: (topo) => `rode ork init na raiz deste repositorio (${topo}); se o manifesto de fora ` +
274
+ 'nasceu por engano, apague-o junto com o AGENTS.md e o .orkastery/ ao lado dele',
275
+ storeInvalido: (erro) => `store de perfis invalido: ${erro}`,
276
+ storeCorrecao: 'o store fica em .orkastery/private/runtime-profiles.json (arquivo 0600, pasta 0700)',
277
+ contaPaga: 'provider pago (nunca despacha)',
278
+ contaInconclusiva: 'conferencia de login inconclusiva',
279
+ contaSemLogin: 'sem login',
280
+ contaPronta: 'pronto',
281
+ contaFora: (estado, ate) => `${estado}${ate ? ` ate ${ate}` : ''}`,
282
+ contasCorrecao: 'ork accounts check marca os perfis (sem-auth, provider-pago); ork accounts add refaz o login de assinatura ' +
283
+ 'pelo proprio CLI, nunca copiando credencial',
284
+ embeddingPago: (variavel) => `memory.embedding.api_key_env declara ${variavel}, nome da lista de provider pago`,
285
+ embeddingPagoCorrecao: 'use uma chave dedicada ao Orkastery com nome proprio, por exemplo ORKASTERY_EMBEDDING_API_KEY',
286
+ embeddingSemVariavel: (provider) => `memory.embedding com provider ${provider} sem api_key_env`,
287
+ embeddingSemVariavelCorrecao: 'declare em memory.embedding.api_key_env o NOME da variavel com a chave dedicada',
288
+ embeddingRecusada: (variavel) => `${variavel} tem valor recusado: parece URL, DSN ou texto com espaco (valor nunca impresso)`,
289
+ embeddingRecusadaCorrecao: (variavel) => `confira se ${variavel} guarda a chave dedicada, e nao outra credencial`,
290
+ embeddingPresente: (variavel, provider, modelo) => `${variavel} presente no ambiente (valor nunca impresso); ${provider} ${modelo}`,
291
+ embeddingAusente: (variavel) => `${variavel} ausente do ambiente: a busca por significado usa o fallback local ou cai para FTS; o regime nao muda`,
292
+ embeddingAusenteCorrecao: (variavel) => `exporte ${variavel} com a chave dedicada ao Orkastery (com limite de credito no painel do provider)`,
293
+ donoOutro: (total, dir, uids, uid, exemplos, parcialDe) => `${total} entrada(s) de ${dir} com outro dono (uid ${uids}; o do repositorio e ${uid}): ${exemplos}; o git do dono nao grava nelas, ` +
294
+ `e o fetch e o commit falham${parcialDe !== null ? ` (conferencia parcial: mais de ${parcialDe} entradas)` : ''}`,
295
+ donoCorrecao: (comando) => `${comando} (o ork nao roda isso sozinho)`,
296
+ donoParcial: (teto, dir) => `mais de ${teto} entradas em ${dir}: conferencia parcial, sem outro dono ate aqui`,
297
+ donoParcialCorrecao: (comando) => `confira o resto com: ${comando}`,
298
+ donoOk: (vistos, dir, uid) => `${vistos} entradas de ${dir} com o dono do repositorio (uid ${uid})`,
299
+ entrevistaMemoria: (escolha, declarado) => `entrevista escolheu ${escolha}; manifesto declara ${declarado}`,
300
+ entrevistaMemoriaCorrecao: (escolha) => `revise memory.mode: ${escolha} em orkastery.yaml; a entrevista não altera o manifesto`,
301
+ entrevistaFuso: (informado, declarado, chave) => `entrevista informou ${informado}; manifesto declara ${declarado ?? `${chave} ausente`}`,
302
+ entrevistaFusoCorrecao: (chave, informado) => `revise ${chave}: "${informado}" em orkastery.yaml; a entrevista não altera o manifesto`,
303
+ claudeOpcional: (fallback) => 'binario `claude` fora do PATH (opcional para as fases: nenhum bloco dos modos permitidos despacha pelo claude-bg' +
304
+ (fallback ? `; o fallback de ${fallback.blocos} bloco(s) cai nele e falharia: ${fallback.texto}` : '') +
305
+ '; o ork audit run ainda despacha por ele)',
306
+ claudeOpcionalCorrecao: 'para despachar pelo claude-bg (e rodar ork audit run), instale o Claude Code e garanta `claude` no PATH',
307
+ claudeAusente: (principal) => 'binario `claude` fora do PATH' +
308
+ (principal ? `; ${principal.blocos} bloco(s) dos modos permitidos despacham por ele (${principal.texto})` : ''),
309
+ claudeAusenteCorrecao: 'instale o Claude Code e garanta `claude` no PATH; so com o Codex, passe cada bloco para ele ' +
310
+ '(ork setup <modo> --bloco N --runtime codex --model <modelo>) ou tire o modo de conduction.allowed_modes ' +
311
+ '(mantenha o conduction.default_mode entre os permitidos)',
312
+ origemDoCodex: (pelaAdapter, blocos) => [pelaAdapter ? 'runtime.adapter: codex' : '',
313
+ blocos ? `${blocos.blocos} bloco(s) dos modos permitidos no codex (${blocos.texto})` : ''].filter(Boolean).join(' e '),
314
+ codexForaNoDespacho: (origem) => `${origem}, mas o binario \`codex\` esta fora do PATH`,
315
+ codexSandboxQuebrado: (origem, sandbox) => `${origem} com sandbox "${sandbox}", mas o sandbox nao executa nesta maquina (o agente narraria sucesso sem rodar nada)`,
316
+ codexSandboxOk: (origem, sandbox) => `${origem} com sandbox "${sandbox}"`,
317
+ codexSemConfirmacao: (origem, sandbox) => `${origem} com sandbox "${sandbox}" pedido pelo orkastery.yaml, ` +
318
+ 'sem a confirmacao desta maquina: o despacho recusa com runtime.sandbox-nao-confirmado',
319
+ codexForaNoDespachoCorrecao: 'instale o Codex CLI e autentique com `codex login` (assinatura, nunca API key)',
320
+ codexSandboxQuebradoCorrecao: (confirmar) => `instale o bubblewrap do sistema, ou declare runtime.sandbox: danger-full-access ciente do risco e confirme nesta maquina com ${confirmar}`,
321
+ codexSemConfirmacaoCorrecao: (confirmar) => `${confirmar} (ou volte o manifesto para workspace-write)`,
322
+ fabricaPedida: 'o orkastery.yaml pede fabrica.compartilhada: true e esta maquina nao entrou: nada desta maquina e publicado no remoto',
323
+ fabricaPedidaCorrecao: 'ork fabrica entrar, se esta maquina deve publicar o retrato dela no remoto do projeto',
324
+ pastaForaDaRaiz: (dir) => `worktree.dir "${dir}" leva para fora da raiz e esta maquina nao confirmou: a criacao de worktree recusa com worktree.dir-fora-da-raiz`,
325
+ pastaForaDaRaizCorrecao: (confirmar) => `${confirmar}, ou volte worktree.dir para dentro do projeto`,
326
+ fonteDaMemoria: (fonte, divergente) => `${fonte}${divergente ? ' (cópia da worktree divergente preservada)' : ''}`,
327
+ regimeDegradado: (motivo, detalhe) => `pedido orkmind, efetivo files (${motivo}): ${detalhe}`,
328
+ regimeOrkmind: (tenant, variavel) => `orkmind ativo no tenant "${tenant}" pela variavel ${variavel}`,
329
+ filaEscaladoCorrecao: 'pedido escalado alem do limite de retry.max_tentativas: ork retry list e ork gate request <thread>',
330
+ filaEsperaCorrecao: 'ork retry resume retoma o que ja liberou',
331
+ governanca: (g) => `${g.usuario}, Claude e Codex, global com histórico: ${g.total} sessões; ` +
332
+ `${g.semThread} sem thread; ${g.ambiguas} ambíguas; ` +
333
+ `inventário ${g.ok ? 'válido' : 'INCOMPLETO (zero não comprovado)'}` +
334
+ (g.ausentes.length ? `; fonte ausente: ${g.ausentes.join(', ')}` : ''),
335
+ governancaCorrecao: 'ork sessions --global --all --json; adote identidades sem vínculo com ork sessions adopt <id>',
336
+ umaskNaoMedido: 'umask do processo nao medido nesta plataforma',
337
+ umaskOk: (umask) => `umask ${umask} nega escrita de grupo e outros`,
338
+ umaskAberto: (umask) => `umask ${umask} permite escrita de grupo ou outros: o que o runtime criar sera recusado pelo sensor (bits 0o022)`,
339
+ umaskCorrecao: 'umask 022 (ou 077) no shell que roda o ork e os runtimes',
340
+ estadoNaoDiretorio: (dir) => `${dir} nao e diretorio real`,
341
+ estadoAberto: (dir, modo) => `${dir} com modo ${modo}: grupo ou outros podem escrever no estado`,
342
+ estadoComModo: (dir, modo) => `${dir} com modo ${modo}`,
343
+ privadaAusente: (dir) => `${dir} ausente: criada sob demanda com 0700`,
344
+ privadaAberta: (dir, modo) => `${dir} precisa ser diretorio 0700 do proprio usuario (modo ${modo}): recibo HITL e perfis recusam`,
345
+ privadaOk: (dir) => `${dir} com modo 0700`,
346
+ cronSemComando: 'comando crontab ausente nesta maquina',
347
+ cronFalhou: (detalhe) => `crontab -l falhou: ${detalhe}`,
348
+ cronSaiu: (codigo) => `crontab -l saiu ${codigo}`,
349
+ cronAdicione: (linha) => `adicione ao crontab (crontab -e), como no template monitor/pulse.cron: ${linha}`,
350
+ cronSemLeitura: (motivo) => `pulse-host.json presente, mas sem crontab para ler (${motivo}): a varredura nao bate`,
351
+ cronSemLinha: (script) => `pulse-host.json presente, e nenhuma linha do crontab roda ${script}: o resumo nao sai`,
352
+ cronOk: (linhas) => `varredura no cron a cada 15 minutos ou menos (${linhas} linha(s))`,
353
+ cronRitmo: (intervalo) => intervalo === null ? 'com horario que o doctor nao le'
354
+ : intervalo === 60 ? 'de hora em hora' : `a cada ${intervalo} minutos`,
355
+ cronLento: (ritmo, linha) => `a varredura do pulse bate ${ritmo} (\`${linha}\`): a cadencia por tag (RM-039) pede 15 minutos`,
356
+ cronTroque: (linha) => `troque a linha no crontab (crontab -e) por: ${linha}`,
357
+ // RM-063 (F1): com thread aberta, a falta da batida reprova, com ou sem pulse-host.json.
358
+ batidaAusente: (abertas, detalhe) => `${abertas} thread(s) aberta(s) e nenhuma batida da varredura: ${detalhe}; a fabrica para sem ninguem saber`,
359
+ batidaSemLeitura: (motivo) => `sem crontab para ler (${motivo})`,
360
+ batidaSemLinha: (script) => `nenhuma linha do crontab roda ${script} para este projeto`,
361
+ batidaInstale: (comando) => `${comando} (instala a linha do template monitor/pulse.cron no crontab desta maquina)`,
362
+ batidaPeloLog: (minutos) => `nenhuma linha no crontab, mas a varredura rodou ha ${minutos} min (hitl.log): a batida vem de outro agendador`,
363
+ redeSaiu: 'fora da rede (saiu com ork network sair)',
364
+ redeMembroHerdado: 'membro herdado da fabrica',
365
+ redeMembro: 'membro',
366
+ redeCasa: (casa) => `casa ${casa}`,
367
+ redeSemCasa: 'casa ainda nao gravada',
368
+ redeBatida: (quando, idade) => `ultima batida ${quando} (ha ${idade})`,
369
+ redeSemBatida: 'nenhuma batida publicada',
370
+ redeFalha: (quando, origem, erro) => `ultima falha ${quando}${origem ? ` (${origem})` : ''}: ${erro}`,
371
+ redeSemDetalhe: 'sem detalhe',
372
+ redeSemFalha: 'nenhuma falha no rede.log',
373
+ redeParadaCorrecao: 'a batida sai do pulse: confira o cron do pulse e rode ork network publicar',
374
+ redeSemCasaCorrecao: 'a casa da rede ainda nao existe: o dono roda ork network entrar, que cria o repositorio privado; ' +
375
+ 'ou ork network sair, para tirar esta maquina da rede',
376
+ redeSemForjaCorrecao: 'faca login na forja (gh auth login ou glab auth login) e rode ork network publicar',
377
+ redePublicaCorrecao: 'torne a casa da rede privada na forja; nada e publicado num repositorio publico',
378
+ redeNomeCorrecao: 'escolha outro nome com ork network entrar --maquina NOME, ou tome este com --forcar',
379
+ redeOutraCorrecao: 'ork network status mostra as lacunas; ork network publicar tenta de novo',
380
+ /**
381
+ * Redacao do check "analisadores do grafo" (a forma de `RedacaoDosAnalisadores`). A familia do grafo nao
382
+ * importa o catalogo (fronteira do KG3): ela guarda o pt-BR para o `ork grafo status`, e o doctor passa
383
+ * esta. Um teste confere que o pt-BR das duas e o mesmo.
384
+ */
385
+ grafo: {
386
+ recusa: (motivo) => `${motivo}: o ork grafo indexar recusa nesta instalacao, e sem o indice as consultas e as tools ork_grafo_* tambem`,
387
+ soEsm: (versaoDoNode) => `o micromark e so ESM, e este Node (${versaoDoNode}) nao o carrega por require: use Node 20.19, ` +
388
+ '22.12 ou mais novo, sem a opcao --no-experimental-require-module (na linha de comando ou no NODE_OPTIONS)',
389
+ reinstale: (fixada) => `reinstale o ork global, que traz os analisadores como dependencias: npm install -g @orkastery/cli${fixada}` +
390
+ ' (instalado dentro de um projeto ou pelo npx, o npm deixa os analisadores fora do pacote do ork, e o grafo os recusa)',
391
+ },
392
+ /** A fonte de sessoes ausente, como o inventario a nomeia (dado); o ingles so troca o rotulo da conta. */
393
+ fonteDaSessao: (origem) => origem,
394
+ },
395
+ onboarding: locale_onboarding_1.ONBOARDING_PT_BR,
396
+ thread: locale_thread_1.THREAD_PT_BR,
397
+ phase: locale_phase_1.PHASE_PT_BR,
398
+ ajuda: locale_ajuda_1.AJUDA_PT_BR,
399
+ verify: locale_verify_1.VERIFY_PT_BR,
400
+ ship: locale_ship_1.SHIP_PT_BR,
401
+ retry: locale_retry_1.RETRY_PT_BR,
402
+ master: locale_master_1.MASTER_PT_BR,
403
+ pulse: locale_pulse_1.PULSE_PT_BR,
404
+ roadmap: locale_roadmap_1.ROADMAP_PT_BR,
405
+ gerados: locale_gerados_1.GERADOS_PT_BR,
406
+ init: {
407
+ foraDoRepositorio: (dir) => `init.fora-do-repositorio: ${dir} não está num repositório git; nada foi criado. ` +
408
+ 'Entre no repositório do projeto (ou crie um com git init e o primeiro commit) e rode ork init de novo.',
409
+ jaExiste: (caminho) => `Manifesto ja existe: ${caminho}`,
410
+ nadaSobrescrito: 'Nada foi sobrescrito. Use --force para regerar.',
411
+ agentsMd: (estado, caminho) => `AGENTS.md ${estado}: ${caminho}`,
412
+ agentsMdLinha: (estado, caminho) => ` AGENTS.md ${estado}: ${caminho}`,
413
+ estadosAgents: { criado: 'criado', atualizado: 'atualizado', inalterado: 'inalterado' },
414
+ criado: (caminho) => `Manifesto criado: ${caminho}`,
415
+ projeto: (nome, abbrev) => ` projeto ${nome} (abbrev "${abbrev}")`,
416
+ branchBase: (branch) => ` branch base ${branch}`,
417
+ gerenciador: (g) => ` gerenciador ${g}`,
418
+ verify: (v) => ` verify ${v}`,
419
+ semScript: '(nenhum script detectado)',
420
+ estado: (dir) => ` estado ${dir}/ fora do git (${dir}/.gitignore com *; o seu .gitignore fica como está)`,
421
+ proximoPasso: 'Proximo passo: ork doctor; depois ork onboarding para conduzir a entrevista do projeto.',
422
+ },
423
+ };
424
+ const EN = {
425
+ cli: {
426
+ erro: (mensagem) => `error: ${mensagem}`,
427
+ subcomandoDesconhecido: (comando, sub) => sub === undefined ? `missing subcommand: ${comando}` : `unknown subcommand: ${comando} ${sub}`,
428
+ manifestoNaoEncontrado: (nome, dir) => `\`${nome}\` not found in ${dir} or any parent directory; run \`ork init\` first.`,
429
+ },
430
+ horario: {
431
+ brasilia: 'Brasília time',
432
+ legendaBrasilia: 'Times in Brasília time.',
433
+ legenda: (rotulo) => `Times in ${rotulo}.`,
434
+ duracaoDesconhecida: 'unknown time',
435
+ menosDeUmMin: 'less than 1 min',
436
+ jaLiberou: 'already released',
437
+ emMinutos: (n) => `in ${n} min`,
438
+ emHoras: (h, mm) => `in ${h}h${mm}`,
439
+ },
440
+ doctor: {
441
+ titulo: 'ork doctor: what holds on this machine now',
442
+ correcao: 'fix',
443
+ bloqueado: (falhas, avisos) => `Verdict: BLOCKED (${falhas} fail, ${avisos} warn). Fix the items above before dispatching a phase.`,
444
+ pronto: (avisos) => `Verdict: READY (${avisos} warn). Phase dispatch allowed through \`ork phase run\`.`,
445
+ nomes: {
446
+ 'repositorio': 'repository',
447
+ 'manifesto': 'manifest',
448
+ 'manifesto do repositorio': 'repository manifest',
449
+ 'analisadores do grafo': 'graph analyzers',
450
+ 'abbrev do projeto': 'project abbrev',
451
+ 'modos de conducao': 'conduction modes',
452
+ 'fuso do dono': 'owner time zone',
453
+ 'despacho pelo codex': 'codex dispatch',
454
+ 'custo e provider herdado': 'cost and inherited provider',
455
+ 'provider efetivo da fabrica': 'effective factory provider',
456
+ 'fonte da memoria': 'memory source',
457
+ 'regime de memoria': 'memory regime',
458
+ 'chave de embedding': 'embedding key',
459
+ 'fila de rate limit': 'rate limit queue',
460
+ 'estado do projeto': 'project state',
461
+ 'contas por runtime': 'accounts per runtime',
462
+ 'governanca de sessoes': 'session governance',
463
+ 'dono do .git': '.git owner',
464
+ 'onboarding memoria': 'onboarding memory',
465
+ 'onboarding fuso': 'onboarding time zone',
466
+ 'rede': 'network',
467
+ 'sandbox do codex': 'codex sandbox',
468
+ 'permissoes do estado': 'state permissions',
469
+ 'pasta privada': 'private folder',
470
+ 'cadencia do pulse no cron': 'pulse cron cadence',
471
+ 'fabrica compartilhada': 'shared factory',
472
+ 'pasta das worktrees': 'worktree folder',
473
+ },
474
+ instaleNode: 'install Node 20 or later',
475
+ gitAusente: 'not found on PATH',
476
+ instaleGit: 'install git',
477
+ branch: (branch, semCommit) => `branch ${branch}${semCommit ? ' (no commit)' : ''}`,
478
+ foraDeRepo: 'outside a git repository',
479
+ rodeDentroDeRepo: 'run `ork` inside a git repository',
480
+ versaoDesconhecida: 'unknown version',
481
+ codexAusenteUsado: '`codex` binary not on PATH (the project dispatches through it: see codex dispatch)',
482
+ codexAusenteOpcional: '`codex` binary not on PATH (optional: claude-bg is the default runtime)',
483
+ instaleCodex: 'to dispatch through codex, install the Codex CLI and sign in with `codex login`',
484
+ sandboxOk: '`codex sandbox true` runs on this machine',
485
+ sandboxFalhou: (detalhe) => `probe \`codex sandbox true\` failed: ${detalhe}`,
486
+ sandboxCorrecao: (confirmar) => 'install the system bubblewrap package (the bundled bwrap cannot create a user namespace ' +
487
+ `on this machine) or declare \`runtime.sandbox: danger-full-access\` knowing the risk, and confirm on this machine with \`${confirmar}\``,
488
+ manifestoAusente: (nome, dir) => `${nome} not found in ${dir} or any parent directory`,
489
+ rodeInit: 'ork init',
490
+ entreNoRepoEInit: 'enter the project repository (or create one with `git init` and a first commit) and run `ork init`',
491
+ corrijaManifesto: 'fix the manifest and run `ork doctor` again',
492
+ abbrevOk: (abbrev) => `"${abbrev}" (part 1 of the session slug)`,
493
+ abbrevCorrecao: 'set project.abbrev with up to 3 characters [a-z0-9]',
494
+ modos: (padrao, permitidos) => `default ${padrao}; allowed ${permitidos}`,
495
+ fusoDoManifesto: (fuso, chave, rotulo) => `${fuso} (${chave}); times for people in ${rotulo}`,
496
+ fusoDoSistema: (fuso, chave) => `${fuso} (system time zone; ${chave} not set)`,
497
+ fusoCorrecao: (chave) => `set ${chave} to an IANA name`,
498
+ filaVazia: 'empty: no phase died from a usage limit in this project',
499
+ filaResumo: (esperando, escalados) => `${esperando} waiting for a window, ${escalados} escalated to a human`,
500
+ filaProxima: (quando) => `; next window at ${quando}`,
501
+ estadoOk: (dir, qtd) => `${dir} (${qtd} thread(s))`,
502
+ estadoAusente: (dir) => `${dir} missing`,
503
+ estadoCorrecao: '`ork init` creates the state directory',
504
+ claudeSemLogin: (detalhe, auth) => `${detalhe}; ${auth}: dispatch through claude-bg would fail`,
505
+ claudeLoginPago: 'sign in with a subscription (claude.ai) in `claude`, without an API key or a cloud provider',
506
+ claudeLogin: 'run `claude` once, sign in with your subscription (/login) and accept trust in the project directory; ' +
507
+ 'or create a profile with `ork accounts add <id> --runtime claude-bg --dir <folder>`',
508
+ onboardingPendente: (n, etapas) => `${n} step(s) pending: ${etapas}`,
509
+ onboardingCompleto: '9 steps answered',
510
+ foraDaRede: 'outside the network; `ork network entrar` puts this machine on your network',
511
+ manifestoOk: (caminho, bytes, limite) => `${caminho} (${bytes} B of ${limite})`,
512
+ politicaViolada: (politica, envs) => `policy ${politica} violated: ${envs} redirects the claude dispatch`,
513
+ politicaComPaga: (politica, envs) => `policy ${politica}; dispatch stays on the local subscription, but there is a paid credential in the environment: ${envs}`,
514
+ politicaLimpa: (politica) => `policy ${politica}; no paid provider variable active`,
515
+ removaDoAmbiente: (envs) => `remove from the environment: ${envs} (dispatch uses the local Claude subscription)`,
516
+ nuncaDespachePorPaga: (envs) => `no action required; never dispatch a phase through ${envs}`,
517
+ providersAtivos: (nomes) => `active names: ${nomes}`,
518
+ nenhumProvider: 'no name from the provider list is active',
519
+ memoriaFiles: 'files (honest fallback: handoff through files, path#anchor pointer)',
520
+ embeddingNone: 'memory.embedding with provider none: semantic search is off',
521
+ semPerfis: 'no profile configured: each runtime dispatches through the process environment',
522
+ manifestoForaDoRepo: (nome, caminho, topo) => `the ${nome} that was read sits outside this repository (${caminho}): ork runs the project in that folder, not the one in ${topo}`,
523
+ manifestoForaDoRepoCorrecao: (topo) => `run \`ork init\` at the root of this repository (${topo}); if the outside manifest ` +
524
+ 'was created by mistake, delete it together with the AGENTS.md and the .orkastery/ next to it',
525
+ storeInvalido: (erro) => `invalid profile store: ${erro}`,
526
+ storeCorrecao: 'the store lives in .orkastery/private/runtime-profiles.json (file 0600, folder 0700)',
527
+ contaPaga: 'paid provider (never dispatches)',
528
+ contaInconclusiva: 'login check inconclusive',
529
+ contaSemLogin: 'not signed in',
530
+ contaPronta: 'ready',
531
+ contaFora: (estado, ate) => `${estado}${ate ? ` until ${ate}` : ''}`,
532
+ contasCorrecao: '`ork accounts check` marks the profiles (sem-auth, provider-pago); `ork accounts add` redoes the subscription ' +
533
+ 'login through the CLI itself, never copying a credential',
534
+ embeddingPago: (variavel) => `memory.embedding.api_key_env declares ${variavel}, a name from the paid provider list`,
535
+ embeddingPagoCorrecao: 'use a key dedicated to Orkastery, with its own name, for example ORKASTERY_EMBEDDING_API_KEY',
536
+ embeddingSemVariavel: (provider) => `memory.embedding with provider ${provider} and no api_key_env`,
537
+ embeddingSemVariavelCorrecao: 'declare in memory.embedding.api_key_env the NAME of the variable that holds the dedicated key',
538
+ embeddingRecusada: (variavel) => `${variavel} has a refused value: it looks like a URL, a DSN or text with spaces (the value is never printed)`,
539
+ embeddingRecusadaCorrecao: (variavel) => `check that ${variavel} holds the dedicated key, not another credential`,
540
+ embeddingPresente: (variavel, provider, modelo) => `${variavel} present in the environment (value never printed); ${provider} ${modelo}`,
541
+ embeddingAusente: (variavel) => `${variavel} missing from the environment: semantic search uses the local fallback or falls back to FTS; the regime does not change`,
542
+ embeddingAusenteCorrecao: (variavel) => `export ${variavel} with the key dedicated to Orkastery (with a credit limit in the provider dashboard)`,
543
+ donoOutro: (total, dir, uids, uid, exemplos, parcialDe) => `${total} entry(ies) in ${dir} owned by another user (uid ${uids}; the repository owner is ${uid}): ${exemplos}; ` +
544
+ `the owner's git cannot write to them, so fetch and commit fail${parcialDe !== null ? ` (partial check: more than ${parcialDe} entries)` : ''}`,
545
+ donoCorrecao: (comando) => `${comando} (ork never runs this on its own)`,
546
+ donoParcial: (teto, dir) => `more than ${teto} entries in ${dir}: partial check, no other owner so far`,
547
+ donoParcialCorrecao: (comando) => `check the rest with: ${comando}`,
548
+ donoOk: (vistos, dir, uid) => `${vistos} entries in ${dir} owned by the repository owner (uid ${uid})`,
549
+ entrevistaMemoria: (escolha, declarado) => `the interview chose ${escolha}; the manifest declares ${declarado}`,
550
+ entrevistaMemoriaCorrecao: (escolha) => `review memory.mode: ${escolha} in orkastery.yaml; the interview does not change the manifest`,
551
+ entrevistaFuso: (informado, declarado, chave) => `the interview gave ${informado}; ${declarado ? `the manifest declares ${declarado}` : `the manifest has no ${chave}`}`,
552
+ entrevistaFusoCorrecao: (chave, informado) => `review ${chave}: "${informado}" in orkastery.yaml; the interview does not change the manifest`,
553
+ claudeOpcional: (fallback) => '`claude` binary not on PATH (optional for phases: no block of the allowed modes dispatches through claude-bg' +
554
+ (fallback ? `; the fallback of ${fallback.blocos} block(s) lands on it and would fail: ${fallback.texto}` : '') +
555
+ '; `ork audit run` still dispatches through it)',
556
+ claudeOpcionalCorrecao: 'to dispatch through claude-bg (and run `ork audit run`), install Claude Code and make sure `claude` is on PATH',
557
+ claudeAusente: (principal) => '`claude` binary not on PATH' +
558
+ (principal ? `; ${principal.blocos} block(s) of the allowed modes dispatch through it (${principal.texto})` : ''),
559
+ claudeAusenteCorrecao: 'install Claude Code and make sure `claude` is on PATH; with Codex only, move each block to it ' +
560
+ '(`ork setup <mode> --bloco N --runtime codex --model <model>`) or remove the mode from conduction.allowed_modes ' +
561
+ '(keep conduction.default_mode among the allowed ones)',
562
+ origemDoCodex: (pelaAdapter, blocos) => [pelaAdapter ? 'runtime.adapter: codex' : '',
563
+ blocos ? `${blocos.blocos} block(s) of the allowed modes on codex (${blocos.texto})` : ''].filter(Boolean).join(' and '),
564
+ codexForaNoDespacho: (origem) => `${origem}, but the \`codex\` binary is not on PATH`,
565
+ codexSandboxQuebrado: (origem, sandbox) => `${origem} with sandbox "${sandbox}", but the sandbox does not run on this machine (the agent would narrate success without running anything)`,
566
+ codexSandboxOk: (origem, sandbox) => `${origem} with sandbox "${sandbox}"`,
567
+ codexSemConfirmacao: (origem, sandbox) => `${origem} with sandbox "${sandbox}" requested by \`orkastery.yaml\` but not confirmed ` +
568
+ 'on this machine: dispatch is refused with `runtime.sandbox-nao-confirmado`',
569
+ codexForaNoDespachoCorrecao: 'install the Codex CLI and sign in with `codex login` (subscription, never an API key)',
570
+ codexSandboxQuebradoCorrecao: (confirmar) => `install the system bubblewrap, or declare \`runtime.sandbox: danger-full-access\` knowing the risk, and confirm on this machine with \`${confirmar}\``,
571
+ codexSemConfirmacaoCorrecao: (confirmar) => `\`${confirmar}\` (or set the manifest back to \`workspace-write\`)`,
572
+ fabricaPedida: '`orkastery.yaml` asks for `fabrica.compartilhada: true` and this machine has not joined: nothing from this machine is published to the remote',
573
+ fabricaPedidaCorrecao: '`ork fabrica entrar`, if this machine should publish its snapshot to the project remote',
574
+ pastaForaDaRaiz: (dir) => `\`worktree.dir\` "${dir}" points outside the project root and this machine has not confirmed it: worktree creation is refused with \`worktree.dir-fora-da-raiz\``,
575
+ pastaForaDaRaizCorrecao: (confirmar) => `\`${confirmar}\`, or move \`worktree.dir\` back inside the project`,
576
+ fonteDaMemoria: (fonte, divergente) => `${fonte}${divergente ? ' (divergent worktree copy kept)' : ''}`,
577
+ regimeDegradado: (motivo, detalhe) => `orkmind requested, files in effect (${motivo}): ${detalhe}`,
578
+ regimeOrkmind: (tenant, variavel) => `orkmind active in tenant "${tenant}" through the variable ${variavel}`,
579
+ filaEscaladoCorrecao: 'request escalated past the retry.max_tentativas limit: `ork retry list` and `ork gate request <thread>`',
580
+ filaEsperaCorrecao: '`ork retry resume` picks up what is already released',
581
+ governanca: (g) => `${g.usuario}, Claude and Codex, global with history: ${g.total} sessions; ` +
582
+ `${g.semThread} without a thread; ${g.ambiguas} ambiguous; ` +
583
+ `inventory ${g.ok ? 'valid' : 'INCOMPLETE (zero not proven)'}` +
584
+ (g.ausentes.length ? `; source missing: ${g.ausentes.join(', ')}` : ''),
585
+ governancaCorrecao: '`ork sessions --global --all --json`; adopt unlinked identities with `ork sessions adopt <id>`',
586
+ umaskNaoMedido: 'process umask not measured on this platform',
587
+ umaskOk: (umask) => `umask ${umask} denies write to group and others`,
588
+ umaskAberto: (umask) => `umask ${umask} allows write by group or others: whatever the runtime creates will be refused by the sensor (bits 0o022)`,
589
+ umaskCorrecao: '`umask 022` (or 077) in the shell that runs ork and the runtimes',
590
+ estadoNaoDiretorio: (dir) => `${dir} is not a real directory`,
591
+ estadoAberto: (dir, modo) => `${dir} with mode ${modo}: group or others can write to the state`,
592
+ estadoComModo: (dir, modo) => `${dir} with mode ${modo}`,
593
+ privadaAusente: (dir) => `${dir} missing: created on demand with 0700`,
594
+ privadaAberta: (dir, modo) => `${dir} must be a 0700 directory owned by the user (mode ${modo}): HITL receipts and profiles refuse it`,
595
+ privadaOk: (dir) => `${dir} with mode 0700`,
596
+ cronSemComando: 'crontab command missing on this machine',
597
+ cronFalhou: (detalhe) => `\`crontab -l\` failed: ${detalhe}`,
598
+ cronSaiu: (codigo) => `\`crontab -l\` exited ${codigo}`,
599
+ cronAdicione: (linha) => `add to the crontab (\`crontab -e\`), as in the \`monitor/pulse.cron\` template: ${linha}`,
600
+ cronSemLeitura: (motivo) => `pulse-host.json present, but there is no crontab to read (${motivo}): the scan never runs`,
601
+ cronSemLinha: (script) => `pulse-host.json present, and no crontab line runs ${script}: the summary never goes out`,
602
+ cronOk: (linhas) => `scan in cron every 15 minutes or less (${linhas} line(s))`,
603
+ cronRitmo: (intervalo) => intervalo === null ? 'on a schedule the doctor cannot read'
604
+ : intervalo === 60 ? 'every hour' : `every ${intervalo} minutes`,
605
+ cronLento: (ritmo, linha) => `the pulse scan runs ${ritmo} (\`${linha}\`): the cadence by tag (RM-039) needs 15 minutes`,
606
+ cronTroque: (linha) => `replace the crontab line (\`crontab -e\`) with: ${linha}`,
607
+ batidaAusente: (abertas, detalhe) => `${abertas} open thread(s) and no scan beat: ${detalhe}; the factory stops and nobody knows`,
608
+ batidaSemLeitura: (motivo) => `no crontab to read (${motivo})`,
609
+ batidaSemLinha: (script) => `no crontab line runs ${script} for this project`,
610
+ batidaInstale: (comando) => `\`${comando}\` (installs the \`monitor/pulse.cron\` template line in this machine's crontab)`,
611
+ batidaPeloLog: (minutos) => `no crontab line, but the scan ran ${minutos} min ago (hitl.log): the beat comes from another scheduler`,
612
+ redeSaiu: 'outside the network (left with `ork network sair`)',
613
+ redeMembroHerdado: 'member inherited from the factory',
614
+ redeMembro: 'member',
615
+ redeCasa: (casa) => `home ${casa}`,
616
+ redeSemCasa: 'home not recorded yet',
617
+ redeBatida: (quando, idade) => `last heartbeat ${quando} (${idade} ago)`,
618
+ redeSemBatida: 'no heartbeat published',
619
+ redeFalha: (quando, origem, erro) => `last failure ${quando}${origem ? ` (${origem})` : ''}: ${erro}`,
620
+ redeSemDetalhe: 'no detail',
621
+ redeSemFalha: 'no failure in rede.log',
622
+ redeParadaCorrecao: 'the heartbeat comes from the pulse: check the pulse cron and run `ork network publicar`',
623
+ redeSemCasaCorrecao: 'the network home does not exist yet: the owner runs `ork network entrar`, which creates the private ' +
624
+ 'repository; or `ork network sair`, to take this machine out of the network',
625
+ redeSemForjaCorrecao: 'sign in to the forge (`gh auth login` or `glab auth login`) and run `ork network publicar`',
626
+ redePublicaCorrecao: 'make the network home private on the forge; nothing is published to a public repository',
627
+ redeNomeCorrecao: 'pick another name with `ork network entrar --maquina NOME`, or take this one with `--forcar`',
628
+ redeOutraCorrecao: '`ork network status` shows the gaps; `ork network publicar` tries again',
629
+ grafo: {
630
+ recusa: (motivo) => `${motivo}: \`ork grafo indexar\` refuses on this installation, and without the index the queries and the ork_grafo_* tools refuse too`,
631
+ soEsm: (versaoDoNode) => `micromark is ESM only, and this Node (${versaoDoNode}) cannot load it with require: use Node 20.19, ` +
632
+ '22.12 or newer, without the --no-experimental-require-module option (on the command line or in NODE_OPTIONS)',
633
+ reinstale: (fixada) => `reinstall the global ork, which brings the analyzers as dependencies: npm install -g @orkastery/cli${fixada}` +
634
+ ' (installed inside a project or through npx, npm leaves the analyzers outside the ork package, and the graph refuses them)',
635
+ },
636
+ fonteDaSessao: (origem) => origem.replace(/\(conta do processo\)$/, '(process account)').replace(/\(perfil ([^)]+)\)$/, '(profile $1)'),
637
+ },
638
+ onboarding: locale_onboarding_1.ONBOARDING_EN,
639
+ thread: locale_thread_1.THREAD_EN,
640
+ phase: locale_phase_1.PHASE_EN,
641
+ ajuda: locale_ajuda_1.AJUDA_EN,
642
+ verify: locale_verify_1.VERIFY_EN,
643
+ ship: locale_ship_1.SHIP_EN,
644
+ retry: locale_retry_1.RETRY_EN,
645
+ master: locale_master_1.MASTER_EN,
646
+ pulse: locale_pulse_1.PULSE_EN,
647
+ roadmap: locale_roadmap_1.ROADMAP_EN,
648
+ gerados: locale_gerados_1.GERADOS_EN,
649
+ init: {
650
+ foraDoRepositorio: (dir) => `init.fora-do-repositorio: ${dir} is not inside a git repository; nothing was created. ` +
651
+ 'Enter the project repository (or create one with `git init` and a first commit) and run `ork init` again.',
652
+ jaExiste: (caminho) => `Manifest already exists: ${caminho}`,
653
+ nadaSobrescrito: 'Nothing was overwritten. Use `--force` to regenerate.',
654
+ agentsMd: (estado, caminho) => `AGENTS.md ${estado}: ${caminho}`,
655
+ agentsMdLinha: (estado, caminho) => ` AGENTS.md ${estado}: ${caminho}`,
656
+ estadosAgents: { criado: 'created', atualizado: 'updated', inalterado: 'unchanged' },
657
+ criado: (caminho) => `Manifest created: ${caminho}`,
658
+ projeto: (nome, abbrev) => ` project ${nome} (abbrev "${abbrev}")`,
659
+ branchBase: (branch) => ` base branch ${branch}`,
660
+ gerenciador: (g) => ` package mgr ${g}`,
661
+ verify: (v) => ` verify ${v}`,
662
+ semScript: '(no script detected)',
663
+ estado: (dir) => ` state ${dir}/ kept out of git (${dir}/.gitignore with *; your .gitignore stays as is)`,
664
+ proximoPasso: 'Next step: `ork doctor`; then `ork onboarding` to run the project interview.',
665
+ },
666
+ };
667
+ const CATALOGO = { 'pt-BR': PT_BR, en: EN };
668
+ /** As mensagens do locale pedido, ou do ativo. */
669
+ function msg(locale = ativo) {
670
+ return CATALOGO[locale];
671
+ }
672
+ /**
673
+ * D14: erro cujo texto vem do catalogo. Ele nasce no locale ativo (dentro de `comLocale('pt-BR', ...)`,
674
+ * em pt-BR, como o que la se grava), e a entrada do CLI o remonta no locale do comando ao imprimir.
675
+ */
676
+ class ErroDoCatalogo extends Error {
677
+ montar;
678
+ constructor(montar) {
679
+ super(montar(msg()));
680
+ this.montar = montar;
681
+ }
682
+ }
683
+ exports.ErroDoCatalogo = ErroDoCatalogo;
684
+ /** A mensagem de um erro para a pessoa: a do catalogo no locale ativo; as demais como vieram. */
685
+ function mensagemDoErro(e) {
686
+ return e instanceof ErroDoCatalogo ? e.montar(msg()) : e instanceof Error ? e.message : String(e);
687
+ }
688
+ /** G2 e D1 da F2b: os montadores dos textos que o comando coberto guardou num resultado, pelo texto. */
689
+ let remontagem = null;
690
+ /**
691
+ * Liga o registro dos montadores (o CLI, nos comandos cobertos) ou o desliga (o `main`, no comeco de cada
692
+ * chamada). Desligado, nada se guarda: o servidor MCP e o cron nao acumulam texto.
693
+ */
694
+ function ligarRemontagem(ligada) {
695
+ remontagem = ligada ? new Map() : null;
696
+ }
697
+ /**
698
+ * O texto no locale ativo. No escopo da gravacao ele sai em pt-BR, como o ledger e o `--json` o guardam;
699
+ * com o registro ligado, o montador fica guardado para a impressao remonta-lo no locale do comando.
700
+ */
701
+ function textoDoCatalogo(montar) {
702
+ const texto = montar(msg());
703
+ remontagem?.set(texto, montar);
704
+ return texto;
705
+ }
706
+ /** O texto como a pessoa o le no locale ativo: o que veio do catalogo e remontado; o resto sai como veio. */
707
+ function remontar(texto) {
708
+ const montar = remontagem?.get(texto);
709
+ return montar ? montar(msg()) : texto;
710
+ }
711
+ /** Nome de check como o texto o mostra no locale ativo. */
712
+ function nomeDoCheck(nome, locale = ativo) {
713
+ return CATALOGO[locale].doctor.nomes[nome] ?? nome;
714
+ }