@orkastery/cli 0.5.6 → 0.6.0

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 (385) hide show
  1. package/adapters/README.md +18 -0
  2. package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
  3. package/adapters/claude-code/README.md +37 -5
  4. package/adapters/claude-code/agents/ork-check.md +1 -0
  5. package/adapters/claude-code/agents/ork-go.md +1 -0
  6. package/adapters/claude-code/agents/ork-goal.md +1 -0
  7. package/adapters/claude-code/agents/ork-master.md +1 -0
  8. package/adapters/claude-code/agents/ork-plan.md +1 -0
  9. package/adapters/claude-code/agents/ork-ship.md +1 -0
  10. package/adapters/claude-code/hooks/hooks.json +2 -1
  11. package/adapters/claude-code/hooks/ork-guard.js +15 -1
  12. package/adapters/claude-code/hooks/ork-resposta.js +91 -0
  13. package/adapters/claude-code/hooks/ork-sensor.js +18 -2
  14. package/adapters/claude-code/hooks/quota-signal.js +14 -0
  15. package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
  16. package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
  17. package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
  18. package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
  19. package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
  20. package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
  21. package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
  22. package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
  23. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +9 -5
  24. package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
  25. package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
  26. package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
  27. package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
  28. package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
  29. package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
  30. package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
  31. package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
  32. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +1 -1
  33. package/adapters/codex/skills/ork/SKILL.md +2 -0
  34. package/adapters/hermes/README.md +64 -1
  35. package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
  36. package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
  37. package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
  38. package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
  39. package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
  40. package/adapters/hermes/hermes.plugin.json +4 -0
  41. package/adapters/hermes/hitl-ingress/__init__.py +101 -8
  42. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +2 -2
  43. package/adapters/openclaw/README.md +81 -9
  44. package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
  45. package/adapters/openclaw/dist/hitl-ingress.js +106 -9
  46. package/adapters/openclaw/dist/index.js +86 -0
  47. package/adapters/openclaw/openclaw.plugin.json +34 -4
  48. package/adapters/openclaw/package.json +2 -2
  49. package/adapters/openclaw/src/hitl-ingress.ts +103 -9
  50. package/adapters/openclaw/src/index.ts +94 -0
  51. package/assets/adapters-en/claude-code/README.md +403 -0
  52. package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
  53. package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
  54. package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
  55. package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
  56. package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
  57. package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
  58. package/assets/adapters-en/claude-code/commands/check.md +46 -0
  59. package/assets/adapters-en/claude-code/commands/go.md +46 -0
  60. package/assets/adapters-en/claude-code/commands/goal.md +55 -0
  61. package/assets/adapters-en/claude-code/commands/master.md +54 -0
  62. package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
  63. package/assets/adapters-en/claude-code/commands/ork.md +126 -0
  64. package/assets/adapters-en/claude-code/commands/plan.md +47 -0
  65. package/assets/adapters-en/claude-code/commands/ship.md +45 -0
  66. package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
  67. package/assets/adapters-en/hermes/README.md +273 -0
  68. package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
  69. package/assets/references-en/README.md +25 -0
  70. package/assets/references-en/code-review-axes.md +82 -0
  71. package/assets/references-en/definition-of-done.md +74 -0
  72. package/assets/references-en/performance-checklist.md +53 -0
  73. package/assets/references-en/security-checklist.md +101 -0
  74. package/assets/references-en/testing-patterns.md +51 -0
  75. package/assets/security-scan/defaults/.golangci.yml +2 -0
  76. package/assets/security-scan/defaults/eslint.config.mjs +11 -0
  77. package/assets/security-scan/defaults/gitleaks.toml +3 -0
  78. package/assets/security-scan/defaults/ruff.toml +1 -0
  79. package/assets/security-scan/tools-agil.json +87 -0
  80. package/assets/security-scan/tools.json +625 -0
  81. package/assets/skills-en/core/onboarding/SKILL.md +58 -0
  82. package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
  83. package/assets/skills-en/core/thread-state/SKILL.md +88 -0
  84. package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
  85. package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
  86. package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
  87. package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
  88. package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
  89. package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
  90. package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
  91. package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
  92. package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
  93. package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
  94. package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
  95. package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
  96. package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
  97. package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
  98. package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
  99. package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
  100. package/dist/adapters/claude-bg.js +118 -4
  101. package/dist/adapters/codex-controller-worker.js +12 -5
  102. package/dist/adapters/codex-events.js +16 -4
  103. package/dist/adapters/codex.js +3 -1
  104. package/dist/atualizar-branch.js +245 -0
  105. package/dist/auditoria.js +13 -11
  106. package/dist/auditrun.js +51 -46
  107. package/dist/autorizacao-duravel.js +327 -0
  108. package/dist/board.js +94 -40
  109. package/dist/branch-de-estado.js +16 -8
  110. package/dist/busca-semantica.js +7 -5
  111. package/dist/catalogo.js +2 -1
  112. package/dist/changelog-reconciliacao.js +290 -0
  113. package/dist/check-agil.js +500 -0
  114. package/dist/check-modo.js +41 -0
  115. package/dist/check-paralelo.js +183 -0
  116. package/dist/ci.js +248 -45
  117. package/dist/ciclos.js +8 -6
  118. package/dist/claim-lint.js +12 -8
  119. package/dist/claims-conferir.js +47 -39
  120. package/dist/claims.js +10 -9
  121. package/dist/company-brain-client.js +10 -3
  122. package/dist/company-brain-migration.js +11 -5
  123. package/dist/conducao-batida.js +759 -0
  124. package/dist/conducao-sentinela.js +25 -8
  125. package/dist/conducao.js +84 -29
  126. package/dist/conhecimento-consulta.js +270 -0
  127. package/dist/conhecimento.js +111 -87
  128. package/dist/conta-esgotada.js +127 -0
  129. package/dist/dado-privado.js +816 -0
  130. package/dist/decisao-autonoma.js +5 -4
  131. package/dist/demo.js +14 -12
  132. package/dist/dependencias-da-worktree.js +25 -0
  133. package/dist/divida.js +38 -36
  134. package/dist/docs.js +81 -74
  135. package/dist/doctor-forja.js +345 -0
  136. package/dist/doctor-pulse-cron.js +113 -1
  137. package/dist/doctor.js +164 -6
  138. package/dist/dsn-da-memoria.js +417 -0
  139. package/dist/entrega-por-mod.js +503 -0
  140. package/dist/entrega-pr.js +143 -43
  141. package/dist/esgotamentos.js +13 -11
  142. package/dist/estado-thread.js +21 -18
  143. package/dist/evalrunner.js +35 -32
  144. package/dist/fabrica-batida.js +34 -21
  145. package/dist/fabrica-estado.js +13 -10
  146. package/dist/fix.js +21 -19
  147. package/dist/forja/adaptador.js +6 -0
  148. package/dist/forja/ambiente-de-ci.js +27 -0
  149. package/dist/forja/api.js +256 -0
  150. package/dist/forja/cache.js +89 -0
  151. package/dist/forja/cli.js +60 -0
  152. package/dist/forja/contrato.js +9 -0
  153. package/dist/forja/endereco.js +43 -0
  154. package/dist/forja/estado.js +22 -0
  155. package/dist/forja/executor.js +73 -0
  156. package/dist/forja/github/ci.js +95 -0
  157. package/dist/forja/github/dono-da-rede.js +18 -0
  158. package/dist/forja/github/metadados.js +15 -0
  159. package/dist/forja/github/pedidos.js +200 -0
  160. package/dist/forja/gitlab/ci.js +141 -0
  161. package/dist/forja/gitlab/consultas.js +59 -0
  162. package/dist/forja/gitlab/dono-da-rede.js +43 -0
  163. package/dist/forja/gitlab/metadados.js +15 -0
  164. package/dist/forja/gitlab/pedidos-abertos.js +158 -0
  165. package/dist/forja/gitlab/pedidos.js +141 -0
  166. package/dist/forja/produtor.js +32 -0
  167. package/dist/forja/registro.js +31 -0
  168. package/dist/forja/resolver.js +121 -0
  169. package/dist/forja/texto.js +13 -0
  170. package/dist/forja/versao.js +71 -0
  171. package/dist/forja.js +123 -80
  172. package/dist/handoff.js +23 -13
  173. package/dist/hitl-contract.js +46 -43
  174. package/dist/hitl-curto.js +37 -25
  175. package/dist/hitl-gates.js +13 -11
  176. package/dist/hitl-local-receipt.js +51 -0
  177. package/dist/hitl-local.js +11 -2
  178. package/dist/hitl-lock.js +5 -11
  179. package/dist/hitl-public-receipt.js +11 -0
  180. package/dist/hitl-resumo.js +44 -1
  181. package/dist/hitl-sessions.js +62 -9
  182. package/dist/hitl-texto-livre.js +7 -4
  183. package/dist/hitl.js +34 -31
  184. package/dist/horario.js +16 -0
  185. package/dist/hosts.js +104 -134
  186. package/dist/index.js +848 -548
  187. package/dist/indice-vetorial.js +14 -12
  188. package/dist/init.js +11 -2
  189. package/dist/integracoes-locais.js +2 -0
  190. package/dist/intelligence-graph-cli.js +123 -69
  191. package/dist/intelligence-graph-query.js +37 -22
  192. package/dist/leases.js +19 -18
  193. package/dist/ledger-stats.js +17 -16
  194. package/dist/ledger.js +31 -1
  195. package/dist/licoes.js +12 -11
  196. package/dist/locale-accounts.js +220 -0
  197. package/dist/locale-adapter.js +291 -0
  198. package/dist/locale-ajuda.js +76 -4
  199. package/dist/locale-audit.js +199 -0
  200. package/dist/locale-claims.js +213 -0
  201. package/dist/locale-conducao.js +138 -0
  202. package/dist/locale-conhecimento.js +181 -0
  203. package/dist/locale-decisao.js +205 -0
  204. package/dist/locale-docs.js +230 -0
  205. package/dist/locale-estado.js +101 -0
  206. package/dist/locale-forja.js +290 -0
  207. package/dist/locale-gerados.js +5 -0
  208. package/dist/locale-grafo.js +129 -0
  209. package/dist/locale-master.js +83 -0
  210. package/dist/locale-network.js +524 -0
  211. package/dist/locale-operacao-restante.js +931 -0
  212. package/dist/locale-projetos.js +100 -0
  213. package/dist/locale-prompts.js +194 -0
  214. package/dist/locale-pulse.js +140 -2
  215. package/dist/locale-reservas.js +87 -0
  216. package/dist/locale-retry.js +145 -6
  217. package/dist/locale-security-scan.js +69 -0
  218. package/dist/locale-setup.js +192 -0
  219. package/dist/locale-ship.js +169 -66
  220. package/dist/locale-thread.js +149 -5
  221. package/dist/locale-verify.js +80 -4
  222. package/dist/locale-worktree.js +246 -0
  223. package/dist/locale.js +553 -9
  224. package/dist/maestro-runtime.js +22 -3
  225. package/dist/manifest.js +287 -11
  226. package/dist/maquina-ociosa.js +211 -0
  227. package/dist/maquina.js +10 -5
  228. package/dist/master-nota-local.js +200 -0
  229. package/dist/master-nota.js +10 -2
  230. package/dist/master.js +118 -41
  231. package/dist/mcp-conhecimento.js +52 -0
  232. package/dist/mcp-experiencia.js +26 -5
  233. package/dist/mcp-install.js +73 -8
  234. package/dist/mcp-noctum.js +101 -0
  235. package/dist/mcp-server.js +82 -14
  236. package/dist/mcp-ship-transporte.js +977 -0
  237. package/dist/mcp-ship.js +68 -24
  238. package/dist/mcp-transportes.js +17 -0
  239. package/dist/memoria.js +63 -58
  240. package/dist/modos-migracao.js +8 -6
  241. package/dist/modos.js +17 -18
  242. package/dist/network-roadmap.js +85 -49
  243. package/dist/noctum-aceite.js +789 -0
  244. package/dist/noctum-arco.js +540 -33
  245. package/dist/noctum-capacidade.js +3 -3
  246. package/dist/noctum-changelog.js +399 -0
  247. package/dist/noctum-cli.js +482 -0
  248. package/dist/noctum-coordenacao.js +1225 -0
  249. package/dist/noctum-entrega.js +1169 -0
  250. package/dist/noctum-envelope.js +252 -16
  251. package/dist/noctum-execucao.js +95 -23
  252. package/dist/noctum-fechamento.js +405 -0
  253. package/dist/noctum-fila.js +43 -9
  254. package/dist/noctum-guarda.js +256 -0
  255. package/dist/noctum-integracao.js +507 -0
  256. package/dist/noctum-maquinas.js +383 -0
  257. package/dist/noctum-medicao.js +450 -0
  258. package/dist/noctum-modo.js +362 -0
  259. package/dist/noctum-pergunta-canal.js +96 -0
  260. package/dist/noctum-pergunta.js +115 -0
  261. package/dist/noctum-provas.js +838 -0
  262. package/dist/noctum-reconciliacao.js +591 -0
  263. package/dist/noctum-registro.js +215 -0
  264. package/dist/noctum-relatorio.js +827 -0
  265. package/dist/noctum-resposta.js +207 -0
  266. package/dist/noctum-sessoes-em-voo.js +93 -0
  267. package/dist/noctum-supervisao.js +649 -0
  268. package/dist/noctum-terminal.js +459 -0
  269. package/dist/noctum-transporte.js +655 -0
  270. package/dist/noctum-vigia.js +639 -0
  271. package/dist/ocupacao.js +3 -1
  272. package/dist/onboarding.js +16 -5
  273. package/dist/orkmind.js +39 -23
  274. package/dist/orquestracao.js +31 -35
  275. package/dist/parado-no-condutor.js +146 -124
  276. package/dist/phase.js +53 -27
  277. package/dist/policies.js +33 -0
  278. package/dist/postura-local.js +4 -3
  279. package/dist/procedencia.js +9 -14
  280. package/dist/projeto-alvo.js +59 -20
  281. package/dist/prompts.js +136 -42
  282. package/dist/prova-minima.js +5 -6
  283. package/dist/pulse-cadencia.js +5 -4
  284. package/dist/pulse-consentimento.js +53 -1
  285. package/dist/pulse-delivery.js +143 -27
  286. package/dist/pulse-resposta.js +368 -4
  287. package/dist/pulse.js +136 -3
  288. package/dist/ratelimit.js +12 -4
  289. package/dist/recall.js +14 -13
  290. package/dist/rede-adesao.js +13 -8
  291. package/dist/rede-forja.js +108 -24
  292. package/dist/rede-status.js +63 -45
  293. package/dist/rede.js +86 -46
  294. package/dist/retomada-checkpoint.js +101 -0
  295. package/dist/retry.js +228 -73
  296. package/dist/roadmap-reservas.js +32 -32
  297. package/dist/runtime-ambiente.js +5 -0
  298. package/dist/runtime-context.js +117 -43
  299. package/dist/runtime-escada.js +423 -0
  300. package/dist/runtime-profiles.js +103 -46
  301. package/dist/saida-segura.js +3 -2
  302. package/dist/security-scan/agil.js +355 -0
  303. package/dist/security-scan/cli.js +76 -0
  304. package/dist/security-scan/compare.js +149 -0
  305. package/dist/security-scan/config.js +93 -0
  306. package/dist/security-scan/detect.js +97 -0
  307. package/dist/security-scan/executor.js +188 -0
  308. package/dist/security-scan/guard.js +180 -0
  309. package/dist/security-scan/imagem-de-lint.js +96 -0
  310. package/dist/security-scan/normalize/actionlint.js +12 -0
  311. package/dist/security-scan/normalize/eslint.js +12 -0
  312. package/dist/security-scan/normalize/gitleaks.js +13 -0
  313. package/dist/security-scan/normalize/golangci-lint.js +13 -0
  314. package/dist/security-scan/normalize/govulncheck.js +36 -0
  315. package/dist/security-scan/normalize/index.js +25 -0
  316. package/dist/security-scan/normalize/npm-audit.js +30 -0
  317. package/dist/security-scan/normalize/osv-scanner.js +32 -0
  318. package/dist/security-scan/normalize/oxlint.js +51 -0
  319. package/dist/security-scan/normalize/pip-audit.js +16 -0
  320. package/dist/security-scan/normalize/ruff.js +12 -0
  321. package/dist/security-scan/normalize/semgrep.js +20 -0
  322. package/dist/security-scan/normalize/trivy.js +33 -0
  323. package/dist/security-scan/normalize/util.js +204 -0
  324. package/dist/security-scan/normalize/zizmor.js +19 -0
  325. package/dist/security-scan/report.js +156 -0
  326. package/dist/security-scan/run.js +448 -0
  327. package/dist/security-scan/tools.js +62 -0
  328. package/dist/security-scan/trabalhador.js +74 -0
  329. package/dist/security-scan/types.js +15 -0
  330. package/dist/session-events.js +19 -2
  331. package/dist/session-watcher-claude.js +74 -19
  332. package/dist/session-watcher.js +156 -10
  333. package/dist/sessoes-contas.js +9 -0
  334. package/dist/sessoes-inventario.js +1 -1
  335. package/dist/sessoes.js +25 -23
  336. package/dist/setup.js +59 -58
  337. package/dist/ship-publicar.js +263 -92
  338. package/dist/ship.js +160 -17
  339. package/dist/superficie.js +14 -11
  340. package/dist/thread-close.js +9 -9
  341. package/dist/thread.js +121 -18
  342. package/dist/tokens.js +15 -11
  343. package/dist/trabalho-thread.js +297 -0
  344. package/dist/transporte-do-canal.js +189 -0
  345. package/dist/types.js +12 -1
  346. package/dist/util.js +5 -2
  347. package/dist/varredura-acoes.js +507 -0
  348. package/dist/verify.js +472 -29
  349. package/dist/worktree-local.js +12 -10
  350. package/dist/worktree.js +81 -85
  351. package/eval/casos/check-quality.json +77 -0
  352. package/eval/casos/security-auditor.json +148 -0
  353. package/eval/casos/security-remediation.json +161 -0
  354. package/eval/fixtures/security-scan/README.md +8 -0
  355. package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
  356. package/eval/fixtures/security-scan/go/Dockerfile +4 -0
  357. package/eval/fixtures/security-scan/go/README.md +4 -0
  358. package/eval/fixtures/security-scan/go/config.go +4 -0
  359. package/eval/fixtures/security-scan/go/go.mod +5 -0
  360. package/eval/fixtures/security-scan/go/go.sum +2 -0
  361. package/eval/fixtures/security-scan/go/main.go +31 -0
  362. package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
  363. package/eval/fixtures/security-scan/js/Dockerfile +3 -0
  364. package/eval/fixtures/security-scan/js/README.md +4 -0
  365. package/eval/fixtures/security-scan/js/package-lock.json +844 -0
  366. package/eval/fixtures/security-scan/js/package.json +10 -0
  367. package/eval/fixtures/security-scan/js/src/config.js +4 -0
  368. package/eval/fixtures/security-scan/js/src/server.js +17 -0
  369. package/eval/fixtures/security-scan/js/src/util.ts +4 -0
  370. package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
  371. package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
  372. package/eval/fixtures/security-scan/python/Dockerfile +3 -0
  373. package/eval/fixtures/security-scan/python/README.md +4 -0
  374. package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
  375. package/eval/fixtures/security-scan/python/app/config.py +2 -0
  376. package/eval/fixtures/security-scan/python/app/main.py +19 -0
  377. package/eval/fixtures/security-scan/python/requirements.txt +1 -0
  378. package/package.json +9 -4
  379. package/references/security-checklist.md +3 -3
  380. package/skills/README.md +1 -0
  381. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  382. package/skills/phases/check-quality/SKILL.md +16 -0
  383. package/skills/phases/go-implementation/SKILL.md +6 -0
  384. package/skills/phases/security-remediation/SKILL.md +70 -0
  385. package/skills/reviewers/security-auditor/SKILL.md +25 -0
