@orkastery/cli 0.5.6 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/adapters/README.md +18 -0
  2. package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
  3. package/adapters/claude-code/README.md +37 -5
  4. package/adapters/claude-code/agents/ork-check.md +1 -0
  5. package/adapters/claude-code/agents/ork-go.md +1 -0
  6. package/adapters/claude-code/agents/ork-goal.md +1 -0
  7. package/adapters/claude-code/agents/ork-master.md +1 -0
  8. package/adapters/claude-code/agents/ork-plan.md +1 -0
  9. package/adapters/claude-code/agents/ork-ship.md +1 -0
  10. package/adapters/claude-code/hooks/hooks.json +2 -1
  11. package/adapters/claude-code/hooks/ork-guard.js +15 -1
  12. package/adapters/claude-code/hooks/ork-resposta.js +91 -0
  13. package/adapters/claude-code/hooks/ork-sensor.js +18 -2
  14. package/adapters/claude-code/hooks/quota-signal.js +14 -0
  15. package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
  16. package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
  17. package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
  18. package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
  19. package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
  20. package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
  21. package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
  22. package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
  23. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +9 -5
  24. package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
  25. package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
  26. package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
  27. package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
  28. package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
  29. package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
  30. package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
  31. package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
  32. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +1 -1
  33. package/adapters/codex/skills/ork/SKILL.md +2 -0
  34. package/adapters/hermes/README.md +64 -1
  35. package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
  36. package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
  37. package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
  38. package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
  39. package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
  40. package/adapters/hermes/hermes.plugin.json +4 -0
  41. package/adapters/hermes/hitl-ingress/__init__.py +101 -8
  42. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +2 -2
  43. package/adapters/openclaw/README.md +81 -9
  44. package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
  45. package/adapters/openclaw/dist/hitl-ingress.js +106 -9
  46. package/adapters/openclaw/dist/index.js +86 -0
  47. package/adapters/openclaw/openclaw.plugin.json +34 -4
  48. package/adapters/openclaw/package.json +2 -2
  49. package/adapters/openclaw/src/hitl-ingress.ts +103 -9
  50. package/adapters/openclaw/src/index.ts +94 -0
  51. package/assets/adapters-en/claude-code/README.md +403 -0
  52. package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
  53. package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
  54. package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
  55. package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
  56. package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
  57. package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
  58. package/assets/adapters-en/claude-code/commands/check.md +46 -0
  59. package/assets/adapters-en/claude-code/commands/go.md +46 -0
  60. package/assets/adapters-en/claude-code/commands/goal.md +55 -0
  61. package/assets/adapters-en/claude-code/commands/master.md +54 -0
  62. package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
  63. package/assets/adapters-en/claude-code/commands/ork.md +126 -0
  64. package/assets/adapters-en/claude-code/commands/plan.md +47 -0
  65. package/assets/adapters-en/claude-code/commands/ship.md +45 -0
  66. package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
  67. package/assets/adapters-en/hermes/README.md +273 -0
  68. package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
  69. package/assets/references-en/README.md +25 -0
  70. package/assets/references-en/code-review-axes.md +82 -0
  71. package/assets/references-en/definition-of-done.md +74 -0
  72. package/assets/references-en/performance-checklist.md +53 -0
  73. package/assets/references-en/security-checklist.md +101 -0
  74. package/assets/references-en/testing-patterns.md +51 -0
  75. package/assets/security-scan/defaults/.golangci.yml +2 -0
  76. package/assets/security-scan/defaults/eslint.config.mjs +11 -0
  77. package/assets/security-scan/defaults/gitleaks.toml +3 -0
  78. package/assets/security-scan/defaults/ruff.toml +1 -0
  79. package/assets/security-scan/tools-agil.json +87 -0
  80. package/assets/security-scan/tools.json +625 -0
  81. package/assets/skills-en/core/onboarding/SKILL.md +58 -0
  82. package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
  83. package/assets/skills-en/core/thread-state/SKILL.md +88 -0
  84. package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
  85. package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
  86. package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
  87. package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
  88. package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
  89. package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
  90. package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
  91. package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
  92. package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
  93. package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
  94. package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
  95. package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
  96. package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
  97. package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
  98. package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
  99. package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
  100. package/dist/adapters/claude-bg.js +118 -4
  101. package/dist/adapters/codex-controller-worker.js +12 -5
  102. package/dist/adapters/codex-events.js +16 -4
  103. package/dist/adapters/codex.js +3 -1
  104. package/dist/atualizar-branch.js +245 -0
  105. package/dist/auditoria.js +13 -11
  106. package/dist/auditrun.js +51 -46
  107. package/dist/autorizacao-duravel.js +327 -0
  108. package/dist/board.js +94 -40
  109. package/dist/branch-de-estado.js +16 -8
  110. package/dist/busca-semantica.js +7 -5
  111. package/dist/catalogo.js +2 -1
  112. package/dist/changelog-reconciliacao.js +290 -0
  113. package/dist/check-agil.js +500 -0
  114. package/dist/check-modo.js +41 -0
  115. package/dist/check-paralelo.js +183 -0
  116. package/dist/ci.js +248 -45
  117. package/dist/ciclos.js +8 -6
  118. package/dist/claim-lint.js +12 -8
  119. package/dist/claims-conferir.js +47 -39
  120. package/dist/claims.js +10 -9
  121. package/dist/company-brain-client.js +10 -3
  122. package/dist/company-brain-migration.js +11 -5
  123. package/dist/conducao-batida.js +759 -0
  124. package/dist/conducao-sentinela.js +25 -8
  125. package/dist/conducao.js +84 -29
  126. package/dist/conhecimento-consulta.js +270 -0
  127. package/dist/conhecimento.js +111 -87
  128. package/dist/conta-esgotada.js +127 -0
  129. package/dist/dado-privado.js +816 -0
  130. package/dist/decisao-autonoma.js +5 -4
  131. package/dist/demo.js +14 -12
  132. package/dist/dependencias-da-worktree.js +25 -0
  133. package/dist/divida.js +38 -36
  134. package/dist/docs.js +81 -74
  135. package/dist/doctor-forja.js +345 -0
  136. package/dist/doctor-pulse-cron.js +113 -1
  137. package/dist/doctor.js +164 -6
  138. package/dist/dsn-da-memoria.js +417 -0
  139. package/dist/entrega-por-mod.js +503 -0
  140. package/dist/entrega-pr.js +143 -43
  141. package/dist/esgotamentos.js +13 -11
  142. package/dist/estado-thread.js +21 -18
  143. package/dist/evalrunner.js +35 -32
  144. package/dist/fabrica-batida.js +34 -21
  145. package/dist/fabrica-estado.js +13 -10
  146. package/dist/fix.js +21 -19
  147. package/dist/forja/adaptador.js +6 -0
  148. package/dist/forja/ambiente-de-ci.js +27 -0
  149. package/dist/forja/api.js +256 -0
  150. package/dist/forja/cache.js +89 -0
  151. package/dist/forja/cli.js +60 -0
  152. package/dist/forja/contrato.js +9 -0
  153. package/dist/forja/endereco.js +43 -0
  154. package/dist/forja/estado.js +22 -0
  155. package/dist/forja/executor.js +73 -0
  156. package/dist/forja/github/ci.js +95 -0
  157. package/dist/forja/github/dono-da-rede.js +18 -0
  158. package/dist/forja/github/metadados.js +15 -0
  159. package/dist/forja/github/pedidos.js +200 -0
  160. package/dist/forja/gitlab/ci.js +141 -0
  161. package/dist/forja/gitlab/consultas.js +59 -0
  162. package/dist/forja/gitlab/dono-da-rede.js +43 -0
  163. package/dist/forja/gitlab/metadados.js +15 -0
  164. package/dist/forja/gitlab/pedidos-abertos.js +158 -0
  165. package/dist/forja/gitlab/pedidos.js +141 -0
  166. package/dist/forja/produtor.js +32 -0
  167. package/dist/forja/registro.js +31 -0
  168. package/dist/forja/resolver.js +121 -0
  169. package/dist/forja/texto.js +13 -0
  170. package/dist/forja/versao.js +71 -0
  171. package/dist/forja.js +123 -80
  172. package/dist/handoff.js +23 -13
  173. package/dist/hitl-contract.js +46 -43
  174. package/dist/hitl-curto.js +37 -25
  175. package/dist/hitl-gates.js +13 -11
  176. package/dist/hitl-local-receipt.js +51 -0
  177. package/dist/hitl-local.js +11 -2
  178. package/dist/hitl-lock.js +5 -11
  179. package/dist/hitl-public-receipt.js +11 -0
  180. package/dist/hitl-resumo.js +44 -1
  181. package/dist/hitl-sessions.js +62 -9
  182. package/dist/hitl-texto-livre.js +7 -4
  183. package/dist/hitl.js +34 -31
  184. package/dist/horario.js +16 -0
  185. package/dist/hosts.js +104 -134
  186. package/dist/index.js +848 -548
  187. package/dist/indice-vetorial.js +14 -12
  188. package/dist/init.js +11 -2
  189. package/dist/integracoes-locais.js +2 -0
  190. package/dist/intelligence-graph-cli.js +123 -69
  191. package/dist/intelligence-graph-query.js +37 -22
  192. package/dist/leases.js +19 -18
  193. package/dist/ledger-stats.js +17 -16
  194. package/dist/ledger.js +31 -1
  195. package/dist/licoes.js +12 -11
  196. package/dist/locale-accounts.js +220 -0
  197. package/dist/locale-adapter.js +291 -0
  198. package/dist/locale-ajuda.js +76 -4
  199. package/dist/locale-audit.js +199 -0
  200. package/dist/locale-claims.js +213 -0
  201. package/dist/locale-conducao.js +138 -0
  202. package/dist/locale-conhecimento.js +181 -0
  203. package/dist/locale-decisao.js +205 -0
  204. package/dist/locale-docs.js +230 -0
  205. package/dist/locale-estado.js +101 -0
  206. package/dist/locale-forja.js +290 -0
  207. package/dist/locale-gerados.js +5 -0
  208. package/dist/locale-grafo.js +129 -0
  209. package/dist/locale-master.js +83 -0
  210. package/dist/locale-network.js +524 -0
  211. package/dist/locale-operacao-restante.js +931 -0
  212. package/dist/locale-projetos.js +100 -0
  213. package/dist/locale-prompts.js +194 -0
  214. package/dist/locale-pulse.js +140 -2
  215. package/dist/locale-reservas.js +87 -0
  216. package/dist/locale-retry.js +145 -6
  217. package/dist/locale-security-scan.js +69 -0
  218. package/dist/locale-setup.js +192 -0
  219. package/dist/locale-ship.js +169 -66
  220. package/dist/locale-thread.js +149 -5
  221. package/dist/locale-verify.js +80 -4
  222. package/dist/locale-worktree.js +246 -0
  223. package/dist/locale.js +553 -9
  224. package/dist/maestro-runtime.js +22 -3
  225. package/dist/manifest.js +287 -11
  226. package/dist/maquina-ociosa.js +211 -0
  227. package/dist/maquina.js +10 -5
  228. package/dist/master-nota-local.js +200 -0
  229. package/dist/master-nota.js +10 -2
  230. package/dist/master.js +118 -41
  231. package/dist/mcp-conhecimento.js +52 -0
  232. package/dist/mcp-experiencia.js +26 -5
  233. package/dist/mcp-install.js +73 -8
  234. package/dist/mcp-noctum.js +101 -0
  235. package/dist/mcp-server.js +82 -14
  236. package/dist/mcp-ship-transporte.js +977 -0
  237. package/dist/mcp-ship.js +68 -24
  238. package/dist/mcp-transportes.js +17 -0
  239. package/dist/memoria.js +63 -58
  240. package/dist/modos-migracao.js +8 -6
  241. package/dist/modos.js +17 -18
  242. package/dist/network-roadmap.js +85 -49
  243. package/dist/noctum-aceite.js +789 -0
  244. package/dist/noctum-arco.js +540 -33
  245. package/dist/noctum-capacidade.js +3 -3
  246. package/dist/noctum-changelog.js +399 -0
  247. package/dist/noctum-cli.js +482 -0
  248. package/dist/noctum-coordenacao.js +1225 -0
  249. package/dist/noctum-entrega.js +1169 -0
  250. package/dist/noctum-envelope.js +252 -16
  251. package/dist/noctum-execucao.js +95 -23
  252. package/dist/noctum-fechamento.js +405 -0
  253. package/dist/noctum-fila.js +43 -9
  254. package/dist/noctum-guarda.js +256 -0
  255. package/dist/noctum-integracao.js +507 -0
  256. package/dist/noctum-maquinas.js +383 -0
  257. package/dist/noctum-medicao.js +450 -0
  258. package/dist/noctum-modo.js +362 -0
  259. package/dist/noctum-pergunta-canal.js +96 -0
  260. package/dist/noctum-pergunta.js +115 -0
  261. package/dist/noctum-provas.js +838 -0
  262. package/dist/noctum-reconciliacao.js +591 -0
  263. package/dist/noctum-registro.js +215 -0
  264. package/dist/noctum-relatorio.js +827 -0
  265. package/dist/noctum-resposta.js +207 -0
  266. package/dist/noctum-sessoes-em-voo.js +93 -0
  267. package/dist/noctum-supervisao.js +649 -0
  268. package/dist/noctum-terminal.js +459 -0
  269. package/dist/noctum-transporte.js +655 -0
  270. package/dist/noctum-vigia.js +639 -0
  271. package/dist/ocupacao.js +3 -1
  272. package/dist/onboarding.js +16 -5
  273. package/dist/orkmind.js +39 -23
  274. package/dist/orquestracao.js +31 -35
  275. package/dist/parado-no-condutor.js +146 -124
  276. package/dist/phase.js +53 -27
  277. package/dist/policies.js +33 -0
  278. package/dist/postura-local.js +4 -3
  279. package/dist/procedencia.js +9 -14
  280. package/dist/projeto-alvo.js +59 -20
  281. package/dist/prompts.js +136 -42
  282. package/dist/prova-minima.js +5 -6
  283. package/dist/pulse-cadencia.js +5 -4
  284. package/dist/pulse-consentimento.js +53 -1
  285. package/dist/pulse-delivery.js +143 -27
  286. package/dist/pulse-resposta.js +368 -4
  287. package/dist/pulse.js +136 -3
  288. package/dist/ratelimit.js +12 -4
  289. package/dist/recall.js +14 -13
  290. package/dist/rede-adesao.js +13 -8
  291. package/dist/rede-forja.js +108 -24
  292. package/dist/rede-status.js +63 -45
  293. package/dist/rede.js +86 -46
  294. package/dist/retomada-checkpoint.js +101 -0
  295. package/dist/retry.js +228 -73
  296. package/dist/roadmap-reservas.js +32 -32
  297. package/dist/runtime-ambiente.js +5 -0
  298. package/dist/runtime-context.js +117 -43
  299. package/dist/runtime-escada.js +423 -0
  300. package/dist/runtime-profiles.js +103 -46
  301. package/dist/saida-segura.js +3 -2
  302. package/dist/security-scan/agil.js +355 -0
  303. package/dist/security-scan/cli.js +76 -0
  304. package/dist/security-scan/compare.js +149 -0
  305. package/dist/security-scan/config.js +93 -0
  306. package/dist/security-scan/detect.js +97 -0
  307. package/dist/security-scan/executor.js +188 -0
  308. package/dist/security-scan/guard.js +180 -0
  309. package/dist/security-scan/imagem-de-lint.js +96 -0
  310. package/dist/security-scan/normalize/actionlint.js +12 -0
  311. package/dist/security-scan/normalize/eslint.js +12 -0
  312. package/dist/security-scan/normalize/gitleaks.js +13 -0
  313. package/dist/security-scan/normalize/golangci-lint.js +13 -0
  314. package/dist/security-scan/normalize/govulncheck.js +36 -0
  315. package/dist/security-scan/normalize/index.js +25 -0
  316. package/dist/security-scan/normalize/npm-audit.js +30 -0
  317. package/dist/security-scan/normalize/osv-scanner.js +32 -0
  318. package/dist/security-scan/normalize/oxlint.js +51 -0
  319. package/dist/security-scan/normalize/pip-audit.js +16 -0
  320. package/dist/security-scan/normalize/ruff.js +12 -0
  321. package/dist/security-scan/normalize/semgrep.js +20 -0
  322. package/dist/security-scan/normalize/trivy.js +33 -0
  323. package/dist/security-scan/normalize/util.js +204 -0
  324. package/dist/security-scan/normalize/zizmor.js +19 -0
  325. package/dist/security-scan/report.js +156 -0
  326. package/dist/security-scan/run.js +448 -0
  327. package/dist/security-scan/tools.js +62 -0
  328. package/dist/security-scan/trabalhador.js +74 -0
  329. package/dist/security-scan/types.js +15 -0
  330. package/dist/session-events.js +19 -2
  331. package/dist/session-watcher-claude.js +74 -19
  332. package/dist/session-watcher.js +156 -10
  333. package/dist/sessoes-contas.js +9 -0
  334. package/dist/sessoes-inventario.js +1 -1
  335. package/dist/sessoes.js +25 -23
  336. package/dist/setup.js +59 -58
  337. package/dist/ship-publicar.js +263 -92
  338. package/dist/ship.js +160 -17
  339. package/dist/superficie.js +14 -11
  340. package/dist/thread-close.js +9 -9
  341. package/dist/thread.js +121 -18
  342. package/dist/tokens.js +15 -11
  343. package/dist/trabalho-thread.js +297 -0
  344. package/dist/transporte-do-canal.js +189 -0
  345. package/dist/types.js +12 -1
  346. package/dist/util.js +5 -2
  347. package/dist/varredura-acoes.js +507 -0
  348. package/dist/verify.js +472 -29
  349. package/dist/worktree-local.js +12 -10
  350. package/dist/worktree.js +81 -85
  351. package/eval/casos/check-quality.json +77 -0
  352. package/eval/casos/security-auditor.json +148 -0
  353. package/eval/casos/security-remediation.json +161 -0
  354. package/eval/fixtures/security-scan/README.md +8 -0
  355. package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
  356. package/eval/fixtures/security-scan/go/Dockerfile +4 -0
  357. package/eval/fixtures/security-scan/go/README.md +4 -0
  358. package/eval/fixtures/security-scan/go/config.go +4 -0
  359. package/eval/fixtures/security-scan/go/go.mod +5 -0
  360. package/eval/fixtures/security-scan/go/go.sum +2 -0
  361. package/eval/fixtures/security-scan/go/main.go +31 -0
  362. package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
  363. package/eval/fixtures/security-scan/js/Dockerfile +3 -0
  364. package/eval/fixtures/security-scan/js/README.md +4 -0
  365. package/eval/fixtures/security-scan/js/package-lock.json +844 -0
  366. package/eval/fixtures/security-scan/js/package.json +10 -0
  367. package/eval/fixtures/security-scan/js/src/config.js +4 -0
  368. package/eval/fixtures/security-scan/js/src/server.js +17 -0
  369. package/eval/fixtures/security-scan/js/src/util.ts +4 -0
  370. package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
  371. package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
  372. package/eval/fixtures/security-scan/python/Dockerfile +3 -0
  373. package/eval/fixtures/security-scan/python/README.md +4 -0
  374. package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
  375. package/eval/fixtures/security-scan/python/app/config.py +2 -0
  376. package/eval/fixtures/security-scan/python/app/main.py +19 -0
  377. package/eval/fixtures/security-scan/python/requirements.txt +1 -0
  378. package/package.json +9 -4
  379. package/references/security-checklist.md +3 -3
  380. package/skills/README.md +1 -0
  381. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  382. package/skills/phases/check-quality/SKILL.md +16 -0
  383. package/skills/phases/go-implementation/SKILL.md +6 -0
  384. package/skills/phases/security-remediation/SKILL.md +70 -0
  385. package/skills/reviewers/security-auditor/SKILL.md +25 -0
