@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/doctor.js CHANGED
@@ -71,7 +71,11 @@ const runtime_profiles_1 = require("./runtime-profiles");
71
71
  const preflight_1 = require("./preflight");
72
72
  const setup_1 = require("./setup");
73
73
  const doctor_pulse_cron_1 = require("./doctor-pulse-cron");
74
+ const postura_local_1 = require("./postura-local");
75
+ const worktree_local_1 = require("./worktree-local");
76
+ const maquina_1 = require("./maquina");
74
77
  const doctor_rede_1 = require("./doctor-rede");
78
+ const locale_1 = require("./locale");
75
79
  /**
76
80
  * Ensaio de 03/10/2026 (RM-049): o manifesto e achado subindo a partir do diretorio atual. Um
77
81
  * `orkastery.yaml` de uma pasta acima do repositorio (um `ork init` rodado por engano no HOME) era
@@ -101,8 +105,8 @@ function manifestoForaDoRepositorio(dirInicial, caminhoDoManifesto) {
101
105
  return {
102
106
  nome: 'manifesto do repositorio',
103
107
  nivel: 'warn',
104
- detalhe: `o ${manifest_1.NOME_MANIFESTO} lido fica fora deste repositorio (${caminhoDoManifesto}): o ork conduz o projeto daquela pasta, nao o de ${topo.stdout.trim()}`,
105
- correcao: `rode ork init na raiz deste repositorio (${topo.stdout.trim()}); se o manifesto de fora nasceu por engano, apague-o junto com o AGENTS.md e o .orkastery/ ao lado dele`,
108
+ detalhe: (0, locale_1.msg)().doctor.manifestoForaDoRepo(manifest_1.NOME_MANIFESTO, caminhoDoManifesto, topo.stdout.trim()),
109
+ correcao: (0, locale_1.msg)().doctor.manifestoForaDoRepoCorrecao(topo.stdout.trim()),
106
110
  };
107
111
  }
108
112
  /**
@@ -116,12 +120,12 @@ function checarContas(raiz, auth = (p) => p.runtime === 'claude-bg' ? adapter.co
116
120
  perfis = (0, runtime_profiles_1.lerPerfisComContas)(raiz).perfis.filter(p => p.estado !== 'desativado');
117
121
  }
118
122
  catch (e) {
119
- return { nome: 'contas por runtime', nivel: 'fail', detalhe: `store de perfis invalido: ${e.message}`,
120
- correcao: 'o store fica em .orkastery/private/runtime-profiles.json (arquivo 0600, pasta 0700)' };
123
+ return { nome: 'contas por runtime', nivel: 'fail', detalhe: (0, locale_1.msg)().doctor.storeInvalido(e.message),
124
+ correcao: (0, locale_1.msg)().doctor.storeCorrecao };
121
125
  }
122
126
  if (perfis.length === 0)
123
127
  return { nome: 'contas por runtime', nivel: 'ok',
124
- detalhe: 'nenhum perfil configurado: cada runtime despacha pelo ambiente do processo' };
128
+ detalhe: (0, locale_1.msg)().doctor.semPerfis };
125
129
  const partes = [];
126
130
  let nivel = 'ok';
127
131
  for (const runtime of runtime_profiles_1.RUNTIMES_COM_PERFIL) {
@@ -131,8 +135,8 @@ function checarContas(raiz, auth = (p) => p.runtime === 'claude-bg' ? adapter.co
131
135
  const estados = doRuntime.map(p => {
132
136
  const a = auth((0, runtime_profiles_1.perfilDeDespacho)(p));
133
137
  return { id: p.id, pronto: a.ok && (0, runtime_profiles_1.perfilDisponivel)(p),
134
- texto: !a.ok ? (a.pago ? 'provider pago (nunca despacha)' : a.transitorio ? 'conferencia de login inconclusiva' : 'sem login')
135
- : (0, runtime_profiles_1.perfilDisponivel)(p) ? 'pronto' : `${p.estado}${p.esgotadoAte ? ` ate ${p.esgotadoAte}` : ''}` };
138
+ texto: !a.ok ? (a.pago ? (0, locale_1.msg)().doctor.contaPaga : a.transitorio ? (0, locale_1.msg)().doctor.contaInconclusiva : (0, locale_1.msg)().doctor.contaSemLogin)
139
+ : (0, runtime_profiles_1.perfilDisponivel)(p) ? (0, locale_1.msg)().doctor.contaPronta : (0, locale_1.msg)().doctor.contaFora(p.estado, p.esgotadoAte) };
136
140
  });
137
141
  const prontos = estados.filter(e => e.pronto).length;
138
142
  if (prontos === 0)
@@ -142,7 +146,7 @@ function checarContas(raiz, auth = (p) => p.runtime === 'claude-bg' ? adapter.co
142
146
  partes.push(`${runtime}: ${estados.map(e => `${e.id} ${e.texto}`).join(', ')}`);
143
147
  }
144
148
  return { nome: 'contas por runtime', nivel, detalhe: partes.join('; '),
145
- ...(nivel !== 'ok' ? { correcao: 'ork accounts check marca os perfis (sem-auth, provider-pago); ork accounts add refaz o login de assinatura pelo proprio CLI, nunca copiando credencial' } : {}) };
149
+ ...(nivel !== 'ok' ? { correcao: (0, locale_1.msg)().doctor.contasCorrecao } : {}) };
146
150
  }
147
151
  /**
148
152
  * Variaveis que REDIRECIONAM o despacho do `claude` para um provider pago.
@@ -168,27 +172,24 @@ function checarChaveDeEmbedding(carregado, env = process.env) {
168
172
  const nome = 'chave de embedding';
169
173
  const config = (0, manifest_1.configDeEmbedding)(carregado.manifesto);
170
174
  if (config.provider === 'none')
171
- return { nome, nivel: 'ok', detalhe: 'memory.embedding com provider none: busca por significado desligada' };
175
+ return { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.embeddingNone };
172
176
  const variavel = config.api_key_env;
173
177
  if (runtime_ambiente_1.ENVS_DE_PROVIDER_PAGO.includes(variavel)) {
174
- return { nome, nivel: 'fail', detalhe: `memory.embedding.api_key_env declara ${variavel}, nome da lista de provider pago`,
175
- correcao: 'use uma chave dedicada ao Orkastery com nome proprio, por exemplo ORKASTERY_EMBEDDING_API_KEY' };
178
+ return { nome, nivel: 'fail', detalhe: (0, locale_1.msg)().doctor.embeddingPago(variavel), correcao: (0, locale_1.msg)().doctor.embeddingPagoCorrecao };
176
179
  }
177
180
  if (!variavel) {
178
- return { nome, nivel: 'fail', detalhe: `memory.embedding com provider ${config.provider} sem api_key_env`,
179
- correcao: 'declare em memory.embedding.api_key_env o NOME da variavel com a chave dedicada' };
181
+ return { nome, nivel: 'fail', detalhe: (0, locale_1.msg)().doctor.embeddingSemVariavel(config.provider),
182
+ correcao: (0, locale_1.msg)().doctor.embeddingSemVariavelCorrecao };
180
183
  }
181
184
  const valor = (env[variavel] ?? '').trim();
182
185
  const dsn = carregado.manifesto.memory.database_url_env ? (env[carregado.manifesto.memory.database_url_env] ?? '') : '';
183
186
  if (valor !== '' && !(0, orkmind_1.chaveDeEmbeddingAceita)(valor, dsn)) {
184
- return { nome, nivel: 'fail', detalhe: `${variavel} tem valor recusado: parece URL, DSN ou texto com espaco (valor nunca impresso)`,
185
- correcao: `confira se ${variavel} guarda a chave dedicada, e nao outra credencial` };
187
+ return { nome, nivel: 'fail', detalhe: (0, locale_1.msg)().doctor.embeddingRecusada(variavel), correcao: (0, locale_1.msg)().doctor.embeddingRecusadaCorrecao(variavel) };
186
188
  }
187
189
  if (valor !== '') {
188
- return { nome, nivel: 'ok', detalhe: `${variavel} presente no ambiente (valor nunca impresso); ${config.provider} ${config.model}` };
190
+ return { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.embeddingPresente(variavel, config.provider, config.model) };
189
191
  }
190
- return { nome, nivel: 'warn', detalhe: `${variavel} ausente do ambiente: a busca por significado usa o fallback local ou cai para FTS; o regime nao muda`,
191
- correcao: `exporte ${variavel} com a chave dedicada ao Orkastery (com limite de credito no painel do provider)` };
192
+ return { nome, nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.embeddingAusente(variavel), correcao: (0, locale_1.msg)().doctor.embeddingAusenteCorrecao(variavel) };
192
193
  }
193
194
  /** Acima disso a conferencia do dono do `.git` fica parcial (aviso), para o doctor nao pesar. */
