@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
@@ -42,6 +42,7 @@ exports.faseJaFeita = faseJaFeita;
42
42
  exports.bloqueioDepoisDoDespacho = bloqueioDepoisDoDespacho;
43
43
  exports.passoDaThread = passoDaThread;
44
44
  exports.passosDoCondutor = passosDoCondutor;
45
+ exports.passoDeQuemAge = passoDeQuemAge;
45
46
  exports.statusDaSentinela = statusDaSentinela;
46
47
  exports.textoDoStatusDaSentinela = textoDoStatusDaSentinela;
47
48
  /**
@@ -52,7 +53,8 @@ exports.textoDoStatusDaSentinela = textoDoStatusDaSentinela;
52
53
  * Dois fatos moram aqui, e so aqui:
53
54
  *
54
55
  * - a PRESENCA dela nesta maquina, com prazo curto renovado pela batida: enquanto ela vale, o condutor externo cede
55
- * o despacho e o retry; vencida (a sessao do dono fechou), ele volta a conduzir sozinho, como reserva;
56
+ * o despacho e o retry, menos a retomada por cota (RM-064 T5, `passosDaBatida`); vencida (a sessao do dono fechou),
57
+ * ele volta a conduzir sozinho, como reserva;
56
58
  * - o PASSO DO CONDUTOR de cada thread aberta, calculado com as mesmas leituras do pulse (`entregasDoProjeto`,
57
59
  * `esperaDoCondutor`), sem o limiar de 30 min e sem ler a forja. No #Auto, depois de uma fase concluida, sai a
58
60
  * fase seguinte a prova mais adiantada que a sessao do bloco deixou (artefato gravado depois do despacho, produto
@@ -69,8 +71,10 @@ const estado_thread_1 = require("./estado-thread");
69
71
  const ledger_1 = require("./ledger");
70
72
  const manifest_1 = require("./manifest");
71
73
  const maquina_1 = require("./maquina");
74
+ const noctum_guarda_1 = require("./noctum-guarda");
72
75
  const parado_no_condutor_1 = require("./parado-no-condutor");
73
76
  const thread_1 = require("./thread");
77
+ const locale_1 = require("./locale");
74
78
  var conducao_2 = require("./conducao");
75
79
  Object.defineProperty(exports, "CANAL_DA_SENTINELA", { enumerable: true, get: function () { return conducao_2.CANAL_DA_SENTINELA; } });
76
80
  Object.defineProperty(exports, "CONTRATO_DA_SENTINELA", { enumerable: true, get: function () { return conducao_2.CONTRATO_DA_SENTINELA; } });
@@ -343,6 +347,8 @@ function temPedidoGuardado(raiz, t) {
343
347
  function passosDoCondutor(carregado, opcoes = {}) {
344
348
  const quando = opcoes.quando ?? new Date().toISOString();
345
349
  const entregas = (0, parado_no_condutor_1.entregasDoProjeto)(carregado, { quando, limiarMin: 0 });
350
+ // RM-058, integracao (T1.2): os arcos desta raiz, lidos uma vez para todas as threads.
351
+ const arcos = (0, noctum_guarda_1.lerArcosDaRaiz)(carregado.raiz, quando);
346
352
  const passos = [];
347
353
  for (const estado of entregas.estados) {
348
354
  let t;
@@ -357,10 +363,21 @@ function passosDoCondutor(carregado, opcoes = {}) {
357
363
  eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(carregado.raiz, t.id));
358
364
  }
359
365
  catch { /* ledger ilegivel: sem bloqueio */ }
360
- passos.push(passoDaThread(t, estado, eventos, temPedidoGuardado(carregado.raiz, t), (fase) => faseJaFeita(carregado.raiz, t, fase, estado, eventos), (0, parado_no_condutor_1.pendenciaDoDono)(t, eventos, quando)));
366
+ const passo = passoDaThread(t, estado, eventos, temPedidoGuardado(carregado.raiz, t), (fase) => faseJaFeita(carregado.raiz, t, fase, estado, eventos), (0, parado_no_condutor_1.pendenciaDoDono)(t, eventos, quando));
367
+ const arco = (0, noctum_guarda_1.arcoDoPasso)(carregado.raiz, arcos, t.id, eventos);
368
+ passos.push(arco ? { ...passo, arco } : passo);
361
369
  }
362
370
  return passos.sort((a, b) => (a.thread < b.thread ? -1 : a.thread > b.thread ? 1 : 0));
363
371
  }
372
+ /**
373
+ * RM-058, integracao (T1.2): o passo como quem age o le. A thread que o arco segura nao tem acao nenhuma de fora; a que ele
374
+ * retem nao e despachada nem retomada. O motivo vai no `porque`, e o passo do nucleo (o da fila do arco) nao muda.
375
+ */
376
+ function passoDeQuemAge(p) {
377
+ if (!p.arco || (p.arco.efeito === 'retencao' && p.acao !== 'despachar' && p.acao !== 'retomar'))
378
+ return p;
379
+ return { ...p, acao: 'nada', fase: null, porque: p.arco.detalhe };
380
+ }
364
381
  /** O `ork conducao sentinela status`: a presenca desta maquina e o passo do condutor em cada thread aberta. */