@@ -33,11 +33,13 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.THREAD_REMOVIDA = exports.ARTEFATO_DA_FASE = exports.INTERVALO_WATCH_CLAUDE_MS = void 0;
36
+ exports.THREAD_REMOVIDA = exports.ARTEFATO_DA_FASE = exports.OCIOSA_DEPOIS_DO_STOP_MS = exports.INTERVALO_WATCH_CLAUDE_MS = void 0;
37
37
  exports.normalizarNativo = normalizarNativo;
38
38
  exports.stopCorrelacionado = stopCorrelacionado;
39
+ exports.trabalhoPendenteDoStop = trabalhoPendenteDoStop;
39
40
  exports.bloqueioPendente = bloqueioPendente;
40
41
  exports.classificarSessaoClaude = classificarSessaoClaude;
42
+ exports.arquivoDaTranscricao = arquivoDaTranscricao;
41
43
  exports.ultimoErroDeApi = ultimoErroDeApi;
42
44
  exports.falhaDeContaDaTranscricao = falhaDeContaDaTranscricao;
43
45
  exports.comFalhaDeConta = comFalhaDeConta;
@@ -77,8 +79,19 @@ const thread_1 = require("./thread");
77
79
  const util_1 = require("./util");
78
80
  const procedencia_1 = require("./procedencia");
