@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
@@ -0,0 +1,327 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PRAZO_MAXIMO_DIAS = exports.ACOES_DA_AUTORIZACAO = exports.ARQUIVO_DA_AUTORIZACAO = exports.CONTRATO_DA_AUTORIZACAO = void 0;
37
+ exports.caminhoDaAutorizacao = caminhoDaAutorizacao;
38
+ exports.lerAutorizacao = lerAutorizacao;
39
+ exports.autorizada = autorizada;
40
+ exports.referenciaDaAutorizacao = referenciaDaAutorizacao;
41
+ exports.linhaDaAutorizacao = linhaDaAutorizacao;
42
+ exports.prazoDoPedido = prazoDoPedido;
43
+ exports.gravarAutorizacao = gravarAutorizacao;
44
+ exports.textoDaAutorizacao = textoDaAutorizacao;
45
+ /**
46
+ * RM-063 (F5): a autorizacao duravel do dono para a varredura agir sozinha nesta maquina.
47
+ *
48
+ * Incidente de 03 a 12/10/2026 (P4 e P5 da pagina da RM-063): o PR #112 foi mesclado e ficou dois dias sem
49
+ * `ork ship registrar-pr`, e as sessoes fantasmas de threads fechadas ficaram registradas, porque nada roda esses
50
+ * comandos sem um condutor. Agora a batida da varredura (`pulse-delivery`) faz isso sozinha, mas SO com a autorizacao
51
+ * do dono gravada nesta maquina, com prazo e com a lista do que ela pode. Sem autorizacao (ou com ela vencida,
52
+ * ilegivel, de outra maquina ou de outro projeto), cada acao vira um item da fila do pulse com o comando pronto.
53
+ *
54
+ * O arquivo e desta maquina e fica fora do git, como o `pulse-host.json` (RM-047):
55
+ * `.orkastery/monitor/autorizacao.json` no checkout canonico. O contrato e `ork.autorizacao-duravel/v1`; a referencia
56
+ * esta em `docs/referencia/contratos/autorizacao-duravel-rm063.md`. A leitura (`lerAutorizacao`) nunca grava; a F7
57
+ * grava pelo `ork conducao autorizar` (`gravarAutorizacao`), ato do dono, na mesma forma que a leitura confere.
58
+ */
59
+ const fs = __importStar(require("node:fs"));
60
+ const path = __importStar(require("node:path"));
61
+ const node_crypto_1 = require("node:crypto");
62
+ const estado_thread_1 = require("./estado-thread");
63
+ const horario_1 = require("./horario");
64
+ const ledger_1 = require("./ledger");
65
+ const master_1 = require("./master");
66
+ const master_nota_1 = require("./master-nota");
67
+ const maquina_1 = require("./maquina");
68
+ const procedencia_1 = require("./procedencia");
69
+ const runtime_ambiente_1 = require("./runtime-ambiente");
70
+ const util_1 = require("./util");
71
+ const locale_1 = require("./locale");
72
+ exports.CONTRATO_DA_AUTORIZACAO = 'ork.autorizacao-duravel/v1';
73
+ exports.ARQUIVO_DA_AUTORIZACAO = 'autorizacao.json';
74
+ /** Um arquivo de autorizacao tem poucas linhas; acima disto, nao e o que o dono gravou. */
75
+ const TETO_DO_ARQUIVO = 64 * 1024;
76
+ /**
77
+ * As acoes do contrato. A varredura da F5 faz `limpar` (sessoes fantasmas), `registrar` (a entrega de PR ja mesclado)
78
+ * e `master` (o MASTER por omissao); a batida da conducao da F7 (`ork conducao batida`) faz tambem `merge` (o PR verde de
79
+ * branch `ork/*`) e `despachar` (a fase seguinte com o prompt gravado). Tag e publicacao nunca entram.
80
+ */
81
+ exports.ACOES_DA_AUTORIZACAO = ['limpar', 'registrar', 'master', 'merge', 'despachar'];
82
+ /** O arquivo da autorizacao desta maquina, no checkout canonico (de dentro de uma worktree, o da raiz). */
83
+ function caminhoDaAutorizacao(raiz) {
84
+ return path.join((0, estado_thread_1.raizDoEstado)(raiz), '.orkastery', 'monitor', exports.ARQUIVO_DA_AUTORIZACAO);
85
+ }
86
+ /** A data e a hora existem no calendario (o `Date.parse` aceitaria 30/02 e o levaria a marco, calado). */
87
+ const noCalendario = (v) => {
88
+ const m = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/.exec(v);
89
+ if (!m)
90
+ return false;
91
+ const [ano, mes, dia, hora, minuto] = m.slice(1).map(Number);
92
+ const d = new Date(Date.UTC(ano, mes - 1, dia));
93
+ return d.getUTCFullYear() === ano && d.getUTCMonth() === mes - 1 && d.getUTCDate() === dia && hora <= 23 && minuto <= 59;
94
+ };
95
+ /** O instante com o fuso explicito (`Z` ou `-03:00`): sem ele, o prazo dependeria do fuso de quem le. */
96
+ const instante = (v) => typeof v === 'string' &&
97
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?(Z|[+-]\d{2}:\d{2})$/.test(v) && noCalendario(v) &&
98
+ Number.isFinite(Date.parse(v));
99
+ const textoCurto = (v, teto) => typeof v === 'string' && v.trim() !== '' && v.length <= teto &&
100
+ !/\p{Cc}/u.test(v);
101
+ /**
102
+ * Le e confere a autorizacao desta maquina. Cada recusa tem motivo tipado e detalhe; so a valida, no prazo, desta
103
+ * maquina e deste projeto, autoriza alguma coisa.
104
+ */
105
+ function lerAutorizacao(raiz, opcoes) {
106
+ const arquivo = caminhoDaAutorizacao(raiz);
107
+ const recusa = (motivo, detalhe, autorizacao) => ({ valida: false, arquivo, motivo, detalhe, ...(autorizacao ? { autorizacao } : {}) });
108
+ const st = fs.lstatSync(arquivo, { throwIfNoEntry: false });
109
+ if (!st)
110
+ return recusa('autorizacao.ausente', 'nenhuma autorizacao duravel gravada nesta maquina');
111
+ // RM-047: como o transporte do pulse, a autorizacao so vale do arquivo local desta maquina.
112
+ if (!st.isFile())
113
+ return recusa('autorizacao.rastreada', 'a autorizacao precisa ser um arquivo comum desta maquina, nao link nem diretorio');
114
+ if ((0, procedencia_1.rastreadoPeloGit)(raiz, arquivo))
115
+ return recusa('autorizacao.rastreada', 'a autorizacao esta versionada no git; ela so vale do arquivo local desta maquina');
116
+ if (st.size > TETO_DO_ARQUIVO)
117
+ return recusa('autorizacao.ilegivel', `o arquivo passa de ${TETO_DO_ARQUIVO} bytes`);
118
+ let bruto, dado;
119
+ try {
120
+ bruto = fs.readFileSync(arquivo, 'utf8');
121
+ const lido = JSON.parse(bruto);
122
+ if (!lido || typeof lido !== 'object' || Array.isArray(lido))
123
+ throw new Error('nao e um objeto JSON');
124
+ dado = lido;
125
+ }
126
+ catch (e) {
127
+ return recusa('autorizacao.ilegivel', `o arquivo nao e JSON valido (${e.message.slice(0, 120)})`);
128
+ }
129
+ if (dado.contrato !== exports.CONTRATO_DA_AUTORIZACAO)
130
+ return recusa('autorizacao.contrato', `o contrato precisa ser ${exports.CONTRATO_DA_AUTORIZACAO}`);
131
+ for (const [campo, teto] of [['maquina', 80], ['projeto', 80], ['por', 120]]) {
132
+ if (!textoCurto(dado[campo], teto))
133
+ return recusa('autorizacao.campo', `o campo ${campo} precisa ser texto de ate ${teto} caracteres`);
134
+ }
135
+ // A autoria e a mesma regra da nota do MASTER: nome de agente, de runtime ou generico nao autoriza nada.
136
+ if (!(0, master_1.autoriaHumana)(dado.por)) {
137
+ return recusa('autorizacao.campo', 'o campo por precisa nomear a pessoa que autorizou; agente, runtime ou nome generico nao autoriza');
138
+ }
139
+ for (const campo of ['concedidaEm', 'ate']) {
140
+ if (!instante(dado[campo])) {
141
+ return recusa('autorizacao.campo', `o campo ${campo} precisa ser um instante ISO com fuso (Z ou -03:00), como 2026-10-18T23:59:00-03:00`);
142
+ }
143
+ }
144
+ if (dado.nota !== undefined && !textoCurto(dado.nota, 300))
145
+ return recusa('autorizacao.campo', 'a nota precisa ser texto de ate 300 caracteres');
146
+ const pode = dado.pode;
147
+ if (!Array.isArray(pode) || pode.length === 0 || pode.some((a) => typeof a !== 'string') || new Set(pode).size !== pode.length) {
148
+ return recusa('autorizacao.campo', 'o campo pode precisa ser uma lista de acoes, sem repeticao');
149
+ }
150
+ const desconhecida = pode.find((a) => !exports.ACOES_DA_AUTORIZACAO.includes(a));
151
+ if (desconhecida !== undefined) {
152
+ return recusa('autorizacao.acao-desconhecida', `a acao ${JSON.stringify(desconhecida)} nao e do contrato (${exports.ACOES_DA_AUTORIZACAO.join(', ')})`);
153
+ }
154
+ const autorizacao = {
155
+ contrato: exports.CONTRATO_DA_AUTORIZACAO, maquina: dado.maquina, projeto: dado.projeto, por: dado.por,
156
+ concedidaEm: dado.concedidaEm, ate: dado.ate, pode: pode,
157
+ ...(typeof dado.nota === 'string' ? { nota: dado.nota } : {}),
158
+ };
159
+ const maquina = opcoes.maquina ?? (0, maquina_1.nomeDaMaquina)();
160
+ if (autorizacao.maquina !== maquina) {
161
+ return recusa('autorizacao.outra-maquina', `a autorizacao e da maquina ${autorizacao.maquina}, e esta e ${maquina}`, autorizacao);
162
+ }
163
+ if (autorizacao.projeto !== opcoes.projeto) {
164
+ return recusa('autorizacao.outro-projeto', `a autorizacao e do projeto ${autorizacao.projeto}, e este e ${opcoes.projeto}`, autorizacao);
165
+ }
166
+ const agora = opcoes.agora ?? new Date();
167
+ if (Date.parse(autorizacao.ate) <= agora.getTime()) {
168
+ return recusa('autorizacao.expirada', `o prazo acabou em ${(0, horario_1.formatarDataHoraRotulada)(autorizacao.ate, { agora: agora.toISOString() })}`, autorizacao);
169
+ }
170
+ return { valida: true, arquivo, autorizacao, sha256: (0, node_crypto_1.createHash)('sha256').update(bruto, 'utf8').digest('hex') };
171
+ }
172
+ /** A acao esta autorizada agora? */
173
+ function autorizada(leitura, acao) {
174
+ return leitura.valida && leitura.autorizacao.pode.includes(acao);
175
+ }
176
+ /** A referencia que vai ao ledger com cada acao feita: quem autorizou, ate quando e qual arquivo. */
177
+ function referenciaDaAutorizacao(leitura) {
178
+ if (!leitura.valida)
179
+ return null;
180
+ const a = leitura.autorizacao;
181
+ return { contrato: a.contrato, por: a.por, ate: a.ate, pode: a.pode, sha256: leitura.sha256, ...(a.nota ? { nota: a.nota } : {}) };
182
+ }
183
+ /** Uma linha para o `ork fabrica batida status` e para o pulse. */
184
+ function linhaDaAutorizacao(leitura, agora = new Date().toISOString()) {
185
+ const m = (0, locale_1.msg)().conducao.autorizacao;
186
+ if (leitura.valida) {
187
+ const a = leitura.autorizacao;
188
+ return m.linhaValida(a.por, (0, horario_1.formatarDataHoraRotulada)(a.ate, { agora }), a.pode.join(', '));
189
+ }
190
+ if (leitura.motivo === 'autorizacao.ausente') {
191
+ return m.linhaAusente;
192
+ }
193
+ return m.linhaInvalida(leitura.motivo, leitura.detalhe);
194
+ }
195
+ // ---------------------------------------------------------------------------
196
+ // RM-063 (F7): a gravacao, pelo `ork conducao autorizar`.
197
+ // ---------------------------------------------------------------------------
198
+ /** O que nunca entra na autorizacao duravel, nem com o nome que o dono der: fica sempre com ele. */
199
+ const ACOES_PROIBIDAS = ['tag', 'tags', 'publicar', 'publicacao', 'publicação', 'release', 'publish', 'npm', 'versao', 'versão'];
200
+ /**
201
+ * O prazo mais longo que uma autorizacao pode ter: o dono renova quando quiser, e a permissao esquecida nao vale para
202
+ * sempre.
203
+ */
204
+ exports.PRAZO_MAXIMO_DIAS = 31;
205
+ /**
206
+ * O prazo do `--ate`, sempre com o fuso escrito. Instante com fuso vale como veio; so a data vale ate 23:59 dela no fuso
207
+ * do dono; data e hora sem fuso, no fuso do dono. O resto e recusado: o prazo nao e adivinhado.
208
+ */
209
+ function prazoDoPedido(bruto, fuso) {
210
+ const v = bruto.trim();
211
+ if (instante(v))
212
+ return v;
213
+ const m = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2}))?$/.exec(v);
214
+ const nome = (0, horario_1.normalizarFuso)(fuso);
215
+ if (!m || !nome)
216
+ return null;
217
+ const hora = m[4] ? Number(m[4]) : 23, minuto = m[5] ? Number(m[5]) : 59;
218
+ if (hora > 23 || minuto > 59)
219
+ return null;
220
+ const ms = (0, horario_1.instanteNoFuso)(Number(m[1]), Number(m[2]), Number(m[3]), hora, minuto, nome);
221
+ return Number.isFinite(ms) ? (0, horario_1.isoComFuso)(ms, nome) : null;
222
+ }
223
+ /** O `user.name` do git do checkout, quando nomeia uma pessoa. */
224
+ function autorDoGit(raiz) {
225
+ const r = (0, util_1.exec)('git', ['config', 'user.name'], (0, estado_thread_1.raizDoEstado)(raiz), 10000);
226
+ const nome = r.ok ? r.stdout.trim() : '';
227
+ return nome && textoCurto(nome, 120) && (0, master_1.autoriaHumana)(nome) ? nome : null;
228
+ }
229
+ /**
230
+ * RM-063 (F7): grava a autorizacao duravel do dono nesta maquina, na forma que `lerAutorizacao` confere. E ato do dono:
231
+ * a sessao despachada pelo `ork` (com a identidade de despacho no ambiente) nunca concede autorizacao a si mesma. O
232
+ * arquivo novo substitui o anterior inteiro, e cada concessao vai ao ledger do projeto (`autorizacao_concedida`), com a
233
+ * que ela substituiu. Tag e publicacao nunca entram, nem com outro nome.
234
+ */
235
+ function gravarAutorizacao(raiz, pedido) {
236
+ const recusa = (motivo, detalhe) => ({ ok: false, motivo, detalhe });
237
+ const ambiente = pedido.ambiente ?? process.env;
238
+ if ((ambiente[runtime_ambiente_1.ENV_IDENTIDADE_DE_DESPACHO] ?? '').trim() || (ambiente[runtime_ambiente_1.ENV_THREAD_DO_DESPACHO] ?? '').trim()) {
239
+ return recusa('autorizacao.sessao-despachada', 'a autorização durável é ato do dono: uma sessão despachada pelo ork não a concede ' +
240
+ '(rode no terminal do dono, fora da sessão da fase)');
241
+ }
242
+ // A mesma regra da nota do MASTER em nome de pessoa (D8): de dentro de um host de agente (Claude Code, Codex, Hermes,
243
+ // OpenClaw), quem escreve o --por e o agente. O dono autoriza no proprio terminal.
244
+ const host = (0, master_nota_1.marcaDeHost)(ambiente);
245
+ if (host) {
246
+ return recusa('autorizacao.host', `a autorização durável é ato do dono no terminal dele: vinda de ${host}, ela não vale ` +
247
+ '(o agente não autoriza a si mesmo)');
248
+ }
249
+ const agora = pedido.agora ?? new Date();
250
+ const ate = prazoDoPedido(pedido.ate, pedido.fuso);
251
+ if (!ate) {
252
+ return recusa('autorizacao.ate-invalido', `--ate ${JSON.stringify(pedido.ate)} não é um prazo: use 2026-10-18 (até 23:59 no fuso ` +
253
+ `${pedido.fuso}), 2026-10-18T18:00 ou um instante com fuso, como 2026-10-18T23:59:00-03:00`);
254
+ }
255
+ if (Date.parse(ate) <= agora.getTime()) {
256
+ return recusa('autorizacao.ate-passado', `o prazo ${(0, horario_1.formatarDataHoraRotulada)(ate, { agora: agora.toISOString() })} já passou`);
257
+ }
258
+ if (Date.parse(ate) - agora.getTime() > exports.PRAZO_MAXIMO_DIAS * 24 * 60 * 60 * 1000) {
259
+ return recusa('autorizacao.ate-longe', `o prazo vai além de ${exports.PRAZO_MAXIMO_DIAS} dias: autorize por menos e renove quando quiser`);
260
+ }
261
+ const pode = pedido.pode.split(',').map((a) => a.trim().toLowerCase()).filter(Boolean);
262
+ if (!pode.length)
263
+ return recusa('autorizacao.pode-vazio', `--pode precisa de pelo menos uma ação (${exports.ACOES_DA_AUTORIZACAO.join(', ')})`);
264
+ if (new Set(pode).size !== pode.length)
265
+ return recusa('autorizacao.pode-repetido', '--pode repete uma ação');
266
+ const proibida = pode.find((a) => ACOES_PROIBIDAS.includes(a));
267
+ if (proibida) {
268
+ return recusa('autorizacao.acao-proibida', `${JSON.stringify(proibida)}: tag e publicação nunca entram na autorização durável; ` +
269
+ 'ficam sempre com o dono');
270
+ }
271
+ const desconhecida = pode.find((a) => !exports.ACOES_DA_AUTORIZACAO.includes(a));
272
+ if (desconhecida !== undefined) {
273
+ return recusa('autorizacao.acao-desconhecida', `a ação ${JSON.stringify(desconhecida)} não é do contrato (${exports.ACOES_DA_AUTORIZACAO.join(', ')})`);
274
+ }
275
+ const por = (pedido.por ?? '').trim() || autorDoGit(raiz);
276
+ if (!por || !textoCurto(por, 120) || !(0, master_1.autoriaHumana)(por)) {
277
+ return recusa('autorizacao.por', por ? `--por ${JSON.stringify(por)} não nomeia uma pessoa (agente, runtime ou nome genérico não autoriza)`
278
+ : 'informe --por <seu nome>: o git deste checkout não tem user.name de uma pessoa');
279
+ }
280
+ const nota = (pedido.nota ?? '').trim();
281
+ if (nota && !textoCurto(nota, 300))
282
+ return recusa('autorizacao.nota', 'a nota precisa ser texto de até 300 caracteres, sem controle');
283
+ const arquivo = caminhoDaAutorizacao(raiz);
284
+ const st = fs.lstatSync(arquivo, { throwIfNoEntry: false });
285
+ if ((st && !st.isFile()) || (0, procedencia_1.rastreadoPeloGit)(raiz, arquivo)) {
286
+ return recusa('autorizacao.rastreada', `${arquivo} está no git, ou é link ou diretório: a autorização só vale do arquivo local desta máquina`);
287
+ }
288
+ const lida = lerAutorizacao(raiz, { projeto: pedido.projeto, agora, maquina: pedido.maquina });
289
+ const anterior = lida.valida ? lida.autorizacao : null;
290
+ const autorizacao = {
291
+ contrato: exports.CONTRATO_DA_AUTORIZACAO, maquina: pedido.maquina ?? (0, maquina_1.nomeDaMaquina)(), projeto: pedido.projeto, por,
292
+ concedidaEm: (0, horario_1.isoComFuso)(agora.getTime(), (0, horario_1.normalizarFuso)(pedido.fuso) ?? 'UTC'), ate, pode: pode,
293
+ ...(nota ? { nota } : {}),
294
+ };
295
+ fs.mkdirSync(path.dirname(arquivo), { recursive: true });
296
+ const temporario = `${arquivo}.${process.pid}.${(0, node_crypto_1.randomUUID)().slice(0, 8)}.tmp`;
297
+ try {
298
+ fs.writeFileSync(temporario, JSON.stringify(autorizacao, null, 2) + '\n', { encoding: 'utf8', mode: 0o600, flag: 'wx' });
299
+ fs.renameSync(temporario, arquivo);
300
+ }
301
+ finally {
302
+ fs.rmSync(temporario, { force: true });
303
+ }
304
+ const leitura = lerAutorizacao(raiz, { projeto: pedido.projeto, agora, maquina: pedido.maquina });
305
+ if (!leitura.valida)
306
+ throw new Error(`a autorização gravada não foi aceita na releitura (${leitura.motivo}: ${leitura.detalhe})`);
307
+ try {
308
+ (0, ledger_1.registrar)(path.join((0, estado_thread_1.raizDoEstado)(raiz), '.orkastery'), 'projeto', ledger_1.TIPOS_DE_EVENTO.autorizacaoConcedida, {
309
+ maquina: autorizacao.maquina, por, concedidaEm: autorizacao.concedidaEm, ate, pode, ...(nota ? { nota } : {}),
310
+ sha256: leitura.sha256, canal: pedido.canal ?? null,
311
+ substituiu: anterior ? { por: anterior.por, ate: anterior.ate, pode: anterior.pode } : null,
312
+ });
313
+ }
314
+ catch { /* o arquivo e a autorizacao; o ledger do projeto e o rastro, e a releitura ja provou o arquivo */ }
315
+ return { ok: true, leitura, anterior };
316
+ }
317
+ /** O texto do `ork conducao autorizacao`: a vigente, ou por que nao ha, e o que isso quer dizer para a batida. */
318
+ function textoDaAutorizacao(leitura, agora = new Date().toISOString()) {
319
+ const m = (0, locale_1.msg)().conducao.autorizacao;
320
+ if (!leitura.valida) {
321
+ return [m.sem(leitura.motivo, leitura.detalhe), m.semEfeito, m.autorizar].join('\n');
322
+ }
323
+ const a = leitura.autorizacao;
324
+ return [m.valida(a.por, (0, horario_1.formatarDataHoraRotulada)(a.ate, { agora }), a.pode.join(', ')),
325
+ m.concedida((0, horario_1.formatarDataHoraRotulada)(a.concedidaEm, { agora }), a.maquina, a.projeto, a.nota ?? ''),
326
+ m.arquivo(leitura.arquivo, leitura.sha256.slice(0, 12)), m.limite].join('\n');
327
+ }
package/dist/board.js CHANGED
@@ -50,7 +50,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
50
50
  exports.perfisDetectados = perfisDetectados;
