@orkastery/cli 0.5.6 → 0.6.1

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 (396) 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 +123 -9
  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/adapters/grok-events.js +227 -0
  105. package/dist/adapters/grok-mcp-servidor.js +612 -0
  106. package/dist/adapters/grok-mcp.js +178 -0
  107. package/dist/adapters/grok.js +686 -0
  108. package/dist/agendador-cpu.js +92 -0
  109. package/dist/atualizar-branch.js +245 -0
  110. package/dist/auditoria.js +13 -11
  111. package/dist/auditrun.js +51 -46
  112. package/dist/autorizacao-duravel.js +327 -0
  113. package/dist/board.js +94 -40
  114. package/dist/branch-de-estado.js +23 -10
  115. package/dist/busca-semantica.js +7 -5
  116. package/dist/catalogo.js +2 -1
  117. package/dist/changelog-reconciliacao.js +290 -0
  118. package/dist/check-agil.js +528 -0
  119. package/dist/check-modo.js +41 -0
  120. package/dist/check-paralelo.js +238 -0
  121. package/dist/ci.js +248 -45
  122. package/dist/ciclos.js +8 -6
  123. package/dist/claim-lint.js +12 -8
  124. package/dist/claims-conferir.js +47 -39
  125. package/dist/claims.js +10 -9
  126. package/dist/company-brain-client.js +10 -3
  127. package/dist/company-brain-migration.js +11 -5
  128. package/dist/conducao-batida.js +759 -0
  129. package/dist/conducao-sentinela.js +25 -8
  130. package/dist/conducao.js +89 -29
  131. package/dist/conhecimento-consulta.js +270 -0
  132. package/dist/conhecimento.js +111 -87
  133. package/dist/conta-esgotada.js +127 -0
  134. package/dist/dado-privado.js +816 -0
  135. package/dist/decisao-autonoma.js +5 -4
  136. package/dist/demo.js +14 -12
  137. package/dist/dependencias-da-worktree.js +25 -0
  138. package/dist/divida.js +38 -36
  139. package/dist/docs.js +89 -89
  140. package/dist/doctor-forja.js +343 -0
  141. package/dist/doctor-pulse-cron.js +113 -1
  142. package/dist/doctor.js +164 -6
  143. package/dist/dsn-da-memoria.js +417 -0
  144. package/dist/entrega-por-mod.js +503 -0
  145. package/dist/entrega-pr.js +154 -54
  146. package/dist/esgotamentos.js +13 -11
  147. package/dist/estado-thread.js +21 -18
  148. package/dist/evalrunner.js +35 -32
  149. package/dist/fabrica-batida.js +34 -21
  150. package/dist/fabrica-estado.js +33 -21
  151. package/dist/fix.js +21 -19
  152. package/dist/forja/adaptador.js +6 -0
  153. package/dist/forja/ambiente-de-ci.js +27 -0
  154. package/dist/forja/api.js +256 -0
  155. package/dist/forja/cache.js +89 -0
  156. package/dist/forja/cli.js +60 -0
  157. package/dist/forja/contrato.js +9 -0
  158. package/dist/forja/endereco.js +43 -0
  159. package/dist/forja/estado.js +22 -0
  160. package/dist/forja/executor.js +73 -0
  161. package/dist/forja/github/ci.js +95 -0
  162. package/dist/forja/github/dono-da-rede.js +18 -0
  163. package/dist/forja/github/metadados.js +15 -0
  164. package/dist/forja/github/pedidos.js +200 -0
  165. package/dist/forja/gitlab/ci.js +141 -0
  166. package/dist/forja/gitlab/consultas.js +59 -0
  167. package/dist/forja/gitlab/dono-da-rede.js +43 -0
  168. package/dist/forja/gitlab/metadados.js +15 -0
  169. package/dist/forja/gitlab/pedidos-abertos.js +158 -0
  170. package/dist/forja/gitlab/pedidos.js +141 -0
  171. package/dist/forja/produtor.js +32 -0
  172. package/dist/forja/registro.js +31 -0
  173. package/dist/forja/resolver.js +121 -0
  174. package/dist/forja/texto.js +13 -0
  175. package/dist/forja/versao.js +71 -0
  176. package/dist/forja.js +123 -80
  177. package/dist/handoff.js +23 -13
  178. package/dist/hitl-contract.js +46 -43
  179. package/dist/hitl-curto.js +37 -25
  180. package/dist/hitl-gates.js +13 -11
  181. package/dist/hitl-local-receipt.js +51 -0
  182. package/dist/hitl-local.js +11 -2
  183. package/dist/hitl-lock.js +5 -11
  184. package/dist/hitl-public-receipt.js +11 -0
  185. package/dist/hitl-resumo.js +44 -1
  186. package/dist/hitl-sessions.js +62 -9
  187. package/dist/hitl-texto-livre.js +7 -4
  188. package/dist/hitl.js +34 -31
  189. package/dist/horario.js +20 -1
  190. package/dist/hosts.js +104 -134
  191. package/dist/index.js +864 -554
  192. package/dist/indice-vetorial.js +14 -12
  193. package/dist/init.js +11 -2
  194. package/dist/integracoes-locais.js +4 -0
  195. package/dist/intelligence-graph-cli.js +123 -69
  196. package/dist/intelligence-graph-query.js +37 -22
  197. package/dist/leases.js +19 -18
  198. package/dist/ledger-stats.js +17 -16
  199. package/dist/ledger.js +31 -1
  200. package/dist/licoes.js +12 -11
  201. package/dist/locale-accounts.js +228 -0
  202. package/dist/locale-adapter.js +291 -0
  203. package/dist/locale-ajuda.js +86 -10
  204. package/dist/locale-audit.js +199 -0
  205. package/dist/locale-claims.js +213 -0
  206. package/dist/locale-conducao.js +138 -0
  207. package/dist/locale-conhecimento.js +181 -0
  208. package/dist/locale-decisao.js +205 -0
  209. package/dist/locale-docs.js +230 -0
  210. package/dist/locale-estado.js +101 -0
  211. package/dist/locale-forja.js +288 -0
  212. package/dist/locale-gerados.js +5 -0
  213. package/dist/locale-grafo.js +129 -0
  214. package/dist/locale-master.js +83 -0
  215. package/dist/locale-network.js +524 -0
  216. package/dist/locale-operacao-restante.js +931 -0
  217. package/dist/locale-projetos.js +100 -0
  218. package/dist/locale-prompts.js +194 -0
  219. package/dist/locale-pulse.js +140 -2
  220. package/dist/locale-reservas.js +87 -0
  221. package/dist/locale-retry.js +183 -6
  222. package/dist/locale-security-scan.js +69 -0
  223. package/dist/locale-setup.js +192 -0
  224. package/dist/locale-ship.js +177 -66
  225. package/dist/locale-thread.js +149 -5
  226. package/dist/locale-verify.js +80 -4
  227. package/dist/locale-worktree.js +246 -0
  228. package/dist/locale.js +553 -9
  229. package/dist/maestro-runtime.js +22 -3
  230. package/dist/manifest.js +293 -12
  231. package/dist/maquina-ociosa.js +211 -0
  232. package/dist/maquina.js +10 -5
  233. package/dist/master-nota-local.js +200 -0
  234. package/dist/master-nota.js +10 -2
  235. package/dist/master.js +118 -41
  236. package/dist/mcp-conhecimento.js +52 -0
  237. package/dist/mcp-experiencia.js +26 -5
  238. package/dist/mcp-install.js +90 -15
  239. package/dist/mcp-noctum.js +101 -0
  240. package/dist/mcp-server.js +116 -22
  241. package/dist/mcp-ship-transporte.js +977 -0
  242. package/dist/mcp-ship.js +68 -24
  243. package/dist/mcp-transportes.js +17 -0
  244. package/dist/memoria.js +63 -58
  245. package/dist/merge-da-entrega.js +85 -0
  246. package/dist/modos-migracao.js +8 -6
  247. package/dist/modos.js +17 -18
  248. package/dist/network-roadmap.js +94 -54
  249. package/dist/noctum-aceite.js +929 -0
  250. package/dist/noctum-arco.js +540 -33
  251. package/dist/noctum-capacidade.js +3 -3
  252. package/dist/noctum-changelog.js +399 -0
  253. package/dist/noctum-cli.js +539 -0
  254. package/dist/noctum-coordenacao.js +1225 -0
  255. package/dist/noctum-entrega.js +1217 -0
  256. package/dist/noctum-envelope.js +253 -17
  257. package/dist/noctum-execucao.js +100 -24
  258. package/dist/noctum-fechamento.js +416 -0
  259. package/dist/noctum-fila.js +49 -10
  260. package/dist/noctum-guarda.js +333 -0
  261. package/dist/noctum-integracao.js +507 -0
  262. package/dist/noctum-maquinas.js +387 -0
  263. package/dist/noctum-medicao.js +450 -0
  264. package/dist/noctum-modo.js +390 -0
  265. package/dist/noctum-pergunta-canal.js +96 -0
  266. package/dist/noctum-pergunta.js +115 -0
  267. package/dist/noctum-provas.js +838 -0
  268. package/dist/noctum-reconciliacao.js +594 -0
  269. package/dist/noctum-rede.js +102 -0
  270. package/dist/noctum-registro.js +215 -0
  271. package/dist/noctum-relatorio.js +861 -0
  272. package/dist/noctum-resposta.js +207 -0
  273. package/dist/noctum-retomada-rede.js +71 -0
  274. package/dist/noctum-sessoes-em-voo.js +93 -0
  275. package/dist/noctum-supervisao.js +649 -0
  276. package/dist/noctum-terminal.js +459 -0
  277. package/dist/noctum-transporte.js +655 -0
  278. package/dist/noctum-vigia.js +679 -0
  279. package/dist/ocupacao.js +3 -1
  280. package/dist/onboarding.js +16 -5
  281. package/dist/orkmind.js +39 -23
  282. package/dist/orquestracao.js +31 -35
  283. package/dist/parado-no-condutor.js +160 -139
  284. package/dist/phase.js +96 -42
  285. package/dist/policies.js +33 -0
  286. package/dist/postura-local.js +11 -6
  287. package/dist/preflight.js +2 -1
  288. package/dist/procedencia.js +9 -14
  289. package/dist/projeto-alvo.js +59 -20
  290. package/dist/prompts.js +136 -42
  291. package/dist/prova-minima.js +5 -6
  292. package/dist/pulse-cadencia.js +5 -4
  293. package/dist/pulse-consentimento.js +53 -1
  294. package/dist/pulse-delivery.js +143 -27
  295. package/dist/pulse-resposta.js +368 -4
  296. package/dist/pulse.js +136 -3
  297. package/dist/ratelimit.js +13 -4
  298. package/dist/recall.js +14 -13
  299. package/dist/rede-adesao.js +13 -8
  300. package/dist/rede-forja.js +108 -24
  301. package/dist/rede-status.js +63 -45
  302. package/dist/rede.js +86 -46
  303. package/dist/retomada-checkpoint.js +101 -0
  304. package/dist/retry.js +326 -78
  305. package/dist/roadmap-reservas.js +32 -32
  306. package/dist/runtime-ambiente.js +5 -0
  307. package/dist/runtime-context.js +279 -85
  308. package/dist/runtime-escada.js +429 -0
  309. package/dist/runtime-profiles.js +130 -63
  310. package/dist/runtimes.js +42 -5
  311. package/dist/saida-segura.js +3 -2
  312. package/dist/security-scan/agil.js +366 -0
  313. package/dist/security-scan/cli.js +76 -0
  314. package/dist/security-scan/compare.js +149 -0
  315. package/dist/security-scan/config.js +93 -0
  316. package/dist/security-scan/detect.js +97 -0
  317. package/dist/security-scan/executor.js +196 -0
  318. package/dist/security-scan/guard.js +180 -0
  319. package/dist/security-scan/imagem-de-lint.js +96 -0
  320. package/dist/security-scan/normalize/actionlint.js +12 -0
  321. package/dist/security-scan/normalize/eslint.js +12 -0
  322. package/dist/security-scan/normalize/gitleaks.js +13 -0
  323. package/dist/security-scan/normalize/golangci-lint.js +13 -0
  324. package/dist/security-scan/normalize/govulncheck.js +36 -0
  325. package/dist/security-scan/normalize/index.js +25 -0
  326. package/dist/security-scan/normalize/npm-audit.js +30 -0
  327. package/dist/security-scan/normalize/osv-scanner.js +32 -0
  328. package/dist/security-scan/normalize/oxlint.js +51 -0
  329. package/dist/security-scan/normalize/pip-audit.js +16 -0
  330. package/dist/security-scan/normalize/ruff.js +12 -0
  331. package/dist/security-scan/normalize/semgrep.js +20 -0
  332. package/dist/security-scan/normalize/trivy.js +33 -0
  333. package/dist/security-scan/normalize/util.js +204 -0
  334. package/dist/security-scan/normalize/zizmor.js +19 -0
  335. package/dist/security-scan/report.js +156 -0
  336. package/dist/security-scan/run.js +448 -0
  337. package/dist/security-scan/tools.js +62 -0
  338. package/dist/security-scan/trabalhador.js +74 -0
  339. package/dist/security-scan/types.js +15 -0
  340. package/dist/session-events.js +19 -2
  341. package/dist/session-watcher-claude.js +74 -19
  342. package/dist/session-watcher-grok.js +425 -0
  343. package/dist/session-watcher.js +174 -13
  344. package/dist/sessoes-contas.js +42 -5
  345. package/dist/sessoes-inventario.js +1 -1
  346. package/dist/sessoes.js +25 -23
  347. package/dist/setup.js +67 -66
  348. package/dist/ship-publicar.js +263 -92
  349. package/dist/ship.js +160 -17
  350. package/dist/superficie.js +14 -11
  351. package/dist/thread-close.js +9 -9
  352. package/dist/thread.js +121 -18
  353. package/dist/tokens.js +15 -11
  354. package/dist/trabalho-thread.js +297 -0
  355. package/dist/transporte-do-canal.js +189 -0
  356. package/dist/types.js +12 -1
  357. package/dist/util.js +5 -2
  358. package/dist/varredura-acoes.js +500 -0
  359. package/dist/verify.js +491 -32
  360. package/dist/worktree-local.js +12 -10
  361. package/dist/worktree.js +81 -85
  362. package/eval/casos/check-quality.json +77 -0
  363. package/eval/casos/security-auditor.json +148 -0
  364. package/eval/casos/security-remediation.json +161 -0
  365. package/eval/fixtures/security-scan/README.md +8 -0
  366. package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
  367. package/eval/fixtures/security-scan/go/Dockerfile +4 -0
  368. package/eval/fixtures/security-scan/go/README.md +4 -0
  369. package/eval/fixtures/security-scan/go/config.go +4 -0
  370. package/eval/fixtures/security-scan/go/go.mod +5 -0
  371. package/eval/fixtures/security-scan/go/go.sum +2 -0
  372. package/eval/fixtures/security-scan/go/main.go +31 -0
  373. package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
  374. package/eval/fixtures/security-scan/js/Dockerfile +3 -0
  375. package/eval/fixtures/security-scan/js/README.md +4 -0
  376. package/eval/fixtures/security-scan/js/package-lock.json +844 -0
  377. package/eval/fixtures/security-scan/js/package.json +10 -0
  378. package/eval/fixtures/security-scan/js/src/config.js +4 -0
  379. package/eval/fixtures/security-scan/js/src/server.js +17 -0
  380. package/eval/fixtures/security-scan/js/src/util.ts +4 -0
  381. package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
  382. package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
  383. package/eval/fixtures/security-scan/python/Dockerfile +3 -0
  384. package/eval/fixtures/security-scan/python/README.md +4 -0
  385. package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
  386. package/eval/fixtures/security-scan/python/app/config.py +2 -0
  387. package/eval/fixtures/security-scan/python/app/main.py +19 -0
  388. package/eval/fixtures/security-scan/python/requirements.txt +1 -0
  389. package/package.json +10 -5
  390. package/references/security-checklist.md +3 -3
  391. package/skills/README.md +1 -0
  392. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  393. package/skills/phases/check-quality/SKILL.md +16 -0
  394. package/skills/phases/go-implementation/SKILL.md +6 -0
  395. package/skills/phases/security-remediation/SKILL.md +70 -0
  396. package/skills/reviewers/security-auditor/SKILL.md +25 -0