194
195
  exports.TETO_DO_DONO_DO_GIT = 200_000;
@@ -254,31 +255,29 @@ function checarDonoDoGit(dirInicial, opcoes = {}) {
254
255
  }
255
256
  if (total > 0) {
256
257
  return { nome, nivel: 'fail',
257
- detalhe: `${total} entrada(s) de ${relativo(dirComum)} com outro dono (uid ${[...uids].sort((a, b) => a - b).join(', ')}; o do ` +
258
- `repositorio e ${raiz.uid}): ${estranhos.join(', ')}${total > estranhos.length ? ', ...' : ''}; o git do dono nao grava nelas, ` +
259
- `e o fetch e o commit falham${parcial ? ` (conferencia parcial: mais de ${teto} entradas)` : ''}`,
260
- correcao: `sudo chown -R ${raiz.uid}:${raiz.gid} ${noShell(dirComum)} (o ork nao roda isso sozinho)` };
258
+ detalhe: (0, locale_1.msg)().doctor.donoOutro(total, relativo(dirComum), [...uids].sort((a, b) => a - b).join(', '), raiz.uid, `${estranhos.join(', ')}${total > estranhos.length ? ', ...' : ''}`, parcial ? teto : null),
259
+ correcao: (0, locale_1.msg)().doctor.donoCorrecao(`sudo chown -R ${raiz.uid}:${raiz.gid} ${noShell(dirComum)}`) };
261
260
  }
262
261
  if (parcial) {
263
- return { nome, nivel: 'warn', detalhe: `mais de ${teto} entradas em ${relativo(dirComum)}: conferencia parcial, sem outro dono ate aqui`,
264
- correcao: `confira o resto com: find ${noShell(dirComum)} -not -uid ${raiz.uid}` };
262
+ return { nome, nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.donoParcial(teto, relativo(dirComum)),
263
+ correcao: (0, locale_1.msg)().doctor.donoParcialCorrecao(`find ${noShell(dirComum)} -not -uid ${raiz.uid}`) };
265
264
  }
266
- return { nome, nivel: 'ok', detalhe: `${vistos} entradas de ${relativo(dirComum)} com o dono do repositorio (uid ${raiz.uid})` };
265
+ return { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.donoOk(vistos, relativo(dirComum), raiz.uid) };
267
266
  }