79
81
  const hitl_1 = require("./hitl");
82
+ const conta_esgotada_1 = require("./conta-esgotada");
80
83
  /** Uma consulta nativa custa cerca de 0,3 s; cinco segundos mantém o custo abaixo de 10%. */
81
84
  exports.INTERVALO_WATCH_CLAUDE_MS = 5000;
85
+ /**
86
+ * RM-037 (defeitos de 19 e 20/10/2026, defeito 4): quanto a sessão fica ociosa no prompt (`working` com `status: idle`)
87
+ * depois do Stop correlacionado até o observador tomar o turno por encerrado. O Claude Code mantém `working` a sessão cuja
88
+ * resposta final ele lê como "ainda há passo" e só a encerra (`done`) depois de 60 min ociosa (`bg retire <id>:
89
+ * idle-prompt, idle 60m` no log do daemon, medido em 20/10/2026), e nesse tempo a sessão segurava a condução. O `status`
90
+ * ocioso não basta (CHECK 3 da ork-rm037defeit2, medido no Claude Code 2.1.304): com só um despertar agendado a sessão
91
+ * aparece `idle` e volta a escrever quando ele dispara. Só conta a ociosidade depois do Stop que disse zero tarefa em
92
+ * segundo plano e zero despertar (`trabalhoPendenteDoStop`).
93
+ */
94
+ exports.OCIOSA_DEPOIS_DO_STOP_MS = 5 * 60 * 1000;
82
95
  const LIMITE_EVIDENCIA_BYTES = 4096;
83
96
  /** D15 (5): teto dos textos nativos (`state`, `status`, `id`, `kind`) e do erro do diagnóstico. */
84
97
  const LIMITE_TEXTO_NATIVO = 64;
@@ -129,6 +142,22 @@ function stopCorrelacionado(eventos, sessao) {
129
142
  return null;
130
143
  return correlacionados[ultimo];
131
144
  }