@@ -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,9 @@ 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 session_watcher_grok_1 = require("./session-watcher-grok");
62
+ const conta_esgotada_1 = require("./conta-esgotada");
63
+ const trabalho_thread_1 = require("./trabalho-thread");
58
64
  /** Falhas operacionais e bloqueios sem retry automático não alegam conclusão do produto. */
59
65
  function bloqueioPreservado(terminal) {
60
66
  return terminal.classificacao === 'gate_blocked' && terminal.motivo !== null &&
@@ -281,7 +287,7 @@ function conferirRegistro(dir, registro) {
281
287
  * com o dono da remoção.
282
288
  */
283
289
  function desfazerNaThreadRemovida(pasta, criadas) {
284
- for (const cursor of ['cursor.json', 'cursor-claude.json']) {
290
+ for (const cursor of ['cursor.json', 'cursor-claude.json', 'cursor-grok.json']) {
285
291
  try {
286
292
  fs.rmSync(path.join(pasta, cursor), { force: true });
287
293
  }
@@ -325,6 +331,9 @@ function diagnosticoWatcher(e) {
325
331
  erro: 'estado canônico temporariamente sem vínculo; auditoria será repetida', transitorio: true };
326
332
  if (['ENOENT', 'EAGAIN', 'EBUSY', 'EINTR'].includes(erro?.code ?? ''))
327
333
  return { ...base, categoria, erro: `leitura temporariamente indisponível (${erro.code})`, transitorio: true };
334
+ if (mensagem === 'runtime.unavailable: rollout do controller ausente' ||
335
+ mensagem === 'runtime.unavailable: rollout do controller sem session_meta conferível')
336
+ return { ...base, categoria, erro: 'fonte do runtime ainda não está pronta', transitorio: true };
328
337
  if (e instanceof SyntaxError || /^JSON invalido em /.test(erro?.message ?? '') ||
329
338
  metadado)
330
339
  return { ...base, categoria: metadado ? categoria : 'json.invalido', erro: 'metadado JSON indisponível ou incompleto', transitorio: true };
@@ -374,10 +383,115 @@ function observarSessao(carregado, sessionId, opcoes = {}) {
374
383
  throw e;
375
384
  }
376
385
  }
386
+ /**
387
+ * RM-064 T9: a batida não depende do processo watcher ter nascido. Para a última sessão
388
+ * despachada e verificada, recompõe a fonte do próprio despacho, observa o runtime diretamente
389
+ * e, depois do mesmo limite do watcher, registra uma parada tipada que o retry consegue tratar.
390
+ */
391
+ function reconciliarSessaoSemWatcher(carregado, threadId, agoraMs = Date.now()) {
392
+ const thread = (0, thread_1.lerThread)(carregado.raiz, threadId);
393
+ const sessao = thread.sessoes.at(-1);
394
+ const ignorada = (detalhe) => ({ thread: threadId,
395
+ sessionId: sessao?.sessionId ?? null, estado: 'ignorada', detalhe });
396
+ if (thread.status === 'fechada' || !sessao || sessao.verificada !== true ||
397
+ !['codex', 'claude-bg', 'grok'].includes(sessao.runtime) || typeof sessao.despachadaEm !== 'string')
398
+ return ignorada('sem sessão despachada e verificada que o watcher possa reconciliar');
399
+ const dir = (0, thread_1.dirThread)(carregado.raiz, threadId);
400
+ let eventos = (0, ledger_1.lerLedger)(dir);
401
+ if (eventos.some(e => e.tipo === 'phase_result' && e.sessionId === sessao.sessionId &&
402
+ (e.despachoEm === undefined || e.despachoEm === sessao.despachadaEm)))
403
+ return ignorada('sessão já possui phase_result');
404
+ const iniciado = eventos.filter(e => e.tipo === 'session_watcher_started' && e.sessionId === sessao.sessionId &&
405
+ e.despachoEm === sessao.despachadaEm).at(-1);
406
+ const identidade = iniciado?.identidade;
407
+ if (identidade && iniciado?.pid === identidade.pid && (0, codex_runner_1.estadoProcesso)(identidade) === 'vivo')
408
+ return ignorada('watcher verificado continua vivo');
409
+ try {
410
+ const registro = eventos.filter(e => e.tipo === 'session_sensor_registered' && e.sessionId === sessao.sessionId &&
411
+ e.despachoEm === sessao.despachadaEm).at(-1);
412
+ if (!registro && sessao.runtime === 'claude-bg') {
413
+ (0, session_watcher_claude_1.garantirFonteClaude)(carregado.raiz, thread, (0, session_events_1.exigirSessaoDespachada)(sessao, sessao.sessionId));
414
+ }
415
+ else if (!registro && sessao.runtime === 'codex') {
416
+ const despacho = eventos.filter(e => e.tipo === 'phase_dispatch' && e.sessionId === sessao.sessionId).at(-1);
417
+ const controlador = (despacho?.controlador ?? sessao.controlador);
418
+ const cwd = despacho?.cwd;
419
+ if (controlador && cwd) {
420
+ const fonte = { controlador, cwd };
421
+ validarRegistroWatcher(carregado.raiz, sessao.sessionId, fonte);
422
+ (0, session_events_1.comLockDeSessao)(dir, () => {
423
+ const atuais = (0, ledger_1.lerLedger)(dir);
424
+ if (!atuais.some(e => e.tipo === 'session_sensor_registered' && e.sessionId === sessao.sessionId &&
425
+ e.despachoEm === sessao.despachadaEm)) {
426
+ (0, ledger_1.registrar)(dir, threadId, 'session_sensor_registered', { fase: sessao.fase, sessionId: sessao.sessionId,
427
+ despachoEm: sessao.despachadaEm, ...fonte, origem: 'conducao.batida',
428
+ ...(despacho?.perfil ? { perfil: despacho.perfil } : {}) });
429
+ }
430
+ });
431
+ }
432
+ }
433
+ const observado = observarSessao(carregado, sessao.sessionId, { threadId, agoraMs });
434
+ if (!observado.ocupado) {
435
+ const observadoEm = new Date(agoraMs).toISOString();
436
+ (0, session_events_1.comLockDeSessao)(dir, () => {
437
+ const atuais = (0, ledger_1.lerLedger)(dir);
438
+ if (!atuais.some(e => e.tipo === 'session_watcher_observed' && e.sessionId === sessao.sessionId &&
439
+ e.despachoEm === sessao.despachadaEm && e.ts === observadoEm)) {
440
+ (0, ledger_1.registrar)(dir, threadId, 'session_watcher_observed', { ts: observadoEm, fase: sessao.fase,
441
+ sessionId: sessao.sessionId, despachoEm: sessao.despachadaEm, origem: 'conducao.batida' });
442
+ }
443
+ });
444
+ }
445
+ if (observado.concluido)
446
+ return { thread: threadId, sessionId: sessao.sessionId,
447
+ estado: 'concluida', detalhe: `runtime observado: ${observado.classificacao ?? 'terminal'}` };
448
+ return { thread: threadId, sessionId: sessao.sessionId, estado: 'acompanhada',
449
+ detalhe: observado.ocupado ? 'observação ocupada; nova batida repetirá' : 'runtime ainda sem terminal' };
450
+ }
451
+ catch (erro) {
452
+ // `observarSessao` diagnostica sua própria falha; a recomposição estrutural passa pelo mesmo
453
+ // recibo. Só depois do limite a batida transforma a ausência persistente em parada.
454
+ tentarRegistrarErroWatcher(carregado.raiz, threadId, sessao.sessionId, erro);
455
+ eventos = (0, ledger_1.lerLedger)(dir);
456
+ const doIntervalo = (0, session_watcher_claude_1.eventosDoIntervalo)(eventos, (0, session_events_1.exigirSessaoDespachada)(sessao, sessao.sessionId));
457
+ const uteis = doIntervalo.filter(e => ['runtime_heartbeat', 'runtime_event', 'runtime_stop', 'runtime_subagent_stop', 'commit',
458
+ 'mcp_git_committed', 'sessao_bloqueada', 'sessao_destravada'].includes(e.tipo));
459
+ const observacoesBoas = doIntervalo.filter(e => e.sessionId === sessao.sessionId &&
460
+ (e.tipo === 'session_watcher_observed' || e.tipo === 'session_watcher_error' && e.encerramento === 'recuperado'));
461
+ const ultimaObservacao = Math.max(Date.parse(sessao.despachadaEm), ...[...uteis, ...observacoesBoas].map(e => Date.parse(e.ts)).filter(Number.isFinite));
462
+ const errosDaSerie = doIntervalo.filter(e => e.tipo === 'session_watcher_error' && e.sessionId === sessao.sessionId &&
463
+ e.encerramento !== 'recuperado').map(e => Date.parse(e.ts)).filter(ts => Number.isFinite(ts) && ts >= ultimaObservacao);
464
+ const primeiroErro = errosDaSerie.length > 0 ? Math.min(...errosDaSerie) : Number.NEGATIVE_INFINITY;
465
+ const ultimoUtil = Math.max(ultimaObservacao, primeiroErro);
466
+ if (agoraMs - ultimoUtil < exports.LIMITE_MORTE_MS)
467
+ return { thread: threadId, sessionId: sessao.sessionId,
468
+ estado: 'acompanhada', detalhe: 'fonte ainda indisponível dentro do limite de estabilidade' };
469
+ const sessionId = sessao.sessionId;
470
+ const chave = (0, node_crypto_1.createHash)('sha256').update(sessionId + '|' + sessao.despachadaEm).digest('hex');
471
+ const sensorResultId = `codex:${chave}`;
472
+ (0, session_events_1.comLockDeSessao)(dir, () => {
473
+ const atuais = (0, ledger_1.lerLedger)(dir);
474
+ if (atuais.some(e => e.tipo === 'phase_result' && e.sessionId === sessao.sessionId &&
475
+ e.despachoEm === sessao.despachadaEm))
476
+ return;
477
+ const dados = { fase: sessao.fase, sessionId: sessao.sessionId, despachoEm: sessao.despachadaEm,
478
+ sensorResultId, classificacao: 'gate_blocked', motivo: 'runtime.unavailable', runtime: sessao.runtime,
479
+ fonte: 'conducao.batida: sessão verificada sem watcher e sem evento útil', fonteVencedora: null,
480
+ ok: false, conclusaoNativa: false, conclusaoNativaAusente: 'watcher ausente e fonte indisponível além do limite',
481
+ estado: 'bloqueada', observadoEm: new Date(agoraMs).toISOString(), gate: 'phase.dispatch',
482
+ origem: 'conducao.batida', morteLatenciaMs: agoraMs - ultimoUtil };
483
+ (0, ledger_1.registrar)(dir, threadId, 'sessao_morta', dados);
484
+ (0, ledger_1.registrar)(dir, threadId, 'gate_blocked', dados);
485
+ (0, ledger_1.registrar)(dir, threadId, 'phase_result', dados);
486
+ });
487
+ return { thread: threadId, sessionId: sessao.sessionId, estado: 'parada',
488
+ detalhe: 'sessão verificada sem watcher e sem evento útil além do limite' };
489
+ }
490
+ }
377
491
  function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registrada }, opcoes) {
378
492
  const sessao = (0, session_events_1.exigirSessaoDespachada)(registrada, sessionId);
379
- if (sessao.runtime !== 'codex' && sessao.runtime !== 'claude-bg')
380
- throw new Error('watch requer sessão Codex ou claude-bg registrada');
493
+ if (sessao.runtime !== 'codex' && sessao.runtime !== 'claude-bg' && sessao.runtime !== 'grok')
494
+ throw new Error('watch requer sessão Codex ou claude-bg ou grok registrada');
381
495
  const now = opcoes.agoraMs ?? Date.now();
382
496
  if (!Number.isFinite(now))
383
497
  throw new Error('relógio inválido');
@@ -413,7 +527,14 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
413
527
  thread, sessao, dir, pasta, chave, agoraMs: now, limiteMs: exports.LIMITE_MORTE_MS, consulta: opcoes.consultaClaude, carregado })) ?? { ...base, ocupado: true };