268
267
  /** Checks locais; ler a entrevista não abre driver, banco, runtime ou rede. */
269
268
  function checarOnboarding(carregado) {
270
269
  const estado = (0, onboarding_1.lerOnboarding)(carregado.raiz);
271
270
  const pendentes = onboarding_1.ETAPAS_ONBOARDING.filter(e => estado.etapas[e] === null);
272
271
  const checks = [{ nome: 'onboarding', nivel: pendentes.length ? 'warn' : 'ok',
273
- detalhe: pendentes.length ? `${pendentes.length} etapa(s) pendente(s): ${pendentes.join(', ')}` : '9 etapas respondidas',
272
+ detalhe: pendentes.length ? (0, locale_1.msg)().doctor.onboardingPendente(pendentes.length, pendentes.join(', ')) : (0, locale_1.msg)().doctor.onboardingCompleto,
274
273
  ...(pendentes.length ? { correcao: 'ork onboarding' } : {}) }];
275
274
  const escolha = estado.etapas.memoria?.conteudo;
276
275
  const modo = escolha === 'sim' || escolha === true ? 'orkmind' :
277
276
  escolha === 'orkmind' || escolha === 'files' ? escolha :
278
277
  escolha && typeof escolha === 'object' && !Array.isArray(escolha) ? escolha.modo : null;
279
278
  if ((modo === 'orkmind' || modo === 'files') && modo !== carregado.manifesto.memory.mode) {
280
- checks.push({ nome: 'onboarding memoria', nivel: 'warn', detalhe: `entrevista escolheu ${modo}; manifesto declara ${carregado.manifesto.memory.mode}`,
281
- correcao: `revise memory.mode: ${modo} em orkastery.yaml; a entrevista não altera o manifesto` });
279
+ checks.push({ nome: 'onboarding memoria', nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.entrevistaMemoria(modo, carregado.manifesto.memory.mode),
280
+ correcao: (0, locale_1.msg)().doctor.entrevistaMemoriaCorrecao(modo) });
282
281
  }
283
282
  // I-35: o fuso respondido na etapa maestro orienta owner.timezone, sem editar o manifesto. Com
284
283
  // `owner.timezone` na mesma resposta (gravado no manifesto pelo `onboarding set`), vale ele: no
@@ -291,8 +290,8 @@ function checarOnboarding(carregado) {
291
290
  ? (0, horario_1.normalizarFuso)(fusoDoOwner) ?? (0, horario_1.normalizarFuso)(maestro.fuso) : undefined;
292
291
  if (fusoDaEntrevista && fusoDaEntrevista !== carregado.manifesto.owner?.timezone) {
293
292
  checks.push({ nome: 'onboarding fuso', nivel: 'warn',
294
- detalhe: `entrevista informou ${fusoDaEntrevista}; manifesto declara ${carregado.manifesto.owner?.timezone ?? `${horario_1.CHAVE_DO_FUSO} ausente`}`,
295
- correcao: `revise ${horario_1.CHAVE_DO_FUSO}: "${fusoDaEntrevista}" em orkastery.yaml; a entrevista não altera o manifesto` });
293
+ detalhe: (0, locale_1.msg)().doctor.entrevistaFuso(fusoDaEntrevista, carregado.manifesto.owner?.timezone, horario_1.CHAVE_DO_FUSO),
294
+ correcao: (0, locale_1.msg)().doctor.entrevistaFusoCorrecao(horario_1.CHAVE_DO_FUSO, fusoDaEntrevista) });
296
295
  }
297
296
  return checks;
298
297
  }