51
51
  exports.threadsDeTodosOsPerfis = threadsDeTodosOsPerfis;
52
52
  exports.estadosDeSessao = estadosDeSessao;
53
+ exports.leituraDoRuntime = leituraDoRuntime;
54
+ exports.leituraReaproveitada = leituraReaproveitada;
53
55
  exports.vagaDoDespacho = vagaDoDespacho;
56
+ exports.sessoesQueOcupam = sessoesQueOcupam;
54
57
  exports.esperarVaga = esperarVaga;
55
58
  exports.planejar = planejar;
56
59
  exports.devolverVagas = devolverVagas;
@@ -128,6 +131,31 @@ function estadosDeSessao(raiz = null, staleMin) {
128
131
  return null;
129
132
  return (0, sessoes_contas_1.estadosNasContas)(raiz, { staleMin });
130
133
  }
134
+ /** Prazo da consulta do runtime, por conta, dentro do portao: ele roda no despacho e nao pode prende-lo. */
135
+ const PRAZO_DA_CONSULTA_MS = 20_000;
136
+ /** As sessoes de todas as contas, com `--all`: a sessao parada (`stopped`) so aparece nessa lista (medido em 12/10/2026). */
137
+ function leituraDoRuntime(carregado) {
138
+ return () => (0, sessoes_contas_1.consultarContas)(carregado.raiz, { todas: true, staleMin: carregado.manifesto.concurrency.stale_after_min, prazoMs: PRAZO_DA_CONSULTA_MS });
139
+ }
140
+ /** A mesma leitura reaproveitada por `janelaMs`: quem espera a vaga nao consulta o runtime a cada volta. */
141
+ function leituraReaproveitada(ler, janelaMs, relogio = Date.now) {
142
+ let guardada = null;
143
+ return () => {
144
+ const agoraMs = relogio();
145
+ if (!guardada || agoraMs - guardada.em >= janelaMs)
146
+ guardada = { em: agoraMs, leitura: ler() };
147
+ return guardada.leitura;
148
+ };
149
+ }
150
+ /** As sessoes que o runtime mostra encerradas. Leitura que lanca nao prova nada: nenhuma sai da conta. */
151
+ function encerradasNoRuntime(ler) {
152
+ try {
153
+ return new Set(ler().sessoes.filter(sessoes_contas_1.encerradaNaLista).map((s) => s.sessionId));
154
+ }
155
+ catch {
156
+ return new Set();
157
+ }
158
+ }
131
159
  /**
132
160
  * RM-037 (rm037defeito, defeito 3): o portao de vaga do `ork phase run`. Com `max_parallel_threads: 5`,
133
161
  * um sexto despacho saiu as 09h03 de 29/09/2026 com cinco sessoes vivas: o `phase run` nao consultava
@@ -142,9 +170,41 @@ function estadosDeSessao(raiz = null, staleMin) {
142
170
  */