365
382
  function statusDaSentinela(carregado, opcoes = {}) {
366
383
  const agora = opcoes.agora ?? new Date();
@@ -368,20 +385,20 @@ function statusDaSentinela(carregado, opcoes = {}) {
368
385
  return {
369
386
  contrato: conducao_1.CONTRATO_DA_SENTINELA, consultadoEm: agora.toISOString(), maquina,
370
387
  presenca: presencaDaSentinela(carregado.raiz, { agora, maquina }),
371
- threads: passosDoCondutor(carregado, { quando: agora.toISOString() }),
388
+ // RM-058, integracao (T1.2): a Sentinela despacha o que este status diz; a thread do arco sai com `nada` e o motivo.
389
+ threads: passosDoCondutor(carregado, { quando: agora.toISOString() }).map(passoDeQuemAge),
372
390
  };
373
391
  }
374
392
  /** O status em texto, para o terminal. */
375
393
  function textoDoStatusDaSentinela(s) {
394
+ const m = (0, locale_1.msg)().conducao.sentinela;
376
395
  const linhas = [];
377
396
  const p = s.presenca;
378
- linhas.push(!p ? `Sentinela: desligada na maquina ${s.maquina}; o condutor externo conduz.`
379
- : p.ativa ? `Sentinela: ligada na maquina ${s.maquina}, canal ${p.canal}, sessao ${p.sessao.slice(0, 8)}; o condutor externo cede o despacho e o retry.`
380
- : `Sentinela: a presenca da sessao ${p.sessao.slice(0, 8)} venceu; o condutor externo conduz.`);
397
+ linhas.push(!p ? m.desligada(s.maquina) : p.ativa ? m.ligada(s.maquina, p.canal, p.sessao.slice(0, 8)) : m.vencida(p.sessao.slice(0, 8)));
381
398
  if (s.threads.length === 0)
382
- linhas.push(' nenhuma thread aberta neste checkout');
399
+ linhas.push(m.nenhuma);
383
400
  for (const t of s.threads) {
384
- const acao = t.acao === 'despachar' ? `despachar ${t.fase}` : t.acao;
401
+ const acao = t.acao === 'despachar' ? m.despachar(t.fase) : t.acao;
385
402
  linhas.push(` ${t.thread.padEnd(20)} ${t.modo.padEnd(8)} ${acao.padEnd(16)} ${t.porque}`);
386
403
  }
387
404
  return linhas.join('\n');
package/dist/conducao.js CHANGED
@@ -113,6 +113,11 @@ exports.CANAIS_DE_CONDUCAO = {
113
113
  origem: 'sessao do Codex',
114
114
  declaracao: 'servidor MCP iniciado com --host codex',
115
115
  },
116
+ // RM-067 (F4b, G5): o servidor do grok so serve a sessao filha; o canal e o do host dele, como no codex.
117
+ grok: {
118
+ origem: 'sessao filha do Grok Build',
119
+ declaracao: 'servidor MCP iniciado com --host grok, so na sessao filha vinculada a thread',
120
+ },
116
121
  mcp: {
117
122
  origem: 'cliente MCP sem host homologado',
118
123
  declaracao: 'reservado: o servidor MCP atual exige host homologado e declara o canal dele',
@@ -239,10 +244,30 @@ function nomeDaConducao(threadId) {
239
244
  }
240
245
  /** Estados em que o runtime ja deu a sessao por encerrada. */
241
246
  const TERMINAIS = ['done', 'completed', 'exited', 'stopped', 'failed'];
247
+ /** Os eventos que sao contabilidade do proprio ork, e nao sinal de que a sessao voltou a trabalhar. */
248
+ const SO_DA_CONTABILIDADE = /^(conducao_|retry_|session_watcher_|despacho_idempotente$|varredura_acao$)/;
249
+ /**
250
+ * RM-063 (fatia 3, achado c): o observador viu a sessao num estado terminal do runtime (`done`, `failed`, `stopped`) e
251
+ * encerrou sem inferir a conclusao da fase (`session_watcher_error` com `estadoNativo`). A fase pode nao estar provada,
252
+ * mas a sessao nao executa mais nada: o lease dela cai. Vale o ultimo desses vistos, se nenhum evento da mesma sessao
253
+ * depois dele mostra trabalho (a sessao retomada por alguem).
254
+ */
255
+ function terminalVistoPeloObservador(eventos, sessionId, desde) {
256
+ let visto = null;
257
+ for (const e of eventos) {
258
+ if (e.sessionId !== sessionId || Date.parse(e.ts) < desde)
259
+ continue;
260
+ if (e.tipo === 'session_watcher_error' && typeof e.estadoNativo === 'string' && TERMINAIS.includes(e.estadoNativo))
261
+ visto = e;
262
+ else if (visto && !SO_DA_CONTABILIDADE.test(e.tipo))
263
+ visto = null;
264
+ }
265
+ return visto;
266
+ }
242
267
  /**
243
268
  * O evento que prova que a sessao dona do lease acabou: o resultado da fase dela (a prova da I-34
244
- * que o observador grava), a morte registrada, a superacao, ou a thread fechada. So conta evento
245
- * posterior ao inicio da conducao.
269
+ * que o observador grava), a morte registrada, a superacao, o estado terminal que o observador viu
270
+ * no runtime (RM-063), ou a thread fechada. So conta evento posterior ao inicio da conducao.
246
271
  */
247
272
  function fimDaSessao(eventos, lease) {
248
273
  const dono = lease.conducao?.dono;
@@ -250,7 +275,7 @@ function fimDaSessao(eventos, lease) {
250
275
  return null;
251
276
  const desde = Date.parse(lease.adquiridoEm);
252
277
  return eventos.find((e) => Date.parse(e.ts) >= desde && ((['phase_result', 'sessao_morta', 'session_superseded'].includes(e.tipo) && e.sessionId === dono.sessionId) ||
253
- ['thread_closed_admin', 'master_done'].includes(e.tipo))) ?? null;
278
+ ['thread_closed_admin', 'master_done'].includes(e.tipo))) ?? terminalVistoPeloObservador(eventos, dono.sessionId, desde);
254
279
  }
255
280
  /**
256
281
  * A leitura pura, para quem so tem os dados (o snapshot do Maestro le por um leitor confinado).
@@ -375,16 +400,49 @@ const emCurso = new Map();
375
400
  function chave(raiz, threadId) {
376
401
  return `${(0, leases_1.caminhoLease)(raiz, nomeDaConducao(threadId))}`;
377
402
  }
403
+ /**
404
+ * RM-063 (fatia 3, achado c): a consulta do claude-bg na conta do perfil da sessao (`CLAUDE_CONFIG_DIR` dele). A conta do
405
+ * processo nao lista a sessao de outro perfil, e a ausencia la nao prova nada; na conta dela, prova. `null` quando o
406
+ * perfil nao esta mais no store desta maquina (vale a consulta de sempre).
407
+ */
408
+ function consultaNaContaDoPerfil(dono, raiz) {
409
+ if (dono.runtime !== 'claude-bg' || !dono.perfil)
410
+ return null;
411
+ // Carregados na hora, como o controle nativo: a leitura da conducao nao puxa o adapter inteiro.
412
+ const { lerPerfis, perfilDeDespacho } = require('./runtime-profiles');
413
+ const { ambienteDoPerfil, consultarSessoes } = require('./adapters/claude-bg');
414
+ let perfil = null;
415
+ try {
416
+ const p = lerPerfis(raiz).perfis.find((x) => x.id === dono.perfil && x.runtime === 'claude-bg');
417
+ perfil = p ? perfilDeDespacho(p) : null;
418
+ }
419
+ catch {
420
+ return null;
421
+ }
422
+ if (!perfil?.configDir)
423
+ return null;
424
+ const r = consultarSessoes(undefined, true, ambienteDoPerfil(perfil));
425
+ if (!r.ok)
426
+ return { ok: false, estado: null, detalhe: `o runtime nao respondeu a consulta na conta do perfil ${dono.perfil}`, naConta: true };
427
+ const achada = r.sessoes.find((x) => x.sessionId === dono.sessionId);
428
+ const estado = achada ? String(achada.state ?? achada.status ?? '') : null;
429
+ return { ok: true, estado, detalhe: achada ? `estado ${estado} na conta do perfil ${dono.perfil}` : `sessao ausente da conta do perfil ${dono.perfil}`,
430
+ naConta: true };
431
+ }
378
432
  /** A consulta padrao: o controle nativo do runtime (claude-bg ou o controller do codex). */
379
433
  const consultaNativa = (dono, raiz, threadId) => {
380
434
  try {
435
+ const naConta = consultaNaContaDoPerfil(dono, raiz);
436
+ if (naConta)
437
+ return naConta;
381
438
  // Carregado na hora: o modulo de sessoes puxa o HITL inteiro, que nao pertence a leitura.
382
439
  const { controleNativo } = require('./hitl-sessions');
383
440
  const r = controleNativo(dono.runtime, raiz, threadId, dono.sessionId).consultar();
384
441
  if (!r.ok)
385
442
  return { ok: false, estado: null, detalhe: 'o runtime nao respondeu a consulta' };
386
443
  const achadas = r.sessoes.filter((s) => s.sessionId === dono.sessionId);
387
- return { ok: true, estado: achadas[0]?.estado ?? null, detalhe: achadas.length ? `estado ${achadas[0].estado}` : 'sessao ausente' };
444
+ return { ok: true, estado: achadas[0]?.estado ?? null, detalhe: achadas.length ? `estado ${achadas[0].estado}` : 'sessao ausente',
445
+ naConta: !dono.perfil };
388
446
  }
389
447
  catch (e) {
390
448
  return { ok: false, estado: null, detalhe: e.message };
@@ -425,7 +483,9 @@ function provaDeFimDaSessao(raiz, threadId, lease, pedido, anotarEstado = () =>
425
483
  anotarEstado(r.estado);
426
484
  if (r.estado && TERMINAIS.includes(r.estado))
427
485
  return { motivo: 'sessao-orfa', prova: `runtime ${dono.runtime}: ${r.detalhe}` };
428
- if (r.estado === null && !dono.perfil)
486
+ // A ausencia so prova o fim quando a consulta foi feita na conta da sessao: sem perfil, a do processo; com perfil, a
487
+ // dele (RM-063, fatia 3, achado c).
488
+ if (r.estado === null && (!dono.perfil || r.naConta === true))
429
489
  return { motivo: 'sessao-orfa', prova: `runtime ${dono.runtime}: ${r.detalhe}` };
430
490
  return null;
431
491
  }
@@ -624,9 +684,10 @@ function sucessaoAindaVale(raiz, threadId, estado) {
624
684
  // Sem resposta do runtime nao ha prova de que ela segue parada: a sucessao nao vale.
625
685
  if (!r.ok)
626
686
  return false;
627
- // S1 do CHECK 6: a sessao que sumiu do runtime, sem perfil, acabou; a mesma prova de `provaDeFimDaSessao`.
687
+ // S1 do CHECK 6: a sessao que sumiu do runtime, sem perfil (ou da conta do perfil dela), acabou; a mesma prova de
688
+ // `provaDeFimDaSessao`.
628
689
  if (r.estado === null)
629
- return !dono.perfil;
690
+ return !dono.perfil || r.naConta === true;
630
691
  return r.estado === 'blocked' || TERMINAIS.includes(r.estado);
631
692
  }
632
693
  function renovar(raiz, threadId, estado, prazoDoProximoMs, agoraMs) {
@@ -718,6 +779,7 @@ function comandoDeEsperar(threadId, pedido) {
718
779
  case 'baseline': return `ork verify ${threadId} --baseline --esperar 30`;
719
780
  case 'fix.open': return `ork fix open ${threadId} --esperar 30`;
720
781
  case 'fix.reverify': return `ork fix reverify ${threadId} --esperar 30`;
782
+ case 'branch.atualizar': return `ork conducao atualizar ${threadId} --esperar 30`;
721
783
  default: return `ork verify ${threadId} --esperar 30`;
722
784
  }
723
785
  }
@@ -731,32 +793,30 @@ function comandoDeAcompanhar(threadId, atual) {
731
793
  * aconteceu e o que fazer: o texto sai daqui e de lugar nenhum mais, e o JSON e a mesma estrutura.
732
794
  */
733
795
  function recusaDeConducao(threadId, atual, pedido, opcoes = {}) {
796
+ const m = (0, locale_1.msg)().conducao.recusa;
734
797
  const conducao = atual
735
798
  ? { ...atual, desdeLocal: (0, horario_1.formatarDataHoraRotulada)(atual.desde, opcoes), linha: (0, conducao_texto_1.linhaDeConducao)(atual, opcoes) }
736
799
  : null;
737
800
  const acoes = [
738
- { acao: 'esperar', comando: comandoDeEsperar(threadId, pedido),
739
- explicacao: 'Esperar a vez: repete este pedido e segue sozinho quando a conducao atual terminar (ate 30 min).' },
740
- { acao: 'acompanhar', comando: comandoDeAcompanhar(threadId, atual),
741
- explicacao: 'Acompanhar quem conduz, sem mexer em nada.' },
742
- { acao: 'assumir', comando: `ork conducao assumir ${threadId} --por <voce> --motivo "<por que>"`,
743
- explicacao: 'Assumir a conducao: encerra a atual pelo proprio runtime e registra no ledger quem assumiu, de qual canal e por que.' },
801
+ { acao: 'esperar', comando: comandoDeEsperar(threadId, pedido), explicacao: m.esperar },
802
+ { acao: 'acompanhar', comando: comandoDeAcompanhar(threadId, atual), explicacao: m.acompanhar },
803
+ { acao: 'assumir', comando: m.comandoAssumir(threadId),
804
+ explicacao: m.assumir },
744
805
  ];
745
806
  const linhas = [
746
- `Pedido nao executado: a thread ${threadId} ja esta sendo conduzida agora, e duas execucoes na mesma worktree ` +
747
- 'se corrompem (foi o que aconteceu em 19/09/2026).',
807
+ m.titulo(threadId),
748
808
  ];
749
809
  if (conducao) {
750
- linhas.push(` Quem conduz: canal ${conducao.canal}, ${(0, conducao_texto_1.quemConduz)(conducao)}, fase ${conducao.fase ?? '-'}, desde ${conducao.desdeLocal}.`);
810
+ linhas.push(m.quem(conducao.canal, (0, conducao_texto_1.quemConduz)(conducao), conducao.fase ?? '-', conducao.desdeLocal));
751
811
  if (conducao.promptSha256)
752
- linhas.push(` Pedido em curso: prompt sha256 ${conducao.promptSha256.slice(0, 12)}.`);
812
+ linhas.push(m.prompt(conducao.promptSha256.slice(0, 12)));
753
813
  }
754
814
  else {
755
- linhas.push(' Outra operacao esta tomando a conducao neste instante; o registro dela ainda nao apareceu.');
815
+ linhas.push(m.entrando);
756
816
  }
757
- linhas.push(` Pedido recusado: ${conducao_texto_1.NOME_DA_OPERACAO[pedido.operacao]}${pedido.fase ? ` da fase ${pedido.fase}` : ''}, pelo canal ${pedido.canal}.`);
758
- linhas.push('O que voce pode fazer:');
759
- acoes.forEach((a, i) => { linhas.push(` ${i + 1}. ${a.explicacao}`); linhas.push(` ${a.comando}`); });
817
+ linhas.push(m.pedido((0, locale_1.msg)().thread.operacoes[pedido.operacao], pedido.fase ?? null, pedido.canal));
818
+ linhas.push(m.opcoes);
819
+ acoes.forEach((a, i) => { linhas.push(m.passo(i + 1, a.explicacao)); linhas.push(` ${a.comando}`); });
760
820
  return {
761
821
  contrato: 'ork.conducao-recusa/v1',
762
822
  motivo: 'conducao.em-andamento',
@@ -1032,8 +1092,7 @@ function assumirConducao(raiz, threadId, opcoes) {
1032
1092
  worktree: estadoDaWorktree(raiz, threadId),
1033
1093
  });
1034
1094
  return { ok: true, thread: threadId, anterior, mecanismo,
1035
- detalhe: `conducao assumida por ${por} pelo canal ${opcoes.canal}; a proxima operacao desse canal usa a reserva ate ` +
1036
- `${(0, horario_1.formatarDataHoraRotulada)(reserva.expiraEm)}` };
1095
+ detalhe: (0, locale_1.msg)().conducao.cli.detalheAssumida(por, opcoes.canal, (0, horario_1.formatarDataHoraRotulada)(reserva.expiraEm)) };
1037
1096
  }
1038
1097
  finally {
1039
1098
  fs.closeSync(fd);
@@ -1041,14 +1100,15 @@ function assumirConducao(raiz, threadId, opcoes) {
1041
1100
  }
1042
1101
  /** Texto de `ork conducao status`. */
1043
1102
  function textoDoStatusDaConducao(threadId, atual) {
1103
+ const m = (0, locale_1.msg)().conducao.status;
1044
1104
  if (!atual)
1045
- return `Thread ${threadId}: ninguem conduz agora. Qualquer canal pode despachar ou verificar.`;
1046
- const linhas = [`Thread ${threadId}: ${(0, conducao_texto_1.linhaDeConducao)(atual)}`];
1105
+ return m.livre(threadId);
1106
+ const linhas = [m.titulo(threadId, (0, conducao_texto_1.linhaDeConducao)(atual))];
1047
1107
  if (atual.promptSha256)
1048
- linhas.push(` prompt sha256 ${atual.promptSha256.slice(0, 12)}`);
1049
- linhas.push(` prazo do lease (metadado, nao prova): ${(0, horario_1.formatarDataHoraRotulada)(atual.expiraEm)}`);
1108
+ linhas.push(m.prompt(atual.promptSha256.slice(0, 12)));
1109
+ linhas.push(m.prazo((0, horario_1.formatarDataHoraRotulada)(atual.expiraEm)));
1050
1110
  if (atual.sessao)
1051
- linhas.push(` acompanhar: ork sessions logs ${atual.sessao.slice(0, 8)}`);
1052
- linhas.push(` assumir: ork conducao assumir ${threadId} --por <voce> --motivo "<por que>"`);
1111
+ linhas.push(m.acompanhar(atual.sessao.slice(0, 8)));
1112
+ linhas.push(m.assumir(threadId));
1053
1113
  return linhas.join('\n');
1054
1114
  }
@@ -0,0 +1,270 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONSULTAS_DO_CONHECIMENTO = void 0;
4
+ exports.brainDoProjeto = brainDoProjeto;
5
+ exports.consultarConhecimento = consultarConhecimento;
6
+ exports.consultaRespondeu = consultaRespondeu;
7
+ exports.textoDoConhecimento = textoDoConhecimento;
8
+ /**
9
+ * RM-026 K7 (fatia 2): as consultas do conhecimento escrito, a porta pública do contrato `ork.conhecimento/v1`. A CLI
10
+ * (`ork conhecimento listar|mostrar|colecoes|verificar`) e as tools MCP (`ork_conhecimento_*`) chamam
11
+ * `consultarConhecimento` e devolvem o mesmo JSON (D11).
12
+ *
13
+ * Só leitura. O id do Brain referenciado confere por `get` no Company Brain (D12), só onde a resposta mostra
14
+ * referência: o `mostrar` (as do documento pedido) e o `verificar` (as de todos). `listar` e `colecoes` não abrem o
15
+ * Brain e não mostram referência nem lacuna de referência. Id inexistente, retido e Brain fora do ar são lacunas
16
+ * distintas, nunca resposta. O transporte do Brain é o do `ork brain get` (`memory.cli` conferido no manifesto, cwd
17
+ * fora do clone), na fronteira da RM-047. Contrato: docs/referencia/contratos/conhecimento-rm026.md.
18
+ */
19
+ const company_brain_client_1 = require("./company-brain-client");
20
+ const company_brain_contract_1 = require("./company-brain-contract");
21
+ const conhecimento_1 = require("./conhecimento");
22
+ const locale_1 = require("./locale");
23
+ const project_state_1 = require("./project-state");
24
+ const saida_segura_1 = require("./saida-segura");
25
+ exports.CONSULTAS_DO_CONHECIMENTO = ['listar', 'mostrar', 'colecoes', 'verificar'];
26
+ /**
27
+ * O Brain do projeto, como o `ork brain get` o abre: a configuração de memória vem da árvore principal também numa
28
+ * worktree (`memoryState`), e o tenant do pedido é o dela.
29
+ */
30
+ function brainDoProjeto(c) {
31
+ const contexto = (0, project_state_1.memoryState)(c);
32
+ return { transporte: (0, company_brain_client_1.brainClient)(contexto.loaded), tenant: contexto.loaded.manifesto.memory.tenant };
33
+ }
34
+ const comparar = (a, b) => a < b ? -1 : a > b ? 1 : 0;
35
+ const t = conhecimento_1.detalheDoConhecimento;
36
+ /** Lacuna da pasta: nada foi lido, e nenhuma consulta responde. */
37
+ const daPasta = (l) => l.codigo.startsWith('conhecimento.');
38
+ /** O código de erro do Brain, só quando tem a forma de um; texto alheio não chega ao detalhe. */
39
+ const erroDoBrain = (e) => typeof e === 'string' && /^brain\.[a-z0-9.-]{1,80}$/.test(e) ? e : null;
40
+ /** O código de uma exceção na abertura do Brain (`project-state.memory.unavailable`), só quando tem a forma de um. */
41
+ const codigoDaExcecao = (e) => {
42
+ const m = e instanceof Error ? e.message : '';
43
+ return /^[a-z][a-z0-9-]*(?:\.[a-z0-9-]+){1,4}$/.test(m) && m.length <= 80 ? m : null;
44
+ };
45
+ /** D12: a resposta `ok` do `get` vale só no contrato da entidade, com o id e o tenant pedidos. */
46
+ function referenciaDoBrain(r, id, tenant) {
47
+ let e;
48
+ try {
49
+ e = (0, company_brain_contract_1.validateContract)(r.entity);
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ if (e.schema !== 'orkmind.company-brain-entity/v1' || e.id !== id || e.tenant_id !== tenant)
55
+ return null;
56
+ return { id, kind: e.kind, titulo: (0, saida_segura_1.emUmaLinha)(e.title), versao: e.version, fonte: e.source.source_ref, sha256: e.source.source_hash };
57
+ }
58
+ /** Os estados do Brain que encerram a conferência: os mesmos que o contexto e o dossiê tratam como falha. */
59
+ const FALHAS_DO_BRAIN = ['unavailable', 'forbidden', 'conflict'];
60
+ /**
61
+ * D12 (revista depois do CHECK): um `get` por id distinto, em ordem, até o teto de `get` e o prazo da consulta (cada
62
+ * `get` é um processo do `memory.cli`). O Brain que não responde (fora do ar, sem configuração, recusa ou conflito) para
63
+ * a conferência: nenhum `get` sai depois, e o resto leva o mesmo detalhe. A resposta fora do contrato vale só para o id
64
+ * dela. `unknown` e `empty` são o id que o Brain não tem, como no dossiê.
65
+ */
66
+ function conferirNoBrain(ids, abrir, limites) {
67
+ const conferidas = new Map();
68
+ const naoConferida = (detalhe) => ({ codigo: 'referencia.brain-indisponivel', detalhe });
69
+ let brain = null, parada = null, gets = 0;
70
+ const inicio = Date.now();
71
+ for (const id of [...new Set(ids)].sort(comparar)) {
72
+ if (parada === null && gets >= limites.getsDoBrain)
73
+ parada = t((l) => l.brainTeto(limites.getsDoBrain));
74
+ if (parada === null && gets > 0 && Date.now() - inicio > limites.msDaConferencia) {
75
+ parada = t((l) => l.brainPrazo(limites.msDaConferencia / 1000));
76
+ }
77
+ if (parada !== null) {
78
+ conferidas.set(id, naoConferida(parada));
79
+ continue;
80
+ }
81
+ if (brain === null) {
82
+ try {
83
+ brain = abrir();
84
+ }
85
+ catch (e) {
86
+ const codigo = codigoDaExcecao(e);
87
+ parada = t((l) => l.brainSemConfiguracao(codigo));
88
+ conferidas.set(id, naoConferida(parada));
89
+ continue;
90
+ }
91
+ }
92
+ gets++;
93
+ let r;
94
+ try {
95
+ r = brain.transporte({ schema: company_brain_client_1.BRAIN_API, operation: 'get', payload: { tenant_id: brain.tenant, id } });
96
+ }
97
+ catch (e) {
98
+ const codigo = erroDoBrain(codigoDaExcecao(e));
99
+ parada = t((l) => l.brainNaoRespondeu('unavailable', codigo));
100
+ conferidas.set(id, naoConferida(parada));
101
+ continue;
102
+ }
103
+ if (r.state === 'ok')
104
+ conferidas.set(id, referenciaDoBrain(r, id, brain.tenant) ?? naoConferida(t((l) => l.brainForaDoContrato)));
105
+ else if (r.state === 'unknown' || r.state === 'empty') {
106
+ conferidas.set(id, { codigo: 'referencia.brain-inexistente', detalhe: t((l) => l.brainInexistente) });
107
+ }
108
+ else if (r.state === 'withheld')
109
+ conferidas.set(id, { codigo: 'referencia.brain-retido', detalhe: t((l) => l.brainRetido) });
110
+ else if (FALHAS_DO_BRAIN.includes(r.state)) {
111
+ const estado = r.state, erro = erroDoBrain(r.error);
112
+ parada = t((l) => l.brainNaoRespondeu(estado, erro));
113
+ conferidas.set(id, naoConferida(parada));
114
+ }
115
+ else
116
+ conferidas.set(id, naoConferida(t((l) => l.brainForaDoContrato)));
117
+ }
118
+ return conferidas;
119
+ }
120
+ /** As referências do Brain conferidas; a que não confere vira lacuna, e o documento segue sem ela (D4). */
121
+ function conferirDocumentos(docs, abrir, lacunas, limites) {
122
+ const conferencias = conferirNoBrain(docs.flatMap((d) => d.referencias.brain), abrir, limites);
123
+ return docs.map((d) => {
124
+ const brain = [];
125
+ for (const id of d.referencias.brain) {
126
+ const r = conferencias.get(id);
127
+ if ('codigo' in r)
128
+ lacunas.push((0, conhecimento_1.lacunaDoConhecimento)(r.codigo, r.detalhe, { arquivo: d.arquivo, documento: d.id, referencia: id }));
129
+ else
130
+ brain.push(r);
131
+ }
132
+ return { id: d.id, titulo: d.titulo, colecoes: d.colecoes, referencias: { brain, decisoes: d.referencias.decisoes },
133
+ arquivo: d.arquivo, bytes: d.bytes, sha256: d.sha256 };
134
+ });
135
+ }
136
+ const resumo = (d) => ({ id: d.id, titulo: d.titulo, colecoes: d.colecoes, arquivo: d.arquivo, bytes: d.bytes, sha256: d.sha256 });
137
+ /**
138
+ * A consulta pedida, no contrato `ork.conhecimento/v1`. Nunca lança por causa do conteúdo do repositório nem do Brain:
139
+ * o que não vale vira lacuna. O pedido fora da forma (id de documento, nome de coleção) é erro de quem chama; a CLI e
140
+ * as tools o recusam antes. A resposta nasce em pt-BR em qualquer locale (D13): o detalhe das lacunas é o do `--json`
141
+ * e do MCP, e só a impressão o remonta.
142
+ */
143
+ function consultarConhecimento(c, pedido, abrirBrain = () => brainDoProjeto(c), limites = conhecimento_1.LIMITES_DO_CONHECIMENTO) {
144
+ if (pedido.consulta === 'mostrar' && !conhecimento_1.ID_DE_DOCUMENTO.test(pedido.id))
145
+ throw new Error('conhecimento.pedido-invalido: id de documento');
146
+ if (pedido.consulta === 'listar' && pedido.colecao !== undefined && !conhecimento_1.NOME_DE_COLECAO.test(pedido.colecao)) {
147
+ throw new Error('conhecimento.pedido-invalido: nome de coleção');
148
+ }
149
+ return (0, locale_1.comLocale)('pt-BR', () => responder(c, pedido, abrirBrain, limites));
150
+ }
151
+ function responder(c, pedido, abrirBrain, limites) {
152
+ // D12 (revista): as decisões só conferem onde a resposta as mostra; listar e colecoes não leem ledger.
153
+ const k = (0, conhecimento_1.lerConhecimento)(c, limites, pedido.consulta === 'mostrar' ? { corpoDe: pedido.id, decisoesDe: pedido.id }
154
+ : pedido.consulta === 'verificar' ? {} : { decisoesDe: 'nenhum' });
155
+ const base = { contrato: conhecimento_1.CONTRATO_CONHECIMENTO, consulta: pedido.consulta, dir: k.dir };
156
+ // D12: quem não mostra referência não mostra a lacuna dela.
157
+ const semReferencia = () => k.lacunas.filter((l) => !l.codigo.startsWith('referencia.'));
158
+ switch (pedido.consulta) {
159
+ case 'listar': {
160
+ const colecao = pedido.colecao ?? null;
161
+ return { ...base, consulta: 'listar', colecao,
162
+ documentos: k.documentos.filter((d) => colecao === null || d.colecoes.includes(colecao)).map(resumo), lacunas: semReferencia() };
163
+ }
164
+ case 'colecoes':
165
+ return { ...base, consulta: 'colecoes', colecoes: k.colecoes, lacunas: semReferencia() };
166
+ case 'mostrar': {
167
+ const comum = { ...base, consulta: 'mostrar', id: pedido.id };
168
+ if (k.lacunas.some(daPasta))
169
+ return { ...comum, documento: null, lacunas: k.lacunas };
170
+ const lacunas = k.lacunas.filter((l) => l.documento === pedido.id);
171
+ const doc = k.documentos.find((d) => d.id === pedido.id);
172
+ if (!doc) {
173
+ // D13: o id que nenhum documento válido tem; os arquivos que viraram lacuna antes de o id ser lido entram na conta.
174
+ if (!lacunas.length) {
175
+ const semId = k.lacunas.filter((l) => l.arquivo !== null && l.documento === null).length;
176
+ lacunas.push((0, conhecimento_1.lacunaDoConhecimento)('documento.inexistente', t((l) => l.documentoInexistente(pedido.id, semId)), { documento: pedido.id }));
177
+ }
178
+ return { ...comum, documento: null, lacunas };
179
+ }
180
+ const [conferido] = conferirDocumentos([doc], abrirBrain, lacunas, limites);
181
+ return { ...comum, documento: { ...conferido, corpo: doc.corpo ?? '' }, lacunas: lacunas.sort(conhecimento_1.compararLacunas) };
182
+ }
183
+ case 'verificar': {
184
+ const lacunas = [...k.lacunas];
185
+ const documentos = conferirDocumentos(k.documentos, abrirBrain, lacunas, limites);
186
+ return { ...base, consulta: 'verificar', documentos, colecoes: k.colecoes, lacunas: lacunas.sort(conhecimento_1.compararLacunas) };
187
+ }
188
+ }
189
+ }
190
+ /**
191
+ * D13: a consulta respondeu? `listar` e `colecoes`, quando a pasta foi lida; `mostrar`, quando o documento veio;
192
+ * `verificar`, sem nenhuma lacuna. É a saída 0 da CLI e a tool sem `isError`.
193
+ */
194
+ function consultaRespondeu(r) {
195
+ if (r.consulta === 'verificar')
196
+ return r.lacunas.length === 0;
197
+ if (r.consulta === 'mostrar')
198
+ return r.documento !== null;
199
+ return !r.lacunas.some(daPasta);
200
+ }
201
+ /**
202
+ * D13: o texto para gente, pelo catálogo, no locale ativo. O detalhe das lacunas nasce em pt-BR na consulta e é
203
+ * remontado aqui; o corpo do documento é dado do repositório e sai linha a linha, sem caractere invisível.
204
+ */
205
+ function textoDoConhecimento(r) {
206
+ const m = (0, locale_1.msg)().conhecimento, linhas = [];
207
+ const leu = !r.lacunas.some(daPasta), dir = r.dir ?? '';
208
+ if (r.consulta === 'listar') {
209
+ if (!leu)
210
+ linhas.push(m.naoLido);
211
+ else {
212
+ linhas.push(m.listar(dir, r.documentos.length, r.colecao));
213
+ const largura = r.documentos.reduce((n, d) => Math.max(n, d.id.length), 0);
214
+ for (const d of r.documentos)
215
+ linhas.push(m.documento(d.id.padEnd(largura), d.titulo, d.colecoes.join(', ')));
216
+ if (!r.documentos.length)
217
+ linhas.push(m.nenhumDocumento);
218
+ }
219
+ }
220
+ else if (r.consulta === 'colecoes') {
221
+ if (!leu)
222
+ linhas.push(m.naoLido);
223
+ else {
224
+ linhas.push(m.colecoes(dir, r.colecoes.length));
225
+ const largura = r.colecoes.reduce((n, x) => Math.max(n, x.nome.length), 0);
226
+ for (const x of r.colecoes)
227
+ linhas.push(m.colecao(x.nome.padEnd(largura), x.documentos.join(', ')));
228
+ if (!r.colecoes.length)
229
+ linhas.push(m.nenhumaColecao);
230
+ }
231
+ }
232
+ else if (r.consulta === 'mostrar') {
233
+ const d = r.documento;
234
+ if (!d)
235
+ linhas.push(leu ? m.semDocumento(r.id) : m.naoLido);
236
+ else {
237
+ linhas.push(m.mostrar(d.id, d.titulo), m.colecoesDoDocumento(d.colecoes.join(', ')), m.arquivo(d.arquivo), m.versao(d.sha256, d.bytes));
238
+ for (const b of d.referencias.brain)
239
+ linhas.push(m.brain(b.id, b.titulo, b.kind, b.versao, b.fonte));
240
+ for (const x of d.referencias.decisoes)
241
+ linhas.push(m.decisao(x.ref, x.tipo, x.fonte));
242
+ if (!d.referencias.brain.length && !d.referencias.decisoes.length)
243
+ linhas.push(m.semReferencia);
244
+ }
245
+ }
246
+ else if (!leu)
247
+ linhas.push(m.naoLido);
248
+ else {
249
+ const soma = (f) => r.documentos.reduce((n, d) => n + f(d), 0);
250
+ linhas.push(m.verificar(dir, r.documentos.length, soma((d) => d.referencias.brain.length), soma((d) => d.referencias.decisoes.length)));
251
+ }
252
+ if (r.lacunas.length) {
253
+ linhas.push(m.lacunasTitulo(r.lacunas.length));
254
+ for (const l of r.lacunas) {
255
+ const onde = (l.arquivo ?? m.pasta) + (l.documento ? ` (${l.documento})` : '') + (l.referencia !== null ? `, ${m.naReferencia(l.referencia)}` : '');
256
+ linhas.push(m.lacuna(l.codigo, onde, (0, locale_1.remontar)(l.detalhe)));
257
+ }
258
+ }
259
+ if (r.consulta === 'listar' && r.documentos.length)
260
+ linhas.push(m.paraLer);
261
+ if (r.consulta === 'verificar')
262
+ linhas.push(r.lacunas.length ? m.reprovado(r.lacunas.length) : m.aprovado);
263
+ // O corpo vai linha a linha: espalhar um documento de muitas linhas nos argumentos estoura a pilha (achado do CHECK).
264
+ if (r.consulta === 'mostrar' && r.documento) {
265
+ linhas.push('', m.corpo);
266
+ for (const linha of r.documento.corpo.replace(/\n$/, '').split('\n'))
267
+ linhas.push((0, saida_segura_1.emUmaLinha)(linha));
268
+ }
269
+ return linhas.join('\n');
270
+ }