@@ -352,15 +351,12 @@ function temPerfilAtivo(carregado, runtime) {
352
351
  function checarRuntimeClaude(carregado, claude, versao, auth = null) {
353
352
  const nome = 'runtime claude-bg';
354
353
  if (claude) {
355
- const detalhe = `${claude} (${versao ?? 'versao desconhecida'})`;
354
+ const detalhe = `${claude} (${versao ?? (0, locale_1.msg)().doctor.versaoDesconhecida})`;
356
355
  // Ensaio de 03/10 (R1): sem perfil de conta, o despacho usa o login do proprio `claude`; sem ele, o
357
356
  // primeiro despacho falha. Conferencia inconclusiva (timeout, JSON ilegivel) nao prova falta de login.
358
357
  if (auth && !auth.ok && !auth.transitorio) {
359
- return { nome, nivel: 'warn', detalhe: `${detalhe}; ${auth.detalhe}: o despacho pelo claude-bg falharia`,
360
- correcao: auth.pago
361
- ? 'faca o login de assinatura (claude.ai) no `claude`, sem API key nem provider de nuvem'
362
- : 'rode `claude` uma vez, faca o login de assinatura (/login) e aceite a confianca no diretorio do projeto; ' +
363
- 'ou crie um perfil com ork accounts add <id> --runtime claude-bg --dir <pasta>' };
358
+ return { nome, nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.claudeSemLogin(detalhe, auth.detalhe),
359
+ correcao: auth.pago ? (0, locale_1.msg)().doctor.claudeLoginPago : (0, locale_1.msg)().doctor.claudeLogin };
364
360
  }
365
361
  return { nome, nivel: 'ok', detalhe };
366
362
  }
@@ -368,18 +364,13 @@ function checarRuntimeClaude(carregado, claude, versao, auth = null) {
368
364
  if (blocos && blocos.principal.length === 0) {
369
365
  // CHECK, rodada 1 (S6): as fases nao precisam dele, mas o `ork audit run` despacha sempre pelo claude-bg.
370
366
  return { nome, nivel: 'warn',
371
- detalhe: 'binario `claude` fora do PATH (opcional para as fases: nenhum bloco dos modos permitidos despacha pelo claude-bg' +
372
- (blocos.fallback.length
373
- ? `; o fallback de ${blocos.fallback.length} bloco(s) cai nele e falharia: ${textoDosBlocos(blocos.fallback)}` : '') +
374
- '; o ork audit run ainda despacha por ele)',
375
- correcao: 'para despachar pelo claude-bg (e rodar ork audit run), instale o Claude Code e garanta `claude` no PATH' };
367
+ detalhe: (0, locale_1.msg)().doctor.claudeOpcional(blocos.fallback.length
368
+ ? { blocos: blocos.fallback.length, texto: textoDosBlocos(blocos.fallback) } : null),
369
+ correcao: (0, locale_1.msg)().doctor.claudeOpcionalCorrecao };
376
370
  }
377
371
  return { nome, nivel: 'fail',
378
- detalhe: 'binario `claude` fora do PATH' + (blocos
379
- ? `; ${blocos.principal.length} bloco(s) dos modos permitidos despacham por ele (${textoDosBlocos(blocos.principal)})` : ''),
380
- correcao: 'instale o Claude Code e garanta `claude` no PATH; so com o Codex, passe cada bloco para ele ' +
381
- '(ork setup <modo> --bloco N --runtime codex --model <modelo>) ou tire o modo de conduction.allowed_modes ' +
382
- '(mantenha o conduction.default_mode entre os permitidos)' };
372
+ detalhe: (0, locale_1.msg)().doctor.claudeAusente(blocos ? { blocos: blocos.principal.length, texto: textoDosBlocos(blocos.principal) } : null),
373
+ correcao: (0, locale_1.msg)().doctor.claudeAusenteCorrecao };
383
374
  }
