@orkastery/cli 0.4.3 → 0.5.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 (121) hide show
  1. package/adapters/README.md +11 -0
  2. package/adapters/claude-code/.claude-plugin/plugin.json +3 -1
  3. package/adapters/claude-code/agents/ork-check.md +1 -1
  4. package/adapters/claude-code/agents/ork-go.md +2 -2
  5. package/adapters/claude-code/agents/ork-goal.md +1 -1
  6. package/adapters/claude-code/agents/ork-master.md +1 -1
  7. package/adapters/claude-code/agents/ork-plan.md +1 -1
  8. package/adapters/claude-code/agents/ork-ship.md +1 -1
  9. package/adapters/claude-code/commands/master.md +11 -8
  10. package/adapters/claude-code/commands/ork.md +8 -0
  11. package/adapters/claude-code/commands/ship.md +2 -2
  12. package/adapters/codex/skills/ork/SKILL.md +12 -1
  13. package/adapters/hermes/README.md +3 -0
  14. package/adapters/hermes/bin/ork-abrir-thread.sh +17 -2
  15. package/adapters/hermes/bin/ork-brain.sh +3 -0
  16. package/adapters/hermes/bin/ork-maestro.sh +4 -1
  17. package/adapters/hermes/bin/ork-network-roadmap.sh +11 -0
  18. package/adapters/hermes/bin/ork-roadmap-status.sh +9 -0
  19. package/adapters/hermes/hermes.plugin.json +2 -0
  20. package/adapters/hermes/hitl-ingress/__init__.py +36 -3
  21. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +19 -20
  22. package/adapters/openclaw/README.md +34 -2
  23. package/adapters/openclaw/dist/hitl-ingress.js +37 -3
  24. package/adapters/openclaw/dist/index.js +92 -20
  25. package/adapters/openclaw/openclaw.plugin.json +10 -1
  26. package/adapters/openclaw/package.json +2 -2
  27. package/adapters/openclaw/src/hitl-ingress.ts +32 -3
  28. package/adapters/openclaw/src/index.ts +108 -20
  29. package/assets/docs/padroes/documentacao-de-produto.md +2 -2
  30. package/assets/docs/padroes/roadmap-de-produto.md +1 -1
  31. package/assets/docs/produto/_modelo-feature.md +2 -0
  32. package/assets/orkmind_bridge.py +214 -1
  33. package/dist/adapters/claude-bg.js +6 -3
  34. package/dist/board.js +74 -0
  35. package/dist/branch-de-estado.js +5 -4
  36. package/dist/busca-semantica.js +161 -0
  37. package/dist/ci.js +141 -10
  38. package/dist/company-brain-cli.js +27 -2
  39. package/dist/company-brain-context.js +132 -0
  40. package/dist/company-brain-dossie.js +376 -0
  41. package/dist/company-brain-mcp.js +4 -1
  42. package/dist/conducao.js +71 -18
  43. package/dist/decisao-autonoma.js +42 -0
  44. package/dist/docs.js +64 -22
  45. package/dist/doctor.js +33 -0
  46. package/dist/entrega-pr.js +109 -5
  47. package/dist/experiencia-instalacao.js +256 -0
  48. package/dist/experiencia.js +72 -0
  49. package/dist/fabrica-estado.js +43 -10
  50. package/dist/fechamento.js +105 -0
  51. package/dist/forja.js +435 -0
  52. package/dist/gates.js +9 -1
  53. package/dist/hitl-classificacao.js +11 -1
  54. package/dist/hitl-contract.js +50 -7
  55. package/dist/hitl-curto.js +158 -0
  56. package/dist/hitl-gates.js +67 -1
  57. package/dist/hitl-lote.js +30 -15
  58. package/dist/hitl-presentation.js +10 -7
  59. package/dist/hitl-resumo.js +33 -12
  60. package/dist/hitl-texto-livre.js +150 -0
  61. package/dist/hosts.js +86 -1
  62. package/dist/index.js +602 -38
  63. package/dist/indice-vetorial.js +317 -0
  64. package/dist/init.js +13 -0
  65. package/dist/integracoes-locais.js +1 -1
  66. package/dist/intelligence-benchmark-contract.js +570 -0
  67. package/dist/intelligence-graph-cli.js +430 -0
  68. package/dist/intelligence-graph-contract.js +577 -0
  69. package/dist/intelligence-graph-extract-md.js +469 -0
  70. package/dist/intelligence-graph-extract-ts.js +810 -0
  71. package/dist/intelligence-graph-extract.js +369 -0
  72. package/dist/intelligence-graph-index.js +512 -0
  73. package/dist/intelligence-graph-parsers.js +327 -0
  74. package/dist/intelligence-graph-query.js +344 -0
  75. package/dist/intelligence-graph-repo.js +187 -0
  76. package/dist/leases.js +84 -0
  77. package/dist/ledger.js +14 -0
  78. package/dist/maestro-cli.js +10 -1
  79. package/dist/maestro-contract.js +5 -1
  80. package/dist/maestro-discovery.js +16 -2
  81. package/dist/maestro-snapshot.js +6 -2
  82. package/dist/manifest.js +142 -5
  83. package/dist/master-batch.js +3 -2
  84. package/dist/master-digest.js +2 -2
  85. package/dist/master-nota.js +203 -0
  86. package/dist/master.js +4 -0
  87. package/dist/mcp-experiencia.js +164 -0
  88. package/dist/mcp-git.js +4 -0
  89. package/dist/mcp-install.js +3 -1
  90. package/dist/mcp-maestro.js +3 -2
  91. package/dist/mcp-server.js +84 -5
  92. package/dist/memoria.js +147 -1
  93. package/dist/network-roadmap.js +907 -0
  94. package/dist/ocupacao.js +38 -2
  95. package/dist/onboarding.js +113 -7
  96. package/dist/orkmind.js +165 -9
  97. package/dist/phase.js +166 -13
  98. package/dist/policies.js +2 -0
  99. package/dist/projeto-alvo.js +551 -0
  100. package/dist/prompts.js +1 -1
  101. package/dist/pulse-consentimento.js +4 -2
  102. package/dist/pulse-delivery.js +5 -0
  103. package/dist/pulse-resposta.js +674 -49
  104. package/dist/pulse.js +21 -0
  105. package/dist/retry.js +51 -8
  106. package/dist/roadmap-reservas.js +262 -20
  107. package/dist/roadmap-status.js +213 -0
  108. package/dist/thread-close.js +3 -0
  109. package/dist/verify.js +4 -3
  110. package/eval/casos/orchestration-experience-pt-br.json +48 -0
  111. package/eval/casos/orchestration-experience.json +48 -0
  112. package/package.json +1 -1
  113. package/schemas/code-artifact-graph.v1.schema.json +581 -0
  114. package/schemas/graph-benchmark.v1.schema.json +2240 -0
  115. package/schemas/maestro-snapshot.schema.json +23 -0
  116. package/skills/README.md +7 -5
  117. package/skills/core/onboarding/SKILL.md +7 -0
  118. package/skills/core/orchestration-experience/SKILL.md +113 -0
  119. package/skills/core/orchestration-experience-pt-br/SKILL.md +112 -0
  120. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  121. package/skills/phases/go-implementation/SKILL.md +2 -0
