@orkastery/cli 0.5.1 → 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 (260) hide show
  1. package/adapters/claude-code/README.md +158 -0
  2. package/adapters/claude-code/agents/ork-master.md +2 -0
  3. package/adapters/claude-code/commands/master.md +8 -0
  4. package/adapters/claude-code/commands/ork.md +9 -0
  5. package/adapters/claude-code/mods/autoridade.json +56 -0
  6. package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
  7. package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
  8. package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
  9. package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
  10. package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
  11. package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
  12. package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
  13. package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
  14. package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
  15. package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
  16. package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
  17. package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
  18. package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
  19. package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
  20. package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
  21. package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
  22. package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
  23. package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
  24. package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
  25. package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
  26. package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
  27. package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
  28. package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
  29. package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
  30. package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
  31. package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
  32. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +117 -0
  33. package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
  34. package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
  35. package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
  36. package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
  37. package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
  38. package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
  39. package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
  40. package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
  41. package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
  42. package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
  43. package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
  44. package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
  45. package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
  46. package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
  47. package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
  48. package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
  49. package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
  50. package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
  51. package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
  52. package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
  53. package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
  54. package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
  55. package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
  56. package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
  57. package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
  58. package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
  59. package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
  60. package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
  61. package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
  62. package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
  63. package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
  64. package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
  65. package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
  66. package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
  67. package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
  68. package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
  69. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
  70. package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
  71. package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
  72. package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
  73. package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
  74. package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
  75. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
  76. package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
  77. package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
  78. package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
  79. package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
  80. package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
  81. package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
  82. package/adapters/codex/skills/ork/SKILL.md +18 -3
  83. package/adapters/hermes/README.md +1 -0
  84. package/adapters/hermes/bin/ork-network-status.sh +10 -0
  85. package/adapters/hermes/hermes.plugin.json +1 -0
  86. package/adapters/hermes/hitl-ingress/__init__.py +2 -2
  87. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +7 -6
  88. package/adapters/openclaw/README.md +26 -5
  89. package/adapters/openclaw/dist/hitl-ingress.js +2 -2
  90. package/adapters/openclaw/dist/index.js +46 -11
  91. package/adapters/openclaw/openclaw.plugin.json +5 -1
  92. package/adapters/openclaw/package.json +2 -2
  93. package/adapters/openclaw/src/hitl-ingress.ts +2 -2
  94. package/adapters/openclaw/src/index.ts +49 -11
  95. package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
  96. package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
  97. package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
  98. package/assets/docs-en/produto/README.md +14 -0
  99. package/assets/docs-en/produto/_modelo-feature.md +62 -0
  100. package/assets/docs-en/roadmap/README.md +14 -0
  101. package/assets/docs-en/roadmap/_modelo-item.md +75 -0
  102. package/assets/orkmind_bridge.py +117 -9
  103. package/dist/adapters/claude-bg.js +116 -18
  104. package/dist/adapters/codex.js +14 -4
  105. package/dist/agents-md.js +24 -14
  106. package/dist/auditrun.js +22 -3
  107. package/dist/board.js +20 -17
  108. package/dist/branch-de-estado.js +88 -10
  109. package/dist/busca-semantica.js +52 -12
  110. package/dist/canarios-rm057.js +149 -0
  111. package/dist/canarios.js +2 -0
  112. package/dist/catalogo.js +33 -0
  113. package/dist/ci.js +21 -8
  114. package/dist/claims-conferir.js +342 -0
  115. package/dist/claims.js +41 -1
  116. package/dist/company-brain-client.js +36 -1
  117. package/dist/company-brain-context.js +158 -22
  118. package/dist/company-brain-journal.js +2 -1
  119. package/dist/company-brain-migration.js +36 -1
  120. package/dist/conducao-sentinela.js +388 -0
  121. package/dist/conducao-texto.js +12 -18
  122. package/dist/conducao.js +122 -30
  123. package/dist/conhecimento.js +490 -0
  124. package/dist/docs.js +70 -17
  125. package/dist/doctor-pulse-cron.js +349 -0
  126. package/dist/doctor-rede.js +150 -0
  127. package/dist/doctor.js +195 -111
  128. package/dist/entrega-pr.js +42 -29
  129. package/dist/escopo-escrita.js +10 -1
  130. package/dist/esgotamentos.js +181 -0
  131. package/dist/estado-thread.js +23 -1
  132. package/dist/experiencia-instalacao.js +45 -25
  133. package/dist/experiencia.js +12 -2
  134. package/dist/fabrica-batida.js +310 -0
  135. package/dist/fabrica-estado.js +52 -14
  136. package/dist/fabrica-publicar.js +9 -1
  137. package/dist/fechamento.js +20 -66
  138. package/dist/fila-pesada.js +444 -0
  139. package/dist/fix.js +3 -2
  140. package/dist/forja.js +31 -7
  141. package/dist/gates.js +3 -24
  142. package/dist/handoff.js +10 -6
  143. package/dist/hitl-contract.js +59 -4
  144. package/dist/hitl-curto.js +11 -6
  145. package/dist/hitl-gates.js +5 -0
  146. package/dist/hitl-local-receipt.js +2 -0
  147. package/dist/hitl-lote.js +5 -2
  148. package/dist/hitl-resumo.js +38 -3
  149. package/dist/hitl-tempo-parado.js +201 -0
  150. package/dist/hitl-texto-livre.js +5 -5
  151. package/dist/hitl.js +29 -33
  152. package/dist/horario.js +41 -7
  153. package/dist/hosts.js +104 -11
  154. package/dist/impedimento.js +299 -0
  155. package/dist/index.js +961 -542
  156. package/dist/indice-vetorial.js +87 -10
  157. package/dist/indice.js +9 -1
  158. package/dist/init.js +56 -43
  159. package/dist/instabilidade.js +144 -0
  160. package/dist/integracoes-locais.js +4 -0
  161. package/dist/intelligence-graph-cli.js +170 -16
  162. package/dist/intelligence-graph-contexto.js +254 -0
  163. package/dist/intelligence-graph-contract.js +2 -1
  164. package/dist/intelligence-graph-extract-md.js +56 -4
  165. package/dist/intelligence-graph-extract-ts.js +71 -3
  166. package/dist/intelligence-graph-parsers.js +6 -4
  167. package/dist/intelligence-graph-query.js +66 -19
  168. package/dist/leases.js +664 -87
  169. package/dist/ledger-stats.js +15 -1
  170. package/dist/ledger.js +18 -1
  171. package/dist/licoes.js +1 -0
  172. package/dist/liveness.js +6 -3
  173. package/dist/locale-ajuda.js +761 -0
  174. package/dist/locale-gerados.js +160 -0
  175. package/dist/locale-master.js +99 -0
  176. package/dist/locale-onboarding.js +92 -0
  177. package/dist/locale-phase.js +151 -0
  178. package/dist/locale-pulse.js +211 -0
  179. package/dist/locale-retry.js +385 -0
  180. package/dist/locale-roadmap.js +102 -0
  181. package/dist/locale-ship.js +494 -0
  182. package/dist/locale-thread.js +277 -0
  183. package/dist/locale-verify.js +125 -0
  184. package/dist/locale.js +714 -0
  185. package/dist/maestro-runtime.js +4 -1
  186. package/dist/manifest.js +149 -4
  187. package/dist/maquina.js +23 -4
  188. package/dist/master-digest.js +6 -1
  189. package/dist/master-nota.js +18 -11
  190. package/dist/master.js +145 -31
  191. package/dist/mcp-artifacts.js +43 -3
  192. package/dist/mcp-git.js +42 -8
  193. package/dist/mcp-grafo-worker.js +5 -3
  194. package/dist/mcp-grafo.js +55 -6
  195. package/dist/mcp-server.js +22 -3
  196. package/dist/mcp-ship.js +3 -1
  197. package/dist/mcp-verify.js +6 -1
  198. package/dist/memoria.js +48 -6
  199. package/dist/modos.js +3 -6
  200. package/dist/network-roadmap.js +196 -18
  201. package/dist/noctum-arco.js +911 -0
  202. package/dist/noctum-capacidade.js +141 -0
  203. package/dist/noctum-envelope.js +810 -0
  204. package/dist/noctum-execucao.js +304 -0
  205. package/dist/noctum-fila.js +280 -0
  206. package/dist/ocupacao.js +40 -5
  207. package/dist/onboarding.js +40 -21
  208. package/dist/orkmind.js +99 -7
  209. package/dist/orquestracao.js +24 -21
  210. package/dist/parado-no-condutor.js +219 -38
  211. package/dist/phase.js +160 -52
  212. package/dist/policies.js +56 -5
  213. package/dist/portfolio.js +8 -3
  214. package/dist/postura-local.js +234 -0
  215. package/dist/preflight.js +11 -10
  216. package/dist/procedencia.js +225 -0
  217. package/dist/projeto-alvo.js +132 -5
  218. package/dist/prompts.js +40 -1
  219. package/dist/prova-ativacao.js +75 -6
  220. package/dist/pulse-delivery.js +47 -4
  221. package/dist/pulse.js +98 -19
  222. package/dist/ratelimit.js +24 -6
  223. package/dist/recall.js +3 -1
  224. package/dist/redacao-saida.js +63 -0
  225. package/dist/rede-adesao.js +399 -0
  226. package/dist/rede-forja.js +289 -0
  227. package/dist/rede-projetos.js +239 -0
  228. package/dist/rede-status.js +337 -0
  229. package/dist/rede.js +980 -0
  230. package/dist/retry.js +291 -140
  231. package/dist/roadmap-reservas.js +20 -3
  232. package/dist/roadmap-status.js +150 -34
  233. package/dist/runtime-context.js +181 -3
  234. package/dist/runtime-profiles.js +22 -1
  235. package/dist/runtimes.js +2 -1
  236. package/dist/saida-segura.js +58 -0
  237. package/dist/session-events.js +7 -3
  238. package/dist/session-watcher-claude.js +120 -24
  239. package/dist/session-watcher.js +185 -33
  240. package/dist/sessoes-contas.js +187 -0
  241. package/dist/sessoes-inventario.js +6 -18
  242. package/dist/sessoes.js +83 -2
  243. package/dist/ship-publicar.js +800 -0
  244. package/dist/ship.js +157 -88
  245. package/dist/steal.js +77 -0
  246. package/dist/thread-close.js +3 -2
  247. package/dist/thread.js +299 -49
  248. package/dist/util.js +8 -1
  249. package/dist/verify.js +141 -52
  250. package/dist/vida-da-thread.js +254 -0
  251. package/dist/worktree-local.js +165 -0
  252. package/dist/worktree.js +25 -2
  253. package/dist/yaml.js +27 -8
  254. package/eval/fixtures/fx-pedido-colado/caso.json +20 -0
  255. package/package.json +7 -3
  256. package/references/definition-of-done.md +1 -1
  257. package/schemas/code-artifact-graph.v1.schema.json +2 -1
  258. package/skills/README.md +1 -1
  259. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  260. package/skills/phases/master-metrics/SKILL.md +8 -3
