@orkastery/cli 0.2.0 → 0.3.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 (242) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +86 -65
  3. package/adapters/README.md +30 -15
  4. package/adapters/claude-code/.claude-plugin/plugin.json +11 -5
  5. package/adapters/claude-code/README.md +110 -8
  6. package/adapters/claude-code/commands/onboarding.md +21 -0
  7. package/adapters/claude-code/commands/ork.md +99 -27
  8. package/adapters/claude-code/hooks/hooks.json +6 -1
  9. package/adapters/claude-code/hooks/ork-sensor.js +66 -0
  10. package/adapters/codex/skills/ork/SKILL.md +57 -0
  11. package/adapters/hermes/README.md +163 -0
  12. package/adapters/hermes/bin/ork-abrir-thread.sh +2 -0
  13. package/adapters/hermes/bin/ork-brain.sh +4 -0
  14. package/adapters/hermes/bin/ork-hitl-answer.py +82 -0
  15. package/adapters/hermes/bin/ork-maestro.sh +6 -0
  16. package/adapters/hermes/bin/ork-master-enviar.py +84 -0
  17. package/adapters/hermes/bin/ork-objective-message.sh +17 -0
  18. package/adapters/hermes/bin/ork-objective-status.sh +12 -0
  19. package/adapters/hermes/bin/ork-pulse-enviar.py +47 -0
  20. package/adapters/hermes/hermes.plugin.json +26 -4
  21. package/adapters/hermes/hitl-ingress/__init__.py +356 -0
  22. package/adapters/hermes/hitl-ingress/plugin.yaml +4 -0
  23. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +75 -22
  24. package/adapters/openclaw/README.md +135 -26
  25. package/adapters/openclaw/bin/ork-brain.sh +4 -0
  26. package/adapters/openclaw/construir.sh +19 -0
  27. package/adapters/openclaw/dist/hitl-ingress.js +199 -0
  28. package/adapters/openclaw/dist/index.js +437 -0
  29. package/adapters/openclaw/openclaw.plugin.json +39 -134
  30. package/adapters/openclaw/package.json +26 -0
  31. package/adapters/openclaw/src/hitl-ingress.ts +180 -0
  32. package/adapters/openclaw/src/index.ts +458 -0
  33. package/adapters/openclaw/src/tipos-openclaw.d.ts +58 -0
  34. package/adapters/openclaw/tsconfig.json +15 -0
  35. package/assets/docs/markdownlint-cli2.jsonc +22 -0
  36. package/assets/docs/padroes/documentacao-de-produto.md +133 -0
  37. package/assets/docs/padroes/roadmap-de-produto.md +98 -0
  38. package/assets/docs/produto/README.md +14 -0
  39. package/assets/docs/produto/_modelo-feature.md +59 -0
  40. package/assets/docs/roadmap/README.md +14 -0
  41. package/assets/docs/roadmap/_modelo-item.md +73 -0
  42. package/assets/orkmind-native-schema.json +32 -0
  43. package/assets/orkmind_bridge.py +357 -0
  44. package/assets/orkmind_fixture.py +67 -0
  45. package/assets/orkmind_prospective.py +138 -0
  46. package/assets/reference-tariffs-i07.json +23 -0
  47. package/dist/adapters/claude-bg.js +488 -39
  48. package/dist/adapters/codex-controller-sensor.js +449 -0
  49. package/dist/adapters/codex-controller-worker.js +361 -0
  50. package/dist/adapters/codex-controller.js +252 -0
  51. package/dist/adapters/codex-events.js +205 -0
  52. package/dist/adapters/codex-question.js +26 -0
  53. package/dist/adapters/codex-runner.js +133 -0
  54. package/dist/adapters/codex.js +394 -0
  55. package/dist/agents-md.js +84 -0
  56. package/dist/auditoria.js +11 -8
  57. package/dist/auditrun.js +5 -4
  58. package/dist/board.js +173 -22
  59. package/dist/branch-de-estado.js +136 -0
  60. package/dist/canarios-hitl.js +177 -0
  61. package/dist/canarios-i43.js +543 -0
  62. package/dist/canarios-pulse.js +147 -0
  63. package/dist/canarios-sensores.js +129 -0
  64. package/dist/canarios.js +111 -2
  65. package/dist/catalogo.js +9 -0
  66. package/dist/ci.js +216 -0
  67. package/dist/ciclos.js +2 -1
  68. package/dist/claim-lint.js +64 -0
  69. package/dist/claims.js +60 -0
  70. package/dist/company-brain-capture.js +195 -0
  71. package/dist/company-brain-cli.js +123 -0
  72. package/dist/company-brain-client.js +61 -0
  73. package/dist/company-brain-contract.js +166 -0
  74. package/dist/company-brain-journal.js +192 -0
  75. package/dist/company-brain-mcp.js +33 -0
  76. package/dist/company-brain-migration.js +60 -0
  77. package/dist/company-brain-source.js +177 -0
  78. package/dist/company-brain-worker.js +18 -0
  79. package/dist/conducao-texto.js +61 -0
  80. package/dist/conducao.js +876 -0
  81. package/dist/contrato-publico.js +39 -0
  82. package/dist/creation-operation-store.js +251 -0
  83. package/dist/creation-operation.js +148 -0
  84. package/dist/decisao-autonoma.js +183 -0
  85. package/dist/delegation.js +79 -0
  86. package/dist/demo.js +120 -0
  87. package/dist/docs.js +828 -0
  88. package/dist/doctor.js +183 -24
  89. package/dist/entrega-pr.js +117 -0
  90. package/dist/escopo-escrita.js +71 -0
  91. package/dist/estado-thread.js +222 -0
  92. package/dist/evalrunner.js +12 -0
  93. package/dist/fabrica-estado.js +329 -0
  94. package/dist/fabrica-publicar.js +76 -0
  95. package/dist/fix.js +21 -0
  96. package/dist/gates.js +55 -9
  97. package/dist/handoff.js +39 -23
  98. package/dist/hitl-canais.js +333 -0
  99. package/dist/hitl-classificacao.js +131 -0
  100. package/dist/hitl-contract.js +465 -0
  101. package/dist/hitl-estado.js +136 -0
  102. package/dist/hitl-gates.js +554 -0
  103. package/dist/hitl-ingress-receipt.js +382 -0
  104. package/dist/hitl-local-atestado.js +57 -0
  105. package/dist/hitl-local-receipt.js +328 -0
  106. package/dist/hitl-local.js +143 -0
  107. package/dist/hitl-lock.js +139 -0
  108. package/dist/hitl-lote.js +223 -0
  109. package/dist/hitl-native-offer.js +97 -0
  110. package/dist/hitl-native.js +65 -0
  111. package/dist/hitl-presentation.js +209 -0
  112. package/dist/hitl-public-receipt.js +176 -0
  113. package/dist/hitl-resumo.js +209 -0
  114. package/dist/hitl-sessions.js +475 -0
  115. package/dist/hitl.js +711 -0
  116. package/dist/horario.js +269 -0
  117. package/dist/hosts.js +198 -22
  118. package/dist/index.js +1736 -93
  119. package/dist/indice.js +99 -0
  120. package/dist/init.js +28 -3
  121. package/dist/integracoes-locais.js +17 -0
  122. package/dist/leases.js +65 -21
  123. package/dist/ledger-stats.js +272 -0
  124. package/dist/ledger.js +107 -2
  125. package/dist/licoes.js +215 -0
  126. package/dist/liveness.js +218 -0
  127. package/dist/maestro-actions.js +51 -0
  128. package/dist/maestro-authority.js +152 -0
  129. package/dist/maestro-cli.js +97 -0
  130. package/dist/maestro-contract.js +55 -0
  131. package/dist/maestro-discovery.js +132 -0
  132. package/dist/maestro-runtime.js +268 -0
  133. package/dist/maestro-snapshot.js +86 -0
  134. package/dist/maestro-sources.js +224 -0
  135. package/dist/manifest.js +165 -6
  136. package/dist/maquina.js +102 -0
  137. package/dist/master-audit.js +101 -0
  138. package/dist/master-batch.js +43 -0
  139. package/dist/master-digest.js +149 -0
  140. package/dist/master-migracao.js +155 -0
  141. package/dist/master.js +361 -77
  142. package/dist/mcp-artifacts.js +234 -0
  143. package/dist/mcp-git.js +433 -0
  144. package/dist/mcp-install.js +310 -0
  145. package/dist/mcp-maestro.js +25 -0
  146. package/dist/mcp-server.js +469 -0
  147. package/dist/mcp-ship.js +436 -0
  148. package/dist/mcp-verify.js +173 -0
  149. package/dist/memoria-humana.js +207 -0
  150. package/dist/memoria.js +314 -78
  151. package/dist/memory-migration.js +279 -0
  152. package/dist/memory-prospective.js +148 -0
  153. package/dist/modos-migracao.js +191 -0
  154. package/dist/modos.js +151 -15
  155. package/dist/monitor-lock.js +110 -0
  156. package/dist/objective.js +449 -0
  157. package/dist/ocupacao.js +267 -0
  158. package/dist/onboarding.js +303 -0
  159. package/dist/orkmind.js +389 -90
  160. package/dist/orquestracao.js +96 -69
  161. package/dist/phase.js +596 -150
  162. package/dist/playbook-capabilities.js +150 -0
  163. package/dist/playbook-contracts.js +188 -0
  164. package/dist/portfolio-context.js +61 -0
  165. package/dist/portfolio.js +180 -0
  166. package/dist/preflight.js +207 -0
  167. package/dist/process-audit.js +112 -0
  168. package/dist/project-state.js +93 -0
  169. package/dist/prompts.js +25 -5
  170. package/dist/prova-minima.js +112 -0
  171. package/dist/pulse-cadencia.js +163 -0
  172. package/dist/pulse-consentimento.js +260 -0
  173. package/dist/pulse-delivery.js +323 -0
  174. package/dist/pulse-resposta.js +542 -0
  175. package/dist/pulse.js +262 -0
  176. package/dist/ratelimit.js +35 -2
  177. package/dist/recall.js +80 -3
  178. package/dist/redacao-saida.js +45 -0
  179. package/dist/redacao-url.js +66 -0
  180. package/dist/retry.js +637 -115
  181. package/dist/roadmap-reservas.js +243 -0
  182. package/dist/runtime-ambiente.js +38 -0
  183. package/dist/runtime-context.js +215 -0
  184. package/dist/runtime-profiles.js +869 -0
  185. package/dist/runtimes.js +103 -0
  186. package/dist/sandbox.js +9 -0
  187. package/dist/session-events.js +203 -0
  188. package/dist/session-watcher-claude.js +637 -0
  189. package/dist/session-watcher.js +683 -0
  190. package/dist/sessoes-adopt.js +154 -0
  191. package/dist/sessoes-inventario.js +159 -0
  192. package/dist/sessoes.js +16 -35
  193. package/dist/setup.js +691 -0
  194. package/dist/ship.js +150 -15
  195. package/dist/slug.js +1 -1
  196. package/dist/thread-close.js +115 -0
  197. package/dist/thread.js +142 -28
  198. package/dist/tokens.js +1 -1
  199. package/dist/util.js +4 -2
  200. package/dist/verify-sandbox.js +265 -0
  201. package/dist/verify.js +270 -25
  202. package/dist/versao.js +60 -0
  203. package/dist/worktree.js +31 -2
  204. package/dist/write-activation.js +291 -0
  205. package/dist/yaml.js +2 -0
  206. package/eval/casos/onboarding.json +102 -0
  207. package/eval/casos/orkastery-bootstrap.json +35 -1
  208. package/eval/casos/scope-check-capability-map.json +45 -7
  209. package/eval/casos/ship-release.json +2 -2
  210. package/eval/fixtures/b0-slug-e-modos/caso.json +35 -22
  211. package/eval/fixtures/b2-master-log/caso.json +1 -1
  212. package/eval/fixtures/fx-adapter-editado-detectado/caso.json +19 -0
  213. package/eval/fixtures/fx-auto-quiet/caso.json +11 -0
  214. package/eval/fixtures/fx-blanket-approve/caso.json +10 -0
  215. package/eval/fixtures/fx-check-runtime-cruzado/caso.json +20 -0
  216. package/eval/fixtures/fx-codex-dry/caso.json +18 -0
  217. package/eval/fixtures/fx-donewhen-executavel/caso.json +15 -0
  218. package/eval/fixtures/fx-estado-dividido/caso.json +15 -0
  219. package/eval/fixtures/fx-fase-orfa/caso.json +116 -0
  220. package/eval/fixtures/fx-happy/caso.json +6 -4
  221. package/eval/fixtures/fx-hitl-latency/caso.json +20 -0
  222. package/eval/fixtures/fx-indice-reversao/caso.json +25 -0
  223. package/eval/fixtures/fx-listagem-abertas/caso.json +16 -0
  224. package/eval/fixtures/fx-maestro-bootstrap/caso.json +21 -0
  225. package/eval/fixtures/fx-modo-aposentado-escritor/caso.json +21 -0
  226. package/eval/fixtures/fx-modo-aposentado-leitor/caso.json +16 -0
  227. package/eval/fixtures/fx-objective-oscillation/caso.json +14 -0
  228. package/eval/fixtures/fx-omnicanal/caso.json +17 -0
  229. package/eval/fixtures/fx-sensores-runtime/caso.json +17 -0
  230. package/monitor/company-brain.cjs +17 -0
  231. package/monitor/pulse-scope.cjs +45 -0
  232. package/monitor/pulse.cron +18 -0
  233. package/monitor/varredura-pulse.sh +27 -0
  234. package/package.json +25 -4
  235. package/schemas/claims.schema.json +25 -0
  236. package/schemas/company-brain.schema.json +1158 -0
  237. package/schemas/creation-operation.schema.json +365 -0
  238. package/schemas/maestro-snapshot.schema.json +2716 -0
  239. package/skills/core/onboarding/SKILL.md +50 -0
  240. package/skills/core/orkastery-bootstrap/SKILL.md +95 -65
  241. package/skills/core/thread-state/SKILL.md +3 -1
  242. package/skills/governance/scope-check-capability-map/SKILL.md +17 -7