@@ -0,0 +1,376 @@
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.ID_DE_DECISAO = exports.DOSSIE_SCHEMA = void 0;
37
+ exports.buildDossie = buildDossie;
38
+ /**
39
+ * K3.1: dossiê de decisão. Só leitura: compõe o que o núcleo já grava (o ledger da thread, o objetivo
40
+ * do K1 e o escopo vinculado) com o pacote de contexto do Brain, sem registrar nada. Decidir continua
41
+ * sendo `ork decisao registrar` (decisão delegada) ou a resposta do dono pelo ingresso autenticado.
42
+ */
43
+ const fs = __importStar(require("node:fs"));
44
+ const path = __importStar(require("node:path"));
45
+ const company_brain_client_1 = require("./company-brain-client");
46
+ const company_brain_contract_1 = require("./company-brain-contract");
47
+ const company_brain_context_1 = require("./company-brain-context");
48
+ const company_brain_source_1 = require("./company-brain-source");
49
+ const decisao_autonoma_1 = require("./decisao-autonoma");
50
+ const gates_1 = require("./gates");
51
+ const hitl_contract_1 = require("./hitl-contract");
52
+ const objective_1 = require("./objective");
53
+ const portfolio_1 = require("./portfolio");
54
+ const thread_1 = require("./thread");
55
+ exports.DOSSIE_SCHEMA = 'ork.dossie-de-decisao/v1';
56
+ /** O id que o dossiê aceita para uma decisão: o do pedido ou o que o Brain dá ao fato. */
57
+ exports.ID_DE_DECISAO = /^(?:[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}|fact-[a-f0-9]{64})$/;
58
+ /** Os mesmos números do pacote de contexto: lote da seleção e teto de `get` no caso misto. */
59
+ const LIMITE = 1000;
60
+ const LIMITE_DE_GET = 100;
61
+ const comparar = (a, b) => a < b ? -1 : a > b ? 1 : 0;
62
+ const falha = (state) => ['forbidden', 'unavailable', 'conflict'].includes(state);
63
+ const texto = (v) => typeof v === 'string' ? v : null;
64
+ /**
65
+ * D10: a mesma conferência do ramo `context` de `ork brain`, repetida aqui para não tocar aquele
66
+ * comando enquanto outra thread o muda. O escopo vale só se for desta thread e do formato do bind.
67
+ */
68
+ function escopoVinculado(raiz, thread) {
69
+ const file = path.join((0, thread_1.dirThread)(raiz, thread), 'brain-scope.json');
70
+ if (!fs.existsSync(file))
71
+ return null;
72
+ let binding;
73
+ try {
74
+ binding = JSON.parse(fs.readFileSync(file, 'utf8'));
75
+ }
76
+ catch {
77
+ throw Error('brain.scope.invalid');
78
+ }
79
+ if (binding?.schema !== 'ork.brain-cycle-scope/v1' || binding.version !== 1 || binding.thread !== thread || typeof binding.projectId !== 'string' ||
80
+ !Array.isArray(binding.initiativeIds) || binding.initiativeIds.some((i) => typeof i !== 'string'))
81
+ throw Error('brain.scope.invalid');
82
+ return { projectId: binding.projectId, initiativeIds: binding.initiativeIds };
83
+ }
84
+ /**
85
+ * D3: o objetivo é o ticket do K1 (`creationOrigin.ticketId`) e, sem ele, o objetivo cuja lista de
86
+ * threads contém esta; o projeto é o escopo vinculado (o que a captura grava no `cycle`) e, sem ele, o
87
+ * `portfolio` do objetivo. Fonte faltando ou discordando vira lacuna, nunca escolha silenciosa.
88
+ */
89
+ function vinculoDaThread(raiz, t, lacuna) {
90
+ let achado = null, semObjetivo = true;
91
+ const ticket = t.creationOrigin?.ticketId;
92
+ try {
93
+ if (ticket) {
94
+ const o = (0, objective_1.readObjective)(raiz, ticket);
95
+ if (!o.threads.some(x => x.id === t.id)) {
96
+ lacuna(t.id, 'vinculo.divergente');
97
+ semObjetivo = false;
98
+ }
99
+ else
100
+ achado = { o, origem: 'ticket' };
101
+ }
102
+ else {
103
+ const comEla = (0, objective_1.listObjectives)(raiz).filter(o => o.threads.some(x => x.id === t.id));
104
+ if (comEla.length > 1) {
105
+ lacuna(t.id, 'vinculo.divergente');
106
+ semObjetivo = false;
107
+ }
108
+ else if (comEla.length === 1)
109
+ achado = { o: comEla[0], origem: 'lista-de-threads' };
110
+ }
111
+ }
112
+ catch {
113
+ lacuna(ticket ?? t.id, 'objetivo.indisponivel');
114
+ semObjetivo = false;
115
+ }
116
+ if (!achado && semObjetivo)
117
+ lacuna(t.id, 'objetivo.ausente');
118
+ const escopo = escopoVinculado(raiz, t.id), doObjetivo = achado?.o.envelope.portfolio ?? null;
119
+ const ordenados = (ids) => [...new Set(ids)].sort(comparar);
120
+ let projeto = null;
121
+ if (escopo) {
122
+ const entidade = (0, portfolio_1.findEntity)(raiz, escopo.projectId);
123
+ projeto = { productId: entidade?.kind === 'project' ? entidade.productId : null, projectId: escopo.projectId,
124
+ initiativeIds: ordenados(escopo.initiativeIds), origem: 'escopo-vinculado' };
125
+ if (doObjetivo && (doObjetivo.projectId !== projeto.projectId ||
126
+ JSON.stringify(ordenados(doObjetivo.initiativeIds)) !== JSON.stringify(projeto.initiativeIds)))
127
+ lacuna(t.id, 'vinculo.divergente');
128
+ }
129
+ else if (doObjetivo) {
130
+ projeto = { productId: doObjetivo.productId, projectId: doObjetivo.projectId, initiativeIds: ordenados(doObjetivo.initiativeIds), origem: 'objetivo' };
131
+ }
132
+ else
133
+ lacuna(t.id, 'projeto.ausente');
134
+ // Título e estado ficam fora do envelope com hash: o que faltar sai vazio, nunca `undefined` no digest.
135
+ const objetivo = achado ? { id: achado.o.id, titulo: texto(achado.o.title) ?? '', estado: texto(achado.o.status) ?? '',
136
+ envelopeHash: achado.o.envelope.hash, origem: achado.origem } : null;
137
+ return { objetivo, projeto, brain: { thread_id: t.id, objective_id: objetivo?.id ?? null, project_id: projeto?.projectId ?? null,
138
+ initiative_ids: projeto?.initiativeIds ?? [] } };
139
+ }
140
+ /**
141
+ * Uma seleção por lote de ids `fact-…`; retido chega sem id, e só o caso misto pede `get`, como no contexto.
142
+ * Seleção que não responde `ok` nem `empty` fecha o dossiê: sem estado conhecido, nada local vira conteúdo.
143
+ */
144
+ function consultarFatos(transport, tenant, ids) {
145
+ const ok = new Map(), retidos = new Set();
146
+ let gets = 0;
147
+ for (let inicio = 0; inicio < ids.length; inicio += LIMITE) {
148
+ const lote = ids.slice(inicio, inicio + LIMITE), doLote = new Set(lote);
149
+ const r = transport({ schema: company_brain_client_1.BRAIN_API, operation: 'query', payload: (0, company_brain_contract_1.validateContract)({ schema: 'orkmind.company-brain-selection/v1',
150
+ tenant_id: tenant, facets: { ids: lote, kinds: [], workspace_ids: [], source_instances: [] }, mode: 'selection', limit: lote.length, offset: 0 }) });
151
+ if (r.state !== 'ok' && r.state !== 'empty')
152
+ return r;
153
+ const itens = Array.isArray(r.items) ? r.items : [];
154
+ for (const item of itens)
155
+ if (item?.state === 'ok' && doLote.has(item.entity?.id))
156
+ ok.set(item.entity.id, item.entity);
157
+ const faltantes = lote.filter(id => !ok.has(id)), retidosNoLote = itens.filter((i) => i?.state === 'withheld').length;
158
+ if (retidosNoLote && retidosNoLote === faltantes.length)
159
+ faltantes.forEach(id => retidos.add(id));
160
+ else if (retidosNoLote)
161
+ for (const id of faltantes) {
162
+ if (++gets > LIMITE_DE_GET)
163
+ return { schema: company_brain_client_1.BRAIN_API, state: 'unavailable', error: 'brain.dossie.get-limit' };
164
+ const g = transport({ schema: company_brain_client_1.BRAIN_API, operation: 'get', payload: { tenant_id: tenant, id } });
165
+ if (falha(g.state))
166
+ return g;
167
+ if (g.state === 'withheld')
168
+ retidos.add(id);
169
+ else if (g.state === 'ok' && g.entity?.id === id)
170
+ ok.set(id, g.entity);
171
+ }
172
+ }
173
+ return { ok, retidos };
174
+ }
175
+ const TIPOS_DO_DOSSIE = new Set(['autonomous_decision', 'hitl_requested', 'human_gate', 'human_decision']);
176
+ /**
177
+ * P2: o ledger é lido pela `readCycle`, a mesma leitura da captura. Uma linha que o contrato do Brain não
178
+ * representa (horário fora do formato, em ledgers antigos) derruba a leitura inteira; então a faixa que
179
+ * recusa é partida ao meio até isolar a linha, que fica sem id no Brain. Qualquer outro erro (linha
180
+ * corrompida, de outra thread) continua recusando o dossiê, como recusa a captura.
181
+ */
182
+ function linhasDoLedger(bytes, scope) {
183
+ const brutas = bytes.subarray(0, bytes.lastIndexOf(10) + 1).toString('utf8').split('\n').slice(0, -1);
184
+ const inicios = [0];
185
+ for (const raw of brutas)
186
+ inicios.push(inicios[inicios.length - 1] + Buffer.byteLength(raw) + 1);
187
+ const linhas = [];
188
+ const faixa = (de, ate) => {
189
+ try {
190
+ (0, company_brain_source_1.readCycle)(bytes.subarray(0, inicios[ate]), scope, inicios[de]).records
191
+ .forEach((r, i) => linhas.push({ n: de + i + 1, e: JSON.parse(brutas[de + i]), evento: r.event }));
192
+ }
193
+ catch (erro) {
194
+ if (erro.message !== 'brain.contract.invalid')
195
+ throw erro;
196
+ if (ate - de === 1) {
197
+ linhas.push({ n: de + 1, e: JSON.parse(brutas[de]), evento: null });
198
+ return;
199
+ }
200
+ const meio = de + Math.floor((ate - de) / 2);
201
+ faixa(de, meio);
202
+ faixa(meio, ate);
203
+ }
204
+ };
205
+ if (brutas.length)
206
+ faixa(0, brutas.length);
207
+ return linhas.filter(l => TIPOS_DO_DOSSIE.has(l.e.tipo));
208
+ }
209
+ /**
210
+ * Monta o dossiê de uma thread ou de uma decisão dela. A fonte canônica da decisão é o ledger; o Brain
211
+ * é projeção, e a diferença entre os dois sai como frescor e lacuna. Item sem citação, resposta sem
212
+ * recibo conferido e decisão fora do contrato viram lacuna, nunca conteúdo.
213
+ */
214
+ function buildDossie(c, thread, decisao, transport) {
215
+ // Filtro vazio é erro, não a thread inteira: quem pede uma decisão recebe essa ou a recusa.
216
+ if (decisao !== undefined && !exports.ID_DE_DECISAO.test(decisao))
217
+ throw Error('brain.dossie.decisao-invalida');
218
+ const filtro = decisao ?? null;
219
+ const t = (0, thread_1.lerThread)(c.raiz, thread), tenant = c.manifesto.memory.tenant;
220
+ const lacunas = [];
221
+ const lacuna = (id, codigo) => { lacunas.push({ id, codigo }); };
222
+ const vinculo = vinculoDaThread(c.raiz, t, lacuna);
223
+ const base = { schema: exports.DOSSIE_SCHEMA, tenant, contrato: company_brain_contract_1.CONTRACT_HASH, thread: t.id, decisao: filtro };
224
+ const encerrar = (r) => ({ ...base, state: r.state, ...(r.error ? { error: r.error } : {}),
225
+ vinculo, contexto: null, decisoes: [], lacunas: [], digest: null, consultadoEm: new Date().toISOString() });
226
+ const arquivo = path.join((0, thread_1.dirThread)(c.raiz, t.id), 'ledger.jsonl');
227
+ const bytes = fs.existsSync(arquivo) ? (0, company_brain_source_1.readSourceFile)(arquivo) : Buffer.alloc(0);
228
+ const linhas = linhasDoLedger(bytes, { tenant, instance: c.manifesto.project.name, thread: t.id, aclRef: 'ork-factory' });
229
+ // Cada linha é classificada uma vez, pelo validador do contrato; o que não valida é formato anterior.
230
+ const classe = new Map(), respostas = new Map(), revertidaPor = new Map();
231
+ const semIngresso = [];
232
+ const pedidoDe = (l) => l.e.pedido;
233
+ for (const l of linhas) {
234
+ const p = l.e.pedido;
235
+ if (l.e.tipo === 'autonomous_decision') {
236
+ let decidido = false;
237
+ try {
238
+ (0, hitl_contract_1.validarPedidoHitlV2)(p);
239
+ decidido = p.classe === 'decidido';
240
+ }
241
+ catch {
242
+ decidido = false;
243
+ }
244
+ classe.set(l, decidido ? 'decidido' : 'legado');
245
+ if (decidido && typeof l.e.reverte === 'string')
246
+ revertidaPor.set(l.e.reverte, l);
247
+ }
248
+ else if (l.e.tipo === 'hitl_requested') {
249
+ try {
250
+ (0, hitl_contract_1.validarPedidoHitl)(p);
251
+ if ((0, hitl_contract_1.alvoDoPedido)(p)?.tipo === 'gate')
252
+ classe.set(l, 'pergunta');
253
+ }
254
+ catch { /* fora do contrato: não é pergunta */ }
255
+ }
256
+ else if (l.e.tipo === 'human_gate' && typeof l.e.pedidoId === 'string')
257
+ respostas.set(l.e.pedidoId, [...(respostas.get(l.e.pedidoId) ?? []), l]);
258
+ else if (l.e.tipo === 'human_decision')
259
+ semIngresso.push(l);
260
+ }
261
+ const candidatas = [...classe.keys()];
262
+ const referencia = (l) => `threads/${t.id}/ledger.jsonl#L${l.n}`;
263
+ const idDe = (l) => classe.get(l) !== 'legado' ? String(pedidoDe(l).id) : l.evento?.aggregate_id ?? referencia(l);
264
+ const escolhidas = filtro === null ? candidatas : candidatas.filter(l => idDe(l) === filtro || l.evento?.aggregate_id === filtro);
265
+ if (filtro !== null && !escolhidas.length)
266
+ lacuna(filtro, 'decisao.desconhecida');
267
+ // D8: `human_decision` é o relato de alguém sobre o dono, sem recibo: nunca vira decisão do dono.
268
+ if (filtro === null)
269
+ for (const l of semIngresso)
270
+ lacuna(referencia(l), 'decisao.humana-sem-ingresso');
271
+ // D4: a resposta só entra com o recibo reconferido pelas validadoras do núcleo, qualquer que seja o veredito.
272
+ const provadas = new Map();
273
+ for (const l of escolhidas)
274
+ if (classe.get(l) === 'pergunta') {
275
+ const gates = respostas.get(idDe(l)) ?? [];
276
+ if (gates.length === 1 && gates[0].evento && (0, gates_1.reciboHumanoConfere)(c.raiz, t.id, gates[0].e))
277
+ provadas.set(idDe(l), gates[0]);
278
+ }
279
+ let contexto = null;
280
+ if (vinculo.projeto) {
281
+ contexto = (0, company_brain_context_1.buildContext)(c, [vinculo.projeto.projectId, ...vinculo.projeto.initiativeIds], transport, t.id);
282
+ if (falha(contexto.state))
283
+ return encerrar(contexto);
284
+ }
285
+ // A decisão que desfaz outra também é conferida: a relação é conteúdo dela, e some se ela estiver retida.
286
+ const reversoras = escolhidas.flatMap(l => classe.get(l) === 'decidido' ? [revertidaPor.get(idDe(l))].filter((x) => !!x) : []);
287
+ const fatos = [...new Set([...escolhidas, ...provadas.values(), ...reversoras].flatMap(l => l.evento ? [l.evento.aggregate_id] : []))].sort(comparar);
288
+ let noBrain = { ok: new Map(), retidos: new Set() };
289
+ if (fatos.length) {
290
+ const r = consultarFatos(transport, tenant, fatos);
291
+ if ('state' in r)
292
+ return encerrar(r);
293
+ noBrain = r;
294
+ }
295
+ const ids = (evento) => ({ assertion_id: evento.aggregate_id, event_id: evento.id, source_event_id: evento.source_event_id });
296
+ const fato = (evento) => {
297
+ const id = evento.aggregate_id;
298
+ if (noBrain.retidos.has(id)) {
299
+ lacuna(id, 'brain.retido');
300
+ return { id, frescor: 'retido' };
301
+ }
302
+ const { instance, source_ref, source_hash, source_version, location } = evento.source, b = noBrain.ok.get(id);
303
+ const frescor = !b ? 'ausente-no-brain' : b.source?.source_hash === source_hash && b.source?.source_ref === source_ref ? 'confere' : 'divergente';
304
+ if (frescor === 'ausente-no-brain')
305
+ lacuna(id, 'brain.ausente');
306
+ if (frescor === 'divergente')
307
+ lacuna(id, 'fonte.divergente');
308
+ return { brain: ids(evento), citacao: { instance, source_ref, source_hash, source_version, location }, frescor };
309
+ };
310
+ const visivel = (l) => !!l?.evento && !noBrain.retidos.has(l.evento.aggregate_id);
311
+ const decisoes = [];
312
+ for (const l of escolhidas) {
313
+ // Sem id no Brain não há citação: a decisão vira lacuna, nunca conteúdo.
314
+ if (!l.evento) {
315
+ lacuna(idDe(l), 'citacao.incompleta');
316
+ continue;
317
+ }
318
+ const id = idDe(l), f = fato(l.evento), e = l.e, tipo = classe.get(l);
319
+ // D6: retido pelo Brain não mostra nem o conteúdo local (BR-024-03).
320
+ if (f.frescor === 'retido') {
321
+ decisoes.push(f);
322
+ continue;
323
+ }
324
+ const comum = { id, fase: texto(e.fase), em: e.ts, ...f };
325
+ if (tipo === 'decidido') {
326
+ const p = pedidoDe(l);
327
+ decisoes.push({ ...comum, classe: tipo, contrato: p.contrato, autoria: 'autonoma', decidido: p.decidido, porque: p.porque, comoMudar: p.comoMudar,
328
+ custoDeReverter: { agora: p.custoDeReverter.agora, depois: p.custoDeReverter.depois }, criterio: { tipo: p.criterio.tipo, referencia: p.criterio.referencia },
329
+ quemDecidiu: String(e.quemDecidiu ?? ''), evidencia: String(e.evidencia ?? ''), razao: String(e.razao ?? ''),
330
+ reverte: texto(e.reverte), revertidaPor: visivel(revertidaPor.get(p.id)) ? String(pedidoDe(revertidaPor.get(p.id)).id) : null });
331
+ // D-G3: o contrato do `decidido` não guarda alternativas; o `comoMudar` é o caminho de volta.
332
+ lacuna(id, 'alternativas.nao-registradas');
333
+ }
334
+ else if (tipo === 'pergunta') {
335
+ const p = pedidoDe(l);
336
+ const alternativas = p.contrato === 'ork.hitl/v2'
337
+ ? p.alternativas.map((a, i) => ({ numero: i + 1, letra: a.letra, texto: a.texto, acao: a.acao,
338
+ consequencia: a.consequencia, recomendada: a.recomendada === true, porque: a.porque ?? null }))
339
+ : p.opcoes.map(o => ({ numero: o.numero, letra: null, texto: o.texto, acao: o.acao, consequencia: null, recomendada: false, porque: null }));
340
+ const provada = provadas.get(id), gates = respostas.get(id) ?? [];
341
+ let resposta = null, estado = 'aguardando';
342
+ if (provada) {
343
+ const r = fato(provada.evento), g = provada.e, escolha = alternativas.find(a => a.numero === g.opcao);
344
+ // Resposta retida: nem a escolha nem a autoria saem da linha local.
345
+ estado = r.frescor === 'retido' ? 'retida' : 'decidida';
346
+ resposta = r.frescor === 'retido' ? r : { ...r, opcao: Number.isInteger(g.opcao) ? g.opcao : null, letra: escolha?.letra ?? null,
347
+ texto: escolha?.texto ?? null, veredito: texto(g.estado), quem: String(g.autorizadoPor ?? ''), origem: String(g.origem ?? ''),
348
+ canal: texto(g.canal), recebidoEm: texto(g.recebidoEm), recibo: texto(g.recibo), evidencia: texto(g.evidencia), evidenciaSha256: texto(g.evidenciaSha256) };
349
+ }
350
+ else if (gates.length) {
351
+ estado = 'sem-prova';
352
+ lacuna(id, 'resposta.sem-prova');
353
+ }
354
+ else
355
+ lacuna(id, 'resposta.pendente');
356
+ // O prazo vai como está no pedido; vencido ou não é leitura de quem consulta, e o digest não depende do relógio.
357
+ decisoes.push({ ...comum, classe: tipo, contrato: p.contrato, autoria: estado === 'decidida' ? 'dono' : null, pergunta: String(p.pergunta),
358
+ sobre: (0, hitl_contract_1.alvoDoPedido)(p)?.tipo === 'gate' ? String((0, hitl_contract_1.alvoDoPedido)(p).sobre) : '', alternativas,
359
+ recomendacao: p.contrato === 'ork.hitl/v2' ? null : texto(p.recomendacao), prazo: texto(p.prazo),
360
+ estado, resposta });
361
+ }
362
+ else {
363
+ const rastro = (0, decisao_autonoma_1.rastroDaDecisao)(e);
364
+ decisoes.push({ ...comum, classe: tipo, contrato: 'legado', autoria: 'autonoma', decidido: texto(e.decisao) ?? '',
365
+ quemDecidiu: rastro.quemDecidiu ?? null, evidencia: rastro.evidencia ?? null, razao: rastro.razao ?? null, rastroCompleto: rastro.completa });
366
+ lacuna(id, 'decisao.fora-do-contrato');
367
+ lacuna(id, 'alternativas.nao-registradas');
368
+ }
369
+ }
370
+ const unicas = [...new Map(lacunas.map(x => [`${x.id} ${x.codigo}`, x])).values()]
371
+ .sort((a, b) => comparar(a.id, b.id) || comparar(a.codigo, b.codigo));
372
+ // D7: o digest cobre o digest do pacote de contexto, não o pacote inteiro; o horário fica fora.
373
+ const corpo = { ...base, state: (decisoes.length ? 'ok' : 'empty'), vinculo, contexto: contexto?.digest ?? null,
374
+ decisoes, lacunas: unicas };
375
+ return { ...corpo, contexto, digest: (0, company_brain_contract_1.digest)(corpo), consultadoEm: new Date().toISOString() };
376
+ }
@@ -4,7 +4,8 @@ exports.BRAIN_WRITE_TOOLS = exports.BRAIN_READ_TOOLS = void 0;
4
4
  exports.registerBrainTools = registerBrainTools;