package/dist/hitl.js CHANGED
@@ -88,6 +88,8 @@ const horario_1 = require("./horario");
88
88
  Object.defineProperty(exports, "duracaoCurta", { enumerable: true, get: function () { return horario_1.duracaoCurta; } });
89
89
  const hitl_estado_1 = require("./hitl-estado");
90
90
  const redacao_url_1 = require("./redacao-url");
91
+ const locale_1 = require("./locale");
92
+ const locale_pulse_1 = require("./locale-pulse");
91
93
  /** Limite de atencao padrao, em minutos, igual ao do monitor de orquestracao. */
92
94
  exports.ATENCAO_PADRAO_MIN = 30;
93
95
  function redigirSegredos(texto) {
@@ -110,28 +112,29 @@ function contextoSeguro(texto, linhas = 20) {
110
112
  * `stopped` NAO pede humano: a sessao foi parada por decisao de alguem. `failed` pede,
111
113
  * porque alguem precisa decidir entre retomar, corrigir ou abandonar.
112
114
  */
115
+ // RM-061 (F2b): o detalhe de cada estado tem a fonte no catalogo pt-BR (`locale-pulse.ts`), com o ingles ao lado.
113
116
  const REGRA_POR_ESTADO = {
114
117
  blocked: {
115
118
  classe: 'hitl',
116
119
  precisaDeHumano: true,
117
- detalhe: 'sessao parada esperando acao humana (prompt, permissao ou credencial)',
120
+ detalhe: locale_pulse_1.PULSE_PT_BR.sessao.blocked,
118
121
  },
119
122
  failed: {
120
123
  classe: 'falha',
121
124
  precisaDeHumano: true,
122
- detalhe: 'sessao terminou em erro: alguem decide entre retomar, corrigir ou abandonar',
125
+ detalhe: locale_pulse_1.PULSE_PT_BR.sessao.failed,
123
126
  },
124
- working: { classe: 'trabalhando', precisaDeHumano: false, detalhe: 'sessao em execucao' },
125
- done: { classe: 'concluida', precisaDeHumano: false, detalhe: 'sessao concluiu' },
127
+ working: { classe: 'trabalhando', precisaDeHumano: false, detalhe: locale_pulse_1.PULSE_PT_BR.sessao.working },
128
+ done: { classe: 'concluida', precisaDeHumano: false, detalhe: locale_pulse_1.PULSE_PT_BR.sessao.done },
126
129
  stopped: {
127
130
  classe: 'interrompida',
128
131
  precisaDeHumano: false,
129
- detalhe: 'sessao parada por decisao humana (`claude stop`)',
132
+ detalhe: locale_pulse_1.PULSE_PT_BR.sessao.stopped,
130
133
  },
131
134
  idle: {
132
135
  classe: 'interativa',
133
136
  precisaDeHumano: false,
134
- detalhe: 'sessao interativa ociosa, conduzida por um humano no terminal',
137
+ detalhe: locale_pulse_1.PULSE_PT_BR.sessao.idle,
135
138
  },
136
139
  };
137
140
  /** Estado cru da sessao: `state` manda, `status` e o fallback historico. */
@@ -142,14 +145,13 @@ function estadoBruto(s) {
142
145
  /** Classifica o estado cru do runtime. Estado que nao esta no mapa avisa a mais. */
143
146
  function classificarEstado(estado) {
144
147
  const regra = REGRA_POR_ESTADO[estado];
148
+ // RM-061 (F2b, G2): o detalhe vem do catalogo (o mesmo pt-BR da tabela) e o pulse o remonta no locale.
145
149
  if (regra)
146
- return regra;
150
+ return { ...regra, detalhe: (0, locale_1.textoDoCatalogo)((m) => m.pulse.sessao[estado] ?? regra.detalhe) };
147
151
  return {
148
152
  classe: 'desconhecida',
149
153
  precisaDeHumano: true,
150
- detalhe: estado === ''
151
- ? 'runtime nao informou estado desta sessao: tratada como possivel parada'
152
- : `estado "${estado}" nao esta no catalogo do ork: tratado como possivel parada`,
154
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => estado === '' ? m.pulse.sessaoSemEstado : m.pulse.sessaoEstadoForaDoCatalogo(estado)),
153
155
  };
154
156
  }
155
157
  /** Resposta do `claude logs` quando o job da sessao ja saiu do runtime. */
@@ -279,28 +281,22 @@ function lerPerguntaDaTela(textoLimpo) {
279
281
  * inventa opcao que a sessao nao deu.
280
282
  */
281
283
  function recomendarPara(classe, tipo, id) {
282
- if (classe === 'abandonada') {
283
- return ('nao responda: o job ja saiu. Confira o que ficou na worktree da sessao e ' +
284
- 'redespache so o resto do trabalho.');
285
- }
286
- if (classe === 'falha') {
287
- return `leia \`ork sessions logs ${id}\` e decida entre retomar, corrigir a causa ou abandonar a sessao.`;
288
- }
289
- if (classe === 'desconhecida') {
290
- return `estado fora do catalogo: confirme no \`ork sessions logs ${id}\` se a sessao esta mesmo parada.`;
291
- }
292
- switch (tipo) {
293
- case 'hitl.credencial':
294
- return (`entregue o segredo agora (\`claude attach ${id}\`) para nao segurar a entrega; ` +
295
- 'se este mesmo bloqueio ja se repetiu, troque por credencial de automacao e ele nao volta.');
296
- case 'hitl.permissao':
297
- return (`responda o prompt (\`claude attach ${id}\`); se o comando e rotineiro nesse projeto, ` +
298
- 'coloque-o na allowlist de permissoes para nao parar de novo pelo mesmo motivo.');
299
- case 'hitl.pergunta':
300
- return `abra a sessao (\`claude attach ${id}\`) e escolha entre as opcoes que ela listou.`;
301
- default:
302
- return `veja o que a sessao pede com \`ork sessions logs ${id}\` antes de responder.`;
303
- }
284
+ // RM-061 (F2b, G2): nasce em pt-BR pelo catalogo (o --json guarda) e o pulse a remonta no locale.
285
+ return (0, locale_1.textoDoCatalogo)((m) => {
286
+ const r = m.pulse.recomendacaoDoRadar;
287
+ if (classe === 'abandonada')
288
+ return r.abandonada;
289
+ if (classe === 'falha')
290
+ return r.falha(id);
291
+ if (classe === 'desconhecida')
292
+ return r.desconhecida(id);
293
+ switch (tipo) {
294
+ case 'hitl.credencial': return r.credencial(id);
295
+ case 'hitl.permissao': return r.permissao(id);
296
+ case 'hitl.pergunta': return r.pergunta(id);
297
+ default: return r.outra(id);
298
+ }
299
+ });
304
300
  }
305
301
  /** Minutos inteiros entre um epoch em ms e um carimbo ISO (nunca negativo). */
306
302
  function idadeEmMinutos(inicioMs, ateEm) {
@@ -440,7 +436,7 @@ function varrerSessoes(opcoes = {}) {
440
436
  }
441
437
  const consultaClaude = opcoes.consulta ?? (adapter.disponivel()
442
438
  ? adapter.consultarSessoes(opcoes.soDaRaiz && raiz ? raiz : undefined, true)
443
- : { ok: false, sessoes: [], detalhe: 'runtime adapter indisponivel nesta maquina (`claude` fora do PATH)' });
439
+ : { ok: false, sessoes: [], detalhe: (0, locale_1.textoDoCatalogo)((m) => m.pulse.adapterIndisponivel) });
444
440
  const consulta = { ...consultaClaude, ok: consultaClaude.ok || nativas.size > 0,
445
441
  sessoes: [...consultaClaude.sessoes, ...nativas.values()] };
446
442
  if (!consulta.ok) {
package/dist/horario.js CHANGED
@@ -22,6 +22,7 @@ exports.definirFusoDoDono = definirFusoDoDono;
22
22
  exports.fusoDoDono = fusoDoDono;
23
23
  exports.partesLocais = partesLocais;
24
24
  exports.dataLocal = dataLocal;
25
+ exports.instanteNoFuso = instanteNoFuso;
25
26
  exports.duracaoCurta = duracaoCurta;
26
27
  exports.duracaoRelativa = duracaoRelativa;
27
28
  exports.rotuloDoFuso = rotuloDoFuso;
@@ -33,6 +34,7 @@ exports.formatarPrazo = formatarPrazo;
33
34
  exports.formatarDesde = formatarDesde;
34
35
  exports.localizarTexto = localizarTexto;
35
36
  exports.localizarTextoRotulado = localizarTextoRotulado;
37
+ const locale_1 = require("./locale");
36
38
  exports.CHAVE_DO_FUSO = 'owner.timezone';
37
39
  /** Único fuso com nome próprio no rótulo; exemplo da documentação e do `ork init`. */
38
40
  exports.FUSO_DE_BRASILIA = 'America/Sao_Paulo';
@@ -153,6 +155,32 @@ function dataLocal(quando, fuso = fusoDoDono().fuso) {
153
155
  const p = partesLocais(quando, fuso);
154
156
  return `${p.ano}-${p.mes}-${p.dia}`;
155
157
  }
158
+ /** Quanto o relógio do fuso está à frente do UTC no instante, em milissegundos. */
159
+ function desvioDoFuso(ms, fuso) {
160
+ const p = partesLocais(ms, fuso);
161
+ return Date.UTC(Number(p.ano), Number(p.mes) - 1, Number(p.dia), Number(p.hora), Number(p.minuto), Number(p.segundo)) -
162
+ Math.floor(ms / 1000) * 1000;
163
+ }
164
+ /**
165
+ * RM-037 (fatia 5): o instante de um relógio num fuso IANA (mês de 1 a 12). O runtime diz a hora de
166
+ * volta da cota no fuso dele (`resets 4:40am (<fuso>)`), e lê-la no relógio desta máquina errava o
167
+ * prazo em quem roda noutro fuso. Fuso que o Intl recusa e data que não existe voltam NaN, sem chute.
168
+ * Na volta do horário de verão vale o primeiro dos dois instantes; o relógio que o salto pula cai
169
+ * depois do salto.
170
+ */
171
+ function instanteNoFuso(ano, mes, dia, hora, minuto, fuso) {
172
+ const nome = normalizarFuso(fuso);
173
+ const base = Date.UTC(ano, mes - 1, dia, hora, minuto, 0, 0);
174
+ const data = new Date(Date.UTC(ano, mes - 1, dia));
175
+ if (!nome || !Number.isFinite(base) || data.getUTCFullYear() !== ano || data.getUTCMonth() !== mes - 1 ||
176
+ data.getUTCDate() !== dia)
177
+ return NaN;
178
+ // Os desvios de um dia antes e de um dia depois cobrem os dois lados de qualquer mudança de horário.
179
+ const candidatos = [...new Set([base - 86400000, base, base + 86400000].map((ms) => base - desvioDoFuso(ms, nome)))]
180
+ .sort((a, b) => a - b);
181
+ const exatos = candidatos.filter((ms) => ms + desvioDoFuso(ms, nome) === base);
182
+ return exatos[0] ?? base - desvioDoFuso(base - 86400000, nome);
183
+ }
156
184
  // ---------------------------------------------------------------------------
157
185
  // Texto para pessoa
158
186
  // ---------------------------------------------------------------------------
@@ -167,11 +195,11 @@ function duracaoCurta(minutos) {
167
195
  }
168
196
  /** Duração até ou desde agora: abaixo de 1 min diz `menos de 1 min`, nunca `0min`. */
169
197
  function duracaoRelativa(minutos) {
170
- return minutos < 1 ? 'menos de 1 min' : duracaoCurta(minutos);
198
+ return minutos < 1 ? (0, locale_1.msg)().horario.menosDeUmMin : duracaoCurta(minutos);
171
199
  }
172
- function sigla(fuso, ms) {
200
+ function sigla(fuso, ms, locale = (0, locale_1.localeAtivo)()) {
173
201
  try {
174
- return new Intl.DateTimeFormat('pt-BR', { timeZone: fuso, timeZoneName: 'short' })
202
+ return new Intl.DateTimeFormat(locale === 'en' ? 'en-US' : 'pt-BR', { timeZone: fuso, timeZoneName: 'short' })
175
203
  .formatToParts(new Date(ms)).find(p => p.type === 'timeZoneName')?.value ?? '';
176
204
  }
177
205
  catch {
@@ -181,7 +209,7 @@ function sigla(fuso, ms) {
181
209
  /** Como o fuso aparece entre parênteses: `horário de Brasília`, `UTC`, `Europe/Lisbon, GMT+1`. */
182
210
  function rotuloDoFuso(fuso = fusoDoDono().fuso, quando) {
183
211
  if (fuso === exports.FUSO_DE_BRASILIA)
184
- return 'horário de Brasília';
212
+ return (0, locale_1.msg)().horario.brasilia;
185
213
  if (fuso === 'UTC')
186
214
  return 'UTC';
187
215
  const ms = instante(quando);
@@ -191,16 +219,22 @@ function rotuloDoFuso(fuso = fusoDoDono().fuso, quando) {
191
219
  /** Legenda de mensagem com vários horários: `Horários de Brasília.` */
192
220
  function legendaDoFuso(fuso = fusoDoDono().fuso, quando) {
193
221
  if (fuso === exports.FUSO_DE_BRASILIA)
194
- return 'Horários de Brasília.';
195
- return `Horários em ${rotuloDoFuso(fuso, quando)}.`;
222
+ return (0, locale_1.msg)().horario.legendaBrasilia;
223
+ return (0, locale_1.msg)().horario.legenda(rotuloDoFuso(fuso, quando));
196
224
  }
197
- /** `19/09 15:16`; `19/09/2025 15:16` quando o ano não é o corrente do dono. Inválido volta como veio. */
225
+ /**
226
+ * `19/09 15:16`; `19/09/2025 15:16` quando o ano não é o corrente do dono. Em `en`, sempre
227
+ * `2026-09-19 15:16` (EN6). Inválido volta como veio.
228
+ */
198
229
  function formatarDataHora(quando, opcoes = {}) {
199
230
  const ms = instante(quando ?? null);
200
231
  if (!Number.isFinite(ms))
201
232
  return quando === null || quando === undefined ? '' : String(quando);
202
233
  const fuso = opcoes.fuso ?? fusoDoDono().fuso;
203
234
  const p = partesLocais(ms, fuso), a = partesLocais(instante(opcoes.agora), fuso);
235
+ if ((opcoes.locale ?? (0, locale_1.localeAtivo)()) === 'en') {
236
+ return `${p.ano}-${p.mes}-${p.dia} ${p.hora}:${p.minuto}` + (opcoes.segundos ? `:${p.segundo}` : '');
237
+ }
204
238
  return `${p.dia}/${p.mes}${p.ano !== a.ano ? `/${p.ano}` : ''} ${p.hora}:${p.minuto}` +
205
239
  (opcoes.segundos ? `:${p.segundo}` : '');
206
240
  }
package/dist/hosts.js CHANGED
@@ -57,6 +57,7 @@ exports.ORDEM_DOS_HOSTS = exports.HOSTS = exports.MAESTRO_HOST_SURFACES = export
57
57
  exports.parseHost = parseHost;
58
58
  exports.lerRecibo = lerRecibo;
59
59
  exports.classificarDivergencia = classificarDivergencia;
60
+ exports.avisoDoOrkNoPath = avisoDoOrkNoPath;
60
61
  exports.renderizarArquivo = renderizarArquivo;
61
62
  exports.instalarAdaptador = instalarAdaptador;
62
63
  exports.desinstalarExperiencia = desinstalarExperiencia;
@@ -64,6 +65,7 @@ exports.tabelaDeHosts = tabelaDeHosts;
64
65
  exports.textoDosPitfalls = textoDosPitfalls;
65
66
  exports.textoDaInstalacao = textoDaInstalacao;
66
67
  const node_crypto_1 = require("node:crypto");
68
+ const node_child_process_1 = require("node:child_process");
67
69
  const fs = __importStar(require("node:fs"));
68
70
  exports.BRAIN_HOST_SURFACES = {
69
71
  hermes: 'cli', openclaw: 'cli', 'claude-code': 'mcp', codex: 'mcp',
@@ -246,6 +248,31 @@ function listarArquivos(dir, prefixo = '') {
246
248
  }
247
249
  return achados;
248
250
  }
251
+ function mesmoArquivo(a, b) {
252
+ try {
253
+ return fs.realpathSync(a) === fs.realpathSync(b);
254
+ }
255
+ catch {
256
+ return path.resolve(a) === path.resolve(b);
257
+ }
258
+ }
259
+ /**
260
+ * Ensaio de 03/10: com outro `ork` primeiro no PATH, a extensão segue apontando para o binário que roda o
261
+ * install, e o aviso diz as duas versões para ninguém descobrir a diferença pela extensão chamando o velho.
262
+ */
263
+ function avisoDoOrkNoPath(emExecucao, versao, env = process.env) {
264
+ const doPath = (0, util_1.noPath)('ork', env);
265
+ if (!doPath || mesmoArquivo(doPath, emExecucao))
266
+ return undefined;
267
+ let outra = 'versão desconhecida';
268
+ try {
269
+ const saida = (0, node_child_process_1.execFileSync)(doPath, ['--version'], { encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'], env });
270
+ outra = saida.trim().split('\n')[0]?.trim() || outra;
271
+ }
272
+ catch { /* o aviso sai mesmo sem a versão */ }
273
+ return `o ork do PATH (${doPath}, ${outra}) não é o que roda este install (${emExecucao}, ${versao}). ` +
274
+ `A extensão chama ${emExecucao}; para outro binário, passe --ork <caminho>.`;
275
+ }
249
276
  /** Substitui os tres placeholders. Nao ha template engine aqui de proposito. */
250
277
  function renderizarArquivo(conteudo, valores) {
251
278
  return conteudo
@@ -267,8 +294,10 @@ function instalarAdaptador(host, opcoes = {}) {
267
294
  ? path.resolve(projeto, opcoes.dir)
268
295
  : path.join(projeto, def.destinoPadrao);
269
296
  const destino = def.subdir ? path.join(base, def.subdir) : base;
270
- const orkBin = opcoes.orkBin ?? (0, util_1.noPath)('ork') ?? (0, catalogo_1.cliDoCatalogo)(catalogo);
297
+ const orkBin = opcoes.orkBin ?? opcoes.orkEmExecucao ?? (0, util_1.noPath)('ork') ?? (0, catalogo_1.cliDoCatalogo)(catalogo);
271
298
  const versao = opcoes.versao ?? versao_1.VERSAO_DO_ORK;
299
+ const avisoOrk = opcoes.orkBin === undefined && opcoes.orkEmExecucao
300
+ ? avisoDoOrkNoPath(opcoes.orkEmExecucao, versao) : undefined;
272
301
  const dirDoHost = path.join(catalogo, 'adapters', host);
273
302
  if (!fs.existsSync(dirDoHost)) {
274
303
  throw new Error(`adaptador do host ${host} nao existe em ${dirDoHost}`);
@@ -325,7 +354,7 @@ function instalarAdaptador(host, opcoes = {}) {
325
354
  let planoExperiencia = null;
326
355
  if (preferencias && hostComBloco && !avisoExperiencia) {
327
356
  try {
328
- planoExperiencia = (0, experiencia_instalacao_1.planejarExperiencia)(projeto, host, preferencias.experience ? diretorioExperiencia : null);
357
+ planoExperiencia = (0, experiencia_instalacao_1.planejarExperiencia)(projeto, host, preferencias.experience ? diretorioExperiencia : null, opcoes.locale);
329
358
  }
330
359
  catch (e) {
331
360
  const motivo = e.message;
@@ -392,6 +421,7 @@ function instalarAdaptador(host, opcoes = {}) {
392
421
  estado,
393
422
  });
394
423
  }
424
+ const removidos = sobrasDeMods(destino, recibo, arquivos);
395
425
  const conflitos = arquivos.filter((a) => a.estado === 'sobrescrito');
396
426
  /**
397
427
  * I-43 (D5): a divergencia continua sendo DETECTADA; ela deixa de BARRAR quando e
@@ -424,10 +454,12 @@ function instalarAdaptador(host, opcoes = {}) {
424
454
  ...(reciboVizinho ? { reciboVizinho } : {}),
425
455
  ok: !barrado,
426
456
  orkBin,
457
+ ...(avisoOrk ? { avisoOrk } : {}),
427
458
  pitfalls: def.pitfalls,
428
459
  ...(preferencias || avisoExperiencia ? { experiencia: { ativa: host !== 'openclaw' && !!preferencias?.experience && !avisoExperiencia,
429
460
  arquivos: planoExperiencia?.mudancas.map(m => path.relative(planoExperiencia.projeto, m.arquivo)) ?? [], skill: preferencias?.skill ?? '',
430
461
  ...(avisoExperiencia ? { aviso: avisoExperiencia } : {}) } } : {}),
462
+ ...(removidos.length ? { removidos } : {}),
431
463
  };
432
464
  if (opcoes.dryRun === true || barrado)
433
465
  return resultado;
@@ -447,6 +479,17 @@ function instalarAdaptador(host, opcoes = {}) {
447
479
  if (arquivo.executavel)
448
480
  fs.chmodSync(arquivo.destino, 0o755);
449
481
  }
482
+ // RM-059 (T0.7, A1 do CHECK): o que saiu do catalogo em `mods/` sai da copia, com a pasta que ficar vazia.
483
+ for (const relativo of removidos) {
484
+ const alvo = path.join(destino, relativo);
485
+ fs.unlinkSync(alvo);
486
+ const raizDoMod = path.join(destino, ...relativo.split('/').slice(0, 2));
487
+ for (let dir = path.dirname(alvo); dir.startsWith(raizDoMod); dir = path.dirname(dir)) {
488
+ if (fs.readdirSync(dir).length)
489
+ break;
490
+ fs.rmdirSync(dir);
491
+ }
492
+ }
450
493
  // O recibo: com ele da para saber, depois, se alguem editou a copia instalada em vez do
451
494
  // catalogo. Sem ele a instalacao e um monte de arquivo sem procedencia.
452
495
  fs.writeFileSync(path.join(destino, 'INSTALADO.json'), JSON.stringify({
@@ -467,6 +510,41 @@ function instalarAdaptador(host, opcoes = {}) {
467
510
  (0, experiencia_instalacao_1.aplicarExperiencia)(planoExperiencia);
468
511
  return resultado;
469
512
  }
513
+ /**
514
+ * RM-059 (T0.7, A1 do CHECK): os arquivos de `mods/` do recibo anterior que nao estao mais no catalogo e que a
515
+ * copia guarda como foram instalados (sha256 do recibo), os de cada mod e os comuns da raiz de `mods/` (N2 da
516
+ * rodada 2). Arquivo editado, link ou caminho fora do destino fica: o despacho continua recusando com o motivo,
517
+ * e a decisao e de quem editou.
518
+ */
519
+ function sobrasDeMods(destino, recibo, arquivos) {
520
+ if (!recibo)
521
+ return [];
522
+ const novos = new Set(arquivos.map((a) => a.relativo));
523
+ let base;
524
+ try {
525
+ base = fs.realpathSync(destino);
526
+ }
527
+ catch {
528
+ return [];
529
+ }
530
+ return recibo.arquivos.flatMap((a) => {
531
+ const rel = typeof a.arquivo === 'string' ? a.arquivo : '';
532
+ if (!/^mods\/[^/]+(?:$|\/.)/.test(rel) || novos.has(rel) || path.isAbsolute(rel) || rel.split('/').includes('..'))
533
+ return [];
534
+ const alvo = path.join(destino, rel);
535
+ const st = fs.lstatSync(alvo, { throwIfNoEntry: false });
536
+ if (!st || !st.isFile() || st.nlink !== 1)
537
+ return [];
538
+ try {
539
+ if (!fs.realpathSync(path.dirname(alvo)).startsWith(base + path.sep))
540
+ return [];
541
+ }
542
+ catch {
543
+ return [];
544
+ }
545
+ return sha256(fs.readFileSync(alvo)) === a.sha256 ? [rel] : [];
546
+ });
547
+ }
470
548
  /** Caminho real do maior ancestral existente, com o resto como está: o destino pode não existir ainda. */
471
549
  function caminhoReal(alvo) {
472
550
  let existente = path.resolve(alvo);
@@ -523,28 +601,35 @@ function textoDaInstalacao(r) {
523
601
  : r.ok
524
602
  ? `Arquivos do adaptador ${r.host} preparados.`
525
603
  : `Instalacao do adaptador ${r.host} BARRADA: ha arquivo diferente no destino.`);
604
+ // Ensaio de 03/10 (R6): a ativacao sai no comeco e de novo no fim, depois da lista de arquivos e dos
605
+ // pitfalls, para que o fim da saida diga o proximo passo.
606
+ const ativacao = [];
526
607
  if (r.ok && !r.dryRun && r.host === 'claude-code') {
527
608
  const destino = "'" + r.destino.replace(/'/g, "'\"'\"'") + "'";
528
609
  linhas.push('Uso no Claude Code ainda nao verificado por esta copia.');
529
610
  linhas.push('No diretorio deste projeto, valide e ative o plugin:');
530
- linhas.push(` claude plugin validate ${destino}`);
531
- linhas.push(` claude plugin marketplace add ${destino} --scope project`);
532
- linhas.push(' claude plugin install orkastery@orkastery --scope project');
533
- linhas.push(' claude plugin list --json');
534
- linhas.push('Depois, na sessao deste projeto: /orkastery:ork');
611
+ ativacao.push(` claude plugin validate ${destino}`);
612
+ ativacao.push(` claude plugin marketplace add ${destino} --scope project`);
613
+ ativacao.push(' claude plugin install orkastery@orkastery --scope project');
614
+ ativacao.push(' claude plugin list --json');
615
+ ativacao.push('Depois, na sessao deste projeto: /orkastery:ork');
535
616
  }
536
617
  else if (r.ok && !r.dryRun && r.host === 'codex') {
537
- linhas.push('Abra o Codex neste projeto e use $ork.');
538
- linhas.push('Descoberta e uso nativo ainda nao verificados por esta copia.');
618
+ ativacao.push('Abra o Codex neste projeto e use $ork.');
619
+ ativacao.push('Descoberta e uso nativo ainda nao verificados por esta copia.');
539
620
  }
540
621
  if (r.ok && !r.dryRun && (r.host === 'codex' || r.host === 'claude-code')) {
541
622
  const projeto = "'" + r.projeto.replace(/'/g, "'\"'\"'") + "'";
542
- linhas.push(`Prepare tambem as ferramentas do projeto: ork mcp install --project ${projeto} --host ${r.host}`);
543
- linhas.push('A configuracao MCP exige descoberta e consentimento no cliente; a copia nao concede aprovacoes.');
623
+ ativacao.push(`Prepare tambem as ferramentas do projeto: ork mcp install --project ${projeto} --host ${r.host}`);
544
624
  }
625
+ linhas.push(...ativacao);
626
+ if (ativacao.length)
627
+ linhas.push('A configuracao MCP exige descoberta e consentimento no cliente; a copia nao concede aprovacoes.');
545
628
  linhas.push(` catalogo: ${r.catalogo}`);
546
629
  linhas.push(` destino: ${r.destino}`);
547
630
  linhas.push(` ork: ${r.orkBin}`);
631
+ if (r.avisoOrk)
632
+ linhas.push(` Aviso: ${r.avisoOrk}`);
548
633
  linhas.push('');
549
634
  const novos = r.arquivos.filter((a) => a.estado === 'novo').length;
550
635
  const iguais = r.arquivos.filter((a) => a.estado === 'igual').length;
@@ -555,6 +640,9 @@ function textoDaInstalacao(r) {
555
640
  const porque = a.divergencia ? ` (${a.divergencia})` : '';
556
641
  linhas.push(` ${marca} ${a.relativo}${porque}`);
557
642
  }
643
+ // RM-059 (T0.7): arquivo de mod que saiu do catalogo sai da copia, para o despacho nao recusar o mod.
644
+ for (const rel of r.removidos ?? [])
645
+ linhas.push(` - ${rel} (saiu do catalogo${r.dryRun ? ', seria removido' : ', removido'})`);
558
646
  // I-43 (D5): o `--dir` na raiz avisa, em vez de reportar "tudo novo" com saida 0.
559
647
  if (r.reciboVizinho) {
560
648
  linhas.push('');
@@ -592,5 +680,10 @@ function textoDaInstalacao(r) {
592
680
  }
593
681
  linhas.push('');
594
682
  linhas.push(textoDosPitfalls(r.host));
683
+ if (ativacao.length) {
684
+ linhas.push('');
685
+ linhas.push(r.host === 'claude-code' ? 'Proximo passo, no diretorio deste projeto (o mesmo do comeco):' : 'Proximo passo (o mesmo do comeco):');
686
+ linhas.push(...ativacao);
687
+ }
595
688
  return linhas.join('\n');
596
689
  }