@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
@@ -42,11 +42,13 @@ var __importStar = (this && this.__importStar) || (function () {
42
42
  };
43
43
  })();
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.JANELA_CURTA_MAX_MS = exports.NOME_ADAPTER = void 0;
45
+ exports.JANELA_CURTA_MAX_MS = exports.MOD_DOS_TETOS = exports.MINIMO_DA_API_DE_MODS = exports.NOME_ADAPTER = void 0;
46
46
  exports.ambienteDoPerfil = ambienteDoPerfil;
47
47
  exports.semContextoDeDespacho = semContextoDeDespacho;
48
48
  exports.disponivel = disponivel;
49
49
  exports.versao = versao;
50
+ exports.modsParaOClaude = modsParaOClaude;
51
+ exports.agentTeamsDoDespacho = agentTeamsDoDespacho;
50
52
  exports.montarComando = montarComando;
51
53
  exports.extrairSessionId = extrairSessionId;
52
54
  exports.listarSessoes = listarSessoes;
@@ -66,12 +68,14 @@ exports.parar = parar;
66
68
  exports.pararAchada = pararAchada;
67
69
  exports.acharSessaoNasContas = acharSessaoNasContas;
68
70
  exports.ocupacaoDeContexto = ocupacaoDeContexto;
71
+ const horario_1 = require("../horario");
69
72
  const util_1 = require("../util");
70
73
  const runtime_ambiente_1 = require("../runtime-ambiente");
71
74
  const path = __importStar(require("node:path"));
72
75
  const runtime_context_1 = require("../runtime-context");
73
76
  const runtime_profiles_1 = require("../runtime-profiles");
74
77
  const mcp_grafo_1 = require("../mcp-grafo");
78
+ const locale_1 = require("../locale");
75
79
  function exec(cmd, args, cwd, timeoutMs, ambiente = (0, runtime_ambiente_1.ambienteDeAssinatura)()) {
76
80
  return (0, util_1.exec)(cmd, args, cwd, timeoutMs, ambiente);
77
81
  }
@@ -137,6 +141,63 @@ function versao() {
137
141
  }
138
142
  /** Ferramentas de arquivo negadas no PLAN: o plano sai pelo núcleo, não pelo disco. */
139
143
  const ESCRITA_DE_ARQUIVO = ['Edit', 'Write', 'NotebookEdit'];
144
+ /** O contexto do despacho conferido para o host Claude Code (D4 do RM-037: o host errado recusa antes de tudo). */
145
+ function validarDoClaude(contexto, cwd) {
146
+ if (contexto.host !== 'claude-code')
147
+ throw Error('runtime.context.invalid: host Claude esperado');
148
+ return (0, runtime_context_1.validarContextoRuntime)(contexto, cwd);
149
+ }
150
+ /** RM-059 (T0.7, D2): a API de mods saiu no Claude Code 2.1.287; nenhum mod vai a um `claude` mais velho. */
151
+ exports.MINIMO_DA_API_DE_MODS = '2.1.287';
152
+ /** `2.1.296 (Claude Code)` vira `[2, 1, 296]`; texto sem versao vira `null`. */
153
+ function versaoNumerica(texto) {
154
+ const m = /(\d+)\.(\d+)\.(\d+)/.exec(texto ?? '');
155
+ return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
156
+ }
157
+ function atende(versao, minimo) {
158
+ const i = versao.findIndex((parte, j) => parte !== minimo[j]);
159
+ return i < 0 || versao[i] > minimo[i];
160
+ }
161
+ /**
162
+ * RM-059 (T0.7, D2): os mods de fase que este `claude` carrega. O mod que pede versao mais nova fica de
163
+ * fora e o despacho segue, porque o nucleo nao depende de mod; versao ilegivel nao leva mod nenhum. Mod
164
+ * cuja dependencia ficou de fora (por versao, ou por ser so de papel `dono`) tambem fica: sem ela, ele
165
+ * carregaria pela metade na sessao de fase.
166
+ */
167
+ function modsParaOClaude(mods, versao) {
168
+ const atual = versaoNumerica(versao);
169
+ if (!atual)
170
+ return [];
171
+ const piso = versaoNumerica(exports.MINIMO_DA_API_DE_MODS);
172
+ let vao = mods.filter((m) => atende(atual, piso) && atende(atual, versaoNumerica(m.claudeCodeMinimo) ?? piso));
173
+ for (;;) {
174
+ const nomes = new Set(vao.map((m) => m.nome));
175
+ const sobram = vao.filter((m) => m.dependencias.every((d) => nomes.has(d)));
176
+ if (sobram.length === vao.length)
177
+ return vao;
178
+ vao = sobram;
179
+ }
180
+ }
181
+ /** RM-059 (T10.4): o mod que aplica os tetos de agent teams dentro da sessao de fase. */
182
+ exports.MOD_DOS_TETOS = 'ork-portao';
183
+ /**
184
+ * RM-059 (T10.4, D11 da thread ork-rm059portao): o que o despacho acrescenta ao `--settings` para agent teams no
185
+ * piloto, e so quando o contexto validado trouxe os tetos (manifesto ligado, GO no bloco) e o Portao de Tarefas esta
186
+ * entre os mods que vao de fato a sessao: sem ele, ninguem aplicaria os tetos. A sessao de fundo nao tem `tmux`, entao
187
+ * os teammates rodam no mesmo processo (`teammateMode` `in-process`).
188
+ */
189
+ function agentTeamsDoDespacho(tetos, mods) {
190
+ if (!tetos || !mods.some((m) => m.nome === exports.MOD_DOS_TETOS))
191
+ return null;
192
+ return {
193
+ env: {
194
+ CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: '1',
195
+ ORK_AGENT_TEAMS_TEAMMATES: String(tetos.teammates),
196
+ ORK_AGENT_TEAMS_CUSTO_USD: String(tetos.custo_usd),
197
+ },
198
+ teammateMode: 'in-process',
199
+ };
200
+ }
140
201
  /** Monta a linha de comando exata do despacho (usada tambem pelo `--dry-run`). */