414
528
  return (0, ledger_1.threadPresente)(dir) ? r : desfazer();
415
529
  }
416
- return comLockWatcher(pasta, () => {
530
+ // RM-067 (F2): o grok tem observador próprio (stream, recibo do supervisor e pasta da sessão), no mesmo lock.
531
+ if (sessao.runtime === 'grok') {
532
+ const r = comLockWatcher(pasta, () => (0, session_watcher_grok_1.observarGrokSobLock)({ raiz: carregado.raiz, thread, sessao, dir, pasta, chave,
533
+ agoraMs: now, limiteMs: exports.LIMITE_MORTE_MS, relogioReal: opcoes.agoraMs === undefined })) ?? { ...base, ocupado: true };
534
+ return (0, ledger_1.threadPresente)(dir) ? r : desfazer();
535
+ }
536
+ let contaParaReconciliar = null;
537
+ const observado = comLockWatcher(pasta, () => {
417
538
  const eventos = (0, ledger_1.lerLedger)(dir), resultadoId = `codex:${chave}`;
418
539
  const pronto = eventos.find(e => e.tipo === 'phase_result' && e.sensorResultId === resultadoId);
419
540
  if (pronto)
@@ -610,10 +731,12 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
610
731
  terminal = { ...terminal, classificacao: 'gate_blocked', motivo: 'runtime.unavailable' };
611
732
  }
612
733
  // 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.
734
+ // É bloqueio, nunca conclusão; o retry deriva checkpoint quando já houve produção.
614
735
  if (conta)
615
736
  terminal = { ...terminal, classificacao: 'gate_blocked', motivo: conta.falha.motivo, falhaDeConta: conta.falha,
616
737
  fonte: `${conta.fonte}: ${conta.falha.motivo} (${conta.falha.trecho})` };
738
+ const respostaFinal = terminal.respostaFinal
739
+ ? (0, trabalho_thread_1.gravarRespostaFinalDaSessao)(carregado.raiz, thread.id, sessionId, terminal.respostaFinal) : null;
617
740
  const dados = { fase: sessao.fase, sessionId, despachoEm: sessao.despachadaEm, sensorResultId: resultadoId,
618
741
  classificacao: terminal.classificacao, motivo: terminal.motivo, runtime: 'codex', fonte: terminal.fonte,
619
742
  fonteVencedora: incompleto || invalido || aberto || descorrelacionado ? null : terminais[0]?.nome ?? null,
@@ -627,13 +750,18 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
627
750
  estado: terminal.classificacao === 'fase_concluida' ? 'concluida' : 'bloqueada',
628
751
  observadoEm: terminal.timestamp, gate: 'phase.dispatch', origem: 'sessions.watch',
629
752
  morteLatenciaMs: morte ? now - cursor.progressoEm : null, ...(perfil ? { perfil } : {}),
753
+ ...(respostaFinal ? { respostaFinal: { arquivo: (0, trabalho_thread_1.caminhoDoTrabalho)(thread.id) + respostaFinal.arquivo,
754
+ sha256: respostaFinal.sha256, bytes: respostaFinal.bytes, truncada: respostaFinal.truncada } } : {}),
630
755
  ...(conta ? { falhaDeConta: { motivo: conta.falha.motivo, resetEm: conta.falha.resetEm, fonte: conta.falha.fonte,
631
756
  trecho: conta.falha.trecho } } : {}) };
632
757
  const tipo = semTerminal && morte && !incompleto && !conta ? 'sessao_morta' : terminal.classificacao;
633
758
  // I-33 (D12): o perfil sai do rodizio na primeira gravacao do resultado, onde a evidencia esta.
634
759
  if (conta && perfil && !atuais.some(e => e.tipo === 'phase_result' && e.sensorResultId === resultadoId)) {
635
760
  try {
636
- (0, ratelimit_1.marcarContaDaFalha)(carregado, perfil, conta.falha, now);
761
+ const marcado = (0, ratelimit_1.marcarContaDaFalha)(carregado, perfil, conta.falha, now);
762
+ if (marcado?.esgotadoAte)
763
+ contaParaReconciliar = { perfil, falha: conta.falha,
764
+ esgotadoAte: marcado.esgotadoAte, erroEm: terminal.timestamp };
637
765
  }
638
766
  catch { /* store ocupado ou invalido: o retry marca de novo pelo gate tipado */ }
639
767
  }
@@ -646,7 +774,11 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
646
774
  (0, ledger_1.registrar)(dir, thread.id, 'phase_result', dados);
647
775
  return { ...base, bytesLidos, concluido: true, classificacao: terminal.classificacao };
648
776
  });
649
- }) ?? { ...base, ocupado: true };
777
+ });
778
+ const episodio = contaParaReconciliar;
779
+ if (episodio)
780
+ (0, conta_esgotada_1.reconciliarContaEsgotada)({ raiz: carregado.raiz, agoraMs: now, ...episodio });
781
+ return observado ?? { ...base, ocupado: true };
650
782
  }