@@ -0,0 +1,481 @@
1
+ // O Mensageiro de Sessoes do Orkastery (RM-059, fatia F9; ficha M9 do plano dos mods). Na sessao do dono, leva a
2
+ // resposta que o dono deu pelo dialogo nativo a sessao de fase `claude-bg` que parou esperando por ela: pega a
3
+ // mensagem na caixa de saida do nucleo (`ork_session_outbox`, so na memoria do servidor desta sessao), envia por
4
+ // `$.session.send` sem mexer no texto e anota o envio no nucleo. Na sessao de fase, so deixa entrar na conversa a
5
+ // mensagem de outra sessao que o nucleo confirma, pela `ork_session_inbox`, como a resposta do dono reservada para
6
+ // ela; o resto que chega de outra sessao e consumido antes do modelo. Le o que segue incerto pelo `$.ork.retrato`,
7
+ // nunca o estado em `.orkastery/` por conta propria. Nunca responde, aprova ou abre pedido pelo dono. A logica fica
8
+ // nos modulos puros ao lado; aqui so os ganchos e as chamadas ao `$`, sempre escritas como `x.noun.metodo(...)`, como
9
+ // o validador exige.
10
+ import type { EngineInterface, Register, SessionReceiveInput, SessionReceiveResult } from 'claude-code'
11
+ import type { MensageiroDono, MensageiroFase, MensageiroMostrado, MensageiroRecebida } from '../types'
12
+ import type { EntradaDaCaixa } from './caixa'
13
+ import {
14
+ argsDaAnotacao, argsDoEnvio, atualizarEntregas, deveEnviar, DONO_VAZIO, entradaAnotada, FERRAMENTA_DA_CAIXA, incertasDoRetrato,
15
+ jsonDoMcp, lerCaixa, pedidosNoRetrato, resultadoDoEnvio, textoDaFaixa, threadDoLedger, umaLinha,
16
+ } from './caixa'
17
+ import { desenharPainel, linhasDaFase, linhasDoDono, mostradosVisiveis } from './painel'
18
+ import type { Conferencia } from './recepcao'
19
+ import {
20
+ argsDaConferencia, argsDaConfirmacao, classificarOrigem, comRecebida, confirmadasDaFase, ESPERAS_DA_CONFIRMACAO_MS, FASE_VAZIA,
21
+ decisaoNaFalha, FERRAMENTA_DA_CONFERENCIA, idsDaMarca, impressaoDoTexto, lerConferencia, lerConfirmacao, LIMITE_DA_MENSAGEM,
22
+ mensagemSemEnvelope, motivoDoConsumo, mudarRecebida, nomeDaOrigem, registroDaRecebida, temMarca, textoComRotulo, textoParaOModelo,
23
+ } from './recepcao'
24
+
25
+ const MOD = 'ork-mensageiro'
26
+ const PAINEL = 'mensageiro'
27
+ const TITULO = 'Mensageiro de Sessões'
28
+ const DONO = { plugin: 'ork-mensageiro', key: 'dono' } as const
29
+ const FASE = { plugin: 'ork-mensageiro', key: 'fase' } as const
30
+ /** D9 da thread ork-rm059mensag: o tique do lado do dono, que tambem mantem o Mensageiro vivo na caixa de saida. */
31
+ const PERIODO_DO_TIQUE_MS = 20000
32
+ /** Os ledgers que mudam juntos entram numa leitura so. */
33
+ const ESPERA_DO_LOTE_MS = 1000
34
+ /** Teto de cada chamada ao nucleo. */
35
+ const PRAZO_DO_NUCLEO_MS = 20000
36
+ /** O servidor do nucleo pode conectar depois do inicio da sessao: o papel e conferido de novo nestas esperas. */
37
+ const ESPERAS_DO_PAPEL_MS = [3000, 10000, 30000]
38
+ const ESPERA_LONGA_DO_PAPEL_MS = 300000
39
+
40
+ // O que o modulo guarda entre ganchos. O estado em `$.state` (o lado do dono e o da fase) e o que o desenho le; aqui
41
+ // ficam a copia dele, gravada inteira por `$.state.set` sem versao (uma gravacao por mudanca), e o que nao se
42
+ // desenha. Uma recarga do modulo zera tudo, e o `session.start` dispara de novo nela.
43
+ let ativa = false
44
+ let naFase = false
45
+ let desistiu = false
46
+ let ciclo: { cancel: () => void } | undefined
47
+ let lote: { cancel: () => void } | undefined
48
+ let lendo: Promise<void> | undefined
49
+ let pendente = false
50
+ let dono: MensageiroDono = DONO_VAZIO
51
+ let fase: MensageiroFase = FASE_VAZIA
52
+ /**
53
+ * O papel e a thread que a ponte deu. O papel `fase` sai do `ORK_DISPATCH_ID` do despacho e nunca muda na sessao, e
54
+ * a sessao que nao e de fase nunca vira: o receptor decide por isto, lido uma vez.
55
+ */
56
+ let contextoVisto: { papel: string; thread: string | null } | null = null
57
+ /**
58
+ * As mensagens que o nucleo confirmou e que ainda nao entraram na fila, com o texto que o modelo vai ler: o `.catch`
59
+ * do receptor deixa passar so elas, e no envelope do Mensageiro.
60
+ */
61
+ const confirmadasEmVoo = new Map<string, string>()
62
+ /** O ultimo texto publicado na faixa; null antes da primeira publicacao. */
63
+ let ultimaFaixa: string | undefined | null = null
64
+ /** O que o desenho pos na janela de rolagem e ainda nao foi ao registro da ponte (M5). */
65
+ const vistosNoDesenho = new Map<string, MensageiroMostrado>()
66
+ /** O que ja foi ao registro nesta sessao, por chave e texto. */
67
+ const jaMostrado = new Set<string>()
68
+ /** A falha de um trabalho em segundo plano que nem o painel conseguiu guardar. */
69
+ let problemaSemAviso: string | null = null
70
+
71
+ const mensagem = (erro: unknown) => umaLinha(erro, 200)
72
+
73
+ /** A chamada com teto proprio: o relogio da sessao recusa a espera que passar dele. */
74
+ function comPrazo<T>($: EngineInterface, chamada: Promise<T>, ms = PRAZO_DO_NUCLEO_MS): Promise<T> {
75
+ return new Promise<T>((resolver, recusar) => {
76
+ const prazo = $.clock.after(ms, () => recusar(new Error(`o núcleo passou de ${Math.round(ms / 1000)} s`)))
77
+ chamada.then(v => { prazo.cancel(); resolver(v) }, e => { prazo.cancel(); recusar(e) })
78
+ })
79
+ }
80
+
81
+ /**
82
+ * O instante do relogio da sessao para as linhas do estado; sem ele, o da ultima linha. O prazo da conferencia nao usa
83
+ * isto: sem relogio, a conferencia falha e a mensagem e consumida.
84
+ */
85
+ async function instante($: EngineInterface): Promise<number> {
86
+ try {
87
+ return await $.clock.now()
88
+ } catch {
89
+ return fase.recebidas.at(-1)?.em ?? 0
90
+ }
91
+ }
92
+
93
+ async function gravarDono($: EngineInterface, novo: MensageiroDono): Promise<void> {
94
+ dono = novo
95
+ await $.state.set(DONO, novo)
96
+ }
97
+
98
+ async function gravarFase($: EngineInterface, nova: MensageiroFase): Promise<void> {
99
+ fase = nova
100
+ await $.state.set(FASE, nova)
101
+ }
102
+
103
+ /**
104
+ * Trabalho em segundo plano (o tique, o lote, a leitura pedida, o recibo da entrega): a falha vai ao painel; sem como
105
+ * gravar (a sessao acabou ou o estado recusou), ela fica guardada aqui e o proximo desenho a mostra. O `.catch` nao
106
+ * depende do `$`.
107
+ */
108
+ function emSegundoPlano($: EngineInterface, trabalho: Promise<unknown>, oQue: string): void {
109
+ trabalho.catch(async erro => {
110
+ const texto = `${oQue} parou: ${mensagem(erro)}`
111
+ try {
112
+ if (naFase) await gravarFase($, { ...fase, erro: texto })
113
+ else await gravarDono($, { ...dono, erro: texto })
114
+ } catch (erroDoAviso) {
115
+ problemaSemAviso = `${texto} (o aviso também falhou: ${mensagem(erroDoAviso)})`
116
+ }
117
+ })
118
+ }
119
+
120
+ /**
121
+ * O papel e a thread pela ponte. `null` so quando o `$.ork` nao existe (a ponte nao carregou); a falha da propria
122
+ * ponte lanca. O que a ponte respondeu fica em `contextoVisto`.
123
+ */
124
+ async function contextoDaSessao($: EngineInterface): Promise<{ papel: string; thread: string | null } | null> {
125
+ let lido: { papel: unknown; thread: unknown }
126
+ try {
127
+ lido = await comPrazo($, $.ork.contexto())
128
+ } catch (erro) {
129
+ if (erro instanceof TypeError) return null
130
+ throw erro
131
+ }
132
+ contextoVisto = { papel: String(lido.papel), thread: typeof lido.thread === 'string' ? lido.thread : null }
133
+ return contextoVisto
134
+ }
135
+
136
+ /** Liga o lado do dono: o `/mensageiro`, o tique e a primeira leitura da caixa. */
137
+ async function ativarDono($: EngineInterface): Promise<void> {
138
+ if (ativa) return
139
+ ativa = true
140
+ try {
141
+ await $.command.register({ name: 'mensageiro', description: 'Abre o Mensageiro de Sessões: as respostas do dono a caminho das sessões de fase', immediate: true })
142
+ } catch (erro) {
143
+ // Sem o /mensageiro o painel nao abre: o lado do dono volta a dormente e tenta de novo na espera longa.
144
+ ativa = false
145
+ $.clock.after(ESPERA_LONGA_DO_PAPEL_MS, () => { emSegundoPlano($, conferirPapel($, ESPERAS_DO_PAPEL_MS.length), 'a conferência do papel') })
146
+ throw erro
147
+ }
148
+ dono = (await $.state.get(DONO)).value ?? DONO_VAZIO
149
+ ciclo?.cancel()
150
+ ciclo = $.clock.every(PERIODO_DO_TIQUE_MS, () => { emSegundoPlano($, levar($), 'o tique do Mensageiro') })
151
+ agendar($, 1)
152
+ }
153
+
154
+ /** Liga o lado da sessao de fase: o `/mensageiro` mostra o que chegou. O filtro do receptor nao depende disto. */
155
+ async function ativarFase($: EngineInterface): Promise<void> {
156
+ if (naFase) return
157
+ naFase = true
158
+ desistiu = true
159
+ const guardada = (await $.state.get(FASE)).value
160
+ // O que chegou antes desta leitura ja esta na memoria e no estado: a copia guardada so volta quando nada chegou.
161
+ if (guardada && !fase.recebidas.length) fase = guardada
162
+ fase = { ...fase, thread: contextoVisto?.thread ?? fase.thread }
163
+ try {
164
+ await $.command.register({ name: 'mensageiro', description: 'Abre o Mensageiro de Sessões: o que chegou de outras sessões a esta sessão de fase', immediate: true })
165
+ } catch (erro) {
166
+ // O filtro segue sem o comando; o painel diz por que ele nao abre.
167
+ await gravarFase($, { ...fase, erro: `o /mensageiro não foi registrado: ${mensagem(erro)}` })
168
+ }
169
+ }
170
+
171
+ /** Confere o papel: o dono liga o lado do dono, a fase liga o da fase, e a sessao dormente e conferida de novo. */
172
+ async function conferirPapel($: EngineInterface, tentativa: number): Promise<void> {
173
+ if (ativa || naFase || desistiu) return
174
+ let papel: string | null
175
+ try {
176
+ papel = (await contextoDaSessao($))?.papel ?? null
177
+ } catch {
178
+ // A ponte falhou: a sessao conta como dormente e o papel e conferido de novo depois.
179
+ papel = 'dormente'
180
+ }
181
+ if (papel === 'dono') return ativarDono($)
182
+ if (papel === 'fase') return ativarFase($)
183
+ if (papel === null) {
184
+ desistiu = true
185
+ $.ui.toast('mensageiro: a ponte ork-ponte não carregou; o Mensageiro de Sessões não leva respostas nesta sessão, e mensagem de outra sessão é consumida antes do modelo')
186
+ return
187
+ }
188
+ const espera = ESPERAS_DO_PAPEL_MS[tentativa] ?? ESPERA_LONGA_DO_PAPEL_MS
189
+ $.clock.after(espera, () => { emSegundoPlano($, conferirPapel($, tentativa + 1), 'a conferência do papel') })
190
+ }
191
+
192
+ /** Uma leitura daqui a pouco, uma por vez: os ledgers que mudam juntos entram nela. */
193
+ function agendar($: EngineInterface, ms = ESPERA_DO_LOTE_MS): void {
194
+ if (lote) return
195
+ lote = $.clock.after(Math.max(1, ms), () => {
196
+ lote = undefined
197
+ emSegundoPlano($, levar($), 'a leitura da caixa de saída')
198
+ })
199
+ }
200
+
201
+ /** Uma rodada por vez; pedido que chega no meio volta a rodar logo depois, e quem pediu espera as duas. */
202
+ async function levar($: EngineInterface): Promise<void> {
203
+ if (!ativa) return
204
+ if (lendo) {
205
+ pendente = true
206
+ return lendo
207
+ }
208
+ lendo = (async () => {
209
+ try {
210
+ do {
211
+ pendente = false
212
+ await umaRodada($)
213
+ } while (pendente)
214
+ } finally {
215
+ lendo = undefined
216
+ }
217
+ })()
218
+ return lendo
219
+ }
220
+
221
+ /**
222
+ * Uma rodada: a caixa de saida (o `listar` tambem mantem o Mensageiro vivo para o nucleo, D9), o envio do que deve ir
223
+ * (D10), o retrato da secao `hitl` para saber o que ja foi respondido e o que segue noutra sessao, a faixa e o registro
224
+ * do que o painel mostrou.
225
+ */
226
+ async function umaRodada($: EngineInterface): Promise<void> {
227
+ let caixa: EntradaDaCaixa[]
228
+ try {
229
+ caixa = lerCaixa(jsonDoMcp(await comPrazo($, $.mcp.call('orkastery', 'ork_session_outbox', { operacao: 'listar' })), FERRAMENTA_DA_CAIXA))
230
+ } catch (erro) {
231
+ await gravarDono($, { ...dono, erro: `a caixa de saída não foi lida: ${mensagem(erro)}` })
232
+ await publicarFaixa($)
233
+ return
234
+ }
235
+ const agora = await $.clock.now()
236
+ const levadas: EntradaDaCaixa[] = []
237
+ for (const e of caixa) levadas.push(deveEnviar(e, agora) ? await enviar($, e) : e)
238
+ let retrato: unknown = null
239
+ try {
240
+ retrato = (await comPrazo($, $.ork.retrato({ secao: 'hitl' }))).retrato
241
+ } catch {
242
+ // Sem o retrato, nada se conclui sobre o que saiu da caixa nesta volta.
243
+ }
244
+ const noRetrato = retrato === null ? null : pedidosNoRetrato(retrato)
245
+ const depois = await $.clock.now()
246
+ const entregas = atualizarEntregas(dono.entregas, levadas, noRetrato, depois)
247
+ // So e "noutra sessao" o pedido incerto que esta sessao nao conhece: o que saiu da caixa daqui fica na linha dele.
248
+ await gravarDono($, {
249
+ entregas,
250
+ incertas: retrato === null ? dono.incertas : incertasDoRetrato(retrato).filter(i => !entregas.some(e => e.pedidoId === i.pedidoId)),
251
+ lidoEm: depois,
252
+ erro: null,
253
+ })
254
+ await publicarFaixa($)
255
+ await registrarMostrados($)
256
+ }
257
+
258
+ /** Envia a mensagem como o nucleo a compos e anota o resultado no nucleo; a anotacao que falha nao desfaz o envio. */
259
+ async function enviar($: EngineInterface, e: EntradaDaCaixa): Promise<EntradaDaCaixa> {
260
+ let r: { entregue: boolean; motivo: string | null }
261
+ try {
262
+ r = resultadoDoEnvio(await comPrazo($, $.session.send(argsDoEnvio(e))))
263
+ } catch (erro) {
264
+ r = { entregue: false, motivo: `o envio falhou: ${mensagem(erro)}` }
265
+ }
266
+ try {
267
+ const anotada = entradaAnotada(jsonDoMcp(await comPrazo($, $.mcp.call('orkastery', 'ork_session_outbox', argsDaAnotacao(e, r))), FERRAMENTA_DA_CAIXA), e.reservada)
268
+ if (anotada) return anotada
269
+ } catch {
270
+ // O nucleo nao anotou: a proxima leitura da caixa traz a conta dele.
271
+ }
272
+ return { ...e, tentativas: e.tentativas + 1, ultimoEnvio: { em: await $.clock.now(), entregue: r.entregue, motivo: r.motivo } }
273
+ }
274
+
275
+ /** A linha da faixa pela ponte (D7 do plano dos mods), so quando o texto muda; sem nada a dizer, a linha sai. */
276
+ async function publicarFaixa($: EngineInterface): Promise<void> {
277
+ const texto = textoDaFaixa(dono, await $.clock.now())
278
+ if (texto === ultimaFaixa) return
279
+ try {
280
+ if (texto === undefined) await $.ork.faixa({ mod: MOD })
281
+ else await $.ork.faixa({ mod: MOD, texto })
282
+ ultimaFaixa = texto
283
+ } catch {
284
+ // A ponte recusou ou falhou: a proxima rodada tenta de novo.
285
+ }
286
+ }
287
+
288
+ /** O painel do Mensageiro esta posto e a vista do dono. */
289
+ async function painelAVista($: EngineInterface): Promise<boolean> {
290
+ const paineis = await $.ui.panes().catch(() => [])
291
+ return paineis.some(p => p.id === PAINEL && p.isPlaced && p.isShown)
292
+ }
293
+
294
+ /**
295
+ * O que o desenho pos na janela de rolagem do painel posto e a vista vai ao registro da ponte (M5 do dono), uma vez
296
+ * por chave e texto: o Telegram nao repete o que o dono ja viu no terminal.
297
+ */
298
+ async function registrarMostrados($: EngineInterface): Promise<void> {
299
+ if (vistosNoDesenho.size === 0) return
300
+ if (!await painelAVista($)) { vistosNoDesenho.clear(); return }
301
+ for (const [vista, m] of [...vistosNoDesenho]) {
302
+ vistosNoDesenho.delete(vista)
303
+ if (jaMostrado.has(vista)) continue
304
+ try {
305
+ await $.ork.mostrado({ mod: MOD, canal: 'painel', chave: m.chave, ...(m.thread ? { thread: m.thread } : {}), texto: m.texto })
306
+ jaMostrado.add(vista)
307
+ } catch {
308
+ // A ponte recusou ou falhou: volta para a proxima vez.
309
+ vistosNoDesenho.set(vista, m)
310
+ }
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Anota o que chegou no estado da fase e, quando a mensagem nao entrou como devia, uma linha no transcript (dim, fora
316
+ * do modelo). Nunca lanca: o receptor decide sem depender do estado nem do transcript.
317
+ */
318
+ async function anotar($: EngineInterface, mudar: (f: MensageiroFase) => MensageiroFase, registro: MensageiroRecebida | null): Promise<void> {
319
+ try {
320
+ await gravarFase($, mudar(fase))
321
+ } catch (erro) {
322
+ problemaSemAviso = `o estado da sessão de fase não foi gravado: ${mensagem(erro)}`
323
+ }
324
+ const linha = registro ? registroDaRecebida(registro) : null
325
+ if (!linha) return
326
+ try {
327
+ $.ui.log(linha)
328
+ } catch (erro) {
329
+ problemaSemAviso = `o transcript recusou a linha do Mensageiro: ${mensagem(erro)}`
330
+ }
331
+ }
332
+
333
+ /** Consome a mensagem de outra sessao antes do modelo, com o motivo no estado, no transcript e no registro do Claude Code. */
334
+ async function consumir($: EngineInterface, e: SessionReceiveInput, motivo: string, detalhe?: string): Promise<SessionReceiveResult> {
335
+ const r: MensageiroRecebida = { em: await instante($), origem: nomeDaOrigem(e.origin), estado: 'consumida', ...idsDaMarca(e.text),
336
+ motivo: detalhe ? `${motivo}: ${umaLinha(detalhe, 160)}` : motivo, impressao: null }
337
+ await anotar($, f => comRecebida(f, r), r)
338
+ return { consumed: motivoDoConsumo(motivo) }
339
+ }
340
+
341
+ /**
342
+ * A mensagem de outra sessao (T9.3). Na sessao de fase: sem a marca, consumida sem chamar o nucleo (D13); com ela, vai
343
+ * ao `conferir` do nucleo, e so a confirmada segue para a conversa, no envelope fixo do Mensageiro e com o corpo que o
344
+ * nucleo conferiu (D23, que reve a D11), com o `confirmar` depois de entrar na fila. Falha, prazo vencido e resposta
345
+ * fora do contrato consomem. Sem a ponte, ou sem o papel, consome. Nas sessoes do dono e dormente, passa como chegou.
346
+ */
347
+ async function receber($: EngineInterface, e: SessionReceiveInput, next: (e: SessionReceiveInput) => Promise<SessionReceiveResult>): Promise<SessionReceiveResult> {
348
+ let contexto = contextoVisto
349
+ if (contexto === null) {
350
+ try {
351
+ contexto = await contextoDaSessao($)
352
+ } catch (erro) {
353
+ return consumir($, e, 'entrega.sem-papel', mensagem(erro))
354
+ }
355
+ if (contexto === null) return consumir($, e, 'entrega.sem-ponte')
356
+ }
357
+ if (contexto.papel !== 'fase') return next(e)
358
+ if (typeof e.text !== 'string' || e.text.length > LIMITE_DA_MENSAGEM) return consumir($, e, 'entrega.grande')
359
+ if (!temMarca(e.text)) return consumir($, e, 'entrega.sem-marca')
360
+ const thread = contexto.thread
361
+ if (thread === null) return consumir($, e, 'entrega.despacho')
362
+ // A mensagem que o nucleo vai conferir, sem o envelope do motor: e so ela que o modelo vai ler (D23).
363
+ const conferivel = mensagemSemEnvelope(e.text)
364
+ if (conferivel === null) return consumir($, e, 'entrega.formato')
365
+ let conferencia: Conferencia
366
+ try {
367
+ const agora = await $.clock.now()
368
+ conferencia = lerConferencia(jsonDoMcp(await comPrazo($, $.mcp.call('orkastery', 'ork_session_inbox', argsDaConferencia(thread, e.text, agora))), FERRAMENTA_DA_CONFERENCIA))
369
+ } catch (erro) {
370
+ return consumir($, e, 'entrega.conferencia-falhou', mensagem(erro))
371
+ }
372
+ if (!conferencia.confirmada) return consumir($, e, conferencia.motivo)
373
+ const { pedidoId, envioId } = conferencia
374
+ const texto = e.text
375
+ const paraOModelo = textoParaOModelo(conferivel)
376
+ // A impressao da mensagem como a linha da conversa a mostra, para o rotulo visual.
377
+ const impressao = impressaoDoTexto(conferivel)
378
+ confirmadasEmVoo.set(texto, paraOModelo)
379
+ let r: SessionReceiveResult
380
+ try {
381
+ const chegada: MensageiroRecebida = { em: await instante($), origem: nomeDaOrigem(e.origin), estado: 'confirmando', pedidoId, envioId,
382
+ motivo: null, impressao }
383
+ await anotar($, f => comRecebida(f, chegada), null)
384
+ r = await next({ ...e, text: paraOModelo })
385
+ } finally {
386
+ confirmadasEmVoo.delete(texto)
387
+ }
388
+ if (r.consumed !== undefined) {
389
+ const caiu: MensageiroRecebida = { em: await instante($), origem: nomeDaOrigem(e.origin), estado: 'nao-entrou', pedidoId, envioId,
390
+ motivo: `outro plugin a consumiu abaixo do Mensageiro (${umaLinha(r.consumed, 120)})`, impressao: null }
391
+ await anotar($, f => mudarRecebida(f, envioId, caiu.estado, caiu.motivo, caiu.em), caiu)
392
+ return r
393
+ }
394
+ emSegundoPlano($, confirmar($, thread, pedidoId, envioId, texto, 0), 'a confirmação da entrega')
395
+ return r
396
+ }
397
+
398
+ /** O recibo da entrega que entrou na conversa; a falha volta nas esperas e, esgotadas, a linha fica sem recibo. */
399
+ async function confirmar($: EngineInterface, thread: string, pedidoId: string, envioId: string, texto: string, tentativa: number): Promise<void> {
400
+ let r: { ok: boolean; definitiva: boolean; motivo: string | null }
401
+ try {
402
+ r = lerConfirmacao(jsonDoMcp(await comPrazo($, $.mcp.call('orkastery', 'ork_session_inbox', argsDaConfirmacao(thread, envioId, texto))), FERRAMENTA_DA_CONFERENCIA))
403
+ } catch (erro) {
404
+ r = { ok: false, definitiva: false, motivo: mensagem(erro) }
405
+ }
406
+ const em = await instante($)
407
+ if (r.ok) return anotar($, f => mudarRecebida(f, envioId, 'entregue', null, em), null)
408
+ const motivo = r.motivo
409
+ const espera = r.definitiva ? undefined : ESPERAS_DA_CONFIRMACAO_MS[tentativa]
410
+ if (espera === undefined) {
411
+ const semRecibo: MensageiroRecebida = { em, origem: '', estado: 'sem-recibo', pedidoId, envioId, motivo, impressao: null }
412
+ return anotar($, f => mudarRecebida(f, envioId, 'sem-recibo', motivo, em), semRecibo)
413
+ }
414
+ await anotar($, f => mudarRecebida(f, envioId, 'confirmando', `o recibo volta a ser gravado: ${motivo ?? 'sem motivo'}`, em), null)
415
+ $.clock.after(espera, () => { emSegundoPlano($, confirmar($, thread, pedidoId, envioId, texto, tentativa + 1), 'a confirmação da entrega') })
416
+ }
417
+
418
+ export const register: Register = on => {
419
+ on('session.start', async ($, e, next) => {
420
+ const iniciada = await next(e)
421
+ await conferirPapel($, 0).catch(() => undefined)
422
+ return iniciada
423
+ })
424
+
425
+ // Toda entrega que chega a sessao. So a de outra sessao passa pelo receptor (G4); Remote Control, notificacao de
426
+ // tarefa, agendamento, canais, agentes e teammates verificados desta sessao seguem como chegaram, sem chamada ao
427
+ // nucleo. O `.catch` fecha: a mensagem de outra sessao que o gancho nao decidiu e consumida, salvo a que o nucleo
428
+ // ja confirmou e reservou, que segue.
429
+ on('session.receive', async ($, e, next) => {
430
+ if (classificarOrigem(e.origin, e.agentId) !== 'outra-sessao') return next(e)
431
+ return receber($, e, next)
432
+ }).catch(($, e, next) => {
433
+ if (next.called) return next(e)
434
+ const decisao = decisaoNaFalha({ origem: e.origin, agentId: e.agentId, texto: e.text, papel: contextoVisto?.papel ?? null, emVoo: confirmadasEmVoo })
435
+ if (decisao.acao === 'passa') return next(e)
436
+ if (decisao.acao === 'conferida') return next({ ...e, text: decisao.texto })
437
+ return { consumed: motivoDoConsumo('entrega.conferencia-falhou') }
438
+ })
439
+
440
+ // O ledger de uma thread mudou (uma resposta entrou na caixa, a sessao reservou ou confirmou): a leitura entra no
441
+ // proximo lote. Os caminhos vigiados sao os que a ponte pede para o papel dono; o Mensageiro nao pede outros.
442
+ on('classic.FileChanged', async ($, e, next) => {
443
+ if (ativa && threadDoLedger(e.file_path) !== null) agendar($)
444
+ return next(e)
445
+ }).catch(($, e, next) => next(e))
446
+
447
+ // `/mensageiro` abre o painel: na sessao do dono, as entregas, e le a caixa agora; na de fase, o que chegou.
448
+ on('command.run', { command: 'mensageiro' }, async ($) => {
449
+ if (!ativa && !naFase && !desistiu) await conferirPapel($, ESPERAS_DO_PAPEL_MS.length)
450
+ if (!ativa && !naFase) return { text: 'O Mensageiro de Sessões só abre numa sessão do Orkastery: a do dono ou a de uma fase.' }
451
+ const aberto = await $.ui.open({ id: PAINEL, title: TITULO })
452
+ if (ativa) emSegundoPlano($, levar($), 'a leitura da caixa de saída')
453
+ return { text: aberto.isPlaced ? 'Mensageiro de Sessões aberto.' : `Mensageiro de Sessões aberto, à espera de lugar: ${aberto.reason}` }
454
+ })
455
+
456
+ // O painel: na sessao do dono, as entregas desta sessao e as que seguem noutra; na de fase, o que chegou. O desenho
457
+ // nunca escreve: so anota o que pos na janela de rolagem, para o registro do mostrado (M5).
458
+ on('ui.render', { component: 'Pane', requestId: PAINEL }, async ($, e) => {
459
+ const { Box, Text, Button } = $.ui.resolve(e)
460
+ if (naFase) {
461
+ const daFase = (await $.state.get(FASE)).value ?? fase
462
+ const comProblema: MensageiroFase = problemaSemAviso ? { ...daFase, erro: problemaSemAviso } : daFase
463
+ return desenharPainel({ Box, Text, Button }, linhasDaFase(comProblema, await $.clock.now()), {})
464
+ }
465
+ const atual = (await $.state.get(DONO)).value ?? dono
466
+ const comProblema: MensageiroDono = problemaSemAviso ? { ...atual, erro: problemaSemAviso } : atual
467
+ const linhas = linhasDoDono(comProblema, await $.clock.now())
468
+ for (const m of mostradosVisiveis(linhas, e.props.scroll)) vistosNoDesenho.set(`${m.chave}|${m.texto}`, m)
469
+ return desenharPainel({ Box, Text, Button }, linhas, { atualizar: () => { emSegundoPlano($, levar($), 'a leitura da caixa de saída') } })
470
+ })
471
+
472
+ // Na sessao de fase, a linha da resposta que o nucleo confirmou mostra o rotulo no lugar do cabecalho. So visual: o
473
+ // que fica guardado e o que o modelo le nao mudam.
474
+ on('ui.render', { component: 'UserMessage' }, async ($, e, next) => {
475
+ // So a linha de mensagem de outra sessao (`peer`): a de teammate chega `unclassified`, e a do dono, de outra origem.
476
+ if (!naFase || e.props.origin.kind !== 'peer' || !temMarca(e.props.text)) return next(e)
477
+ const daFase = (await $.state.get(FASE)).value ?? fase
478
+ const texto = textoComRotulo(e.props.text, confirmadasDaFase(daFase))
479
+ return texto === null ? next(e) : next({ ...e, props: { ...e.props, text: texto } })
480
+ }).catch(($, e, next) => next(e))
481
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "formato": "ork.mod/v1",
3
+ "papeis": ["dono", "fase"],
4
+ "claudeCodeMinimo": "2.1.287"
5
+ }
@@ -0,0 +1,85 @@
1
+ // Contrato do estado do Mensageiro de Sessoes (`ork-mensageiro`, RM-059, fatia F9). O motor exige que cada chave de
2
+ // `$.state` do mod esteja declarada aqui, em `PluginState`. O Mensageiro nao acrescenta noun ao `$`: le o nucleo pelo
3
+ // `$.ork` da `ork-ponte`, que o plugin.json lista em `dependencies`, e pelas duas ferramentas MCP da entrega. Nenhum
4
+ // campo guarda o texto da resposta do dono (D12 da thread ork-rm059mensag): so ids, estado, motivo e instantes.
5
+ // Sem import nem referencia.
6
+
7
+ /**
8
+ * Onde uma entrega esta, vista da sessao do dono que a leva. `sem-recibo`: a sessao de fase reservou e nao gravou o
9
+ * recibo em 5 min (D21).
10
+ */
11
+ export type MensageiroEstadoDaEntrega =
12
+ | 'na-fila' | 'a-caminho' | 'reservada' | 'sem-recibo' | 'nao-chegou' | 'desistiu' | 'entregue' | 'saiu-da-caixa'
13
+
14
+ /** Uma entrega da caixa de saida desta sessao do dono, sem o texto. */
15
+ export type MensageiroEntrega = {
16
+ thread: string
17
+ pedidoId: string
18
+ envioId: string
19
+ sessionId: string
20
+ estado: MensageiroEstadoDaEntrega
21
+ /** Quantas vezes a mensagem foi enviada (`$.session.send`), pela conta do nucleo. */
22
+ tentativas: number
23
+ /** Por que o ultimo envio nao entrou na fila da sessao, ou por que o Mensageiro parou de tentar. */
24
+ motivo: string | null
25
+ /** Quando a entrega mudou de estado aqui (ms desde a epoca). */
26
+ em: number
27
+ }
28
+
29
+ /** Um pedido que o retrato mostra com a entrega incerta e que a caixa desta sessao nao tem: segue noutra sessao. */
30
+ export type MensageiroIncerta = { thread: string; pedidoId: string }
31
+
32
+ /** O lado do dono: as entregas desta sessao e as incertas de fora, com a ultima leitura. */
33
+ export type MensageiroDono = {
34
+ entregas: MensageiroEntrega[]
35
+ incertas: MensageiroIncerta[]
36
+ /** Quando a caixa foi lida (ms desde a epoca); null antes da primeira leitura. */
37
+ lidoEm: number | null
38
+ /** Por que a ultima leitura falhou, quando falhou (a anterior fica no painel). */
39
+ erro: string | null
40
+ }
41
+
42
+ /**
43
+ * O que aconteceu, na sessao de fase, com uma mensagem que chegou de outra sessao: consumida antes do modelo (sem
44
+ * entrega confirmada pelo nucleo), confirmando (conferida, na conversa, gravando o recibo), entregue (com o recibo),
45
+ * sem recibo (na conversa, mas o recibo nao foi gravado) ou nao entrou (conferida, e outro plugin a consumiu abaixo).
46
+ */
47
+ export type MensageiroEstadoDaRecebida = 'consumida' | 'confirmando' | 'entregue' | 'sem-recibo' | 'nao-entrou'
48
+
49
+ /** Uma mensagem de outra sessao que chegou a sessao de fase, sem o texto dela. */
50
+ export type MensageiroRecebida = {
51
+ /** Quando chegou ou mudou de estado (ms desde a epoca). */
52
+ em: number
53
+ /** O tipo da origem e o plugin que o remetente diz ser, numa linha. */
54
+ origem: string
55
+ estado: MensageiroEstadoDaRecebida
56
+ /** O pedido e a entrega: conferidos pelo nucleo na entrega confirmada; na consumida, so o que a marca dizia. */
57
+ pedidoId: string | null
58
+ envioId: string | null
59
+ /** Por que foi consumida ou ficou sem recibo, com o codigo do nucleo. */
60
+ motivo: string | null
61
+ /** A impressao do texto da entrega confirmada (FNV-1a e tamanho), para o rotulo; nunca o texto. */
62
+ impressao: string | null
63
+ }
64
+
65
+ /** O lado da sessao de fase: a thread do despacho e o que chegou de outras sessoes. */
66
+ export type MensageiroFase = {
67
+ thread: string | null
68
+ recebidas: MensageiroRecebida[]
69
+ /** Por que um trabalho em segundo plano parou, quando parou. */
70
+ erro: string | null
71
+ }
72
+
73
+ /** O que o painel mostrou ao dono e o Telegram tambem diria: a chave junta o que e a mesma coisa (M5). */
74
+ export type MensageiroMostrado = { chave: string; thread: string | null; texto: string }
75
+
76
+ declare module 'claude-code' {
77
+ interface PluginState {
78
+ 'ork-mensageiro': {
79
+ /** O lado do dono: as entregas a caminho das sessoes de fase. */
80
+ dono: MensageiroDono
81
+ /** O lado da sessao de fase: o que chegou de outras sessoes e o que o nucleo confirmou. */
82
+ fase: MensageiroFase
83
+ }
84
+ }
85
+ }
@@ -1,7 +1,8 @@
1
1
  // O CI de cada pista (RM-059, fatia F7, T7.4; D7 da thread ork-rm059pista). Modulo puro: o argv da consulta ao nucleo
2
- // (`ork ci status --sha <sha> --json`, contrato `ork.ci-status/v1`), a leitura dela, as pistas que um evento do GitHub
3
- // cita, as que o relogio de reserva consulta e a etapa de CI que o painel mostra com a leitura mais nova. O evento so
4
- // dispara a consulta: o conteudo dele nunca vira estado, e quem diz o CI e o check do nucleo no sha exato.
2
+ // (`ork ci status --sha <sha> --json`, contrato `ork.ci-status/v2`; a v1 dos nucleos anteriores continua lida), a
3
+ // leitura dela, as pistas que um evento do GitHub cita, as que o relogio de reserva consulta e a etapa de CI que o
4
+ // painel mostra com a leitura mais nova. O evento so dispara a consulta: o conteudo dele nunca vira estado, e quem diz o
5
+ // CI e o check do nucleo no sha exato.
5
6
  import type { PistaCi, PistaEstadoDaEtapa, PistaLinha, PistaQuadro } from '../types'
6
7
  import { jsonDaSaida, umaLinha } from './pista'
7
8
  import type { SaidaDoProcesso } from './pista'
@@ -18,14 +19,17 @@ export function argvDoCi(sha: string): string[] {
18
19
  return ['ork', 'ci', 'status', '--sha', sha, '--json']
19
20
  }
20
21
 
22
+ /** Os contratos do `ork ci status --json` que a Pista le: a v2 (forja, fonte e produtor) e a v1 de antes. */
23
+ const CONTRATOS_DO_CI: readonly string[] = ['ork.ci-status/v1', 'ork.ci-status/v2']
24
+
21
25
  /**
22
26
  * A saida do `ork ci status --sha <sha> --json`: o comando sai 0 so com o check verde, e o JSON vem nos dois casos.
23
27
  * Leitura de outro sha nao vale para a pista.
24
28
  */
25
29
  export function lerCi(saida: SaidaDoProcesso, sha: string, agora: number, motivo: PistaCi['motivo']): PistaCi {
26
30
  const r = jsonDaSaida(saida, 'ork ci status') as Record<string, unknown> | null
27
- if (!r || typeof r !== 'object' || r.schema !== 'ork.ci-status/v1' || !ESTADOS.includes(r.state as PistaCi['estado'])) {
28
- throw new Error('a saída do ork ci status não é o contrato ork.ci-status/v1')
31
+ if (!r || typeof r !== 'object' || !CONTRATOS_DO_CI.includes(r.schema as string) || !ESTADOS.includes(r.state as PistaCi['estado'])) {
32
+ throw new Error('a saída do ork ci status não é o contrato ork.ci-status (v1 ou v2)')
29
33
  }
30
34
  if (r.sha !== sha) throw new Error(`o ork ci status respondeu pelo commit ${umaLinha(r.sha, 40)}, e não pelo head ${sha.slice(0, 7)}`)
31
35
  const estado = r.state as PistaCi['estado']
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "ork-ritual",
3
+ "version": "0.1.0",
4
+ "description": "Ritual do MASTER do Orkastery no Claude Code: as entregas que esperam a sua nota, a prova de cada uma (o que foi entregue, o índice derivado do ledger e as claims com comando e estado, uma por vez) e a nota de 0 a 5 pelo diálogo nativo do host. O mod nunca dá a nota pelo dono.",
5
+ "author": {
6
+ "name": "Orkastery contributors",
7
+ "url": "https://github.com/orkastery"
8
+ },
9
+ "homepage": "https://orkastery.com/",
10
+ "repository": "https://github.com/orkastery/orkastery",
11
+ "license": "MIT",
12
+ "types": "./types/index.d.ts",
13
+ "dependencies": ["ork-ponte"]
14
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "modules": ["./register.tsx"]
3
+ }