@@ -0,0 +1,469 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.criarServidorMcp = criarServidorMcp;
37
+ exports.servirMcp = servirMcp;
38
+ /** Transporte MCP de projeto. O cliente nativo e a configuracao de startup sao confiaveis;
39
+ * argumentos de ferramentas nunca escolhem raiz, shell ou resposta humana. */
40
+ const fs = __importStar(require("node:fs"));
41
+ const path = __importStar(require("node:path"));
42
+ const node_crypto_1 = require("node:crypto");
43
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
44
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
45
+ const zod_to_json_schema_1 = require("zod-to-json-schema");
46
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
47
+ const zod_1 = require("zod");
48
+ const util_1 = require("./util");
49
+ const runtime_ambiente_1 = require("./runtime-ambiente");
50
+ const manifest_1 = require("./manifest");
51
+ const horario_1 = require("./horario");
52
+ const thread_1 = require("./thread");
53
+ const ledger_1 = require("./ledger");
54
+ const phase_1 = require("./phase");
55
+ const leases_1 = require("./leases");
56
+ const hitl_gates_1 = require("./hitl-gates");
57
+ const hitl_contract_1 = require("./hitl-contract");
58
+ const hitl_presentation_1 = require("./hitl-presentation");
59
+ const hitl_sessions_1 = require("./hitl-sessions");
60
+ const hitl_local_1 = require("./hitl-local");
61
+ const mcp_artifacts_1 = require("./mcp-artifacts");
62
+ const mcp_git_1 = require("./mcp-git");
63
+ const preflight_1 = require("./preflight");
64
+ const modos_1 = require("./modos");
65
+ const versao_1 = require("./versao");
66
+ const mcp_verify_1 = require("./mcp-verify");
67
+ const conducao_1 = require("./conducao");
68
+ const conducao_texto_1 = require("./conducao-texto");
69
+ const mcp_ship_1 = require("./mcp-ship");
70
+ const company_brain_mcp_1 = require("./company-brain-mcp");
71
+ const claude_bg_1 = require("./adapters/claude-bg");
72
+ const session_watcher_claude_1 = require("./session-watcher-claude");
73
+ const runtime_profiles_1 = require("./runtime-profiles");
74
+ const mcp_maestro_1 = require("./mcp-maestro");
75
+ const identidade = zod_1.z.string().min(1).max(80).regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/);
76
+ const daThread = zod_1.z.object({ threadId: identidade }).strict();
77
+ const daDecisao = daThread.extend({ pedidoId: identidade }).strict();
78
+ /**
79
+ * O modo de conducao no canal MCP: quem decide e o NUCLEO, o host so transporta.
80
+ *
81
+ * Com `z.enum(ORDEM_DOS_MODOS)` o canal devolvia a MESMA frase para um modo aposentado e
82
+ * para um typo ("Invalid enum value. Expected 'classic' | ... received 'look'"): em
83
+ * ingles, sem motivo tipado e sem dizer por qual modo trocar. O GOAL da I-43 pediu
84
+ * recusa tipada em QUALQUER canal, e quem sabe separar `modo.aposentado` de
85
+ * `modo.desconhecido` e `exigirModoVivo`, no nucleo. O `describe` mantem os modos vivos
86
+ * visiveis na descoberta da ferramenta, derivados da mesma lista.
87
+ */
88
+ const modoDeConducao = zod_1.z.string().trim().min(1).max(40)
89
+ .describe(`modo de conducao vivo: ${modos_1.ORDEM_DOS_MODOS.join(', ')}`)
90
+ .superRefine((bruto, ctx) => {
91
+ try {
92
+ (0, modos_1.exigirModoVivo)(bruto);
93
+ }
94
+ catch (e) {
95
+ ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, message: e.message });
96
+ }
97
+ })
98
+ .transform((bruto) => (0, modos_1.exigirModoVivo)(bruto));
99
+ const nova = zod_1.z.object({ nome: zod_1.z.string().trim().min(1).max(200),
100
+ modo: modoDeConducao.optional() }).strict();
101
+ const fase = daThread.extend({ fase: zod_1.z.enum(['GOAL', 'PLAN', 'GO', 'CHECK', 'SHIP', 'MASTER']),
102
+ prompt: zod_1.z.string().min(1).max(65536), runtime: zod_1.z.enum(['claude-bg', 'codex']).optional(),
103
+ model: zod_1.z.string().trim().min(1).max(200).optional(),
104
+ effort: zod_1.z.enum(['low', 'medium', 'high', 'xhigh', 'max']).optional(), dryRun: zod_1.z.boolean().optional() }).strict();
105
+ // Limite de tipos do conversor externo: validacao continua no schema Zod strict.
106
+ const converterSchema = zod_to_json_schema_1.zodToJsonSchema;
107
+ const resposta = (valor) => ({ content: [{ type: 'text', text: JSON.stringify(valor) }] });
108
+ /** Factory publica para compor transporte nativo ou testes; nao executa ferramentas no startup. */
109
+ function criarServidorMcp(opcoes) {
110
+ if (!path.isAbsolute(opcoes.projeto))
111
+ throw Error('mcp.project.invalid: raiz absoluta obrigatoria');
112
+ if (!['claude-code', 'codex'].includes(opcoes.host))
113
+ throw Error('mcp.host.invalid');
114
+ if (opcoes.permissoesFilho !== undefined && !['interactive', 'worktree'].includes(opcoes.permissoesFilho))
115
+ throw Error('mcp.child-permissions.invalid');
116
+ if (opcoes.threadId !== undefined)
117
+ identidade.parse(opcoes.threadId);
118
+ if (opcoes.dispatchId !== undefined && (opcoes.threadId === undefined || !/^[a-f0-9-]{36}$/.test(opcoes.dispatchId)))
119
+ throw Error('mcp.dispatch.invalid: identidade de despacho exige thread vinculada');
120
+ // I-36 (D6): o canal do MCP e o host ja validado da conexao; a identidade so reentra (D4).
121
+ const conducao = { canal: opcoes.host, identidade: opcoes.dispatchId ?? null };
122
+ const raiz = fs.realpathSync(opcoes.projeto);
123
+ if (fs.realpathSync((0, manifest_1.exigirManifesto)(raiz).raiz) !== raiz)
124
+ throw Error('mcp.project.invalid: informe a raiz do manifesto');
125
+ // I-35: o dono é o do projeto servido, não o do cwd de quem iniciou o servidor.
126
+ (0, horario_1.registrarFonteDoFuso)(() => (0, horario_1.fusoDoManifesto)((0, manifest_1.carregarManifesto)(raiz)));
127
+ const fixacao = fs.statSync(raiz);
128
+ let perfilShip, erroShip = 'mcp.ship.unavailable: perfil de transporte indisponivel';
129
+ try {
130
+ perfilShip = (0, mcp_ship_1.criarPerfilShipMcp)(raiz, opcoes.transporteShip ?? 'github-ssh');
131
+ }
132
+ catch (e) {
133
+ const m = e.message;
134
+ if (m.startsWith('mcp.'))
135
+ erroShip = m;
136
+ }
137
+ const carregar = () => {
138
+ const atual = fs.statSync(raiz);
139
+ if (atual.dev !== fixacao.dev || atual.ino !== fixacao.ino || fs.realpathSync(raiz) !== raiz)
140
+ throw Error('mcp.project.changed');
141
+ const estado = path.join(raiz, '.orkastery');
142
+ if (fs.existsSync(estado)) {
143
+ const real = fs.realpathSync(estado);
144
+ if (!real.startsWith(raiz + path.sep))
145
+ throw Error('mcp.scope.violation: estado fora do projeto');
146
+ }
147
+ const c = (0, manifest_1.exigirManifesto)(raiz);
148
+ if (fs.realpathSync(c.raiz) !== raiz)
149
+ throw Error('mcp.project.changed');
150
+ return c;
151
+ };
152
+ const confinado = (file) => {
153
+ const real = fs.realpathSync(file);
154
+ if (real !== raiz && !real.startsWith(raiz + path.sep))
155
+ throw Error('mcp.scope.violation');
156
+ return real;
157
+ };
158
+ const thread = (id) => {
159
+ if (opcoes.threadId !== undefined && id !== opcoes.threadId)
160
+ throw Error('mcp.thread.scope: sessao vinculada a outra thread');
161
+ identidade.parse(id);
162
+ carregar();
163
+ confinado((0, thread_1.dirThread)(raiz, id));
164
+ (0, mcp_artifacts_1.validarArquivosEstadoMcp)(raiz, id);
165
+ const t = (0, thread_1.lerThread)(raiz, id);
166
+ if (t.id !== id)
167
+ throw Error('mcp.thread.identity');
168
+ if (t.worktree)
169
+ confinado(t.worktree);
170
+ return t;
171
+ };
172
+ if (opcoes.threadId)
173
+ thread(opcoes.threadId);
174
+ const pendencias = (id) => {
175
+ const t = thread(id), eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id)), contexto = (0, hitl_gates_1.contextoHitl)(raiz, id);
176
+ const pedidos = [(0, hitl_presentation_1.pedidoHitlAberto)(raiz, id, t.faseAtual, null),
177
+ ...t.sessoes.filter(s => s.fase === t.faseAtual).map(s => (0, hitl_presentation_1.pedidoHitlAberto)(raiz, id, t.faseAtual, s.sessionId))];
178
+ // FX6: a oferta acompanha o pedido REAL. A conexao viva e ESTA: o host desta sessao MCP,
179
+ // e so ele. Nenhum outro canal mcp-local sai `disponivel` daqui por suposicao.
180
+ return pedidos.filter(p => p && eventos.some(e => e.tipo === 'hitl_requested' && e.contexto === contexto &&
181
+ e.pedido?.id === p.id)).map(p => ({ pedido: p, estado: (0, hitl_contract_1.estadoDoPedido)(p),
182
+ canais: (0, hitl_presentation_1.ofertaDoPedido)(p, [opcoes.host]), prazoLocal: (0, hitl_presentation_1.prazoLocalDoPedido)(p) }));
183
+ };
184
+ const fases = (id) => {
185
+ thread(id);
186
+ const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id)).filter(e => ['phase_dispatch', 'phase_dispatch_verified', 'phase_result',
187
+ 'phase_dispatch_failed', 'session_watcher_started', 'gate_blocked'].includes(e.tipo));
188
+ return { limite: 20, omitidos: Math.max(0, eventos.length - 20), eventos: eventos.slice(-20).map(e => ({
189
+ tipo: e.tipo, ts: e.ts, fase: e.fase, sessionId: e.sessionId, runtime: e.runtime, model: e.model, effort: e.effort,
190
+ classificacao: e.classificacao, motivo: e.motivo, encontrada: e.encontrada, controlador: e.controlador
191
+ })) };
192
+ };
193
+ const observar = (id) => {
194
+ const t = thread(id), eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id));
195
+ // I-34 (D8): a conclusão vem do phase_result do watcher ou, sem ele, da mesma tabela D2
196
+ // aplicada a esta leitura única (sem cursor, só classificações imediatas). Nada é gravado.
197
+ const turnoClaude = (s, nativo, perfil, erroClaude) => {
198
+ const despachoEm = s.despachadaEm;
199
+ if (typeof despachoEm !== 'string' || !Number.isFinite(Date.parse(despachoEm)))
200
+ return { estado: 'nao-confirmado', conclusaoDeFase: 'nao-inferida' };
201
+ const sessao = { sessionId: s.sessionId, fase: s.fase, despachadaEm: despachoEm };
202
+ const stop = (0, session_watcher_claude_1.stopCorrelacionado)(eventos.filter(e => e.thread === id), sessao);
203
+ const turno = { estado: stop ? 'encerrado' : 'nao-confirmado',
204
+ ...(stop ? { evidencia: { tipo: stop.tipo, ts: stop.ts, sessionId: stop.sessionId, fase: stop.fase,
205
+ runtime: stop.runtime, despachoEm: stop.despachoEm, sensorEventId: stop.sensorEventId } } : {}) };
206
+ const nome = (c, m) => c === 'fase_concluida' ? 'fase_concluida' : `gate_blocked:${String(m)}`;
207
+ const registrada = eventos.filter(e => e.tipo === 'phase_result' && e.runtime === 'claude-bg' && e.sessionId === s.sessionId &&
208
+ e.despachoEm === despachoEm && e.origem === 'sessions.watch').at(-1);
209
+ if (registrada)
210
+ return { ...turno, conclusaoDeFase: nome(registrada.classificacao, registrada.motivo), registrada: true,
211
+ conclusao: { sensorResultId: registrada.sensorResultId, ts: registrada.ts, estadoNativo: registrada.estadoNativo, fonte: registrada.fonte } };
212
+ const cursor = { schema: 'ork.session-cursor-claude/v1', sessionId: s.sessionId, despachoEm };
213
+ // D12: mesma prova do lado do `ork` que o watcher exige, só lida quando o turno terminou.
214
+ const fonte = (0, session_watcher_claude_1.fonteRegistrada)(eventos, sessao);
215
+ const prova = () => (0, session_watcher_claude_1.provaDoOrk)(raiz, id, sessao, eventos, { artefato: fonte?.artefato, cwd: fonte?.cwd ?? path.resolve(t.worktree ?? raiz), head: fonte?.head });
216
+ // I-33 (D11b): a leitura declara o mesmo motivo mais especifico que o watcher gravaria.
217
+ const { c } = (0, session_watcher_claude_1.comFalhaDeConta)((0, session_watcher_claude_1.classificarSessaoClaude)({ sessao, eventos, consulta: { ok: erroClaude === '', registros: [], detalhe: erroClaude, consultadoEm: '' },
218
+ registro: nativo, cursor, agoraMs: Date.now(), limiteMs: Infinity, pausaAoFim: (0, thread_1.pausaNaThread)(t, s.fase),
219
+ prova, processo: session_watcher_claude_1.processoNativo }), () => (0, session_watcher_claude_1.falhaDeContaDaTranscricao)(perfil, fonte?.cwd ?? path.resolve(t.worktree ?? raiz), s.sessionId));
220
+ // D15 (6) e D17: sem Stop correlacionado e sem resultado registrado, a sessão encerrada pelo
221
+ // condutor não ganha na leitura um gate que o ledger não tem, mas a leitura declara o que o
222
+ // watcher grava para o mesmo estado. Com Stop, `stopped` segue a mesma regra do watcher.
223
+ if (nativo?.state === 'stopped' && !stop && c.terminal)
224
+ return { ...turno, conclusaoDeFase: 'encerrada-pelo-condutor', registrada: false,
225
+ classificacaoDoWatcher: nome(c.classificacao, c.motivo),
226
+ conclusao: { fonte: 'sessão encerrada pelo condutor (stopped) sem phase_result registrado', estadoNativo: 'stopped', regraDoWatcher: c.fonte } };
227
+ return c.terminal ? { ...turno, conclusaoDeFase: nome(c.classificacao, c.motivo), registrada: false,
228
+ conclusao: { fonte: c.fonte, estadoNativo: nativo?.state } } : { ...turno, conclusaoDeFase: 'nao-inferida' };
229
+ };
230
+ // I-33 (D4): uma consulta por conta. Cada sessao claude-bg e observada com o env do perfil
231
+ // gravado no seu registro; perfil invalido nao cai para o env do processo.
232
+ const porConta = new Map();
233
+ const consultarConta = (perfil) => {
234
+ const chave = perfil ? `${perfil.id}|${perfil.configDir}` : '(processo)';
235
+ const pronta = porConta.get(chave);
236
+ if (pronta)
237
+ return pronta;
238
+ let claude = null, erroClaude = '';
239
+ const r = (0, util_1.exec)('claude', ['agents', '--json', '--all', '--cwd', raiz], raiz, 10000, perfil ? (0, claude_bg_1.ambienteDoPerfil)(perfil) : (0, runtime_ambiente_1.ambienteDeAssinatura)());
240
+ try {
241
+ if (!r.ok || Buffer.byteLength(r.stdout) > 1024 * 1024)
242
+ throw Error('consulta Claude falhou ou excedeu limite');
243
+ const schema = zod_1.z.array(zod_1.z.object({ sessionId: zod_1.z.string().uuid(), cwd: zod_1.z.string().refine(path.isAbsolute),
244
+ state: zod_1.z.string().optional(), status: zod_1.z.string().optional(), waitingFor: zod_1.z.string().max(1000).nullable().optional() }).passthrough()).max(10000);
245
+ const registros = schema.parse(JSON.parse(r.stdout));
246
+ if (new Set(registros.map(s => s.sessionId)).size !== registros.length)
247
+ throw Error('sessao Claude duplicada');
248
+ const estadoComparavel = (v) => ['working', 'running', 'busy'].includes(v) ? 'working' : v;
249
+ claude = registros.map(s => ({ sessionId: s.sessionId, cwd: s.cwd, estado: s.state ?? s.status ?? '', state: s.state, status: s.status,
250
+ divergenciaEstado: s.state !== undefined && s.status !== undefined && estadoComparavel(s.state) !== estadoComparavel(s.status), ...(s.waitingFor ? { waitingFor: s.waitingFor } : {}),
251
+ ...(Number.isSafeInteger(s.pid) && s.pid > 0 ? { pid: s.pid } : {}) }));
252
+ }
253
+ catch {
254
+ erroClaude = 'observacao nativa indisponivel: consulta Claude escopada falhou ou retornou formato invalido';
255
+ }
256
+ const resultado = { claude, erroClaude };
257
+ porConta.set(chave, resultado);
258
+ return resultado;
259
+ };
260
+ const nativas = t.sessoes.map(s => {
261
+ if (s.runtime === 'claude-bg') {
262
+ let perfil;
263
+ try {
264
+ perfil = (0, runtime_profiles_1.perfilDoRegistro)(eventos, { sessionId: s.sessionId, despachadaEm: s.despachadaEm });
265
+ }
266
+ catch {
267
+ return { sessionId: s.sessionId, runtime: s.runtime, disponivel: false,
268
+ detalhe: 'observacao nativa indisponivel: perfil registrado da sessao invalido' };
269
+ }
270
+ const { claude, erroClaude } = consultarConta(perfil);
271
+ const sessao = claude?.find(x => x.sessionId === s.sessionId && x.cwd === path.resolve(t.worktree ?? raiz));
272
+ const nativo = sessao ? { sessionId: sessao.sessionId, cwd: sessao.cwd, state: sessao.state, status: sessao.status, pid: sessao.pid } : null;
273
+ return { sessionId: s.sessionId, runtime: s.runtime, disponivel: !!sessao, turno: turnoClaude(s, nativo, perfil, erroClaude),
274
+ ...(perfil ? { perfil: perfil.id } : {}),
275
+ ...(sessao ? { sessao } : { detalhe: erroClaude || 'observacao nativa indisponivel: UUID/cwd da fase nao encontrado na consulta escopada' }) };
276
+ }
277
+ if (s.runtime !== 'codex')
278
+ return { sessionId: s.sessionId, runtime: s.runtime, disponivel: false,
279
+ detalhe: 'observacao nativa indisponivel: runtime nao suportado' };
280
+ try {
281
+ const consulta = (0, hitl_sessions_1.controleNativo)(s.runtime, raiz, id, s.sessionId).consultar();
282
+ const sessao = consulta.sessoes.find(x => x.sessionId === s.sessionId && x.cwd === path.resolve(t.worktree ?? raiz));
283
+ return { sessionId: s.sessionId, runtime: s.runtime, disponivel: consulta.ok && !!sessao,
284
+ ...(sessao ? { sessao } : { detalhe: 'observacao nativa indisponivel: sessao nao confirmada pelo controller vinculado' }) };
285
+ }
286
+ catch (e) {
287
+ return { sessionId: s.sessionId, runtime: s.runtime, disponivel: false, detalhe: e.message };
288
+ }
289
+ });
290
+ return { thread: t, phases: fases(id), pendencias: pendencias(id), nativas };
291
+ };
292
+ const livre = (id) => {
293
+ const nomes = ['main-tree', ...(id ? ['worktree-write:' + id] : [])];
294
+ for (const nome of nomes) {
295
+ const conflitos = (0, leases_1.leasesColidentes)(raiz, nome, id);
296
+ if (conflitos.length)
297
+ throw Error('lease.busy: ' + conflitos.map(l => l.nome + ' (' + l.thread + ')').join(', '));
298
+ }
299
+ };
300
+ const server = new index_js_1.Server({ name: 'orkastery', version: versao_1.VERSAO_DO_ORK }, { capabilities: { tools: {} }, instructions: 'Opere somente este projeto pelas ferramentas do nucleo. Decisoes humanas usam ork_request_decision e o dialogo do host; argumentos de ferramenta nunca sao respostas.' });
301
+ const ferramentas = new Map();
302
+ function registrarTool(nome, config, executar) {
303
+ if (opcoes.threadId && ['ork_thread_new', 'ork_phase_run', 'ork_request_decision', 'ork_preflight'].includes(nome))
304
+ return;
305
+ const schema = converterSchema(config.inputSchema, { $refStrategy: 'none' });
306
+ ferramentas.set(nome, { tool: { name: nome, description: config.description, annotations: config.annotations,
307
+ inputSchema: schema },
308
+ executar: async (raw, extra) => executar(config.inputSchema.parse(raw), extra) });
309
+ }
310
+ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools: [...ferramentas.values()].map(f => f.tool) }));
311
+ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request, extra) => {
312
+ try {
313
+ const f = ferramentas.get(request.params.name);
314
+ if (!f)
315
+ throw Error('mcp.tool.unknown');
316
+ return await f.executar(request.params.arguments ?? {}, extra);
317
+ }
318
+ catch (e) {
319
+ return { ...resposta({ erro: e.message }), isError: true };
320
+ }
321
+ });
322
+ const ingresso = (0, hitl_local_1.criarIngressoLocal)(raiz, { host: opcoes.host, connectionId: (0, node_crypto_1.randomUUID)() }, async (pedido, signal) => {
323
+ carregar();
324
+ thread(pedido.thread);
325
+ // D12: pergunta nativa que aceita texto NAO vira menu. Um menu sobre pergunta aberta
326
+ // muda a pergunta, e a resposta que chega a sessao deixa de ser a do humano.
327
+ // I-41: a recusa de quem nao tem dialogo mora no contrato, e por isso ela vem primeiro.
328
+ // Depois dela sempre ha resposta aceita; ler `maxCaracteres` de um default inventaria um
329
+ // limite para um formulario que nunca chega a ser montado.
330
+ const apresentacao = (0, hitl_presentation_1.apresentarDecisao)(pedido);
331
+ const aceita = (0, hitl_contract_1.respostaAceitaDoPedido)(pedido);
332
+ const livre = aceita.tipo === 'texto';
333
+ const limite = Math.min(4096, Math.max(1, aceita.maxCaracteres));
334
+ const r = await server.elicitInput({ mode: 'form',
335
+ message: apresentacao.mensagem,
336
+ requestedSchema: { type: 'object', properties: { opcao: livre
337
+ ? { type: 'string', title: 'Sua resposta', maxLength: limite }
338
+ : { type: 'string', title: 'Sua decisão', oneOf: apresentacao.escolhas } },
339
+ required: ['opcao'] } }, { signal, timeout: 300000 });
340
+ if (r.action !== 'accept')
341
+ return { action: r.action };
342
+ const parsed = zod_1.z.object({ opcao: zod_1.z.string().min(1).max(limite) }).strict().parse(r.content);
343
+ return { action: 'accept', content: parsed };
344
+ });
345
+ server.onclose = () => ingresso.fechar();
346
+ (0, company_brain_mcp_1.registerBrainTools)(registrarTool, carregar, thread, opcoes.brainWrites ?? []);
347
+ (0, mcp_maestro_1.registerMaestro)(registrarTool, { root: raiz, threadId: opcoes.threadId, load: carregar, checkThread: thread, tools: () => [...ferramentas.keys()] });
348
+ registrarTool('ork_preflight', { description: 'Preflight contextual por modo e bloco, sem inventário global/modelos. Não autoriza despacho nem comprova entrega.',
349
+ inputSchema: zod_1.z.object({ modo: modoDeConducao }).strict(), annotations: { readOnlyHint: true } }, async ({ modo }) => {
350
+ carregar();
351
+ return resposta((0, preflight_1.preflight)(raiz, modo, opcoes.nomesProviderHerdados));
352
+ });
353
+ registrarTool('ork_git_status', { description: 'Consulta HEADs locais atuais da worktree e branch de destino fixadas. Nao consulta a rede nem reserva os HEADs; commit e SHIP revalidam seus valores.',
354
+ inputSchema: daThread, annotations: { readOnlyHint: true } }, async ({ threadId }) => {
355
+ thread(threadId);
356
+ return resposta((0, mcp_git_1.estadoGitMcp)(raiz, threadId));
357
+ });
358
+ registrarTool('ork_ship', { description: 'Entrega pela API oficial: verifica em sandbox, mergeia e prova push no unico origin fixado no startup. Exige HEADs fonte/destino e respeita gates; interrupcao exige reconciliacao.',
359
+ inputSchema: daThread.extend({ expectedSource: zod_1.z.string().regex(/^[a-f0-9]{40}$/), expectedDestination: zod_1.z.string().regex(/^[a-f0-9]{40}$/) }).strict(),
360
+ annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true } }, async (args, extra) => {
361
+ thread(args.threadId);
362
+ livre(args.threadId);
363
+ if (!perfilShip)
364
+ throw Error(erroShip);
365
+ const r = await (0, mcp_ship_1.shipMcp)(perfilShip, args, extra.signal);
366
+ return { ...resposta(r), ...(r.ok ? {} : { isError: true }) };
367
+ });
368
+ registrarTool('ork_verify', { description: 'Reexecuta claims e verificadores do manifesto na worktree, em sandbox e com prazo total de tres minutos. Registra resultado real; falhas bloqueiam a verificacao.',
369
+ inputSchema: daThread, annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId }) => {
370
+ thread(threadId);
371
+ livre(threadId);
372
+ try {
373
+ const r = (0, mcp_verify_1.verificarMcp)(raiz, threadId, conducao);
374
+ return { ...resposta(r), ...(r.ok ? {} : { isError: true }) };
375
+ }
376
+ catch (e) {
377
+ // I-36 (T18): a mesma recusa tipada do CLI, com o mesmo texto, sem reescrever nada no host.
378
+ if (e instanceof conducao_1.ErroDeConducao)
379
+ return { ...resposta(e.recusa), isError: true };
380
+ throw e;
381
+ }
382
+ });
383
+ registrarTool('ork_git_commit', { description: 'Commita somente paths com claims e HEAD esperado na worktree da thread. Recusa hooks/filtros ativos; preserva configuracao. Commit local nao e SHIP.',
384
+ inputSchema: daThread.extend({ expectedHead: zod_1.z.string().regex(/^[a-f0-9]{40}$/),
385
+ paths: zod_1.z.array(zod_1.z.string().min(1).max(512)).min(1).max(32), mensagem: zod_1.z.string().trim().min(1).max(2048) }).strict(),
386
+ annotations: { readOnlyHint: false, destructiveHint: false } }, async (args, extra) => {
387
+ thread(args.threadId);
388
+ livre(args.threadId);
389
+ const r = await (0, mcp_git_1.commitMcp)(raiz, args, extra.signal);
390
+ return { ...resposta(r), ...(r.ok ? {} : { isError: true }) };
391
+ });
392
+ const documento = daThread.extend({ tipo: zod_1.z.enum(['goal', 'plan', 'check']) }).strict();
393
+ registrarTool('ork_artifact_read', { description: 'Le documento GOAL, PLAN ou CHECK da thread, com hash para revisao; nao le caminhos arbitrarios.',
394
+ inputSchema: documento, annotations: { readOnlyHint: true } }, async ({ threadId, tipo }) => {
395
+ thread(threadId);
396
+ return resposta((0, mcp_artifacts_1.lerArtefatoMcp)(raiz, threadId, tipo));
397
+ });
398
+ registrarTool('ork_artifact_write', { description: 'Grava documento do agente no bloco atual com hash esperado (null para criar). Nao registra recibo oficial nem aprova gate.',
399
+ inputSchema: documento.extend({ conteudo: zod_1.z.string().max(131072), expectedSha256: zod_1.z.string().regex(/^[a-f0-9]{64}$/).nullable() }).strict(),
400
+ annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId, tipo, conteudo, expectedSha256 }) => {
401
+ thread(threadId);
402
+ livre(threadId);
403
+ return resposta((0, mcp_artifacts_1.escreverArtefatoMcp)(raiz, threadId, tipo, conteudo, expectedSha256));
404
+ });
405
+ registrarTool('ork_claims_list', { description: 'Lista alegacoes e seu estado de verificacao registrado pelo nucleo.',
406
+ inputSchema: daThread, annotations: { readOnlyHint: true } }, async ({ threadId }) => {
407
+ thread(threadId);
408
+ return resposta((0, mcp_artifacts_1.listarClaimsMcp)(raiz, threadId));
409
+ });
410
+ registrarTool('ork_claim_add', { description: 'Registra alegacao prospectiva e comandos como dados. Nao executa comandos nem declara a alegacao verificada.',
411
+ inputSchema: daThread.extend({ arquivo: zod_1.z.string().min(1).max(500), alegacao: zod_1.z.string().min(1).max(8192),
412
+ verificar: zod_1.z.array(zod_1.z.string().min(1).max(8192)).max(20) }).strict(), annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId, ...entrada }) => { thread(threadId); livre(threadId); return resposta((0, mcp_artifacts_1.adicionarClaimMcp)(raiz, threadId, entrada)); });
413
+ registrarTool('ork_thread_status', { description: 'Estado canonico de uma thread deste projeto; pausas previstas nao sao pedidos abertos.',
414
+ inputSchema: daThread, annotations: { readOnlyHint: true } }, async ({ threadId }) => {
415
+ const t = thread(threadId);
416
+ const c = (0, conducao_1.conducaoDaThread)(raiz, threadId);
417
+ return resposta({ thread: t, conducao: c, linhaDeConducao: c ? (0, conducao_texto_1.linhaDeConducao)(c) : null, resumo: (0, thread_1.resumoDaThread)(t, c) });
418
+ });
419
+ registrarTool('ork_phase_list', { description: 'Despachos e resultados registrados da thread, sem despachar ou consultar outros projetos.',
420
+ inputSchema: daThread, annotations: { readOnlyHint: true } }, async ({ threadId }) => {
421
+ thread(threadId);
422
+ return resposta({ threadId, phases: fases(threadId) });
423
+ });
424
+ registrarTool('ork_hitl_pending', { description: 'Pedidos HITL atuais da thread, incluindo prazo; nao aprova nem abre pedido.',
425
+ inputSchema: daThread, annotations: { readOnlyHint: true } }, async ({ threadId }) => resposta({ threadId, pendencias: pendencias(threadId) }));
426
+ registrarTool('ork_observe', { description: 'Observa uma vez o progresso canonico e pedidos da thread. Nao cria monitor ou despacho.',
427
+ inputSchema: daThread, annotations: { readOnlyHint: true } }, async ({ threadId }) => {
428
+ return resposta(observar(threadId));
429
+ });
430
+ registrarTool('ork_thread_new', { description: 'Cria uma thread para a demanda autorizada, com worktree isolada; modo validado pelo nucleo. Nao inicia modelo.',
431
+ inputSchema: nova, annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ nome, modo }) => {
432
+ const c = carregar();
433
+ livre();
434
+ const destino = path.resolve(raiz, c.manifesto.worktree.dir);
435
+ if (!destino.startsWith(raiz + path.sep))
436
+ throw Error('mcp.scope.violation: worktree.dir fora do projeto');
437
+ // Validar ancestrais existentes antes de o nucleo criar o diretorio.
438
+ let existente = destino;
439
+ while (!fs.existsSync(existente))
440
+ existente = path.dirname(existente);
441
+ confinado(existente);
442
+ return resposta((0, thread_1.novaThread)(c, { nome, modo: modo ?? c.manifesto.conduction.default_mode, criarWorktree: true }));
443
+ });
444
+ registrarTool('ork_phase_run', { description: 'Despacha fase autorizada pelo nucleo, preservando policies, estado e runtime/modelo. dryRun nao inicia modelo, mas pode registrar prompt/eventos.',
445
+ inputSchema: fase, annotations: { readOnlyHint: false, destructiveHint: false } }, async (args) => {
446
+ const t = thread(args.threadId);
447
+ livre(t.id);
448
+ const { threadId, fase: f, ...op } = args;
449
+ return resposta((0, phase_1.rodarFase)(carregar(), threadId, { ...op, fase: (0, thread_1.exigirFase)(t, f), canal: conducao.canal }));
450
+ });
451
+ registrarTool('ork_gate_request', { description: 'Abre pedido de gate somente quando pausa ou escalacao tipada esta comprovada no nucleo; nao aprova.',
452
+ inputSchema: daThread.extend({ motivo: zod_1.z.enum(['human.pending', 'policy.violation', 'cost.violation',
453
+ 'retry.max_tentativas', 'hitl.credencial', 'runtime.unavailable']).optional() }).strict(),
454
+ annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId, motivo }) => {
455
+ thread(threadId);
456
+ livre(threadId);
457
+ return resposta((0, hitl_gates_1.abrirPedidoGate)(raiz, threadId, motivo));
458
+ });
459
+ registrarTool('ork_request_decision', { description: 'Apresenta pedido existente ao dono por dialogo nativo. Somente IDs; nunca forneca resposta nos argumentos.',
460
+ inputSchema: daDecisao, annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId, pedidoId }, extra) => {
461
+ thread(threadId);
462
+ return resposta(await ingresso.solicitar(threadId, pedidoId, extra.signal));
463
+ });
464
+ return server;
465
+ }
466
+ async function servirMcp(opcoes) {
467
+ const server = criarServidorMcp(opcoes);
468
+ await server.connect(new stdio_js_1.StdioServerTransport());
469
+ }