651
783
  catch (e) {
652
784
  // Thread apagada no meio da observação: encerra sem erro, sem recriar a pasta e sem resíduo.
@@ -655,8 +787,8 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
655
787
  throw e;
656
788
  }
657
789
  }
658
- /** Valida a fonte antes de registro, stderr ou spawn; tambem usada na recuperacao. */
659
- function validarFonteWatcher(raiz, sessionId, fonte) {
790
+ /** Valida vínculo, variante e perfil sem exigir que o runtime já tenha publicado seus metadados. */
791
+ function validarRegistroWatcher(raiz, sessionId, fonte) {
660
792
  const { thread, sessao: registrada } = (0, session_events_1.resolverSessao)(raiz, sessionId);
661
793
  const sessao = (0, session_events_1.exigirSessaoDespachada)(registrada, sessionId);
662
794
  const dir = (0, thread_1.dirThread)(raiz, thread.id);
@@ -669,12 +801,27 @@ function validarFonteWatcher(raiz, sessionId, fonte) {
669
801
  // I-33 (D4): perfil invalido ou divergente do despacho reprova antes de observar pela conta errada.
670
802
  (0, runtime_profiles_1.perfilDoRegistro)([...eventos, ...(fonte ? [{ tipo: 'session_sensor_registered', sessionId,
671
803
  despachoEm: sessao.despachadaEm, ...fonte }] : [])], sessao);
804
+ if (registro.nativo !== undefined && sessao.runtime !== 'claude-bg')
805
+ throw new Error('fonte nativa claude-agents em sessão de outro runtime');
806
+ if (registro.controlador && sessao.runtime !== 'codex')
807
+ throw new Error('fonte do controller Codex em sessão de outro runtime');
808
+ if (registro.grok !== undefined && sessao.runtime !== 'grok')
809
+ throw new Error('fonte do grok em sessão de outro runtime');
810
+ if (sessao.runtime === 'grok' && registro.grok === undefined)
811
+ throw new Error('sessão grok sem a fonte do grok');
812
+ return { thread, sessao, dir, eventos, registro };
813
+ }
814
+ /** Validação profunda feita pelo laço: prontidão eventual nunca impede o registro do vínculo. */
815
+ function validarFonteWatcher(raiz, sessionId, fonte) {
816
+ const { thread, sessao, dir, eventos, registro } = validarRegistroWatcher(raiz, sessionId, fonte);
672
817
  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
818
  (0, session_watcher_claude_1.validarFonteClaude)(eventos, sessionId, registro);
676
819
  return;
677
820
  }
821
+ if (registro.grok !== undefined) {
822
+ (0, session_watcher_grok_1.validarFonteGrok)(eventos, sessionId, registro, dir);
823
+ return;
824
+ }
678
825
  if (registro.controlador) {
679
826
  const despacho = eventos.filter(e => e.tipo === 'phase_dispatch' && e.sessionId === sessionId).at(-1);
680
827
  if (despacho?.controlador !== undefined && despacho.controlador !== registro.controlador)
@@ -690,6 +837,20 @@ function validarFonteWatcher(raiz, sessionId, fonte) {
690
837
  (0, codex_controller_sensor_1.lerSnapshotController)(fixada);
691
838
  }
692
839
  }
840
+ /**
841
+ * No despacho, fixa a fonte que já está pronta e recusa corrupção permanente antes de
842
+ * registrar ou iniciar o watcher. A publicação ainda incompleta do controller é deixada
843
+ * para o laço do watcher, que repete a mesma validação profunda com prazo e diagnóstico.
844
+ */
845
+ function prepararFonteWatcher(raiz, sessionId, fonte) {
846
+ try {
847
+ validarFonteWatcher(raiz, sessionId, fonte);
848
+ }
849
+ catch (e) {
850
+ if (!diagnosticoWatcher(e).transitorio)
851
+ throw e;
852
+ }
853
+ }
693
854
  function iniciarWatcher(raiz, sessionId) {
694
855
  const { thread, sessao: registrada } = (0, session_events_1.resolverSessao)(raiz, sessionId);
695
856
  const sessao = (0, session_events_1.exigirSessaoDespachada)(registrada, sessionId);
@@ -697,7 +858,7 @@ function iniciarWatcher(raiz, sessionId) {
697
858
  // I-34: sessão claude-bg despachada antes do registro nativo ganha a fonte derivada do despacho.
698
859
  if (sessao.runtime === 'claude-bg')
699
860
  (0, session_watcher_claude_1.garantirFonteClaude)(raiz, thread, sessao);
700
- validarFonteWatcher(raiz, sessionId);
861
+ validarRegistroWatcher(raiz, sessionId);
701
862
  const anterior = (0, ledger_1.lerLedger)(dir).filter(e => e.tipo === 'session_watcher_started' &&
702
863
  e.sessionId === sessionId && e.despachoEm === sessao.despachadaEm).at(-1);
703
864
  const identidadeAnterior = anterior?.identidade;
@@ -762,7 +923,7 @@ async function acompanhar() {
762
923
  try {
763
924
  const readyPath = process.argv[5], token = process.argv[6];
764
925
  if (readyPath && token) {
765
- validarFonteWatcher(carregado.raiz, sessionId);
926
+ validarRegistroWatcher(carregado.raiz, sessionId);
766
927
  const sessao = (0, session_events_1.exigirSessaoDespachada)((0, session_events_1.resolverSessao)(carregado.raiz, sessionId, threadId).sessao, sessionId);
767
928
  const identidade = (0, codex_runner_1.identidadeProcesso)(process.pid);
768
929
  if (!identidade)
@@ -33,8 +33,10 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.RUNTIMES_DAS_SESSOES = void 0;
36
37
  exports.pidVivo = pidVivo;
37
38
  exports.ehFantasma = ehFantasma;
39
+ exports.encerradaNaLista = encerradaNaLista;
38
40
  exports.contasDeSessoes = contasDeSessoes;
39
41
  exports.consultarContas = consultarContas;
40
42
  exports.estadosNasContas = estadosNasContas;
@@ -48,6 +50,10 @@ exports.sessoesVivasPorPerfil = sessoesVivasPorPerfil;
48
50
  * perfil do store, sem repetir diretorio, e cada sessao volta com o id do perfil dela (nunca o
49
51
  * diretorio nem nada de dentro dele).
50
52
  *
53
+ * RM-067 (F4): o `grok` entra com a pasta `sessions/` que o proprio runtime grava em cada casa (`GROK_HOME`), lida so
54
+ * pelos nomes e pelo mtime do `updates.jsonl`. A conta do processo dele so entra quando essa pasta existe: maquina sem o
55
+ * `grok` nao ganha fonte nova.
56
+ *
51
57
  * Fantasma (D5): sessao claude-bg com estado nao terminal sem pid, ou com pid sem processo. O
52
58
  * `claude agents` guarda o registro, mas nao ha quem trabalhe: ela nao ocupa vaga, e
53
59
  * `ork sessions limpar-fantasmas` solta o vinculo do `ork` sem tocar no runtime.
@@ -56,6 +62,7 @@ const fs = __importStar(require("node:fs"));
56
62
  const path = __importStar(require("node:path"));
57
63
  const claude_bg_1 = require("./adapters/claude-bg");
58
64
  const codex_1 = require("./adapters/codex");
65
+ const grok_1 = require("./adapters/grok");
59
66
  const runtime_profiles_1 = require("./runtime-profiles");
60
67
  const TERMINAIS = ['done', 'completed', 'exited', 'stopped', 'failed'];
61
68
  const estadoDe = (s) => String(s.state ?? s.status ?? '').trim().toLowerCase();
@@ -75,6 +82,14 @@ function pidVivo(pid) {
75
82
  function ehFantasma(runtime, s, vivo = pidVivo) {
76
83
  return runtime === 'claude-bg' && !TERMINAIS.includes(estadoDe(s)) && !vivo(s.pid);
77
84
  }
85
+ /**
86
+ * RM-037 (ork-rm037esperas, D7): o runtime mostra a sessao encerrada: estado terminal (`done`, `completed`, `exited`,
87
+ * `stopped`, `failed`) ou fantasma, registro sem processo que trabalhe por ele. Domicilio unico dessa leitura: o portao
88
+ * de vaga do `ork phase run` (`vagaDoDespacho`) e a capacidade do #Noctum a usam.
89
+ */
90
+ function encerradaNaLista(s) {
91
+ return s.fantasma || TERMINAIS.includes(estadoDe(s));
92
+ }
78
93
  const real = (dir) => { try {
79
94
  return fs.realpathSync(dir);
80
95
  }
@@ -99,17 +114,26 @@ function contasDeSessoes(raiz, env = process.env) {
99
114
  try {
100
115
  for (const p of (0, runtime_profiles_1.lerPerfis)(raiz).perfis) {
101
116
  const d = (0, runtime_profiles_1.perfilDeDespacho)(p);
102
- incluir(d.runtime, d, (d.configDir ?? d.codexHome));
117
+ if (exports.RUNTIMES_DAS_SESSOES.includes(d.runtime))
118
+ incluir(d.runtime, d, (0, runtime_profiles_1.diretorioDoPerfil)(d));
103
119
  }
104
120
  }
105
121
  catch (e) {
106
122
  fontes.push({ origem: 'perfis de conta (ork accounts)', ok: false, detalhe: e.message });
107
123
  }
108
124
  }
109
- for (const runtime of runtime_profiles_1.RUNTIMES_COM_PERFIL)
125
+ for (const runtime of runtime_profiles_1.RUNTIMES_COM_INVENTARIO)
110
126
  incluir(runtime, null, (0, runtime_profiles_1.diretorioImplicito)(runtime, env));
127
+ const casaGrok = (0, runtime_profiles_1.diretorioImplicito)('grok', env);
128
+ if (fs.existsSync(path.join(casaGrok, 'sessions')))
129
+ incluir('grok', null, casaGrok);
111
130
  return { contas, fontes };
112
131
  }
132
+ /**
133
+ * RM-067 (F4): os runtimes cujas sessoes o `ork sessions` lista por conta. O grok entra aqui, e nao em
134
+ * `RUNTIMES_COM_INVENTARIO`, que tambem diz os runtimes de assinatura do #Noctum (a medicao dele segue sem o grok).
135
+ */
136
+ exports.RUNTIMES_DAS_SESSOES = [...runtime_profiles_1.RUNTIMES_COM_INVENTARIO, 'grok'];
113
137
  const rotulo = (c) => c.perfil ? `perfil ${c.perfil.id}` : 'conta do processo';
114
138
  /**
115
139
  * D4: as sessoes de todas as contas. Consulta que falha vira fonte `ok: false`, nunca "zero
@@ -145,7 +169,7 @@ function consultarContas(raiz, opcoes = {}) {
145
169
  sessoes.push({ ...s, runtime: 'claude-bg', perfil, fantasma, viva: !fantasma && !TERMINAIS.includes(estadoDe(s)) });
146
170
  }
147
171
  }
148
- else {
172
+ else if (conta.runtime === 'codex') {
149
173
  const r = (0, codex_1.consultarRollouts)(opcoes.todas, conta.dir);
150
174
  // A conta do processo segue com o caminho de antes; a do perfil vai pelo id, nunca pela pasta.
151
175
  fontes.push(...(conta.perfil ? r.resultadosFontes.map(f => ({ ...f,
@@ -155,6 +179,17 @@ function consultarContas(raiz, opcoes = {}) {
155
179
  sessoes.push({ ...s, runtime: 'codex', perfil, fantasma: false, viva: estadoDe(s) !== 'completed' && recente });
156
180
  }
157
181
  }
182
+ else if (conta.runtime === 'grok') {
183
+ // RM-067 (F4): a pasta da sessao que o runtime grava; viva e a escrita recente no updates.jsonl, como no codex.
184
+ const r = (0, grok_1.consultarSessoesGrok)(conta.dir);
185
+ const origem = `grok sessions (${rotulo(conta)})`;
186
+ fontes.push(r.ausente ? { origem, ok: true, ausente: true, detalhe: 'nenhuma sessao grok nesta conta ainda' }
187
+ : { origem, ok: r.ok, detalhe: r.detalhe });
188
+ for (const s of r.sessoes) {
189
+ const recente = typeof s.atividadeEm === 'number' && agoraMs - s.atividadeEm <= janelaMs;
190
+ sessoes.push({ ...s, runtime: 'grok', perfil, fantasma: false, viva: recente });
191
+ }
192
+ }
158
193
  }
159
194
  return { sessoes, fontes, contas: base.contas };
160
195
  }
@@ -167,10 +202,12 @@ function consultarContas(raiz, opcoes = {}) {
167
202
  function estadosNasContas(raiz, opcoes = {}) {
168
203
  const r = consultarContas(raiz, opcoes);
169
204
  const claude = r.fontes.filter(f => f.origem.startsWith('claude agents'));
170
- if (claude.length > 0 && !claude.some(f => f.ok) && !r.sessoes.some(s => s.runtime === 'codex'))
205
+ if (claude.length > 0 && !claude.some(f => f.ok) && !r.sessoes.some(s => s.runtime === 'codex' || s.runtime === 'grok'))
171
206
  return null;
207
+ // RM-067 (F4): a sessao grok sem escrita recente fica `idle`; o runtime nao grava estado terminal que o ork leia sem o conteudo.
172
208
  return new Map(r.sessoes.map(s => [s.sessionId,
173
- s.fantasma ? 'fantasma' : s.runtime === 'codex' ? (s.viva ? 'working' : estadoDe(s)) : estadoDe(s)]));
209
+ s.fantasma ? 'fantasma' : s.runtime === 'codex' ? (s.viva ? 'working' : estadoDe(s))
210
+ : s.runtime === 'grok' ? (s.viva ? 'working' : 'idle') : estadoDe(s)]));
174
211
  }
175
212
  /**
176
213
  * RM-056 (D3): sessoes vivas de cada perfil do runtime nesta maquina, a carga do rodizio por
@@ -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
  }