384
375
  /**
385
376
  * O despacho pelo Codex quando o projeto o elege: por `runtime.adapter: codex`, como antes, ou, desde
@@ -392,24 +383,28 @@ function checarDespachoPeloCodex(carregado, codex, sonda) {
392
383
  const blocos = blocosDoRuntime(carregado, 'codex')?.principal ?? [];
393
384
  if (!pelaAdapter && blocos.length === 0)
394
385
  return null;
395
- const origem = [pelaAdapter ? 'runtime.adapter: codex' : '',
396
- blocos.length ? `${blocos.length} bloco(s) dos modos permitidos no codex (${textoDosBlocos(blocos)})` : '']
397
- .filter(Boolean).join(' e ');
386
+ const origem = (0, locale_1.msg)().doctor.origemDoCodex(pelaAdapter, blocos.length ? { blocos: blocos.length, texto: textoDosBlocos(blocos) } : null);
398
387
  const sandboxConfigurado = carregado.manifesto.runtime.sandbox;
399
388
  const sandboxQuebrado = sonda !== null && !sonda.ok && sandboxConfigurado !== 'danger-full-access';
389
+ // RM-047 (P1): a postura que afrouxa o sandbox so despacha com a confirmacao local desta maquina.
390
+ const posturaSemConfirmacao = (0, postura_local_1.recusaDePostura)(carregado.raiz, carregado.manifesto, 'codex') !== null;
400
391
  return {
401
392
  nome: 'despacho pelo codex',
402
- nivel: !codex ? 'fail' : sandboxQuebrado ? 'fail' : 'ok',
393
+ nivel: !codex ? 'fail' : sandboxQuebrado || posturaSemConfirmacao ? 'fail' : 'ok',
403
394
  detalhe: !codex
404
- ? `${origem}, mas o binario \`codex\` esta fora do PATH`
395
+ ? (0, locale_1.msg)().doctor.codexForaNoDespacho(origem)
405
396
  : sandboxQuebrado
406
- ? `${origem} com sandbox "${sandboxConfigurado}", mas o sandbox nao executa nesta maquina (o agente narraria sucesso sem rodar nada)`
407
- : `${origem} com sandbox "${sandboxConfigurado}"`,
397
+ ? (0, locale_1.msg)().doctor.codexSandboxQuebrado(origem, sandboxConfigurado)
398
+ : posturaSemConfirmacao
399
+ ? (0, locale_1.msg)().doctor.codexSemConfirmacao(origem, sandboxConfigurado)
400
+ : (0, locale_1.msg)().doctor.codexSandboxOk(origem, sandboxConfigurado),
408
401
  correcao: !codex
409
- ? 'instale o Codex CLI e autentique com `codex login` (assinatura, nunca API key)'
402
+ ? (0, locale_1.msg)().doctor.codexForaNoDespachoCorrecao
410
403
  : sandboxQuebrado
411
- ? 'instale o bubblewrap do sistema, ou declare runtime.sandbox: danger-full-access ciente do risco'
412
- : undefined,
404
+ ? (0, locale_1.msg)().doctor.codexSandboxQuebradoCorrecao((0, postura_local_1.comandoDeConfirmacao)('danger-full-access'))
405
+ : posturaSemConfirmacao
406
+ ? (0, locale_1.msg)().doctor.codexSemConfirmacaoCorrecao((0, postura_local_1.comandoDeConfirmacao)(sandboxConfigurado))
407
+ : undefined,
413
408
  };
414
409
  }
415
410
  /**
@@ -424,7 +419,7 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
424
419
  nome: 'node',
425
420
  nivel: major >= 20 ? 'ok' : 'fail',
426
421
  detalhe: `v${process.versions.node}`,
427
- correcao: major >= 20 ? undefined : 'instale Node 20 ou superior',
422
+ correcao: major >= 20 ? undefined : (0, locale_1.msg)().doctor.instaleNode,
428
423
  });
429
424
  if (analisadores)
430
425
  checks.push(analisadores());
@@ -432,8 +427,8 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
432
427
  checks.push({
433
428
  nome: 'git',
434
429
  nivel: git ? 'ok' : 'fail',
435
- detalhe: git ?? 'nao encontrado no PATH',
436
- correcao: git ? undefined : 'instale o git',
430
+ detalhe: git ?? (0, locale_1.msg)().doctor.gitAusente,
431
+ correcao: git ? undefined : (0, locale_1.msg)().doctor.instaleGit,
437
432
  });
438
433
  const repo = (0, util_1.exec)('git', ['rev-parse', '--is-inside-work-tree'], dirInicial);
439
434
  const dentroDeRepo = repo.ok && repo.stdout.trim() === 'true';
@@ -444,8 +439,8 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
444
439
  checks.push({
445
440
  nome: 'repositorio',
446
441
  nivel: dentroDeRepo ? 'ok' : 'fail',
447
- detalhe: dentroDeRepo ? `branch ${branch}${semCommit ? ' (sem commit)' : ''}` : 'fora de um repositorio git',
448
- correcao: dentroDeRepo ? undefined : 'rode o ork dentro de um repositorio git',
442
+ detalhe: dentroDeRepo ? (0, locale_1.msg)().doctor.branch(branch, semCommit) : (0, locale_1.msg)().doctor.foraDeRepo,
443
+ correcao: dentroDeRepo ? undefined : (0, locale_1.msg)().doctor.rodeDentroDeRepo,
449
444
  });
450
445
  if (dentroDeRepo) {
451
446
  const dono = checarDonoDoGit(dirInicial);
@@ -470,13 +465,13 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
470
465
  nome: 'runtime codex',
471
466
  nivel: codex ? 'ok' : 'warn',
472
467
  detalhe: codex
473
- ? `${codex} (${codexVersao ?? 'versao desconhecida'})`
468
+ ? `${codex} (${codexVersao ?? (0, locale_1.msg)().doctor.versaoDesconhecida})`
474
469
  : usaCodex
475
- ? 'binario `codex` fora do PATH (o projeto despacha por ele: veja despacho pelo codex)'
476
- : 'binario `codex` fora do PATH (opcional: claude-bg e o runtime padrao)',
470
+ ? (0, locale_1.msg)().doctor.codexAusenteUsado
471
+ : (0, locale_1.msg)().doctor.codexAusenteOpcional,
477
472
  correcao: codex
478
473
  ? undefined
479
- : 'para despachar pelo codex, instale o Codex CLI e autentique com `codex login`',
474
+ : (0, locale_1.msg)().doctor.instaleCodex,
480
475
  });
481
476
  // Pitfall MEDIDO em 06/09/2026: com o sandbox quebrado, o `codex exec` sai 0 e o agente
482
477
  // NARRA sucesso sem executar nada. A sonda e deterministica (roda `true`, sem LLM).
@@ -487,21 +482,20 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
487
482
  nome: 'sandbox do codex',
488
483
  nivel: sondaDoCodex.ok ? 'ok' : 'warn',
489
484
  detalhe: sondaDoCodex.ok
490
- ? '`codex sandbox true` executa nesta maquina'
491
- : `sonda \`codex sandbox true\` falhou: ${sondaDoCodex.detalhe}`,
485
+ ? (0, locale_1.msg)().doctor.sandboxOk
486
+ : (0, locale_1.msg)().doctor.sandboxFalhou(sondaDoCodex.detalhe),
492
487
  correcao: sondaDoCodex.ok
493
488
  ? undefined
494
- : 'instale o pacote bubblewrap do sistema (o bwrap embutido nao cria user namespace ' +
495
- 'nesta maquina) ou declare runtime.sandbox: danger-full-access ciente do risco',
489
+ : (0, locale_1.msg)().doctor.sandboxCorrecao((0, postura_local_1.comandoDeConfirmacao)('danger-full-access')),
496
490
  });
497
491
  }
498
492
  if (!carregado) {
499
493
  checks.push({
500
494
  nome: 'manifesto',
501
495
  nivel: 'fail',
502
- detalhe: `${manifest_1.NOME_MANIFESTO} nao encontrado a partir de ${dirInicial}`,
496
+ detalhe: (0, locale_1.msg)().doctor.manifestoAusente(manifest_1.NOME_MANIFESTO, dirInicial),
503
497
  // Ensaio de 03/10/2026 (RM-049): fora de repositorio, o `ork init` recusa; a correcao diz onde roda-lo.
504
- correcao: dentroDeRepo ? 'ork init' : 'entre no repositorio do projeto (ou crie um com git init e o primeiro commit) e rode ork init',
498
+ correcao: dentroDeRepo ? (0, locale_1.msg)().doctor.rodeInit : (0, locale_1.msg)().doctor.entreNoRepoEInit,
505
499
  });
506
500
  }
507
501
  else {
@@ -510,9 +504,9 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
510
504
  nivel: carregado.erros.length > 0 ? 'fail' : carregado.avisos.length > 0 ? 'warn' : 'ok',
511
505
  detalhe: carregado.erros.length > 0
512
506
  ? `${carregado.caminho}: ${carregado.erros.join('; ')}`
513
- : `${carregado.caminho} (${carregado.bytes} B de ${manifest_1.LIMITE_MANIFESTO_BYTES})` +
514
- (carregado.avisos.length > 0 ? `; ${carregado.avisos.join('; ')}` : ''),
515
- correcao: carregado.erros.length > 0 ? 'corrija o manifesto e rode ork doctor de novo' : undefined,
507
+ : (0, locale_1.msg)().doctor.manifestoOk(carregado.caminho, carregado.bytes, manifest_1.LIMITE_MANIFESTO_BYTES) +
508
+ (carregado.avisos.length > 0 ? `; ${carregado.avisos.map((a) => (0, locale_1.msg)().onboarding.avisoDaPreferencia(a)).join('; ')}` : ''),
509
+ correcao: carregado.erros.length > 0 ? (0, locale_1.msg)().doctor.corrijaManifesto : undefined,
516
510
  });
517
511
  if (dentroDeRepo) {
518
512
  const fora = manifestoForaDoRepositorio(dirInicial, carregado.caminho);
@@ -526,16 +520,15 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
526
520
  nome: 'abbrev do projeto',
527
521
  nivel: checkAbbrev.ok ? 'ok' : 'fail',
528
522
  detalhe: checkAbbrev.ok
529
- ? `"${abbrev}" (parte 1 do slug de sessao)`
523
+ ? (0, locale_1.msg)().doctor.abbrevOk(abbrev)
530
524
  : checkAbbrev.erro,
531
- correcao: checkAbbrev.ok ? undefined : 'defina project.abbrev com ate 3 caracteres [a-z0-9]',
525
+ correcao: checkAbbrev.ok ? undefined : (0, locale_1.msg)().doctor.abbrevCorrecao,
532
526
  });
533
527
  const cond = carregado.manifesto.conduction;
534
528
  checks.push({
535
529
  nome: 'modos de conducao',
536
530
  nivel: 'ok',
537
- detalhe: `padrao ${modos_1.MODOS[cond.default_mode].tag}; ` +
538
- `permitidos ${cond.allowed_modes.map((m) => modos_1.MODOS[m].tag).join(', ')}`,
531
+ detalhe: (0, locale_1.msg)().doctor.modos(modos_1.MODOS[cond.default_mode].tag, cond.allowed_modes.map((m) => modos_1.MODOS[m].tag).join(', ')),
539
532
  });
540
533
  // I-35: o fuso em que todo horario chega ao dono; valor invalido avisa e nao para nada.
541
534
  const fuso = (0, horario_1.fusoDoManifesto)(carregado);
@@ -543,15 +536,28 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
543
536
  nome: 'fuso do dono',
544
537
  nivel: fuso.aviso ? 'warn' : 'ok',
545
538
  detalhe: fuso.aviso ?? (fuso.origem === 'manifesto'
546
- ? `${fuso.fuso} (${horario_1.CHAVE_DO_FUSO}); horarios para pessoas em ${(0, horario_1.rotuloDoFuso)(fuso.fuso)}`
547
- : `${fuso.fuso} (fuso do sistema; ${horario_1.CHAVE_DO_FUSO} nao configurado)`),
548
- correcao: fuso.aviso ? `corrija ${horario_1.CHAVE_DO_FUSO} com um nome IANA` : undefined,
539
+ ? (0, locale_1.msg)().doctor.fusoDoManifesto(fuso.fuso, horario_1.CHAVE_DO_FUSO, (0, horario_1.rotuloDoFuso)(fuso.fuso))
540
+ : (0, locale_1.msg)().doctor.fusoDoSistema(fuso.fuso, horario_1.CHAVE_DO_FUSO)),
541
+ correcao: fuso.aviso ? (0, locale_1.msg)().doctor.fusoCorrecao(horario_1.CHAVE_DO_FUSO) : undefined,
549
542
  });
550
543
  // Quando o manifesto ou um bloco de modo permitido ELEGE o codex, a ausencia dele (ou um
551
544
  // sandbox que nao executa) deixa de ser aviso: e exatamente o que bloquearia a fase.
552
545
  const despachoPeloCodex = checarDespachoPeloCodex(carregado, codex, sondaDoCodex);
553
546
  if (despachoPeloCodex)
554
547
  checks.push(despachoPeloCodex);
548
+ // RM-047 (P5): o manifesto pede a fabrica compartilhada, mas quem liga a publicacao e a maquina.
549
+ const fabricaPedida = (0, maquina_1.avisoDaFabricaPedida)(carregado.manifesto);
550
+ if (fabricaPedida) {
551
+ checks.push({ nome: 'fabrica compartilhada', nivel: 'warn',
552
+ detalhe: (0, locale_1.msg)().doctor.fabricaPedida, correcao: (0, locale_1.msg)().doctor.fabricaPedidaCorrecao });
553
+ }
554
+ // RM-047 (P3): worktree.dir fora da raiz so cria checkout com a confirmacao local desta maquina.
555
+ const recusaDaPasta = (0, worktree_local_1.recusaDePastaDasWorktrees)(carregado.raiz, carregado.manifesto);
556
+ if (recusaDaPasta) {
557
+ checks.push({ nome: 'pasta das worktrees', nivel: 'fail',
558
+ detalhe: (0, locale_1.msg)().doctor.pastaForaDaRaiz(carregado.manifesto.worktree.dir),
559
+ correcao: (0, locale_1.msg)().doctor.pastaForaDaRaizCorrecao(worktree_local_1.COMANDO_CONFIRMAR_WORKTREE) });
560
+ }
555
561
  const politica = carregado.manifesto.runtime.provider_policy;
556
562
  const soAssinatura = politica === 'subscription-only';
557
563
  const redirecionam = ENVS_QUE_REDIRECIONAM.filter(e => nomesHerdados.includes(e));
@@ -561,21 +567,21 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
561
567
  nome: 'custo e provider herdado',
562
568
  nivel: bloqueia ? 'fail' : soAssinatura && pagas.length > 0 ? 'warn' : 'ok',
563
569
  detalhe: bloqueia
564
- ? `politica ${politica} violada: ${redirecionam.join(', ')} redireciona o despacho do claude`
570
+ ? (0, locale_1.msg)().doctor.politicaViolada(politica, redirecionam.join(', '))
565
571
  : pagas.length > 0
566
- ? `politica ${politica}; despacho segue na assinatura local, mas ha credencial paga no ambiente: ${pagas.join(', ')}`
567
- : `politica ${politica}; nenhuma variavel de provider pago ativa`,
572
+ ? (0, locale_1.msg)().doctor.politicaComPaga(politica, pagas.join(', '))
573
+ : (0, locale_1.msg)().doctor.politicaLimpa(politica),
568
574
  correcao: bloqueia
569
- ? `remova do ambiente: ${redirecionam.join(', ')} (o despacho usa a assinatura Claude local)`
575
+ ? (0, locale_1.msg)().doctor.removaDoAmbiente(redirecionam.join(', '))
570
576
  : pagas.length > 0
571
- ? `nenhuma acao obrigatoria; nunca despache fase por ${pagas.join(', ')}`
577
+ ? (0, locale_1.msg)().doctor.nuncaDespachePorPaga(pagas.join(', '))
572
578
  : undefined,
573
579
  });
574
580
  const efetivas = (0, runtime_ambiente_1.nomesDeProviderAtivos)();
575
581
  checks.push({
576
582
  nome: 'provider efetivo da fabrica',
577
583
  nivel: soAssinatura && efetivas.length ? 'warn' : 'ok',
578
- detalhe: efetivas.length ? `nomes ativos: ${efetivas.join(', ')}` : 'nenhum nome da lista de provider ativo',
584
+ detalhe: efetivas.length ? (0, locale_1.msg)().doctor.providersAtivos(efetivas.join(', ')) : (0, locale_1.msg)().doctor.nenhumProvider,
579
585
  });
580
586
  // Bloco B6: o regime de memoria e um CHECK, nao um detalhe do manifesto. Manifesto
581
587
  // que pede `orkmind` e nao consegue liga-lo vira `warn` com a correcao, nunca `fail`:
@@ -583,15 +589,15 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
583
589
  const context = (0, project_state_1.memoryState)(carregado);
584
590
  const { estado } = (0, orkmind_1.resolverRegime)(context.loaded.manifesto, null);
585
591
  checks.push({ nome: 'fonte da memoria', nivel: context.divergent ? 'warn' : 'ok',
586
- detalhe: `${context.source}${context.divergent ? ' (cópia da worktree divergente preservada)' : ''}` });
592
+ detalhe: (0, locale_1.msg)().doctor.fonteDaMemoria(context.source, context.divergent) });
587
593
  checks.push({
588
594
  nome: 'regime de memoria',
589
595
  nivel: estado.efetivo === 'orkmind' ? 'ok' : estado.pedido === 'orkmind' ? 'warn' : 'ok',
590
596
  detalhe: estado.pedido === 'orkmind' && estado.efetivo === 'files'
591
- ? `pedido orkmind, efetivo files (${estado.motivo}): ${estado.detalhe}`
597
+ ? (0, locale_1.msg)().doctor.regimeDegradado(estado.motivo, estado.detalhe)
592
598
  : estado.efetivo === 'orkmind'
593
- ? `orkmind ativo no tenant "${estado.tenant}" pela variavel ${estado.variavel}`
594
- : 'files (fallback honesto: handoff por arquivos, ponteiro path#ancora)',
599
+ ? (0, locale_1.msg)().doctor.regimeOrkmind(estado.tenant, estado.variavel)
600
+ : (0, locale_1.msg)().doctor.memoriaFiles,
595
601
  correcao: estado.pedido === 'orkmind' && estado.efetivo === 'files' ? estado.correcao : undefined,
596
602
  });
597
603
  checks.push(checarChaveDeEmbedding(context.loaded));
@@ -605,13 +611,13 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
605
611
  nome: 'fila de rate limit',
606
612
  nivel: escalados.length > 0 ? 'warn' : 'ok',
607
613
  detalhe: fila.length === 0
608
- ? 'vazia: nenhuma fase morreu por limite de uso neste projeto'
609
- : `${esperando.length} aguardando janela, ${escalados.length} escalado(s) para humano` +
610
- (esperando.length > 0 ? `; proxima janela em ${(0, horario_1.formatarDataHoraRotulada)(esperando[0].liberaEm)}` : ''),
614
+ ? (0, locale_1.msg)().doctor.filaVazia
615
+ : (0, locale_1.msg)().doctor.filaResumo(esperando.length, escalados.length) +
616
+ (esperando.length > 0 ? (0, locale_1.msg)().doctor.filaProxima((0, horario_1.formatarDataHoraRotulada)(esperando[0].liberaEm)) : ''),
611
617
  correcao: escalados.length > 0
612
- ? `pedido escalado alem do limite de retry.max_tentativas: ork retry list e ork gate request <thread>`
618
+ ? (0, locale_1.msg)().doctor.filaEscaladoCorrecao
613
619
  : esperando.length > 0
614
- ? 'ork retry resume retoma o que ja liberou'
620
+ ? (0, locale_1.msg)().doctor.filaEsperaCorrecao
615
621
  : undefined,
616
622
  });
617
623
  const dirEstadoProjeto = path.join((0, estado_thread_1.raizDoEstado)(carregado.raiz), manifest_1.DIR_ESTADO);
@@ -623,9 +629,9 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
623
629
  nome: 'estado do projeto',
624
630
  nivel: fs.existsSync(dirEstadoProjeto) ? 'ok' : 'warn',
625
631
  detalhe: fs.existsSync(dirEstadoProjeto)
626
- ? `${dirEstadoProjeto} (${qtd} thread(s))`
627
- : `${dirEstadoProjeto} ausente`,
628
- correcao: fs.existsSync(dirEstadoProjeto) ? undefined : 'ork init cria o diretorio de estado',
632
+ ? (0, locale_1.msg)().doctor.estadoOk(dirEstadoProjeto, qtd)
633
+ : (0, locale_1.msg)().doctor.estadoAusente(dirEstadoProjeto),
634
+ correcao: fs.existsSync(dirEstadoProjeto) ? undefined : (0, locale_1.msg)().doctor.estadoCorrecao,
629
635
  });
630
636
  // RM-039 (B6): com o transporte do pulse configurado, a varredura tem de bater de 15 em 15
631
637
  // minutos; a instalacao antiga em `0 * * * *` vira aviso com a linha nova. Nunca edita o crontab.
@@ -642,12 +648,9 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
642
648
  checks.push({
643
649
  nome: 'governanca de sessoes',
644
650
  nivel: inventario.ok && inventario.semThread === 0 ? 'ok' : 'warn',
645
- detalhe: `${inventario.escopo.usuario}, Claude e Codex, global com histórico: ${inventario.total} sessões; ` +
646
- `${inventario.semThread} sem thread; ${inventario.ambiguas} ambíguas; ` +
647
- `inventário ${inventario.ok ? 'válido' : 'INCOMPLETO (zero não comprovado)'}` +
648
- (ausentes.length ? `; fonte ausente: ${ausentes.join(', ')}` : ''),
649
- correcao: inventario.ok && inventario.semThread === 0 ? undefined :
650
- 'ork sessions --global --all --json; adote identidades sem vínculo com ork sessions adopt <id>',
651
+ detalhe: (0, locale_1.msg)().doctor.governanca({ usuario: inventario.escopo.usuario, total: inventario.total, semThread: inventario.semThread,
652
+ ambiguas: inventario.ambiguas, ok: inventario.ok, ausentes: ausentes.map((o) => (0, locale_1.msg)().doctor.fonteDaSessao(o)) }),
653
+ correcao: inventario.ok && inventario.semThread === 0 ? undefined : (0, locale_1.msg)().doctor.governancaCorrecao,
651
654
  });
652
655
  }
653
656
  }
@@ -658,9 +661,10 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
658
661
  /** Texto do relatorio, com o resumo "o que vale nesta maquina agora". */