145
+ /**
146
+ * RM-037 (CHECK 3 da ork-rm037defeit2): o trabalho que o Stop disse que ainda vai acordar a sessão, ou `null` quando ele
147
+ * gravou as duas contagens (`backgroundTasks` e `sessionCrons`, da entrada do hook) e as duas são zero. No Claude Code
148
+ * 2.1.304 o `status` fica `shell` com Bash em segundo plano e `idle` com despertar agendado (`CronCreate`,
149
+ * `ScheduleWakeup`, `/loop`) ou tarefa MCP. O Stop sem as contagens (hook ou runtime de antes) não prova que nada vai
150
+ * voltar: a sessão segue esperando, como antes desta regra, o `done` do runtime.
151
+ */
152
+ function trabalhoPendenteDoStop(stop) {
153
+ const { backgroundTasks: tarefas, sessionCrons: despertares } = stop;
154
+ if (tarefas === 0 && despertares === 0)
155
+ return null;
156
+ if (typeof tarefas !== 'number' || typeof despertares !== 'number') {
157
+ return 'o Stop não disse se há tarefa em segundo plano ou despertar agendado (sem background_tasks e session_crons)';
158
+ }
159
+ return `o Stop registrou ${tarefas} tarefa(s) em segundo plano e ${despertares} despertar(es) agendado(s)`;
160
+ }
132
161
  /**
133
162
  * O último entre bloqueio, destravamento e Stop da sessão, depois do despacho, é bloqueio?
134
163
  * O Stop resolve o bloqueio anterior: o turno só termina depois que o prompt de permissão
@@ -201,6 +230,8 @@ function classificarSessaoClaude(e) {
201
230
  delete cursor.mortoDesde;
202
231
  if (estado !== 'blocked')
203
232
  delete cursor.bloqueadoDesde;
233
+ if (estado !== 'working')
234
+ delete cursor.ociosaDesde;
204
235
  if (['done', 'failed', 'stopped', 'working', 'blocked'].includes(estado ?? ''))
205
236
  delete cursor.desconhecidoDesde;
206
237
  switch (estado) {
@@ -248,6 +279,27 @@ function classificarSessaoClaude(e) {
248
279
  return esperaHumana();
249
280
  }
250
281
  delete cursor.bloqueadoDesde;
282
+ // RM-037 (defeito 4 de 19 e 20/10/2026): turno encerrado pelo Stop e a sessão ociosa no prompt (`status: idle`). O
283
+ // runtime só a encerra depois de 60 min; passado `OCIOSA_DEPOIS_DO_STOP_MS` sem atividade, vale a prova do `ork`, como
284
+ // no `done`, mas só depois do Stop que disse zero tarefa em segundo plano e zero despertar agendado (CHECK 3): o
285
+ // despertar deixa a sessão `idle` até disparar. O prazo conta da primeira leitura ociosa e nunca de antes do Stop: a
286
+ // sessão que voltou e parou de novo recomeça a contagem.
287
+ if (estado === 'working' && r.status === 'idle' && stop && !bloqueioPendente(e.eventos, e.sessao)) {
288
+ const pendente = trabalhoPendenteDoStop(stop);
289
+ if (pendente !== null) {
290
+ delete cursor.ociosaDesde;
291
+ return espera(`turno encerrado pelo Stop com a sessão ociosa no prompt (working/idle), mas ${pendente}; ` +
292
+ 'a ociosidade não encerra o turno');
293
+ }
294
+ cursor.ociosaDesde ??= agora;
295
+ const desde = Math.max(cursor.ociosaDesde, Date.parse(stop.ts) || 0);
296
+ if (agora - desde < exports.OCIOSA_DEPOIS_DO_STOP_MS) {
297
+ return espera('turno encerrado pelo Stop com a sessão ociosa no prompt (working/idle); aguardando o prazo da ociosidade');
298
+ }
299
+ return concluir(`Stop correlacionado e sessão ociosa no prompt (working/idle) por ${exports.OCIOSA_DEPOIS_DO_STOP_MS / 60000} min, ` +
300
+ 'sem tarefa em segundo plano nem despertar agendado no Stop', false);
301
+ }
302
+ delete cursor.ociosaDesde;
251
303
  return espera(estado === 'blocked' ? 'sessão bloqueada à espera humana' : 'sessão trabalhando');
252
304
  }
253
305
  default:
@@ -271,7 +323,10 @@ function textoDoErroDeApi(e) {
271
323
  return (0, hitl_1.redigirSegredos)([codigo, textos.filter(Boolean).join(' ')].filter(Boolean).join(': ')).slice(0, 4096);
272
324
  }
273
325
  const UUID = /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i;
274
- /** A transcricao da sessao no diretorio do perfil (ou no implicito, sem perfil); `null` com sessao que nao e uuid. */
326
+ /**
327
+ * A transcricao da sessao no diretorio do perfil (ou no implicito, sem perfil); `null` com sessao que nao e uuid.
328
+ * RM-059 (F9): o Mensageiro de Sessoes (`entrega-por-mod.ts`) acha nela o turno em que a sessao parou.
329
+ */
275
330
  function arquivoDaTranscricao(perfil, cwd, sessionId) {
276
331
  if (!UUID.test(sessionId))
277
332
  return null;
@@ -337,15 +392,6 @@ function falhaDeContaDaTranscricao(perfil, cwd, sessionId, agoraMs = Date.now())
337
392
  function falhaDoErro(erro, agoraMs) {
338
393
  return erro ? (0, claude_bg_1.parseFalhaDeConta)(erro.texto, erro.em ? Date.parse(erro.em) : agoraMs) : null;
339
394
  }
340
- /**
341
- * RM-037 (fatia 5): a cota vista com a sessao viva. Em 02/10/2026 as sessoes de uma conta pararam as 06:00Z no
342
- * limite de gasto ("your session limit resets 4:40am (<fuso>)"), sem Stop e com o processo vivo por mais uma
343
- * hora; o perfil so saiu do rodizio as 07:15Z, quando o processo morreu, e o redespacho das 06:14Z caiu na mesma
344
- * conta. Aqui, a cada volta com a transcricao maior que na anterior, o ultimo erro de API depois do despacho passa
345
- * pelo criterio unico da D16; esgotamento com prazo futuro marca o perfil ate a hora dita (ou a janela padrao
346
- * contada da mensagem) e grava `runtime_quota_detected` uma vez por erro. A fase nao fecha e a conducao nao muda:
347
- * a sessao continua viva, e o fecho segue o caminho de sempre, sem marcar de novo o mesmo erro.
348
- */
349
395
  function cotaAoVivo(ctx, perfil, cwd, cursor, erroDaTranscricao, gravar) {
350
396
  const { sessao, dir } = ctx;
351
397
  const arquivo = arquivoDaTranscricao(perfil, cwd, sessao.sessionId);
@@ -356,22 +402,22 @@ function cotaAoVivo(ctx, perfil, cwd, cursor, erroDaTranscricao, gravar) {
356
402
  tamanho = st?.isFile() ? st.size : NaN;
357
403
  }
358
404
  catch {
359
- return;
405
+ return null;
360
406
  }
361
407
  if (!Number.isFinite(tamanho) || cursor.transcricaoBytes === tamanho)
362
- return;
408
+ return null;
363
409
  cursor.transcricaoBytes = tamanho;
364
410
  const erro = erroDaTranscricao();
365
411
  const erroMs = erro?.em ? Date.parse(erro.em) : NaN;
366
412
  // Linha sem instante, ou de antes deste despacho (sessao retomada), nao prova que a cota e deste turno.
367
413
  if (!erro || !Number.isFinite(erroMs) || erroMs < Date.parse(sessao.despachadaEm))
368
- return;
414
+ return null;
369
415
  const falha = falhaDoErro(erro, ctx.agoraMs);
370
416
  if (falha?.motivo !== 'runtime.quota-exhausted' || !ctx.carregado)
371
- return;
417
+ return null;
372
418
  const esgotadoAte = (0, ratelimit_1.prazoDaCotaVista)(ctx.carregado.manifesto, falha, erroMs, ctx.agoraMs);
373
419
  if (!esgotadoAte)
374
- return;
420
+ return null;
375
421
  // A chave do erro: o uuid da linha ou, sem ele, o instante e o trecho (dado de maquina, nunca texto).
376
422
  const sensorEventId = (0, node_crypto_1.createHash)('sha256')
377
423
  .update(JSON.stringify([sessao.sessionId, sessao.despachadaEm, erro.uuid ?? [erro.em, falha.trecho]])).digest('hex');
@@ -394,6 +440,7 @@ function cotaAoVivo(ctx, perfil, cwd, cursor, erroDaTranscricao, gravar) {
394
440
  esgotadoAte, trecho: falha.trecho.replace(/\p{Cc}/gu, ' '), perfil: perfil ? { id: perfil.id, runtime: perfil.runtime } : null,
395
441
  perfilMarcado: !!perfil, origem: 'sessions.watch' });
396
442
  });
443
+ return { falha, esgotadoAte, erroEm: erro.em };
397
444
  }