143
171
  function vagaDoDespacho(carregado, threadId, quando = (0, util_1.agora)(),
144
172
  /** S-5 do CHECK 3: o `desde` da tomada deste despacho; despacho em curso de outra thread so conta se veio antes. */
145
- desdeProprio) {
173
+ desdeProprio,
174
+ /** RM-037 (ork-rm037esperas, D6): a leitura do runtime no limite; sem ela, a de todas as contas com `--all`. */
175
+ lerRuntime) {
176
+ const limite = Math.max(1, carregado.manifesto.concurrency.max_parallel_threads);
177
+ let ocupam = sessoesQueOcupam(carregado, { exceto: threadId, quando, desdeProprio });
178
+ if (ocupam.length < limite)
179
+ return null;
180
+ // RM-037 (ork-rm037esperas, D6): no limite, a sessao que o runtime mostra encerrada (estado terminal ou fantasma) nao
181
+ // trabalha mais, mesmo com o lease de pe, e sai da conta: em 12/10/2026, uma sessao parada com `claude stop` antes do
182
+ // `phase_result` prendia a vaga ate a thread fechar. So no limite, para o despacho comum nao pagar a consulta; a
183
+ // sessao ausente da lista e a leitura que falha continuam contando.
184
+ if (ocupam.some((o) => o.sessao !== null)) {
185
+ const encerradas = encerradasNoRuntime(lerRuntime ?? leituraDoRuntime(carregado));
186
+ ocupam = ocupam.filter((o) => o.sessao === null || !encerradas.has(o.sessao));
187
+ if (ocupam.length < limite)
188
+ return null;
189
+ }
190
+ return {
191
+ limite,
192
+ ocupam,
193
+ detalhe: `concurrency.limite: o projeto ja tem ${ocupam.length} sessao(oes) viva(s) em outras threads e o limite e ${limite} ` +
194
+ `(concurrency.max_parallel_threads): ${ocupam.map((o) => `${o.thread} ${o.fase ?? '-'} ` +
195
+ (o.sessao ? `${o.runtime} ${o.sessao.slice(0, 8)}` : 'despacho em curso')).join('; ')}`,
196
+ correcao: 'espere uma sessao terminar e repita com --esperar <min>; sessao que morreu sem evento sai com ' +
197
+ 'ork conducao status <thread>; ou suba concurrency.max_parallel_threads no orkastery.yaml',
198
+ };
199
+ }
200
+ /**
201
+ * As vagas do projeto ocupadas agora, pela regra do portao de vaga do despacho (`vagaDoDespacho`): a conducao de uma
202
+ * sessao viva (salvo a parada ou escalada) e o despacho em curso. RM-063 (F6): a maquina ociosa conta por aqui. `exceto`
203
+ * tira a propria thread; `desdeProprio` desempata dois despachos pela ultima vaga. Somente leitura, mais antiga primeiro.
204
+ */
205
+ function sessoesQueOcupam(carregado, opcoes = {}) {
146
206
  const { raiz, manifesto } = carregado;
147
- const limite = Math.max(1, manifesto.concurrency.max_parallel_threads);
207
+ const quando = opcoes.quando ?? (0, util_1.agora)(), desdeProprio = opcoes.desdeProprio, threadId = opcoes.exceto ?? '';
148
208
  const staleMin = manifesto.concurrency.stale_after_min;
149
209
  const ocupam = [];
150
210
  for (const id of (0, thread_1.listarIds)(raiz)) {
@@ -176,24 +236,17 @@ desdeProprio) {
176
236
  sessao: atual.dono.tipo === 'sessao' ? atual.dono.sessionId : null,
177
237
  runtime: atual.dono.tipo === 'sessao' ? atual.dono.runtime : null });