659
662
  function relatorio(checks) {
660
663
  const linhas = [];
661
- linhas.push('ork doctor: o que vale nesta maquina agora');
664
+ const m = (0, locale_1.msg)().doctor;
665
+ linhas.push(m.titulo);
662
666
  linhas.push('');
663
- const largura = Math.max(...checks.map((c) => c.nome.length));
667
+ const largura = Math.max(...checks.map((c) => (0, locale_1.nomeDoCheck)(c.nome).length));
664
668
  // I-35: o Check guarda o ISO (dado de maquina, tambem lido por teste); quem imprime para o dono
665
669
  // localiza. Vale para todo check, nao so o de contas: nenhum horario chega cru ao relatorio.
666
670
  let localizou = false;
@@ -671,9 +675,9 @@ function relatorio(checks) {
671
675
  return l;
672
676
  };
673
677
  for (const c of checks) {
674
- linhas.push(` ${(0, util_1.simbolo)(c.nivel)} ${c.nome.padEnd(largura)} ${local(c.detalhe)}`);
678
+ linhas.push(` ${(0, util_1.simbolo)(c.nivel)} ${(0, locale_1.nomeDoCheck)(c.nome).padEnd(largura)} ${local(c.detalhe)}`);
675
679
  if (c.nivel !== 'ok' && c.correcao) {
676
- linhas.push(` ${' '.repeat(largura)} correcao: ${local(c.correcao)}`);
680
+ linhas.push(` ${' '.repeat(largura)} ${m.correcao}: ${local(c.correcao)}`);
677
681
  }
678
682
  }
679
683
  // O fuso sai uma vez por mensagem, antes do veredito, que segue sendo a ultima linha.
@@ -683,8 +687,8 @@ function relatorio(checks) {
683
687
  const avisos = checks.filter((c) => c.nivel === 'warn').length;
684
688
  linhas.push('');
685
689
  linhas.push(falhas > 0
686
- ? `Veredito: BLOQUEADO (${falhas} fail, ${avisos} warn). Corrija os itens acima antes de despachar fase.`
687
- : `Veredito: PRONTO (${avisos} warn). Despacho de fase liberado por \`ork phase run\`.`);
690
+ ? m.bloqueado(falhas, avisos)
691
+ : m.pronto(avisos));
688
692
  return linhas.join('\n');
689
693
  }
690
694
  /** Executa o doctor e devolve o codigo de saida (0 = pronto). */