398
445
  /**
399
446
  * I-33 (D11): precedencia entre a prova da I-34 e a falha de conta. Com Stop correlacionado vale
@@ -472,11 +519,11 @@ function saidaDoArtefato(raiz, threadId, sessao, fonte, eventos) {
472
519
  : atual.mtimeMs !== null && atual.mtimeMs >= Date.parse(sessao.despachadaEm);
473
520
  return { arquivo, produzido, sha256: atual.sha256, sha256Base: base?.sha256 ?? null, texto: atual.texto };
474
521
  }
475
- /** Exatamente um veredito legível numa linha `Veredito: ...` (PASSOU, PRECISA DE MUDANCA ou BLOQUEADO). */
522
+ /** Exatamente um veredito legível numa linha `Veredito: ...`, incluindo a reprovação curta do prompt de CHECK. */
476
523
  function vereditoDoParecer(texto) {
477
524
  const achados = new Set();
478
525
  for (const linha of texto.split('\n')) {
479
- const m = /^[#>*_`\s-]*veredito[*_`\s]*:[*_`\s]*(passou|precisa de mudan[cç]a|bloqueado)(?![\p{L}\p{N}])/iu.exec(linha);
526
+ const m = /^[#>*_`\s-]*veredito[*_`\s]*:[*_`\s]*(passou|reprovou|precisa de mudan[cç]a|bloqueado)(?![\p{L}\p{N}])/iu.exec(linha);
480
527
  if (m)
481
528
  achados.add(m[1].toUpperCase().replace('Ç', 'C'));
482
529
  }
@@ -698,9 +745,17 @@ function observarClaudeSobLock(ctx) {
698
745
  }
699
746
  if (!c.terminal) {
700
747
  const lidos = cursor.transcricaoBytes;
701
- cotaAoVivo(ctx, perfil, fonte.cwd, cursor, erroDaTranscricao, gravar);
748
+ const cota = cotaAoVivo(ctx, perfil, fonte.cwd, cursor, erroDaTranscricao, gravar);
702
749
  if (cursor.transcricaoBytes !== lidos)
703
750
  (0, codex_runner_1.gravarAtomico)(arquivoCursor, cursor);
751
+ if (cota && perfil && ctx.carregado) {
752
+ (0, conta_esgotada_1.reconciliarContaEsgotada)({ raiz, perfil, falha: cota.falha, esgotadoAte: cota.esgotadoAte,
753
+ erroEm: cota.erroEm, agoraMs: ctx.agoraMs });
754
+ const terminal = (0, ledger_1.lerLedger)(dir).find(e => e.tipo === 'phase_result' && e.sessionId === sessao.sessionId &&
755
+ e.motivo === 'runtime.quota-exhausted');
756
+ if (terminal)
757
+ return { ...base, concluido: true, classificacao: 'gate_blocked' };
758
+ }
704
759
  }
705
760
  if (!c.terminal && c.inconclusivo)
706
761
  return (0, session_events_1.comLockDeSessao)(dir, () => {
@@ -35,7 +35,10 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.BLOCO_WATCH_BYTES = exports.MAX_FALHAS_WATCH = exports.MAX_ESPERA_ERRO_WATCH_MS = exports.INTERVALO_WATCH_MS = exports.LIMITE_MORTE_MS = void 0;
37
37
  exports.observarSessao = observarSessao;
38
+ exports.reconciliarSessaoSemWatcher = reconciliarSessaoSemWatcher;
39
+ exports.validarRegistroWatcher = validarRegistroWatcher;
38
40
  exports.validarFonteWatcher = validarFonteWatcher;
41
+ exports.prepararFonteWatcher = prepararFonteWatcher;
39
42
  exports.iniciarWatcher = iniciarWatcher;
40
43
  exports.acompanharSessao = acompanharSessao;
41
44
  /** D6: observador restrito a uma sessão, cursor canônico e resultados idempotentes. */
@@ -55,6 +58,8 @@ const codex_controller_sensor_1 = require("./adapters/codex-controller-sensor");
55
58
  const retry_1 = require("./retry");
56
59
  const ratelimit_1 = require("./ratelimit");
57
60
  const session_watcher_claude_1 = require("./session-watcher-claude");
61
+ const conta_esgotada_1 = require("./conta-esgotada");
62
+ const trabalho_thread_1 = require("./trabalho-thread");
58
63
  /** Falhas operacionais e bloqueios sem retry automático não alegam conclusão do produto. */
59
64
  function bloqueioPreservado(terminal) {
60
65
  return terminal.classificacao === 'gate_blocked' && terminal.motivo !== null &&
@@ -325,6 +330,9 @@ function diagnosticoWatcher(e) {
325
330
  erro: 'estado canônico temporariamente sem vínculo; auditoria será repetida', transitorio: true };
326
331
  if (['ENOENT', 'EAGAIN', 'EBUSY', 'EINTR'].includes(erro?.code ?? ''))
327
332
  return { ...base, categoria, erro: `leitura temporariamente indisponível (${erro.code})`, transitorio: true };
333
+ if (mensagem === 'runtime.unavailable: rollout do controller ausente' ||
334
+ mensagem === 'runtime.unavailable: rollout do controller sem session_meta conferível')
335
+ return { ...base, categoria, erro: 'fonte do runtime ainda não está pronta', transitorio: true };
328
336
  if (e instanceof SyntaxError || /^JSON invalido em /.test(erro?.message ?? '') ||
329
337
  metadado)
330
338
  return { ...base, categoria: metadado ? categoria : 'json.invalido', erro: 'metadado JSON indisponível ou incompleto', transitorio: true };
@@ -374,6 +382,111 @@ function observarSessao(carregado, sessionId, opcoes = {}) {
374
382
  throw e;
375
383
  }
376
384
  }
385
+ /**
386
+ * RM-064 T9: a batida não depende do processo watcher ter nascido. Para a última sessão
387
+ * despachada e verificada, recompõe a fonte do próprio despacho, observa o runtime diretamente
388
+ * e, depois do mesmo limite do watcher, registra uma parada tipada que o retry consegue tratar.
389
+ */
390
+ function reconciliarSessaoSemWatcher(carregado, threadId, agoraMs = Date.now()) {
391
+ const thread = (0, thread_1.lerThread)(carregado.raiz, threadId);
392
+ const sessao = thread.sessoes.at(-1);
393
+ const ignorada = (detalhe) => ({ thread: threadId,
394
+ sessionId: sessao?.sessionId ?? null, estado: 'ignorada', detalhe });
395
+ if (thread.status === 'fechada' || !sessao || sessao.verificada !== true ||
396
+ !['codex', 'claude-bg'].includes(sessao.runtime) || typeof sessao.despachadaEm !== 'string')
397
+ return ignorada('sem sessão despachada e verificada que o watcher possa reconciliar');
398
+ const dir = (0, thread_1.dirThread)(carregado.raiz, threadId);
399
+ let eventos = (0, ledger_1.lerLedger)(dir);
400
+ if (eventos.some(e => e.tipo === 'phase_result' && e.sessionId === sessao.sessionId &&
401
+ (e.despachoEm === undefined || e.despachoEm === sessao.despachadaEm)))
402
+ return ignorada('sessão já possui phase_result');
403
+ const iniciado = eventos.filter(e => e.tipo === 'session_watcher_started' && e.sessionId === sessao.sessionId &&
404
+ e.despachoEm === sessao.despachadaEm).at(-1);
405
+ const identidade = iniciado?.identidade;
406
+ if (identidade && iniciado?.pid === identidade.pid && (0, codex_runner_1.estadoProcesso)(identidade) === 'vivo')
407
+ return ignorada('watcher verificado continua vivo');
408
+ try {
409
+ const registro = eventos.filter(e => e.tipo === 'session_sensor_registered' && e.sessionId === sessao.sessionId &&
410
+ e.despachoEm === sessao.despachadaEm).at(-1);
411
+ if (!registro && sessao.runtime === 'claude-bg') {
412
+ (0, session_watcher_claude_1.garantirFonteClaude)(carregado.raiz, thread, (0, session_events_1.exigirSessaoDespachada)(sessao, sessao.sessionId));
413
+ }
414
+ else if (!registro && sessao.runtime === 'codex') {
415
+ const despacho = eventos.filter(e => e.tipo === 'phase_dispatch' && e.sessionId === sessao.sessionId).at(-1);
416
+ const controlador = (despacho?.controlador ?? sessao.controlador);
417
+ const cwd = despacho?.cwd;
418
+ if (controlador && cwd) {
419
+ const fonte = { controlador, cwd };
420
+ validarRegistroWatcher(carregado.raiz, sessao.sessionId, fonte);
421
+ (0, session_events_1.comLockDeSessao)(dir, () => {
422
+ const atuais = (0, ledger_1.lerLedger)(dir);
423
+ if (!atuais.some(e => e.tipo === 'session_sensor_registered' && e.sessionId === sessao.sessionId &&
424
+ e.despachoEm === sessao.despachadaEm)) {
425
+ (0, ledger_1.registrar)(dir, threadId, 'session_sensor_registered', { fase: sessao.fase, sessionId: sessao.sessionId,
426
+ despachoEm: sessao.despachadaEm, ...fonte, origem: 'conducao.batida',
427
+ ...(despacho?.perfil ? { perfil: despacho.perfil } : {}) });
428
+ }
429
+ });
430
+ }
431
+ }
432
+ const observado = observarSessao(carregado, sessao.sessionId, { threadId, agoraMs });
433
+ if (!observado.ocupado) {
434
+ const observadoEm = new Date(agoraMs).toISOString();
435
+ (0, session_events_1.comLockDeSessao)(dir, () => {
436
+ const atuais = (0, ledger_1.lerLedger)(dir);
437
+ if (!atuais.some(e => e.tipo === 'session_watcher_observed' && e.sessionId === sessao.sessionId &&
438
+ e.despachoEm === sessao.despachadaEm && e.ts === observadoEm)) {
439
+ (0, ledger_1.registrar)(dir, threadId, 'session_watcher_observed', { ts: observadoEm, fase: sessao.fase,
440
+ sessionId: sessao.sessionId, despachoEm: sessao.despachadaEm, origem: 'conducao.batida' });
441
+ }
442
+ });
443
+ }
444
+ if (observado.concluido)
445
+ return { thread: threadId, sessionId: sessao.sessionId,
446
+ estado: 'concluida', detalhe: `runtime observado: ${observado.classificacao ?? 'terminal'}` };
447
+ return { thread: threadId, sessionId: sessao.sessionId, estado: 'acompanhada',
448
+ detalhe: observado.ocupado ? 'observação ocupada; nova batida repetirá' : 'runtime ainda sem terminal' };
449
+ }
450
+ catch (erro) {
451
+ // `observarSessao` diagnostica sua própria falha; a recomposição estrutural passa pelo mesmo
452
+ // recibo. Só depois do limite a batida transforma a ausência persistente em parada.
453
+ tentarRegistrarErroWatcher(carregado.raiz, threadId, sessao.sessionId, erro);
454
+ eventos = (0, ledger_1.lerLedger)(dir);
455
+ const doIntervalo = (0, session_watcher_claude_1.eventosDoIntervalo)(eventos, (0, session_events_1.exigirSessaoDespachada)(sessao, sessao.sessionId));
456
+ const uteis = doIntervalo.filter(e => ['runtime_heartbeat', 'runtime_event', 'runtime_stop', 'runtime_subagent_stop', 'commit',
457
+ 'mcp_git_committed', 'sessao_bloqueada', 'sessao_destravada'].includes(e.tipo));
458
+ const observacoesBoas = doIntervalo.filter(e => e.sessionId === sessao.sessionId &&
459
+ (e.tipo === 'session_watcher_observed' || e.tipo === 'session_watcher_error' && e.encerramento === 'recuperado'));
460
+ const ultimaObservacao = Math.max(Date.parse(sessao.despachadaEm), ...[...uteis, ...observacoesBoas].map(e => Date.parse(e.ts)).filter(Number.isFinite));
461
+ const errosDaSerie = doIntervalo.filter(e => e.tipo === 'session_watcher_error' && e.sessionId === sessao.sessionId &&
462
+ e.encerramento !== 'recuperado').map(e => Date.parse(e.ts)).filter(ts => Number.isFinite(ts) && ts >= ultimaObservacao);
463
+ const primeiroErro = errosDaSerie.length > 0 ? Math.min(...errosDaSerie) : Number.NEGATIVE_INFINITY;
464
+ const ultimoUtil = Math.max(ultimaObservacao, primeiroErro);
465
+ if (agoraMs - ultimoUtil < exports.LIMITE_MORTE_MS)
466
+ return { thread: threadId, sessionId: sessao.sessionId,
467
+ estado: 'acompanhada', detalhe: 'fonte ainda indisponível dentro do limite de estabilidade' };
468
+ const sessionId = sessao.sessionId;
469
+ const chave = (0, node_crypto_1.createHash)('sha256').update(sessionId + '|' + sessao.despachadaEm).digest('hex');
470
+ const sensorResultId = `codex:${chave}`;
471
+ (0, session_events_1.comLockDeSessao)(dir, () => {
472
+ const atuais = (0, ledger_1.lerLedger)(dir);
473
+ if (atuais.some(e => e.tipo === 'phase_result' && e.sessionId === sessao.sessionId &&
474
+ e.despachoEm === sessao.despachadaEm))
475
+ return;
476
+ const dados = { fase: sessao.fase, sessionId: sessao.sessionId, despachoEm: sessao.despachadaEm,
477
+ sensorResultId, classificacao: 'gate_blocked', motivo: 'runtime.unavailable', runtime: sessao.runtime,
478
+ fonte: 'conducao.batida: sessão verificada sem watcher e sem evento útil', fonteVencedora: null,
479
+ ok: false, conclusaoNativa: false, conclusaoNativaAusente: 'watcher ausente e fonte indisponível além do limite',
480
+ estado: 'bloqueada', observadoEm: new Date(agoraMs).toISOString(), gate: 'phase.dispatch',
481
+ origem: 'conducao.batida', morteLatenciaMs: agoraMs - ultimoUtil };
482
+ (0, ledger_1.registrar)(dir, threadId, 'sessao_morta', dados);
483
+ (0, ledger_1.registrar)(dir, threadId, 'gate_blocked', dados);
484
+ (0, ledger_1.registrar)(dir, threadId, 'phase_result', dados);
485
+ });
486
+ return { thread: threadId, sessionId: sessao.sessionId, estado: 'parada',
487
+ detalhe: 'sessão verificada sem watcher e sem evento útil além do limite' };
488
+ }
489
+ }
377
490
  function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registrada }, opcoes) {
378
491
  const sessao = (0, session_events_1.exigirSessaoDespachada)(registrada, sessionId);
379
492
  if (sessao.runtime !== 'codex' && sessao.runtime !== 'claude-bg')
@@ -413,7 +526,8 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
413
526
  thread, sessao, dir, pasta, chave, agoraMs: now, limiteMs: exports.LIMITE_MORTE_MS, consulta: opcoes.consultaClaude, carregado })) ?? { ...base, ocupado: true };
414
527
  return (0, ledger_1.threadPresente)(dir) ? r : desfazer();
415
528
  }