5
5
  const zod_1 = require("zod");
6
6
  const company_brain_cli_1 = require("./company-brain-cli");
7
- exports.BRAIN_READ_TOOLS = ['ork_brain_status', 'ork_brain_inventory', 'ork_brain_get', 'ork_brain_query', 'ork_brain_receipts'];
7
+ const company_brain_dossie_1 = require("./company-brain-dossie");
8
+ exports.BRAIN_READ_TOOLS = ['ork_brain_status', 'ork_brain_inventory', 'ork_brain_get', 'ork_brain_query', 'ork_brain_receipts', 'ork_brain_context', 'ork_brain_dossie'];
8
9
  exports.BRAIN_WRITE_TOOLS = ['ork_brain_sync', 'ork_brain_apply', 'ork_brain_rollback', 'ork_brain_bind'];
9
10
  /** Installation supplies exact grants; presence of a tool is never activation or human identity. */
10
11
  function registerBrainTools(register, load, checkThread, writeGrants = []) {
@@ -13,6 +14,8 @@ function registerBrainTools(register, load, checkThread, writeGrants = []) {
13
14
  const id = zod_1.z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/), base = zod_1.z.object({ threadId: id }).strict();
14
15
  const definitions = [['status', base], ['inventory', base], ['get', base.extend({ id })], ['receipts', base.extend({ id })],
15
16
  ['query', base.extend({ ids: zod_1.z.array(id).max(1000).optional(), kinds: zod_1.z.array(zod_1.z.enum(['prod', 'proj', 'init', 'assertion'])).optional(), limit: zod_1.z.number().int().min(1).max(1000).optional() })],
17
+ ['context', base.extend({ ids: zod_1.z.array(id).min(1).max(1000).optional() })],
18
+ ['dossie', base.extend({ decisao: zod_1.z.string().regex(company_brain_dossie_1.ID_DE_DECISAO).optional() })],
16
19
  ['sync', base], ['apply', base.extend({ plan: zod_1.z.string().min(1).max(512), expectedSha256: zod_1.z.string().regex(/^[a-f0-9]{64}$/) })],
17
20
  ['rollback', base.extend({ batch: id })], ['bind', base.extend({ project: id, initiatives: zod_1.z.array(id).min(1).max(1000) })]];
18
21
  for (const [operation, inputSchema] of definitions) {
package/dist/conducao.js CHANGED
@@ -338,6 +338,18 @@ function vidaDoProcesso(raiz, threadId, lease) {
338
338
  fs.closeSync(fd);
339
339
  return 'morto';
340
340
  }
341
+ /** Fecha a tomada uma vez so (RM-037, CHECK 4): liberar e devolver podem ser chamados mais de uma vez. */
342
+ function encerrar(k, estado) {
343
+ if (estado.encerrada)
344
+ return;
345
+ estado.encerrada = true;
346
+ if (emCurso.get(k) === estado)
347
+ emCurso.delete(k);
348
+ try {
349
+ fs.closeSync(estado.fd);
350
+ }
351
+ catch { /* ja fechado */ }
352
+ }
341
353
  /** Conducoes que ESTE processo segura, pela chave canonica: a reentrada no mesmo processo. */
342
354
  const emCurso = new Map();
343
355
  function chave(raiz, threadId) {
@@ -432,7 +444,7 @@ function liberarComProva(raiz, threadId, lease, tipo, dados) {
432
444
  * estava livre, entao ele morreu). Dono sessao vale ate a prova de fim. Reserva vale no prazo, e para
433
445
  * o mesmo canal vira a conducao dele.
434
446
  */
435
- function avaliarComTrava(raiz, threadId, pedido, opcoes = { usarReserva: true }) {
447
+ function avaliarComTrava(raiz, threadId, pedido, opcoes = { usarReserva: true }, saida = {}) {
436
448
  const lease = (0, leases_1.lerLease)(raiz, nomeDaConducao(threadId));
437
449
  if (!lease)
438
450
  return null;
@@ -460,6 +472,7 @@ function avaliarComTrava(raiz, threadId, pedido, opcoes = { usarReserva: true })
460
472
  return null;
461
473
  }
462
474
  if (opcoes.usarReserva && atual.canal === pedido.canal) {
475
+ saida.substituido = lease;
463
476
  liberarComProva(raiz, threadId, lease, ledger_1.TIPOS_DE_EVENTO.conducaoLiberada, { motivo: 'reserva-usada', prova: `pedido do mesmo canal ${pedido.canal} de quem assumiu` });
464
477
  return null;
465
478
  }
@@ -477,6 +490,7 @@ function avaliarComTrava(raiz, threadId, pedido, opcoes = { usarReserva: true })
477
490
  // A sucessora (fluxo de superacao das sessoes HITL): a sessao `blocked` espera alguem e nao executa;
478
491
  // o despacho seguinte da MESMA fase a sucede, e a superacao a encerra pelo controle do runtime.
479
492
  if (despacho && mesmaFase && !mesmoPedido && estadoNoRuntime === 'blocked') {
493
+ saida.substituido = lease;
480
494
  liberarComProva(raiz, threadId, lease, ledger_1.TIPOS_DE_EVENTO.conducaoLiberada, {
481
495
  motivo: 'sessao-bloqueada-sucedida',
482
496
  prova: `runtime ${atual.dono.tipo === 'sessao' ? atual.dono.runtime : '?'}: estado blocked; o despacho seguinte da fase ${atual.fase} a sucede`,
@@ -497,7 +511,8 @@ function tomarConducao(raiz, threadId, pedido) {
497
511
  const propria = emCurso.get(k);
498
512
  if (propria && !propria.convertida) {
499
513
  propria.profundidade++;
500
- return reentrada(propria.identidade, () => { propria.profundidade--; });
514
+ // R5-S2 do CHECK 5: a reentrada renova o lease de quem a segura (a baseline dentro da tomada retida).
515
+ return reentrada(propria.identidade, () => { propria.profundidade--; }, (prazo, agoraMs = Date.now()) => renovar(raiz, threadId, propria, prazo, agoraMs));
501
516
  }
502
517
  const existente = (0, leases_1.lerLease)(raiz, nomeDaConducao(threadId));
503
518
  if (pedido.identidade && existente?.conducao?.identidade === pedido.identidade) {
@@ -521,7 +536,8 @@ function tomarConducao(raiz, threadId, pedido) {
521
536
  return { ok: false, idempotente: false, atual };
522
537
  }
523
538
  try {
524
- const ocupada = avaliarComTrava(raiz, threadId, pedido);
539
+ const saida = {};
540
+ const ocupada = avaliarComTrava(raiz, threadId, pedido, undefined, saida);
525
541
  if (ocupada) {
526
542
  fs.closeSync(fd);
527
543
  return ocupada;
@@ -537,7 +553,8 @@ function tomarConducao(raiz, threadId, pedido) {
537
553
  conducao: dadosDoPedido(pedido, identidade, donoProcesso()),
538
554
  };
539
555
  (0, leases_1.regravarLease)(raiz, lease);
540
- const estado = { identidade, profundidade: 0, lease, fd, convertida: false };
556
+ const estado = { identidade, profundidade: 0, lease, fd, convertida: false, ...(saida.substituido ? { substituido: saida.substituido } : {}),
557
+ ...(pedido.consultarSessao ? { consultarSessao: pedido.consultarSessao } : {}) };
541
558
  emCurso.set(k, estado);
542
559
  return {
543
560
  ok: true,
@@ -546,6 +563,8 @@ function tomarConducao(raiz, threadId, pedido) {
546
563
  renovar: (prazoDoProximoMs, agoraMs = Date.now()) => renovar(raiz, threadId, estado, prazoDoProximoMs, agoraMs),
547
564
  converterEmSessao: (dados) => converter(raiz, k, estado, dados),
548
565
  liberar: () => liberarPropria(raiz, k, estado),
566
+ devolver: () => devolverPropria(raiz, threadId, k, estado),
567
+ sucessaoAindaVale: () => sucessaoAindaVale(raiz, threadId, estado),
549
568
  };
550
569
  }
551
570
  catch (e) {
@@ -556,20 +575,42 @@ function tomarConducao(raiz, threadId, pedido) {
556
575
  throw e;
557
576
  }
558
577
  }
559
- function reentrada(identidade, sair) {
578
+ function reentrada(identidade, sair, renovarExterno = () => undefined) {
560
579
  let saiu = false;
561
580
  return {
562
581
  ok: true, reentrada: true, identidade,
563
- renovar: () => undefined,
582
+ renovar: renovarExterno,
564
583
  converterEmSessao: () => undefined,
565
584
  liberar: () => { if (!saiu) {
566
585
  saiu = true;
567
586
  sair();
568
587
  } },
588
+ devolver: () => { if (!saiu) {
589
+ saiu = true;
590
+ sair();
591
+ } },
592
+ sucessaoAindaVale: () => true,
569
593
  };
570
594
  }
595
+ /** Ver `ConducaoTomada.sucessaoAindaVale`. Sessao sucedida que voltou a trabalhar derruba a sucessao. */
596
+ function sucessaoAindaVale(raiz, threadId, estado) {
597
+ // S2 do CHECK 6: tomada ja encerrada nao converte mais em sessao; despachar com ela deixaria a sessao sem lease.
598
+ if (estado.encerrada)
599
+ return false;
600
+ const dono = estado.substituido?.conducao?.dono;
601
+ if (!dono || dono.tipo !== 'sessao' || estado.convertida)
602
+ return true;
603
+ const r = (estado.consultarSessao ?? consultaNativa)(dono, raiz, threadId);
604
+ // Sem resposta do runtime nao ha prova de que ela segue parada: a sucessao nao vale.
605
+ if (!r.ok)
606
+ return false;
607
+ // S1 do CHECK 6: a sessao que sumiu do runtime, sem perfil, acabou; a mesma prova de `provaDeFimDaSessao`.
608
+ if (r.estado === null)
609
+ return !dono.perfil;
610
+ return r.estado === 'blocked' || TERMINAIS.includes(r.estado);
611
+ }
571
612
  function renovar(raiz, threadId, estado, prazoDoProximoMs, agoraMs) {
572
- if (estado.convertida)
613
+ if (estado.convertida || estado.encerrada)
573
614
  return;
574
615
  const falta = Date.parse(estado.lease.expiraEm) - agoraMs;
575
616
  if (falta >= prazoDoProximoMs + exports.MARGEM_DO_PRAZO_MS)
@@ -585,7 +626,7 @@ function renovar(raiz, threadId, estado, prazoDoProximoMs, agoraMs) {
585
626
  });
586
627
  }
587
628
  function converter(raiz, k, estado, dados) {
588
- if (estado.convertida)
629
+ if (estado.convertida || estado.encerrada)
589
630
  return;
590
631
  const c = estado.lease.conducao;
591
632
  estado.lease = {
@@ -596,14 +637,30 @@ function converter(raiz, k, estado, dados) {
596
637
  };
597
638
  (0, leases_1.regravarLease)(raiz, estado.lease);
598
639
  estado.convertida = true;
599
- emCurso.delete(k);
600
- try {
601
- fs.closeSync(estado.fd);
640
+ encerrar(k, estado);
641
+ }
642
+ function devolverPropria(raiz, threadId, k, estado) {
643
+ const anterior = estado.substituido;
644
+ if (estado.convertida || estado.encerrada || estado.profundidade > 0 || !anterior) {
645
+ liberarPropria(raiz, k, estado);
646
+ return;
602
647
  }
603
- catch { /* ja fechado */ }
648
+ const atual = (0, leases_1.lerLease)(raiz, estado.lease.nome);
649
+ // So devolve por cima do proprio lease: outro dono que tenha chegado depois nunca e sobrescrito.
650
+ if (atual?.conducao?.identidade === estado.identidade && atual.conducao.dono.tipo === 'processo') {
651
+ (0, leases_1.regravarLease)(raiz, anterior);
652
+ const devolvida = (0, conducao_texto_1.conducaoDoLease)(anterior);
653
+ (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, threadId), threadId, ledger_1.TIPOS_DE_EVENTO.conducaoDevolvida, {
654
+ lease: anterior.nome,
655
+ devolvida: devolvida ? { canal: devolvida.canal, sessao: devolvida.sessao, fase: devolvida.fase, desde: devolvida.desde,
656
+ operacao: devolvida.operacao, dono: devolvida.dono } : null,
657
+ razao: 'o pedido foi recusado antes de virar sessao: o lease que a tomada consumiu volta a quem o tinha',
658
+ });
659
+ }
660
+ encerrar(k, estado);
604
661
  }
605
662
  function liberarPropria(raiz, k, estado) {
606
- if (estado.convertida)
663
+ if (estado.convertida || estado.encerrada)
607
664
  return;
608
665
  if (estado.profundidade > 0) {
609
666
  estado.profundidade--;
@@ -616,11 +673,7 @@ function liberarPropria(raiz, k, estado) {
616
673
  }
617
674
  catch { /* ja saiu */ }
618
675
  }
619
- emCurso.delete(k);
620
- try {
621
- fs.closeSync(estado.fd);
622
- }
623
- catch { /* ja fechado */ }
676
+ encerrar(k, estado);
624
677
  }
625
678
  /**
626
679
  * Registra a conducao da sessao de um despacho que nao tomou o lease antes (chamada direta de
@@ -39,7 +39,43 @@ const hitl_gates_1 = require("./hitl-gates");
39
39
  const ledger_1 = require("./ledger");
40
40
  const thread_1 = require("./thread");
41
41
  const modos_1 = require("./modos");
42
+ const conducao_1 = require("./conducao");
42
43
  exports.CONTRATO_DECISAO_AUTONOMA = 'ork.decisao-autonoma/v1';
44
+ /**
45
+ * A sessao de OUTRA thread que registra aqui tambem deixa rastro (S-3 do CHECK 3). So o par que o ledger
46
+ * daquela thread confirma (S-b do CHECK 4): o par vazado do daemon do `claude --bg` nao vira rastro falso.
47
+ */
48
+ function despachoDeOutraThread(raiz, threadId) {
49
+ const thread = (process.env[conducao_1.ENV_THREAD_DO_DESPACHO] ?? '').trim(), id = (process.env[conducao_1.ENV_IDENTIDADE_DE_DESPACHO] ?? '').trim();
50
+ if (!thread || thread === threadId || !/^[a-z0-9]{1,3}-[a-z0-9]{1,12}$/.test(thread) || !/^[a-f0-9-]{36}$/.test(id))
51
+ return {};
52
+ // R5-A2 do CHECK 5: a mesma conferencia D-4 da reentrada. O par que o daemon do `claude --bg` vazou e um
53
+ // despacho real, que o ledger confirma; so a sessao que o recebeu de fato o valida.
54
+ let confirmado = false;
55
+ try {
56
+ confirmado = (0, conducao_1.identidadeDoAmbiente)(thread, process.env, raiz) === id;
57
+ }
58
+ catch { /* thread de outro projeto ou ilegivel: sem prova, sem rastro */ }
59
+ if (confirmado) {
60
+ try {
61
+ confirmado = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, thread)).some((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.faseDespachada &&
62
+ e.identidade?.dispatchId === id);
63
+ }
64
+ catch {
65
+ confirmado = false;
66
+ }
67
+ }
68
+ return confirmado ? { despachoNoAmbiente: { thread, dispatchId: id } } : {};
69
+ }
70
+ /** O canal do processo; canal fora do registro nao impede a decisao, e fica dito como tal. */
71
+ function canalSeguro() {
72
+ try {
73
+ return (0, conducao_1.canalDoProcesso)();
74
+ }
75
+ catch {
76
+ return 'desconhecido';
77
+ }
78
+ }
43
79
  /** D3/M7: o p90 das 155 fases ja medidas. Acima disso a fase esta no decil mais alto do projeto. */
44
80
  exports.LIMIAR_DE_DECISOES_POR_FASE = 13;
45
81
  /** Os nomes que o rastro teve antes de ser tipado (M6), na ordem em que valem na leitura. */
@@ -110,6 +146,12 @@ function registrarDecisao(raiz, threadId, entrada) {
110
146
  const evento = (0, ledger_1.registrar)(dir, t.id, ledger_1.TIPOS_DE_EVENTO.decisaoAutonoma, {
111
147
  contratoDecisao: exports.CONTRATO_DECISAO_AUTONOMA, fase: pedido.fase, decisao: pedido.decidido, ...rastro,
112
148
  pedido, ...(entrada.reverte ? { reverte: entrada.reverte } : {}),
149
+ origem: entrada.origem ?? 'cli', ...(entrada.host ? { host: entrada.host } : {}),
150
+ // RM-037 (S5 do CHECK): a porta e quem chamou, pelo processo e nao pelo texto de `quemDecidiu`. A sessao
151
+ // despachada carrega a identidade do despacho no ambiente; o dono no terminal, nao.
152
+ canal: entrada.origem === 'mcp' && entrada.host ? entrada.host : canalSeguro(),
153
+ despacho: entrada.despacho !== undefined ? entrada.despacho : (0, conducao_1.identidadeDoAmbiente)(t.id, process.env, raiz),
154
+ ...despachoDeOutraThread(raiz, t.id),
113
155
  });
114
156
  return { pedido, evento };
115
157
  });