141
202
  function montarComando(pedido) {
142
203
  const args = ['--bg', pedido.prompt, '--name', pedido.nome];
@@ -152,13 +213,17 @@ function montarComando(pedido) {
152
213
  // O `claude --bg` entrega a sessao a um processo reserva do daemon da conta, e o daemon guarda o
153
214
  // ambiente de quem o iniciou: pelo ambiente, a sessao nascia com a identidade de outro despacho.
154
215
  // Medido em 28/09/2026 (2.1.284): o `env` de `--settings` chega ao Bash da sessao e vence o herdado.
155
- const doDespacho = pedido.ambienteExtra ?? {};
156
- if (Object.keys(doDespacho).length)
157
- args.push('--settings', JSON.stringify({ env: doDespacho }));
158
- if (pedido.contextoRuntime) {
159
- if (pedido.contextoRuntime.host !== 'claude-code')
160
- throw Error('runtime.context.invalid: host Claude esperado');
161
- const contexto = (0, runtime_context_1.validarContextoRuntime)(pedido.contextoRuntime, pedido.cwd);
216
+ const contexto = pedido.contextoRuntime ? validarDoClaude(pedido.contextoRuntime, pedido.cwd) : null;
217
+ // RM-059 (T0.7): cada mod de fase conferido entra com o proprio --plugin-dir, depois do plugin do Orkastery.
218
+ const mods = !contexto || contexto.modsDeFase.length === 0 ? []
219
+ : modsParaOClaude(contexto.modsDeFase, pedido.versaoClaude !== undefined ? pedido.versaoClaude : versao());
220
+ // RM-059 (T10.4): agent teams so no piloto, com os tetos no env e o Portao na sessao; sem eles, o --settings de antes.
221
+ const teams = agentTeamsDoDespacho(contexto?.agentTeams, mods);
222
+ const doDespacho = { ...(pedido.ambienteExtra ?? {}), ...(teams ? teams.env : {}) };
223
+ if (Object.keys(doDespacho).length) {
224
+ args.push('--settings', JSON.stringify(teams ? { env: doDespacho, teammateMode: teams.teammateMode } : { env: doDespacho }));
225
+ }
226
+ if (contexto) {
162
227
  const consultas = [...CONSULTAS_MCP, ...(contexto.grafoMcp ? consultasDoGrafoMcp() : [])];
163
228
  // Somente o servidor gerado: nao mesclar MCP de outros escopos nesta sessao filha.
164
229
  const permissoes = contexto.permissoesFilho === 'worktree'
@@ -168,7 +233,7 @@ function montarComando(pedido) {
168
233
  const allow = plano ? [...consultas, 'mcp__orkastery__ork_artifact_write', 'mcp__orkastery__ork_decision_record']
169
234
  : permissoes?.allow ?? consultas;
170
235
  const deny = [...(plano ? ESCRITA_DE_ARQUIVO : []), ...(permissoes?.deny ?? [])];
171
- args.push('--plugin-dir', contexto.instalacao, '--strict-mcp-config', '--mcp-config', JSON.stringify({ mcpServers: { orkastery: contexto.servidor } }), '--allowedTools', allow.join(','));
236
+ args.push('--plugin-dir', contexto.instalacao, ...mods.flatMap((m) => ['--plugin-dir', m.dir]), '--strict-mcp-config', '--mcp-config', JSON.stringify({ mcpServers: { orkastery: contexto.servidor } }), '--allowedTools', allow.join(','));
172
237
  if (deny.length)
173
238
  args.push('--disallowedTools', deny.join(','));
174
239
  }
@@ -202,15 +267,15 @@ function listarSessoes(cwd, todas = false, ambiente = (0, runtime_ambiente_1.amb
202
267
  * falha aqui (o observador e o pulse não concluem nada dele); só o inventário o trata como fonte
203
268
  * ausente, com a correção.
204
269
  */
205
- function consultarSessoes(cwd, todas = false, ambiente = (0, runtime_ambiente_1.ambienteDeAssinatura)()) {
270
+ function consultarSessoes(cwd, todas = false, ambiente = (0, runtime_ambiente_1.ambienteDeAssinatura)(), prazoMs = 60000) {
206
271
  const args = ['agents', '--json'];
207
272
  if (todas)
208
273
  args.push('--all');
209
- const r = exec('claude', args, undefined, 60000, ambiente);
274
+ const r = exec('claude', args, undefined, prazoMs, ambiente);
210
275
  if (r.error === 'ENOENT')
211
- return { ok: false, ausente: true, sessoes: [], detalhe: 'binário `claude` fora do PATH' };
276
+ return { ok: false, ausente: true, sessoes: [], detalhe: (0, locale_1.textoDoCatalogo)((m) => m.pulse.claudeForaDoPath) };
212
277
  if (!r.ok)
213
- return { ok: false, sessoes: [], detalhe: `claude agents falhou (código ${r.code})` };
278
+ return { ok: false, sessoes: [], detalhe: (0, locale_1.textoDoCatalogo)((m) => m.pulse.claudeAgentsFalhou(r.code)) };
214
279
  let dados;
215
280
  try {
216
281
  const bruto = JSON.parse(r.stdout);
@@ -427,12 +492,25 @@ function casarDuracao(texto, agoraMs) {
427
492
  }
428
493
  const MESES = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
429
494
  /**
430
- * N5: data e hora de relogio local nas formas reais. Codex: `or try again at Sep 22nd, 2026 3:05 PM`
495
+ * RM-037 (fatia 5): o fuso IANA entre parenteses logo depois da hora (`resets 4:40am (<Area>/<Cidade>)`),
496
+ * quando o Intl o aceita. O nome vem do texto do runtime; nenhum nome literal de fuso mora aqui (I-35).
497
+ */
498
+ function fusoDito(texto, depois) {
499
+ const m = /^\s*\(([A-Za-z][A-Za-z0-9_+-]*(?:\/[A-Za-z0-9_+-]+)*)\)/.exec(texto.slice(depois));
500
+ return m ? (0, horario_1.normalizarFuso)(m[1]) : undefined;
501
+ }
502
+ /** A data do dia seguinte no calendario (mes de 1 a 12), sem passar por fuso nenhum. */
503
+ function diaSeguinte(ano, mes, dia) {
504
+ const d = new Date(Date.UTC(ano, mes - 1, dia + 1));
505
+ return [d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate()];
506
+ }
507
+ /**
508
+ * N5: data e hora de relogio nas formas reais. Codex: `or try again at Sep 22nd, 2026 3:05 PM`
431
509
  * (`%b %-d` com sufixo ordinal, `, %Y %-I:%M %p`). Claude Code, quando o reset passa de 24 h:
432
510
  * `resets Sep 22, 3pm (<nome IANA do fuso>)` e, em outro ano, `resets Sep 22, 2027, 3:05pm`. Sem ano,
433
- * vale o ano corrente, ou o seguinte quando a data ja ficou mais de um dia para tras. O fuso entre
434
- * parenteses nao entra na regex nem no calculo (a hora e lida no relogio desta maquina), e por isso
435
- * fica como placeholder: o nome literal de fuso mora so em `core/src/horario.ts` (I-35).
511
+ * vale o ano corrente, ou o seguinte quando a data ja ficou mais de um dia para tras. RM-037 (fatia 5):
512
+ * com o fuso entre parenteses, a hora e a desse fuso (`fusoDito`); sem ele, ou com um nome que o Intl
513
+ * recusa, a hora e lida no relogio desta maquina, como antes. `agoraMs` e a ancora: o instante da mensagem.
436
514
  */
437
515
  function casarData(texto, agoraMs) {
438
516
  const m = texto.match(/(?:try again at|reset[a-z]*(?:\s+at)?)\s+(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\.?\s+(\d{1,2})(?:st|nd|rd|th)?,?\s*(?:(\d{4}),?\s*)?(?:at\s+)?(\d{1,2})(?::(\d{2}))?\s*([ap]\.?m\.?)?(?![a-z0-9])/i);
@@ -449,6 +527,16 @@ function casarData(texto, agoraMs) {
449
527
  hora = 0;
450
528
  if (dia < 1 || dia > 31 || hora > 23 || minuto > 59)
451
529
  return null;
530
+ const fuso = fusoDito(texto, (m.index ?? 0) + m[0].length);
531
+ if (fuso) {
532
+ const ano = m[3] !== undefined ? Number(m[3]) : Number((0, horario_1.partesLocais)(agoraMs, fuso).ano);
533
+ let alvo = (0, horario_1.instanteNoFuso)(ano, mes + 1, dia, hora, minuto, fuso);
534
+ if (!Number.isFinite(alvo))
535
+ return null;
536
+ if (m[3] === undefined && alvo < agoraMs - 24 * 3600 * 1000)
537
+ alvo = (0, horario_1.instanteNoFuso)(ano + 1, mes + 1, dia, hora, minuto, fuso);
538
+ return Number.isFinite(alvo) ? { resetEm: new Date(alvo).toISOString(), trecho: m[0].trim() } : null;
539
+ }
452
540
  const base = new Date(agoraMs);
453
541
  const ano = m[3] !== undefined ? Number(m[3]) : base.getFullYear();
454
542
  const alvo = new Date(ano, mes, dia, hora, minuto, 0, 0);
@@ -472,7 +560,17 @@ function casarRelogio(texto, agoraMs) {
472
560
  hora = 0;
473
561
  if (hora > 23 || minuto > 59)
474
562
  return null;
475
- // Proxima ocorrencia daquela hora de relogio a partir de agora, no fuso da maquina.
563
+ // RM-037 (fatia 5): a proxima ocorrencia daquela hora depois da ancora, no fuso dito pelo runtime.
564
+ const fuso = fusoDito(texto, (m.index ?? 0) + m[0].length);
565
+ if (fuso) {
566
+ const p = (0, horario_1.partesLocais)(agoraMs, fuso);
567
+ let alvo = (0, horario_1.instanteNoFuso)(Number(p.ano), Number(p.mes), Number(p.dia), hora, minuto, fuso);
568
+ if (alvo <= agoraMs)
569
+ alvo = (0, horario_1.instanteNoFuso)(...diaSeguinte(Number(p.ano), Number(p.mes), Number(p.dia)), hora, minuto, fuso);
570
+ if (Number.isFinite(alvo))
571
+ return { resetEm: new Date(alvo).toISOString(), trecho: m[0].trim() };
572
+ }
573
+ // Sem fuso dito: a proxima ocorrencia daquela hora de relogio a partir da ancora, no fuso da maquina.
476
574
  const base = new Date(agoraMs);
477
575
  const alvo = new Date(base.getFullYear(), base.getMonth(), base.getDate(), hora, minuto, 0, 0);
478
576
  if (alvo.getTime() <= agoraMs)
@@ -48,6 +48,7 @@ exports.montarComando = montarComando;
48
48
  exports.extrairThreadId = extrairThreadId;
49
49
  exports.acharRollout = acharRollout;
50
50
  exports.parseRateLimitCodex = parseRateLimitCodex;
51
+ exports.ambienteDoFilho = ambienteDoFilho;
51
52
  exports.despachar = despachar;
52
53
  exports.logs = logs;
53
54
  const codex_controller_1 = require("./codex-controller");
@@ -174,9 +175,10 @@ function consultarRollouts(todas = false, casa = casaDoCodex()) {
174
175
  continue;
175
176
  try {
176
177
  const fd = fs.openSync(arquivo, 'r');
177
- let primeira, cauda;
178
+ let primeira, cauda, atividadeEm;
178
179
  try {
179
- const tamanho = fs.fstatSync(fd).size;
180
+ const st = fs.fstatSync(fd), tamanho = st.size;
181
+ atividadeEm = st.mtimeMs;
180
182
  const cab = Buffer.alloc(Math.min(tamanho, 65536));
181
183
  fs.readSync(fd, cab, 0, cab.length, 0);
182
184
  primeira = cab.toString('utf8').split('\n')[0];
@@ -207,7 +209,7 @@ function consultarRollouts(todas = false, casa = casaDoCodex()) {
207
209
  catch { /* primeira/última linha do recorte pode estar parcial */ }
208
210
  }
209
211
  if (todas || state !== 'completed')
210
- sessoes.push({ sessionId: p.id, cwd: p.cwd, state, kind: 'codex-rollout' });
212
+ sessoes.push({ sessionId: p.id, cwd: p.cwd, state, kind: 'codex-rollout', atividadeEm });
211
213
  }
212
214
  catch {
213
215
  falhar(arquivo, 'leitura ou metadados inválidos ou duplicados');
@@ -350,6 +352,14 @@ function parseRateLimitCodex(saida, agoraMs = Date.now()) {
350
352
  const linha = (saida ?? '').split('\n').find((l) => frase.test(l)) ?? saida;
351
353
  return { resetEm: null, fonte: 'sem-horario', trecho: linha.trim().slice(0, 200) };
352
354
  }
355
+ /**
356
+ * O ambiente do filho do despacho: o do processo, sem provider pago, com o contexto da condução POR
357
+ * CIMA. RM-052 (fatia 2, D2): a ordem importa, porque e o extra que neutraliza o `ORK_PROJETO` e o
358
+ * modo host herdados de quem despachou.
359
+ */
360
+ function ambienteDoFilho(pedido, base = process.env) {
361
+ return { ...ambienteDoDespacho(base, pedido.perfil), ...(pedido.ambienteExtra ?? {}) };
362
+ }
353
363
  /** Despacho governado exige vínculo: nenhum fallback implícito para codex exec. */
354
364
  function despachar(pedido) {
355
365
  if (!pedido.vinculo)
@@ -369,7 +379,7 @@ function despachar(pedido) {
369
379
  }
370
380
  let ambiente;
371
381
  try {
372
- ambiente = { ...ambienteDoDespacho(process.env, pedido.perfil), ...(pedido.ambienteExtra ?? {}) };
382
+ ambiente = ambienteDoFilho(pedido);
373
383
  }
374
384
  catch (e) {
375
385
  return { ok: false, comando: [], sessionId: null, verificada: false, stdout: '', stderr: '', erro: e.message };
package/dist/agents-md.js CHANGED
@@ -39,41 +39,51 @@ exports.atualizarAgentsMd = atualizarAgentsMd;
39
39
  /** Bloco de instrucoes do Orkastery em AGENTS.md, preservando todo texto humano. */
40
40
  const fs = __importStar(require("node:fs"));
41
41
  const path = __importStar(require("node:path"));
42
+ const locale_1 = require("./locale");
42
43
  const util_1 = require("./util");
43
44
  exports.INICIO_AGENTS_ORK = '<!-- orkastery:begin -->';
44
45
  exports.FIM_AGENTS_ORK = '<!-- orkastery:end -->';
45
46
  function seguro(valor) {
46
47
  return valor.replace(/[\r\n\0`]+/g, ' ').trim();
47
48
  }
48
- function blocoAgentsMd(manifesto) {
49
+ /**
50
+ * O bloco do `ork init` no `AGENTS.md`. RM-061 (F3a, D1 e D2): o texto sai na lingua pedida, pela familia `gerados`
51
+ * do catalogo; os marcadores, o titulo e as verificacoes do manifesto sao os mesmos nas duas linguas. Sem locale,
52
+ * pt-BR: so o `ork init` passa a lingua do dono.
53
+ */
54
+ function blocoAgentsMd(manifesto, locale = locale_1.LOCALE_PADRAO) {
55
+ const t = (0, locale_1.msg)(locale).gerados.agents;
49
56
  const comandos = Object.entries(manifesto.verify)
50
57
  .filter((item) => typeof item[1] === 'string' && item[1].trim() !== '')
51
58
  .map(([nome, comando]) => `- ${seguro(nome)}: \`${seguro(comando)}\``);
59
+ const modos = manifesto.conduction.allowed_modes.map(m => `#${m[0].toUpperCase()}${m.slice(1)}`).join(', ');
52
60
  return `${exports.INICIO_AGENTS_ORK}
53
61
  ## Orkastery
54
62
 
55
- Projeto: **${seguro(manifesto.project.name)}** (${seguro(manifesto.project.abbrev)}). Branch base: \`${seguro(manifesto.worktree.base_branch)}\`.
63
+ ${t.projeto(seguro(manifesto.project.name), seguro(manifesto.project.abbrev), seguro(manifesto.worktree.base_branch))}
56
64
 
57
- - Comece com \`ork doctor\`, \`ork onboarding\` e \`ork thread status <thread>\`.
58
- - Conduza o ciclo GOAL → PLAN → GO → CHECK → SHIP → MASTER pelo \`ork\`.
59
- - Respeite o modo da thread: ${manifesto.conduction.allowed_modes.map(m => `#${m[0].toUpperCase()}${m.slice(1)}`).join(', ')}.
60
- - Edite produto somente na worktree vinculada; estado em \`.orkastery/\` pertence ao núcleo.
61
- - PLAN não implementa. GO usa commits atômicos. CHECK não corrige. SHIP acontece por \`ork ship\`.
62
- - Toda alegação exige claim e comando reproduzível; self-report não é evidência.
63
- ${comandos.length ? `\nVerificações do manifesto:\n\n${comandos.join('\n')}\n` : ''}
64
- Este bloco é mantido por \`ork init\`. Edite livremente o restante do arquivo.
65
+ - ${t.comece}
66
+ - ${t.ciclo}
67
+ - ${t.modo(modos)}
68
+ - ${t.worktree}
69
+ - ${t.fases}
70
+ - ${t.claims}
71
+ - ${t.master}
72
+ ${comandos.length ? `\n${t.verificacoes}\n\n${comandos.join('\n')}\n` : ''}
73
+ ${t.rodape}
65
74
  ${exports.FIM_AGENTS_ORK}`;
66
75
  }
67
- /** Cria ou substitui somente o bloco delimitado. Marcadores ambiguos recusam sem escrita. */
68
- function atualizarAgentsMd(raiz, manifesto) {
76
+ /** Cria ou substitui somente o bloco delimitado, no `locale` pedido. Marcadores ambiguos recusam sem escrita. */
77
+ function atualizarAgentsMd(raiz, manifesto, locale = locale_1.LOCALE_PADRAO) {
69
78
  const caminho = path.join(raiz, 'AGENTS.md');
70
79
  const anterior = fs.existsSync(caminho) ? fs.readFileSync(caminho, 'utf8') : '';
71
80
  const inicios = anterior.split(exports.INICIO_AGENTS_ORK).length - 1;
72
81
  const fins = anterior.split(exports.FIM_AGENTS_ORK).length - 1;
73
82
  if (inicios !== fins || inicios > 1 || (inicios === 1 && anterior.indexOf(exports.INICIO_AGENTS_ORK) > anterior.indexOf(exports.FIM_AGENTS_ORK))) {
74
- throw new Error('AGENTS.md possui marcadores Orkastery ambiguos; corrija o bloco antes de rodar ork init');
83
+ // RM-061 (F3a): a recusa sai no locale do comando, remontada pela entrada do CLI (D14 da F2a).
84
+ throw new locale_1.ErroDoCatalogo((m) => m.gerados.agents.marcadoresAmbiguos);
75
85
  }
76
- const bloco = blocoAgentsMd(manifesto);
86
+ const bloco = blocoAgentsMd(manifesto, locale);
77
87
  const proximo = inicios === 1
78
88
  ? anterior.slice(0, anterior.indexOf(exports.INICIO_AGENTS_ORK)) + bloco + anterior.slice(anterior.indexOf(exports.FIM_AGENTS_ORK) + exports.FIM_AGENTS_ORK.length)
79
89
  : anterior === '' ? bloco + '\n' : anterior + (anterior.endsWith('\n') ? '\n' : '\n\n') + bloco + '\n';
package/dist/auditrun.js CHANGED
@@ -51,6 +51,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
51
51
  exports.PACK_DA_SUPERFICIE = exports.VERSAO_DA_RODADA = void 0;
52
52
  exports.dirAuditorias = dirAuditorias;
53
53
  exports.dirRodada = dirRodada;
54
+ exports.exigirIdDeRodada = exigirIdDeRodada;
54
55
  exports.caminhoRodada = caminhoRodada;
55
56
  exports.listarRodadas = listarRodadas;
56
57
  exports.lerRodada = lerRodada;
@@ -76,6 +77,7 @@ const adapter = __importStar(require("./adapters/claude-bg"));
76
77
  const auditoria_1 = require("./auditoria");
77
78
  const phase_1 = require("./phase");
78
79
  const policies_1 = require("./policies");
80
+ const projeto_alvo_1 = require("./projeto-alvo");
79
81
  const manifest_1 = require("./manifest");
80
82
  const ledger_1 = require("./ledger");
81
83
  const divida_1 = require("./divida");
@@ -93,7 +95,17 @@ function dirAuditorias(raiz) {
93
95
  }
94
96
  /** Diretorio de uma rodada. */
95
97
  function dirRodada(raiz, id) {
96
- return path.join(dirAuditorias(raiz), id);
98
+ return path.join(dirAuditorias(raiz), exigirIdDeRodada(id));
99
+ }
100
+ /**
101
+ * RM-047 (fronteira de confiança): o id da rodada vira nome de pasta e de relatório, e o `run.json` que o
102
+ * traz pode ter vindo do clone. Um segmento só, como o que `novoIdDeRodada` gera, sem `/` nem `..`.
103
+ */
104
+ function exigirIdDeRodada(id) {
105
+ if (typeof id !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(id) || id.includes('..')) {
106
+ throw new Error(`audit.rodada-invalida: id de rodada ${JSON.stringify(String(id)).slice(0, 60)} não é um nome simples`);
107
+ }
108
+ return id;
97
109
  }
98
110
  /** Caminho do `run.json` da rodada. */
99
111
  function caminhoRodada(raiz, id) {
@@ -372,6 +384,9 @@ function rodarAuditoria(carregado, pack, opcoes = {}) {
372
384
  cwd: raiz,
373
385
  model: base.custo.model,
374
386
  effort,
387
+ // RM-052 (fatia 2, D2, aviso A1 do CHECK): a sessao da auditoria roda na raiz do projeto e le o
388
+ // projeto pelo proprio cwd; o `ORK_PROJETO` e o modo host de quem chamou (ou do daemon) nao a seguem.
389
+ ambienteExtra: { ...projeto_alvo_1.AMBIENTE_SEM_PROJETO_HERDADO },
375
390
  });
376
391
  if (!resultado.ok || !resultado.sessionId) {
377
392
  const rodada = {
@@ -724,7 +739,7 @@ function relatorioDaRodada(carregado, rodadaId, opcoes = {}) {
724
739
  (0, util_1.gravar)(caminho, texto);
725
740
  let publicado = null;
726
741
  if (opcoes.publicar) {
727
- publicado = path.join(raiz, 'docs', 'audit', `${rodada.id}.md`);
742
+ publicado = path.join(raiz, 'docs', 'audit', `${exigirIdDeRodada(rodada.id)}.md`);
728
743
  (0, util_1.gravar)(publicado, texto);
729
744
  }
730
745
  rodada.status = 'relatada';
@@ -893,13 +908,14 @@ function abrirThreadDoAchado(carregado, achadoId, opcoes = {}) {
893
908
  };
894
909
  }
895
910
  const modo = opcoes.modo ?? manifesto.conduction.default_mode;
896
- const { thread, gravada } = (0, thread_1.novaThread)(carregado, {
911
+ const { thread, gravada, worktreePor, worktreeFalharia } = (0, thread_1.novaThread)(carregado, {
897
912
  nome: opcoes.nome ?? achado.titulo,
898
913
  modo,
899
914
  slug: opcoes.slug,
900
915
  assunto: opcoes.assunto,
901
916
  worktree: opcoes.worktree ?? null,
902
917
  criarWorktree: opcoes.criarWorktree,
918
+ origemDaWorktree: opcoes.origemDaWorktree,
903
919
  dryRun: opcoes.dryRun,
904
920
  variante: opcoes.variante ?? null,
905
921
  });
@@ -909,6 +925,8 @@ function abrirThreadDoAchado(carregado, achadoId, opcoes = {}) {
909
925
  achado,
910
926
  thread,
911
927
  pedido,
928
+ worktreePor,
929
+ worktreeFalharia,
912
930
  motivo: null,
913
931
  detalhe: 'simulacao (--dry-run): nenhuma thread e nenhum carimbo no board foram gravados',
914
932
  correcao: '',
@@ -968,6 +986,7 @@ function abrirThreadDoAchado(carregado, achadoId, opcoes = {}) {
968
986
  achado,
969
987
  thread,
970
988
  pedido,
989
+ worktreePor,
971
990
  motivo: achado.claim.estado === 'nao-verificavel' ? 'claims.unverifiable' : null,
972
991
  detalhe: achado.claim.estado === 'nao-verificavel'
973
992
  ? `AVISO: a claim ${achado.claim.id} do achado nao tem comando de verificacao (motivo tipado claims.unverifiable, que avisa e nao bloqueia)`
package/dist/board.js CHANGED
@@ -60,7 +60,7 @@ exports.textoDoBoard = textoDoBoard;
60
60
  const fs = __importStar(require("node:fs"));
61
61
  const path = __importStar(require("node:path"));
62
62
  const adapter = __importStar(require("./adapters/claude-bg"));
63
- const hitl_1 = require("./hitl");
63
+ const sessoes_contas_1 = require("./sessoes-contas");
64
64
  const leases_1 = require("./leases");
65
65
  const ledger_1 = require("./ledger");
66
66
  const manifest_1 = require("./manifest");
@@ -71,6 +71,7 @@ const util_1 = require("./util");
71
71
  const sessoes_adopt_1 = require("./sessoes-adopt");
72
72
  const horario_1 = require("./horario");
73
73
  const conducao_1 = require("./conducao");
74
+ const locale_1 = require("./locale");
74
75
  const conducao_texto_1 = require("./conducao-texto");
75
76
  /**
76
77
  * Perfis detectados no projeto.
@@ -102,28 +103,30 @@ function threadsDeTodosOsPerfis(carregado, todos = true) {
102
103
  const saida = [];
103
104
  for (const perfil of perfis) {
104
105
  const fila = (0, leases_1.lerFila)(perfil.raiz);
106
+ // RM-036 (D7): uma listagem por perfil. Por thread, a leitura do legado das worktrees se repetiria.
107
+ // I-36: a conducao (`exec:`) tem secao propria; o escalonador segue contando so os leases de escrita.
108
+ const ativos = (0, leases_1.listarLeases)(perfil.raiz).filter((l) => !(0, leases_1.expirado)(l) && (0, leases_1.tipoDoLease)(l.nome) !== 'exec');
105
109
  for (const id of (0, thread_1.listarIds)(perfil.raiz)) {
106
110
  const thread = (0, thread_1.lerThread)(perfil.raiz, id);
107
111
  saida.push({
108
112
  perfil: perfil.nome,
109
113
  raiz: perfil.raiz,
110
114
  thread,
111
- // I-36: a conducao (`exec:`) tem secao propria; o escalonador segue contando so os leases de escrita.
112
- leases: (0, leases_1.leasesDaThread)(perfil.raiz, id).filter((l) => (0, leases_1.tipoDoLease)(l.nome) !== 'exec').map((l) => l.nome),
115
+ leases: [...new Set(ativos.filter((l) => l.thread === id).map((l) => l.nome))],
113
116
  naFila: fila.filter((p) => p.thread === id),
114
117
  });
115
118
  }
116
119
  }
117
120
  return saida;
118
121
  }
119
- /** Estados de sessao do runtime, ou null quando ele nao pode ser consultado. */
120
- function estadosDeSessao() {
122
+ /**
123
+ * Estados de sessao do runtime, ou null quando ele nao pode ser consultado. RM-056 (D7): de todas
124
+ * as contas (a do processo e cada perfil do store), com o fantasma fora da vaga e o codex vivo.
125
+ */
126
+ function estadosDeSessao(raiz = null, staleMin) {
121
127
  if (!adapter.disponivel())
122
128
  return null;
123
- return new Map(adapter
124
- .listarSessoes()
125
- .filter((s) => !!s.sessionId)
126
- .map((s) => [s.sessionId, (0, hitl_1.estadoBruto)(s)]));
129
+ return (0, sessoes_contas_1.estadosNasContas)(raiz, { staleMin });
127
130
  }
128
131
  /**
129
132
  * RM-037 (rm037defeito, defeito 3): o portao de vaga do `ork phase run`. Com `max_parallel_threads: 5`,
@@ -210,7 +213,7 @@ function planejar(carregado, opcoes = {}) {
210
213
  const max = Math.max(1, manifesto.concurrency.max_parallel_threads);
211
214
  const staleMin = manifesto.concurrency.stale_after_min;
212
215
  const quando = opcoes.agora ?? (0, util_1.agora)();
213
- const estados = opcoes.estados === undefined ? estadosDeSessao() : opcoes.estados;
216
+ const estados = opcoes.estados === undefined ? estadosDeSessao(raiz, staleMin) : opcoes.estados;
214
217
  const fila = (0, leases_1.lerFila)(raiz);
215
218
  // I-36: a conducao (`exec:`) nao entra na conta de vagas: a ocupacao da sessao ja sai do ledger
216
219
  // e do runtime (`avaliarOcupacao`), e conta-la de novo mudaria o escalonador.
@@ -231,7 +234,7 @@ function planejar(carregado, opcoes = {}) {
231
234
  if (t.status === 'fechada' || (0, sessoes_adopt_1.ehRegistroDeAdocao)(t))
232
235
  continue;
233
236
  const oc = ocupacoes.get(t.id);
234
- const meus = ativos.filter((l) => l.thread === t.id).map((l) => l.nome);
237
+ const meus = [...new Set(ativos.filter((l) => l.thread === t.id).map((l) => l.nome))];
235
238
  const ocupa = oc.ocupaVaga || (meus.length > 0 && oc.classe === 'ociosa');
236
239
  if (!ocupa)
237
240
  continue;
@@ -254,7 +257,7 @@ function planejar(carregado, opcoes = {}) {
254
257
  for (const t of threads) {
255
258
  if (emAndamento.has(t.id))
256
259
  continue;
257
- const meus = ativos.filter((l) => l.thread === t.id).map((l) => l.nome);
260
+ const meus = [...new Set(ativos.filter((l) => l.thread === t.id).map((l) => l.nome))];
258
261
  if (t.status === 'fechada') {
259
262
  vagas.push({
260
263
  thread: t.id,
@@ -286,7 +289,7 @@ function planejar(carregado, opcoes = {}) {
286
289
  situacao: 'pausada',
287
290
  motivo: 'human.pending',
288
291
  detalhe: oc.detalhe,
289
- correcao: `ork gate request ${t.id}`,
292
+ correcao: oc.correcao ?? `ork gate request ${t.id}`,
290
293
  leases: meus,
291
294
  });
292
295
  continue;
@@ -314,8 +317,8 @@ function planejar(carregado, opcoes = {}) {
314
317
  situacao: 'espera',
315
318
  motivo: 'vaga.stale',
316
319
  detalhe: oc.detalhe,
317
- correcao: `redespache com ork phase run ${t.id} --fase ${t.faseAtual}, ` +
318
- `ou feche com ork master ${t.id}`,
320
+ // RM-061 (F2b, G2): o pulse mostra esta correcao nas acoes automaticas e a remonta no locale.
321
+ correcao: (0, locale_1.textoDoCatalogo)((m) => m.pulse.vagaStaleCorrecao(t.id, t.faseAtual)),
319
322
  leases: meus,
320
323
  });
321
324
  continue;
@@ -345,7 +348,7 @@ function planejar(carregado, opcoes = {}) {
345
348
  situacao: 'espera',
346
349
  motivo: 'concurrency.limite',
347
350
  detalhe: `a maquina ja tem ${ocupadas} thread(s) em andamento, o limite e ${max}`,
348
- correcao: 'espere uma thread liberar, ou suba concurrency.max_parallel_threads no orkastery.yaml',
351
+ correcao: (0, locale_1.textoDoCatalogo)((m) => m.pulse.limiteCorrecao),
349
352
  leases: [],
350
353
  });
351
354
  continue;
@@ -385,7 +388,7 @@ function devolverVagas(carregado, opcoes = {}) {
385
388
  const { raiz, manifesto } = carregado;
386
389
  const staleMin = manifesto.concurrency.stale_after_min;
387
390
  const quando = opcoes.agora ?? (0, util_1.agora)();
388
- const estados = opcoes.estados === undefined ? estadosDeSessao() : opcoes.estados;
391
+ const estados = opcoes.estados === undefined ? estadosDeSessao(raiz, staleMin) : opcoes.estados;
389
392
  const quem = opcoes.por ?? 'escalonador (ork board reap)';
390
393
  const devolvidas = [];
391
394
  for (const id of (0, thread_1.listarIds)(raiz)) {