416
- return comLockWatcher(pasta, () => {
529
+ let contaParaReconciliar = null;
530
+ const observado = comLockWatcher(pasta, () => {
417
531
  const eventos = (0, ledger_1.lerLedger)(dir), resultadoId = `codex:${chave}`;
418
532
  const pronto = eventos.find(e => e.tipo === 'phase_result' && e.sensorResultId === resultadoId);
419
533
  if (pronto)
@@ -610,10 +724,12 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
610
724
  terminal = { ...terminal, classificacao: 'gate_blocked', motivo: 'runtime.unavailable' };
611
725
  }
612
726
  // I-33 (D12): o turno terminou pela CONTA (cota, credito ou login), dito pelo proprio runtime.
613
- // E bloqueio, nunca conclusao; a D11c decide no retry se houve producao antes da morte.
727
+ // É bloqueio, nunca conclusão; o retry deriva checkpoint quando já houve produção.
614
728
  if (conta)
615
729
  terminal = { ...terminal, classificacao: 'gate_blocked', motivo: conta.falha.motivo, falhaDeConta: conta.falha,
616
730
  fonte: `${conta.fonte}: ${conta.falha.motivo} (${conta.falha.trecho})` };
731
+ const respostaFinal = terminal.respostaFinal
732
+ ? (0, trabalho_thread_1.gravarRespostaFinalDaSessao)(carregado.raiz, thread.id, sessionId, terminal.respostaFinal) : null;
617
733
  const dados = { fase: sessao.fase, sessionId, despachoEm: sessao.despachadaEm, sensorResultId: resultadoId,
618
734
  classificacao: terminal.classificacao, motivo: terminal.motivo, runtime: 'codex', fonte: terminal.fonte,
619
735
  fonteVencedora: incompleto || invalido || aberto || descorrelacionado ? null : terminais[0]?.nome ?? null,
@@ -627,13 +743,18 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
627
743
  estado: terminal.classificacao === 'fase_concluida' ? 'concluida' : 'bloqueada',
628
744
  observadoEm: terminal.timestamp, gate: 'phase.dispatch', origem: 'sessions.watch',
629
745
  morteLatenciaMs: morte ? now - cursor.progressoEm : null, ...(perfil ? { perfil } : {}),
746
+ ...(respostaFinal ? { respostaFinal: { arquivo: (0, trabalho_thread_1.caminhoDoTrabalho)(thread.id) + respostaFinal.arquivo,
747
+ sha256: respostaFinal.sha256, bytes: respostaFinal.bytes, truncada: respostaFinal.truncada } } : {}),
630
748
  ...(conta ? { falhaDeConta: { motivo: conta.falha.motivo, resetEm: conta.falha.resetEm, fonte: conta.falha.fonte,
631
749
  trecho: conta.falha.trecho } } : {}) };
632
750
  const tipo = semTerminal && morte && !incompleto && !conta ? 'sessao_morta' : terminal.classificacao;
633
751
  // I-33 (D12): o perfil sai do rodizio na primeira gravacao do resultado, onde a evidencia esta.
634
752
  if (conta && perfil && !atuais.some(e => e.tipo === 'phase_result' && e.sensorResultId === resultadoId)) {
635
753
  try {
636
- (0, ratelimit_1.marcarContaDaFalha)(carregado, perfil, conta.falha, now);
754
+ const marcado = (0, ratelimit_1.marcarContaDaFalha)(carregado, perfil, conta.falha, now);
755
+ if (marcado?.esgotadoAte)
756
+ contaParaReconciliar = { perfil, falha: conta.falha,
757
+ esgotadoAte: marcado.esgotadoAte, erroEm: terminal.timestamp };
637
758
  }
638
759
  catch { /* store ocupado ou invalido: o retry marca de novo pelo gate tipado */ }
639
760
  }
@@ -646,7 +767,11 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
646
767
  (0, ledger_1.registrar)(dir, thread.id, 'phase_result', dados);
647
768
  return { ...base, bytesLidos, concluido: true, classificacao: terminal.classificacao };
648
769
  });
649
- }) ?? { ...base, ocupado: true };
770
+ });
771
+ const episodio = contaParaReconciliar;
772
+ if (episodio)
773
+ (0, conta_esgotada_1.reconciliarContaEsgotada)({ raiz: carregado.raiz, agoraMs: now, ...episodio });
774
+ return observado ?? { ...base, ocupado: true };
650
775
  }