178
238
  }
179
- if (ocupam.length < limite)
180
- return null;
181
- ocupam.sort((a, b) => a.desde.localeCompare(b.desde));
182
- return {
183
- limite,
184
- ocupam,
185
- detalhe: `concurrency.limite: o projeto ja tem ${ocupam.length} sessao(oes) viva(s) em outras threads e o limite e ${limite} ` +
186
- `(concurrency.max_parallel_threads): ${ocupam.map((o) => `${o.thread} ${o.fase ?? '-'} ` +
187
- (o.sessao ? `${o.runtime} ${o.sessao.slice(0, 8)}` : 'despacho em curso')).join('; ')}`,
188
- correcao: 'espere uma sessao terminar e repita com --esperar <min>; sessao que morreu sem evento sai com ' +
189
- 'ork conducao status <thread>; ou suba concurrency.max_parallel_threads no orkastery.yaml',
190
- };
239
+ return ocupam.sort((a, b) => a.desde.localeCompare(b.desde));
191
240
  }
192
241
  /** `--esperar`: espera a vaga do projeto ate o prazo. Devolve true quando ha vaga. */
193
- function esperarVaga(carregado, threadId, esperarMs) {
242
+ function esperarVaga(carregado, threadId, esperarMs,
243
+ /** RM-037 (ork-rm037esperas, D6): a leitura do runtime; os testes injetam a deles. */
244
+ ler = leituraDoRuntime(carregado)) {
194
245
  const prazo = Date.now() + esperarMs;
246
+ // RM-037 (ork-rm037esperas, D6): a leitura do runtime vale 30 s nesta espera, e nao uma consulta a cada volta.
247
+ const lerRuntime = leituraReaproveitada(ler, 30_000);
195
248
  for (;;) {
196
- if (!vagaDoDespacho(carregado, threadId))
249
+ if (!vagaDoDespacho(carregado, threadId, undefined, undefined, lerRuntime))
197
250
  return true;
198
251
  if (Date.now() >= prazo)
199
252
  return false;
@@ -429,34 +482,35 @@ function devolverVagas(carregado, opcoes = {}) {
429
482
  }
430
483
  /** Texto de `ork board reap`. */
431
484
  function textoDoReap(devolvidas) {
485
+ const m = (0, locale_1.msg)().operacao.restante.board;
432
486
  if (devolvidas.length === 0) {
433
- return 'Nenhuma vaga a devolver: toda thread aberta tem procura ativa ou esta pronta para rodar.';
487
+ return m.reapVazio;
434
488
  }
435
489
  // I-35: o ledger guarda o ISO; o texto ao dono sai no fuso dele, rotulado uma vez.
436
- const linhas = [`Vagas devolvidas por falta de procura ativa: ${devolvidas.length}. ${(0, horario_1.legendaDoFuso)()}`, ''];
490
+ const linhas = [m.reapTitulo(devolvidas.length, (0, horario_1.legendaDoFuso)()), ''];
437
491
  for (const d of devolvidas) {
438
- const marca = d.registrada ? 'slot_released gravado no ledger' : 'ja registrado antes (idempotente)';
492
+ const marca = d.registrada ? m.reapMarca.gravada : m.reapMarca.anterior;
439
493
  linhas.push(` ${d.thread.padEnd(20)} [${d.motivo}] ${marca}`);
440
- linhas.push(` detalhe : ${(0, horario_1.localizarTexto)(d.detalhe)}`);
441
- linhas.push(` evidencia: ${(0, horario_1.localizarTexto)(d.evidencia)}`);
494
+ linhas.push(m.detalhe((0, horario_1.localizarTexto)(d.detalhe)));
495
+ linhas.push(m.evidencia((0, horario_1.localizarTexto)(d.evidencia)));
442
496
  }
443
497
  return linhas.join('\n');
444
498
  }
445
499
  function linhaDeFila(p, i, agora) {
446
- return ` ${i + 1}. ${p.thread} quer ${p.nome} (colide com ${p.colidiuCom}, thread ${p.bloqueadaPor}) desde ${(0, horario_1.formatarDesde)(p.desdeEm, { agora })}`;
500
+ return (0, locale_1.msg)().operacao.restante.board.filaItem(i + 1, p.thread, p.nome, p.colidiuCom, p.bloqueadaPor, (0, horario_1.formatarDesde)(p.desdeEm, { agora }));
447
501
  }
448
502
  /** Texto de `ork board plan`. */
449
503
  function textoDoPlano(plano) {
504
+ const m = (0, locale_1.msg)().operacao.restante.board;
450
505
  const linhas = [];
451
- linhas.push(`Escalonador por maquina. ${(0, horario_1.legendaDoFuso)(undefined, plano.decididoEm)}`);
452
- linhas.push(` limite de paralelismo: ${plano.maxParalelas} (concurrency.max_parallel_threads) | ` +
453
- `em andamento agora (procura ativa): ${plano.emAndamento}`);
506
+ linhas.push(m.planoTitulo((0, horario_1.legendaDoFuso)(undefined, plano.decididoEm)));
507
+ linhas.push(m.limite(plano.maxParalelas, plano.emAndamento));
454
508
  linhas.push('');
455
509
  if (plano.vagas.length === 0) {
456
- linhas.push(' Nenhuma thread no projeto.');
510
+ linhas.push(m.nenhumaThread);
457
511
  }
458
512
  else {
459
- linhas.push((0, util_1.tabela)(['THREAD', 'SLUG', 'MODO', 'FASE', 'SITUACAO', 'MOTIVO', 'DETALHE'], plano.vagas.map((v) => [
513
+ linhas.push((0, util_1.tabela)([...m.colunasPlano], plano.vagas.map((v) => [
460
514
  v.thread,
461
515
  v.slug,
462
516
  (0, modos_1.tagDoModo)(v.modo),
@@ -468,23 +522,23 @@ function textoDoPlano(plano) {
468
522
  const comCorrecao = plano.vagas.filter((v) => v.correcao !== '');
469
523
  if (comCorrecao.length > 0) {
470
524
  linhas.push('');
471
- linhas.push(' Correcoes acionaveis:');
525
+ linhas.push(m.correcoes);
472
526
  for (const v of comCorrecao)
473
527
  linhas.push(` ${v.thread}: ${(0, horario_1.localizarTexto)(v.correcao, { agora: plano.decididoEm })}`);
474
528
  }
475
529
  }
476
530
  linhas.push('');
477
- linhas.push(`Merge queue (lease ${leases_1.LEASE_MAIN_TREE}, o unico gate de merge)`);
531
+ linhas.push(m.merge);
478
532
  if (plano.filaDeMerge.length === 0) {
479
- linhas.push(' vazia: nenhuma thread esperando para mergear');
533
+ linhas.push(m.mergeVazia);
480
534
  }
481
535
  else {
482
536
  plano.filaDeMerge.forEach((p, i) => linhas.push(linhaDeFila(p, i, plano.decididoEm)));
483
537
  }
484
538
  linhas.push('');
485
- linhas.push('Fila por colisao de regiao');
539
+ linhas.push(m.regiao);
486
540
  if (plano.filaDeRegiao.length === 0) {
487
- linhas.push(' vazia: nenhuma colisao de path, board ou porta');
541
+ linhas.push(m.regiaoVazia);
488
542
  }
489
543
  else {
490
544
  plano.filaDeRegiao.forEach((p, i) => linhas.push(linhaDeFila(p, i, plano.decididoEm)));
@@ -493,17 +547,17 @@ function textoDoPlano(plano) {
493
547
  }
494
548
  /** Texto de `ork board [--all]`: a visao unica das threads. */
495
549
  function textoDoBoard(carregado, todos) {
550
+ const m = (0, locale_1.msg)().operacao.restante.board;
496
551
  const itens = threadsDeTodosOsPerfis(carregado, todos);
497
552
  const perfis = todos ? perfisDetectados(carregado) : perfisDetectados(carregado).slice(0, 1);
498
553
  const linhas = [];
499
- linhas.push(`Board do Orkastery, projeto ${carregado.manifesto.project.name} ` +
500
- `(${itens.length} thread(s) em ${perfis.length} perfil(is): ${perfis.map((p) => p.nome).join(', ')})`);
554
+ linhas.push(m.titulo(carregado.manifesto.project.name, itens.length, perfis.length, perfis.map((p) => p.nome).join(', ')));
501
555
  linhas.push('');
502
556
  if (itens.length === 0) {
503
- linhas.push(' Nenhuma thread ainda. Crie uma com: ork thread new "<nome>" --modo default');
557
+ linhas.push(m.vazio);
504
558
  return linhas.join('\n');
505
559
  }
506
- linhas.push((0, util_1.tabela)(['PERFIL', 'ID', 'SLUG', 'MODO', 'FASE', 'STATUS', 'PAUSAS', 'SCORE', 'WORKTREE', 'LEASES'], itens.map((i) => [
560
+ linhas.push((0, util_1.tabela)([...m.colunas], itens.map((i) => [
507
561
  i.perfil,
508
562
  i.thread.id,
509
563
  i.thread.slug,
@@ -519,14 +573,14 @@ function textoDoBoard(carregado, todos) {
519
573
  const conduzidas = itens.map((i) => ({ id: i.thread.id, c: (0, conducao_1.conducaoDaThread)(i.raiz, i.thread.id) })).filter((x) => x.c);
520
574
  if (conduzidas.length > 0) {
521
575
  linhas.push('');
522
- linhas.push('Conducao agora');
576
+ linhas.push(m.conducao);
523
577
  for (const x of conduzidas)
524
578
  linhas.push(` ${x.id}: ${(0, conducao_texto_1.linhaDeConducao)(x.c)}`);
525
579
  }
526
580
  const comVariante = itens.filter((i) => i.thread.variante);
527
581
  if (comVariante.length > 0) {
528
582
  linhas.push('');
529
- linhas.push(' Variantes de ciclo em uso:');
583
+ linhas.push(m.variantes);
530
584
  for (const i of comVariante)
531
585
  linhas.push(` ${i.thread.id}: --ciclo ${i.thread.variante}`);
532
586
  }
@@ -535,8 +589,8 @@ function textoDoBoard(carregado, todos) {
535
589
  const semScore = itens.filter((i) => !i.thread.score && i.thread.faseAtual === 'MASTER');
536
590
  if (semScore.length > 0) {
537
591
  linhas.push('');
538
- linhas.push(`Fila de batch scoring: ${semScore.length} thread(s) esperando score humano`);
539
- linhas.push(' veja em: ork master (com o indice derivado do ledger)');
592
+ linhas.push(m.batch(semScore.length));
593
+ linhas.push(m.batchVeja);
540
594
  }
541
595
  return linhas.join('\n');
542
596
  }