651
776
  catch (e) {
652
777
  // Thread apagada no meio da observação: encerra sem erro, sem recriar a pasta e sem resíduo.
@@ -655,8 +780,8 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
655
780
  throw e;
656
781
  }
657
782
  }
658
- /** Valida a fonte antes de registro, stderr ou spawn; tambem usada na recuperacao. */
659
- function validarFonteWatcher(raiz, sessionId, fonte) {
783
+ /** Valida vínculo, variante e perfil sem exigir que o runtime já tenha publicado seus metadados. */
784
+ function validarRegistroWatcher(raiz, sessionId, fonte) {
660
785
  const { thread, sessao: registrada } = (0, session_events_1.resolverSessao)(raiz, sessionId);
661
786
  const sessao = (0, session_events_1.exigirSessaoDespachada)(registrada, sessionId);
662
787
  const dir = (0, thread_1.dirThread)(raiz, thread.id);
@@ -669,9 +794,16 @@ function validarFonteWatcher(raiz, sessionId, fonte) {
669
794
  // I-33 (D4): perfil invalido ou divergente do despacho reprova antes de observar pela conta errada.
670
795
  (0, runtime_profiles_1.perfilDoRegistro)([...eventos, ...(fonte ? [{ tipo: 'session_sensor_registered', sessionId,
671
796
  despachoEm: sessao.despachadaEm, ...fonte }] : [])], sessao);
797
+ if (registro.nativo !== undefined && sessao.runtime !== 'claude-bg')
798
+ throw new Error('fonte nativa claude-agents em sessão de outro runtime');
799
+ if (registro.controlador && sessao.runtime !== 'codex')
800
+ throw new Error('fonte do controller Codex em sessão de outro runtime');
801
+ return { thread, sessao, dir, eventos, registro };
802
+ }
803
+ /** Validação profunda feita pelo laço: prontidão eventual nunca impede o registro do vínculo. */
804
+ function validarFonteWatcher(raiz, sessionId, fonte) {
805
+ const { thread, sessao, dir, eventos, registro } = validarRegistroWatcher(raiz, sessionId, fonte);
672
806
  if (registro.nativo !== undefined) {
673
- if (sessao.runtime !== 'claude-bg')
674
- throw new Error('fonte nativa claude-agents em sessão de outro runtime');
675
807
  (0, session_watcher_claude_1.validarFonteClaude)(eventos, sessionId, registro);
676
808
  return;
677
809
  }
@@ -690,6 +822,20 @@ function validarFonteWatcher(raiz, sessionId, fonte) {
690
822
  (0, codex_controller_sensor_1.lerSnapshotController)(fixada);
691
823
  }
692
824
  }
825
+ /**
826
+ * No despacho, fixa a fonte que já está pronta e recusa corrupção permanente antes de
827
+ * registrar ou iniciar o watcher. A publicação ainda incompleta do controller é deixada
828
+ * para o laço do watcher, que repete a mesma validação profunda com prazo e diagnóstico.
829
+ */
830
+ function prepararFonteWatcher(raiz, sessionId, fonte) {
831
+ try {
832
+ validarFonteWatcher(raiz, sessionId, fonte);
833
+ }
834
+ catch (e) {
835
+ if (!diagnosticoWatcher(e).transitorio)
836
+ throw e;
837
+ }
838
+ }
693
839
  function iniciarWatcher(raiz, sessionId) {
694
840
  const { thread, sessao: registrada } = (0, session_events_1.resolverSessao)(raiz, sessionId);
695
841
  const sessao = (0, session_events_1.exigirSessaoDespachada)(registrada, sessionId);
@@ -697,7 +843,7 @@ function iniciarWatcher(raiz, sessionId) {
697
843
  // I-34: sessão claude-bg despachada antes do registro nativo ganha a fonte derivada do despacho.
698
844
  if (sessao.runtime === 'claude-bg')
699
845
  (0, session_watcher_claude_1.garantirFonteClaude)(raiz, thread, sessao);
700
- validarFonteWatcher(raiz, sessionId);
846
+ validarRegistroWatcher(raiz, sessionId);
701
847
  const anterior = (0, ledger_1.lerLedger)(dir).filter(e => e.tipo === 'session_watcher_started' &&
702
848
  e.sessionId === sessionId && e.despachoEm === sessao.despachadaEm).at(-1);
703
849
  const identidadeAnterior = anterior?.identidade;
@@ -762,7 +908,7 @@ async function acompanhar() {
762
908
  try {
763
909
  const readyPath = process.argv[5], token = process.argv[6];
764
910
  if (readyPath && token) {
765
- validarFonteWatcher(carregado.raiz, sessionId);
911
+ validarRegistroWatcher(carregado.raiz, sessionId);
766
912
  const sessao = (0, session_events_1.exigirSessaoDespachada)((0, session_events_1.resolverSessao)(carregado.raiz, sessionId, threadId).sessao, sessionId);
767
913
  const identidade = (0, codex_runner_1.identidadeProcesso)(process.pid);
768
914
  if (!identidade)
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.pidVivo = pidVivo;
37
37
  exports.ehFantasma = ehFantasma;
38
+ exports.encerradaNaLista = encerradaNaLista;
38
39
  exports.contasDeSessoes = contasDeSessoes;
39
40
  exports.consultarContas = consultarContas;
40
41
  exports.estadosNasContas = estadosNasContas;
@@ -75,6 +76,14 @@ function pidVivo(pid) {
75
76
  function ehFantasma(runtime, s, vivo = pidVivo) {
76
77
  return runtime === 'claude-bg' && !TERMINAIS.includes(estadoDe(s)) && !vivo(s.pid);
77
78
  }
79
+ /**
80
+ * RM-037 (ork-rm037esperas, D7): o runtime mostra a sessao encerrada: estado terminal (`done`, `completed`, `exited`,
81
+ * `stopped`, `failed`) ou fantasma, registro sem processo que trabalhe por ele. Domicilio unico dessa leitura: o portao
82
+ * de vaga do `ork phase run` (`vagaDoDespacho`) e a capacidade do #Noctum a usam.
83
+ */
84
+ function encerradaNaLista(s) {
85
+ return s.fantasma || TERMINAIS.includes(estadoDe(s));
86
+ }
78
87
  const real = (dir) => { try {
79
88
  return fs.realpathSync(dir);
80
89
  }
@@ -71,7 +71,7 @@ function raizesDeRegistros(cwds) {
71
71
  function inventariarSessoes(raiz, opcoes = {}) {
72
72
  const canonica = (0, estado_thread_1.raizDoEstado)(raiz);
73
73
  // RM-056 (D4): a conta do processo e cada perfil do store, sem repetir diretorio.
74
- const contas = (0, sessoes_contas_1.consultarContas)(canonica, { todas: opcoes.todas });
74
+ const contas = (0, sessoes_contas_1.consultarContas)(canonica, { todas: opcoes.todas, ...(opcoes.prazoMs ? { prazoMs: opcoes.prazoMs } : {}) });
75
75
  const fontes = contas.fontes;
76
76
  const todas = contas.sessoes.map(s => ({ ...s, vinculos: [] }));
77
77
  // O cruzamento usa o universo global mesmo quando a apresentação é local.
package/dist/sessoes.js CHANGED
@@ -54,24 +54,26 @@ const util_1 = require("./util");
54
54
  const estado_thread_1 = require("./estado-thread");
55
55
  const ledger_1 = require("./ledger");
56
56
  const thread_1 = require("./thread");
57
+ const locale_1 = require("./locale");
57
58
  function textoDoInventario(r) {
59
+ const m = (0, locale_1.msg)().operacao.restante.sessions.inventario;
58
60
  const linhas = [
59
- `Inventário ${r.escopo.global ? 'global' : 'do projeto'} da conta ${r.escopo.usuario}; histórico: ${r.escopo.historico ? 'incluído' : 'omitido'}.`,
60
- `Fontes: ${r.fontes.map(f => `${f.origem} (${f.ausente ? 'ausente' : f.ok ? 'ok' : 'FALHA'})`).join('; ')}`,
61
- `Total: ${r.total}; sem thread: ${r.semThread}; ambíguas: ${r.ambiguas}; fantasmas: ${r.fantasmas}; consulta: ${r.ok ? 'válida' : 'INCOMPLETA'}.`,
61
+ m.abertura(r.escopo.global, r.escopo.usuario, r.escopo.historico),
62
+ m.fontes(r.fontes.map(f => `${f.origem} (${f.ausente ? m.fonteEstado.ausente : f.ok ? m.fonteEstado.ok : m.fonteEstado.falha})`).join('; ')),
63
+ m.resumo(r.total, r.semThread, r.ambiguas, r.fantasmas, r.ok),
62
64
  ];
63
65
  // RM-056 (D4): a coluna PERFIL e o id do perfil (`processo` sem perfil), nunca o diretorio da conta.
64
66
  if (r.sessoes.length)
65
- linhas.push((0, util_1.tabela)(['ID', 'RUNTIME', 'PERFIL', 'ESTADO', 'THREAD/FASE'], r.sessoes.map(s => [s.sessionId, s.runtime, s.perfil ?? 'processo',
66
- `${s.state ?? s.status ?? 'unknown'}${s.fantasma ? ' (fantasma)' : ''}`,
67
- s.vinculos.map(v => `${v.thread}/${v.fase}`).join(', ') || '(fora do ork)'])));
67
+ linhas.push((0, util_1.tabela)([...m.colunas], r.sessoes.map(s => [s.sessionId, s.runtime, s.perfil ?? m.processo,
68
+ `${s.state ?? s.status ?? m.desconhecido}${s.fantasma ? ` (${m.fantasma})` : ''}`,
69
+ s.vinculos.map(v => `${v.thread}/${v.fase}`).join(', ') || m.fora])));
68
70
  if (r.fantasmas > 0)
69
- linhas.push('Fantasma: registro sem processo vivo, não ocupa vaga; `ork sessions limpar-fantasmas` solta o vínculo do ork sem tocar no runtime.');
71
+ linhas.push(m.explicacaoFantasma);
70
72
  for (const f of r.fontes.filter(f => !f.ok))
71
- linhas.push(`Falha: ${f.detalhe}`);
73
+ linhas.push(m.falha(f.detalhe));
72
74
  // Fatia 2 do ensaio da 0.5.0 (P1): a fonte ausente nao e falha, mas diz o que falta e como ter.
73
75
  for (const f of r.fontes.filter(f => f.ausente))
74
- linhas.push(`Ausente: ${f.detalhe}${f.correcao ? `; correção: ${f.correcao}` : ''}`);
76
+ linhas.push(m.ausente(f.detalhe, f.correcao ?? null));
75
77
  return linhas.join('\n');
76
78
  }
77
79
  function tabelaDeSessoes(raiz, todas = false) {
@@ -83,6 +85,7 @@ function tabelaDeSessoes(raiz, todas = false) {
83
85
  * viva). So uma conta pode responder; duas viram recusa, nenhuma mantem a mensagem de antes.
84
86
  */
85
87
  function localizarSessao(chave, raiz) {
88
+ const m = (0, locale_1.msg)().operacao.restante.sessions.localizar;
86
89
  let perfis = [];
87
90
  const falhas = [];
88
91
  if (raiz) {
@@ -99,10 +102,9 @@ function localizarSessao(chave, raiz) {
99
102
  return { achada: r.achadas[0] };
100
103
  if (r.achadas.length > 1) {
101
104
  const contas = r.achadas.map(a => `${a.perfil?.id ?? 'processo'} (${a.sessao.sessionId})`).join(', ');
102
- return { texto: `sessao "${chave}" encontrada em mais de uma conta: ${contas}; use o id completo`, codigo: 1 };
105
+ return { texto: m.ambigua(chave, contas), codigo: 1 };
103
106
  }
104
- return { texto: `sessao "${chave}" nao encontrada no runtime` + (falhas.length ? `; contas sem resposta: ${falhas.join('; ')}` : ''),
105
- codigo: 1 };
107
+ return { texto: m.ausente(chave, falhas.join('; ')), codigo: 1 };
106
108
  }
107
109
  /** Logs de uma sessao pelo id curto, id completo ou nome, lidos na conta onde ela esta. */
108
110
  function logsDaSessao(chave, linhas, raiz) {
@@ -120,7 +122,7 @@ function pararSessao(chave, raiz) {
120
122
  return l;
121
123
  const { sessao, perfil, ambiente } = l.achada;
122
124
  const r = adapter.pararAchada(sessao, ambiente);
123
- return { texto: r.texto || `sessao ${sessao.sessionId} parada${perfil ? ` (perfil ${perfil.id})` : ''}`, codigo: r.ok ? 0 : 1 };
125
+ return { texto: r.texto || (0, locale_1.msg)().operacao.restante.sessions.localizar.parada(sessao.sessionId, perfil?.id ?? null), codigo: r.ok ? 0 : 1 };
124
126
  }
125
127
  /** Comando de attach (precisa de TTY, entao o CLI imprime em vez de executar). */
126
128
  function comandoDeAttach(chave, raiz) {
@@ -138,9 +140,9 @@ const ENCERRAM_A_SESSAO = ['phase_result', 'sessao_morta', 'session_superseded']
138
140
  */
139
141
  function limparFantasmas(raiz, opcoes = {}) {
140
142
  const canonica = (0, estado_thread_1.raizDoEstado)(raiz);
141
- const inv = (0, sessoes_inventario_1.inventariarSessoes)(canonica, { global: true });
143
+ const inv = opcoes.inventario ?? (0, sessoes_inventario_1.inventariarSessoes)(canonica, { global: true });
142
144
  const itens = [];
143
- for (const s of inv.sessoes.filter(x => x.fantasma)) {
145
+ for (const s of inv.sessoes.filter(x => x.fantasma && (!opcoes.sessoes || opcoes.sessoes.includes(x.sessionId)))) {
144
146
  // Fechamento (RM-056, ao fechar): so os vinculos da thread que fecha; o resto fica como estava.
145
147
  const vinculos = opcoes.thread ? s.vinculos.filter(v => v.thread === opcoes.thread && v.raiz === canonica) : s.vinculos;
146
148
  if (opcoes.thread && vinculos.length === 0)
@@ -186,18 +188,18 @@ function sessoesSemFim(raiz, threadId) {
186
188
  return [...new Set(ids)].filter(id => !encerradas.has(id));
187
189
  }
188
190
  function textoDaLimpeza(r) {
191
+ const m = (0, locale_1.msg)().operacao.restante.sessions.limpeza;
189
192
  if (r.itens.length === 0)
190
- return `Nenhuma sessão fantasma${r.ok ? '' : ' nas contas que responderam'}.` +
191
- r.falhas.map(f => `\nFalha: ${f}`).join('');
193
+ return m.nenhuma(!r.ok) + r.falhas.map(f => `\n${m.falha(f)}`).join('');
192
194
  const verbo = {
193
- solto: r.dryRun ? 'soltaria (sessao_morta no ledger)' : 'solto: sessao_morta no ledger',
194
- 'ja-solto': 'já encerrada no ledger', 'sem-thread': 'fora do ork: nada a soltar',
195
- 'outro-projeto': 'vínculo de outro projeto: rode lá',
195
+ solto: r.dryRun ? m.acoes.soltaria : m.acoes.solto,
196
+ 'ja-solto': m.acoes.jaSolto, 'sem-thread': m.acoes.semThread,
197
+ 'outro-projeto': m.acoes.outroProjeto,
196
198
  };
197
199
  return [
198
- `Sessões fantasma (sem pid e sem processo)${r.dryRun ? ', ensaio: nada foi gravado' : ''}. O runtime não foi tocado.`,
199
- (0, util_1.tabela)(['ID', 'PERFIL', 'THREAD/FASE', 'AÇÃO'], r.itens.map(i => [i.sessionId, i.perfil ?? 'processo',
200
+ m.abertura(r.dryRun),
201
+ (0, util_1.tabela)([...m.colunas], r.itens.map(i => [i.sessionId, i.perfil ?? m.processo,
200
202
  i.thread ? `${i.thread}/${i.fase}` : '-', verbo[i.acao]])),
201
- ...r.falhas.map(f => `Falha: ${f}`),
203
+ ...r.falhas.map(f => m.falha(f)),
202
204
  ].join('\n');
203
205
  }