@orkastery/cli 0.2.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) 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/check.md +4 -3
  7. package/adapters/claude-code/commands/goal.md +3 -2
  8. package/adapters/claude-code/commands/master.md +3 -2
  9. package/adapters/claude-code/commands/onboarding.md +21 -0
  10. package/adapters/claude-code/commands/ork.md +99 -27
  11. package/adapters/claude-code/hooks/hooks.json +6 -1
  12. package/adapters/claude-code/hooks/ork-guard.js +1 -1
  13. package/adapters/claude-code/hooks/ork-sensor.js +66 -0
  14. package/adapters/codex/skills/ork/SKILL.md +57 -0
  15. package/adapters/hermes/README.md +161 -0
  16. package/adapters/hermes/bin/ork-abrir-thread.sh +2 -0
  17. package/adapters/hermes/bin/ork-brain.sh +4 -0
  18. package/adapters/hermes/bin/ork-hitl-answer.py +82 -0
  19. package/adapters/hermes/bin/ork-maestro.sh +6 -0
  20. package/adapters/hermes/bin/ork-master-enviar.py +84 -0
  21. package/adapters/hermes/bin/ork-pulse-enviar.py +47 -0
  22. package/adapters/hermes/hermes.plugin.json +24 -4
  23. package/adapters/hermes/hitl-ingress/__init__.py +356 -0
  24. package/adapters/hermes/hitl-ingress/plugin.yaml +4 -0
  25. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +75 -22
  26. package/adapters/openclaw/README.md +136 -27
  27. package/adapters/openclaw/bin/ork-brain.sh +4 -0
  28. package/adapters/openclaw/construir.sh +19 -0
  29. package/adapters/openclaw/dist/hitl-ingress.js +199 -0
  30. package/adapters/openclaw/dist/index.js +437 -0
  31. package/adapters/openclaw/openclaw.plugin.json +39 -134
  32. package/adapters/openclaw/package.json +26 -0
  33. package/adapters/openclaw/src/hitl-ingress.ts +180 -0
  34. package/adapters/openclaw/src/index.ts +460 -0
  35. package/adapters/openclaw/src/tipos-openclaw.d.ts +58 -0
  36. package/adapters/openclaw/tsconfig.json +15 -0
  37. package/assets/docs/markdownlint-cli2.jsonc +22 -0
  38. package/assets/docs/padroes/documentacao-de-produto.md +133 -0
  39. package/assets/docs/padroes/roadmap-de-produto.md +98 -0
  40. package/assets/docs/produto/README.md +14 -0
  41. package/assets/docs/produto/_modelo-feature.md +59 -0
  42. package/assets/docs/roadmap/README.md +14 -0
  43. package/assets/docs/roadmap/_modelo-item.md +73 -0
  44. package/assets/orkmind-native-schema.json +32 -0
  45. package/assets/orkmind_bridge.py +357 -0
  46. package/assets/orkmind_fixture.py +67 -0
  47. package/assets/orkmind_prospective.py +138 -0
  48. package/assets/reference-tariffs-i07.json +23 -0
  49. package/dist/adapters/claude-bg.js +488 -39
  50. package/dist/adapters/codex-controller-sensor.js +449 -0
  51. package/dist/adapters/codex-controller-worker.js +361 -0
  52. package/dist/adapters/codex-controller.js +252 -0
  53. package/dist/adapters/codex-events.js +205 -0
  54. package/dist/adapters/codex-question.js +26 -0
  55. package/dist/adapters/codex-runner.js +133 -0
  56. package/dist/adapters/codex.js +394 -0
  57. package/dist/agents-md.js +84 -0
  58. package/dist/auditoria.js +12 -9
  59. package/dist/auditrun.js +5 -4
  60. package/dist/board.js +174 -23
  61. package/dist/branch-de-estado.js +136 -0
  62. package/dist/canarios-hitl.js +177 -0
  63. package/dist/canarios-i43.js +543 -0
  64. package/dist/canarios-pulse.js +147 -0
  65. package/dist/canarios-sensores.js +129 -0
  66. package/dist/canarios.js +111 -2
  67. package/dist/catalogo.js +9 -0
  68. package/dist/ci.js +223 -0
  69. package/dist/ciclos.js +2 -1
  70. package/dist/claim-lint.js +64 -0
  71. package/dist/claims.js +60 -0
  72. package/dist/company-brain-capture.js +195 -0
  73. package/dist/company-brain-cli.js +123 -0
  74. package/dist/company-brain-client.js +61 -0
  75. package/dist/company-brain-contract.js +166 -0
  76. package/dist/company-brain-journal.js +192 -0
  77. package/dist/company-brain-mcp.js +33 -0
  78. package/dist/company-brain-migration.js +60 -0
  79. package/dist/company-brain-source.js +177 -0
  80. package/dist/company-brain-worker.js +18 -0
  81. package/dist/conducao-texto.js +61 -0
  82. package/dist/conducao.js +876 -0
  83. package/dist/contrato-publico.js +39 -0
  84. package/dist/creation-operation-store.js +251 -0
  85. package/dist/creation-operation.js +148 -0
  86. package/dist/decisao-autonoma.js +183 -0
  87. package/dist/delegation.js +79 -0
  88. package/dist/demo.js +120 -0
  89. package/dist/docs.js +828 -0
  90. package/dist/doctor.js +184 -25
  91. package/dist/entrega-pr.js +117 -0
  92. package/dist/escopo-escrita.js +71 -0
  93. package/dist/estado-thread.js +222 -0
  94. package/dist/evalrunner.js +12 -0
  95. package/dist/fabrica-estado.js +329 -0
  96. package/dist/fabrica-publicar.js +76 -0
  97. package/dist/fix.js +22 -1
  98. package/dist/gates.js +59 -11
  99. package/dist/handoff.js +39 -23
  100. package/dist/hitl-canais.js +333 -0
  101. package/dist/hitl-classificacao.js +131 -0
  102. package/dist/hitl-contract.js +465 -0
  103. package/dist/hitl-estado.js +136 -0
  104. package/dist/hitl-gates.js +554 -0
  105. package/dist/hitl-ingress-receipt.js +382 -0
  106. package/dist/hitl-local-atestado.js +57 -0
  107. package/dist/hitl-local-receipt.js +328 -0
  108. package/dist/hitl-local.js +143 -0
  109. package/dist/hitl-lock.js +139 -0
  110. package/dist/hitl-lote.js +223 -0
  111. package/dist/hitl-native-offer.js +97 -0
  112. package/dist/hitl-native.js +65 -0
  113. package/dist/hitl-presentation.js +209 -0
  114. package/dist/hitl-public-receipt.js +176 -0
  115. package/dist/hitl-resumo.js +209 -0
  116. package/dist/hitl-sessions.js +475 -0
  117. package/dist/hitl.js +711 -0
  118. package/dist/horario.js +269 -0
  119. package/dist/hosts.js +198 -22
  120. package/dist/index.js +1741 -94
  121. package/dist/indice.js +99 -0
  122. package/dist/init.js +28 -3
  123. package/dist/integracoes-locais.js +17 -0
  124. package/dist/leases.js +65 -21
  125. package/dist/ledger-stats.js +272 -0
  126. package/dist/ledger.js +109 -2
  127. package/dist/licoes.js +221 -0
  128. package/dist/liveness.js +218 -0
  129. package/dist/maestro-actions.js +51 -0
  130. package/dist/maestro-authority.js +152 -0
  131. package/dist/maestro-cli.js +97 -0
  132. package/dist/maestro-contract.js +55 -0
  133. package/dist/maestro-discovery.js +132 -0
  134. package/dist/maestro-runtime.js +268 -0
  135. package/dist/maestro-snapshot.js +86 -0
  136. package/dist/maestro-sources.js +224 -0
  137. package/dist/manifest.js +165 -6
  138. package/dist/maquina.js +102 -0
  139. package/dist/master-audit.js +101 -0
  140. package/dist/master-batch.js +43 -0
  141. package/dist/master-digest.js +149 -0
  142. package/dist/master-migracao.js +155 -0
  143. package/dist/master.js +361 -77
  144. package/dist/mcp-artifacts.js +234 -0
  145. package/dist/mcp-git.js +433 -0
  146. package/dist/mcp-install.js +310 -0
  147. package/dist/mcp-maestro.js +25 -0
  148. package/dist/mcp-server.js +469 -0
  149. package/dist/mcp-ship.js +436 -0
  150. package/dist/mcp-verify.js +173 -0
  151. package/dist/memoria-humana.js +207 -0
  152. package/dist/memoria.js +314 -78
  153. package/dist/memory-migration.js +279 -0
  154. package/dist/memory-prospective.js +148 -0
  155. package/dist/modos-migracao.js +191 -0
  156. package/dist/modos.js +151 -15
  157. package/dist/monitor-lock.js +110 -0
  158. package/dist/objective.js +449 -0
  159. package/dist/ocupacao.js +267 -0
  160. package/dist/onboarding.js +303 -0
  161. package/dist/orkmind.js +389 -90
  162. package/dist/orquestracao.js +96 -69
  163. package/dist/phase.js +612 -151
  164. package/dist/playbook-capabilities.js +150 -0
  165. package/dist/playbook-contracts.js +188 -0
  166. package/dist/policies.js +72 -0
  167. package/dist/portfolio-context.js +61 -0
  168. package/dist/portfolio.js +180 -0
  169. package/dist/preflight.js +207 -0
  170. package/dist/process-audit.js +112 -0
  171. package/dist/project-state.js +93 -0
  172. package/dist/prompts.js +25 -5
  173. package/dist/prova-minima.js +112 -0
  174. package/dist/pulse-cadencia.js +163 -0
  175. package/dist/pulse-consentimento.js +260 -0
  176. package/dist/pulse-delivery.js +323 -0
  177. package/dist/pulse-resposta.js +542 -0
  178. package/dist/pulse.js +262 -0
  179. package/dist/ratelimit.js +35 -2
  180. package/dist/recall.js +80 -3
  181. package/dist/redacao-saida.js +45 -0
  182. package/dist/redacao-url.js +66 -0
  183. package/dist/retry.js +640 -118
  184. package/dist/roadmap-reservas.js +243 -0
  185. package/dist/runtime-ambiente.js +38 -0
  186. package/dist/runtime-context.js +215 -0
  187. package/dist/runtime-profiles.js +869 -0
  188. package/dist/runtimes.js +103 -0
  189. package/dist/sandbox.js +9 -0
  190. package/dist/session-events.js +203 -0
  191. package/dist/session-watcher-claude.js +637 -0
  192. package/dist/session-watcher.js +700 -0
  193. package/dist/sessoes-adopt.js +154 -0
  194. package/dist/sessoes-inventario.js +159 -0
  195. package/dist/sessoes.js +16 -35
  196. package/dist/setup.js +691 -0
  197. package/dist/ship.js +168 -19
  198. package/dist/slug.js +1 -1
  199. package/dist/thread-close.js +115 -0
  200. package/dist/thread.js +142 -28
  201. package/dist/tokens.js +1 -1
  202. package/dist/util.js +4 -2
  203. package/dist/verify-sandbox.js +265 -0
  204. package/dist/verify.js +270 -25
  205. package/dist/versao.js +60 -0
  206. package/dist/worktree.js +31 -2
  207. package/dist/write-activation.js +291 -0
  208. package/dist/yaml.js +5 -1
  209. package/eval/casos/master-metrics.json +1 -1
  210. package/eval/casos/onboarding.json +102 -0
  211. package/eval/casos/orkastery-bootstrap.json +37 -3
  212. package/eval/casos/scope-check-capability-map.json +45 -7
  213. package/eval/casos/ship-release.json +3 -3
  214. package/eval/fixtures/b0-slug-e-modos/caso.json +35 -22
  215. package/eval/fixtures/b2-master-log/caso.json +1 -1
  216. package/eval/fixtures/fx-adapter-editado-detectado/caso.json +19 -0
  217. package/eval/fixtures/fx-auto-quiet/caso.json +11 -0
  218. package/eval/fixtures/fx-blanket-approve/caso.json +10 -0
  219. package/eval/fixtures/fx-check-runtime-cruzado/caso.json +20 -0
  220. package/eval/fixtures/fx-codex-dry/caso.json +18 -0
  221. package/eval/fixtures/fx-donewhen-executavel/caso.json +15 -0
  222. package/eval/fixtures/fx-estado-dividido/caso.json +15 -0
  223. package/eval/fixtures/fx-fase-orfa/caso.json +116 -0
  224. package/eval/fixtures/fx-happy/caso.json +6 -4
  225. package/eval/fixtures/fx-hitl-latency/caso.json +20 -0
  226. package/eval/fixtures/fx-indice-reversao/caso.json +25 -0
  227. package/eval/fixtures/fx-listagem-abertas/caso.json +16 -0
  228. package/eval/fixtures/fx-maestro-bootstrap/caso.json +21 -0
  229. package/eval/fixtures/fx-modo-aposentado-escritor/caso.json +21 -0
  230. package/eval/fixtures/fx-modo-aposentado-leitor/caso.json +16 -0
  231. package/eval/fixtures/fx-objective-oscillation/caso.json +14 -0
  232. package/eval/fixtures/fx-omnicanal/caso.json +17 -0
  233. package/eval/fixtures/fx-sensores-runtime/caso.json +17 -0
  234. package/monitor/company-brain.cjs +17 -0
  235. package/monitor/pulse-scope.cjs +45 -0
  236. package/monitor/pulse.cron +18 -0
  237. package/monitor/varredura-pulse.sh +27 -0
  238. package/package.json +28 -7
  239. package/references/definition-of-done.md +2 -2
  240. package/schemas/claims.schema.json +25 -0
  241. package/schemas/company-brain.schema.json +1158 -0
  242. package/schemas/creation-operation.schema.json +365 -0
  243. package/schemas/maestro-snapshot.schema.json +2716 -0
  244. package/skills/README.md +3 -3
  245. package/skills/core/onboarding/SKILL.md +50 -0
  246. package/skills/core/orkastery-bootstrap/SKILL.md +95 -65
  247. package/skills/core/thread-state/SKILL.md +3 -1
  248. package/skills/governance/decision-triage/SKILL.md +4 -4
  249. package/skills/governance/narrative-guardian/SKILL.md +1 -1
  250. package/skills/governance/roadmap-keeper/SKILL.md +1 -1
  251. package/skills/governance/scope-check-capability-map/SKILL.md +17 -7
  252. package/skills/observability/thread-tracing/SKILL.md +1 -1
  253. package/skills/phases/check-quality/SKILL.md +2 -2
  254. package/skills/phases/goal-definition/SKILL.md +1 -1
  255. package/skills/phases/master-metrics/SKILL.md +9 -7
  256. package/skills/phases/plan-specification/SKILL.md +1 -1
  257. package/skills/phases/ship-release/SKILL.md +1 -1
@@ -0,0 +1,543 @@
1
+ "use strict";
2
+ /**
3
+ * Canarios da I-43: cada remocao so e dada como pronta junto do canario que prova que
4
+ * a falha evitada pelo mecanismo removido continua evitada por outra coisa.
5
+ *
6
+ * Remocao sem canario nao e simplificacao, e aposta. E a razao de este arquivo existir
7
+ * separado: o CHECK confere as cinco remocoes num lugar so, e o que cada uma perdeu
8
+ * esta escrito ao lado do que a substitui.
9
+ *
10
+ * Os canarios rodam em sandbox git propria (`sandboxGit`), nunca contra o board vivo:
11
+ * `raizDoEstado` manda o estado para a arvore principal mesmo de dentro de uma worktree
12
+ * vinculada, entao qualquer conferencia feita "no projeto" leria as 137 threads reais
13
+ * e viraria contagem de artefato vivo, que reprova sozinha quando a branch cresce.
14
+ */
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.CANARIOS_I43 = void 0;
50
+ const sandbox_1 = require("./sandbox");
51
+ const fs = __importStar(require("node:fs"));
52
+ const hosts_1 = require("./hosts");
53
+ const thread_1 = require("./thread");
54
+ const modos_1 = require("./modos");
55
+ const hitl_contract_1 = require("./hitl-contract");
56
+ const manifest_1 = require("./manifest");
57
+ const ledger_1 = require("./ledger");
58
+ const master_1 = require("./master");
59
+ const phase_1 = require("./phase");
60
+ const verify_1 = require("./verify");
61
+ const claims_1 = require("./claims");
62
+ const gates_1 = require("./gates");
63
+ const retry_1 = require("./retry");
64
+ const sandbox_2 = require("./sandbox");
65
+ const util_1 = require("./util");
66
+ /** Um pedido `ork.hitl/v1` como os gravados antes da aposentadoria. */
67
+ function pedidoLegado(modo) {
68
+ return { contrato: 'ork.hitl/v1', id: 'pedido-legado', thread: 'ork-smokeb0', fase: 'PLAN',
69
+ modo, alvo: { tipo: 'gate', sobre: 'plano' }, motivo: 'human.pending',
70
+ pergunta: 'Qual e o veredito sobre o plano?',
71
+ opcoes: [{ numero: 1, texto: 'Aprovar', acao: 'aprovar' }, { numero: 2, texto: 'Revisar', acao: 'recusar' }],
72
+ recomendacao: 'Conferir as evidencias.', criadoEm: '2026-09-02T12:00:00Z',
73
+ prazo: '2026-09-02T13:00:00Z', acaoPadraoAoExpirar: 'esperar',
74
+ respostaAceita: { tipo: 'opcao', maxCaracteres: 100 }, profundidade: (0, hitl_contract_1.profundidadeDoModo)(modo) };
75
+ }
76
+ /**
77
+ * fx-modo-aposentado-leitor: o lado que NAO pode encolher.
78
+ *
79
+ * As tres threads reais em `#Look`/`#Ork` sao de 02 e 03/09 e estao fechadas, mas o
80
+ * board continua abrindo todas elas. Se a matriz encolhesse junto com a lista de
81
+ * escrita, `tagDoModo` devolveria `#?look` e um recibo `ork.hitl/v1` com
82
+ * `modo: look, profundidade: profunda` deixaria de validar EM SILENCIO: o produto
83
+ * passaria a negar o que ele mesmo emitiu e assinou.
84
+ *
85
+ * O canario grava uma thread em modo aposentado direto no disco da sandbox, como uma
86
+ * thread de setembro esta gravada, e cobra que ela abra inteira.
87
+ */
88
+ const fxModoAposentadoLeitor = {
89
+ id: 'fx-modo-aposentado-leitor',
90
+ sobre: 'thread e recibo gravados em modo aposentado continuam sendo lidos para sempre',
91
+ precisaDeGit: true,
92
+ rodar: () => {
93
+ const s = (0, sandbox_1.sandboxGit)('modo-aposentado-leitor');
94
+ try {
95
+ const tags = [];
96
+ const pausas = [];
97
+ let recibosValidos = 0;
98
+ for (const morto of modos_1.MODOS_APOSENTADOS) {
99
+ // A thread nasce viva (escrever aposentado esta barrado) e e REGRAVADA em disco
100
+ // com o modo antigo, que e exatamente o estado de `ork-smokeb0` e `ork-b4adapt`.
101
+ const nova = (0, thread_1.novaThread)(s.carregado, { nome: `legada ${morto}`, modo: 'classic' }).thread;
102
+ const emDisco = (0, thread_1.lerThread)(s.dir, nova.id);
103
+ emDisco.modo = morto;
104
+ emDisco.blocos = (0, modos_1.definicaoDoModo)(morto).blocos;
105
+ (0, thread_1.gravarThread)(s.dir, emDisco);
106
+ const relida = (0, thread_1.lerThread)(s.dir, nova.id);
107
+ tags.push((0, modos_1.tagDoModo)(relida.modo));
108
+ pausas.push(relida.blocos.filter((b) => b.pausa).length);
109
+ // O recibo assinado com esse modo continua batendo com a propria profundidade.
110
+ try {
111
+ (0, hitl_contract_1.validarPedidoHitl)(pedidoLegado(morto));
112
+ recibosValidos++;
113
+ }
114
+ catch { /* reprova abaixo */ }
115
+ }
116
+ return {
117
+ tags,
118
+ pausas,
119
+ recibosValidos,
120
+ // RELACOES, nao contagens: a I-42 vai acrescentar `fast` a lista viva, e um
121
+ // numero carimbado aqui reprovaria a irma sem nenhum defeito ter aparecido.
122
+ todoAposentadoTemDefinicao: modos_1.MODOS_APOSENTADOS.every((m) => modos_1.MODOS_LEGADOS.includes(m)),
123
+ nenhumAposentadoEscrivel: modos_1.MODOS_APOSENTADOS.every((m) => !modos_1.ORDEM_DOS_MODOS.includes(m)),
124
+ todoVivoEhLegado: modos_1.ORDEM_DOS_MODOS.every((m) => modos_1.MODOS_LEGADOS.includes(m)),
125
+ // O mapa de profundidade do recibo legado esta intacto (costura da I-41).
126
+ profundidadeDeLook: (0, hitl_contract_1.profundidadeDoModo)('look'),
127
+ profundidadeDeOrk: (0, hitl_contract_1.profundidadeDoModo)('ork'),
128
+ };
129
+ }
130
+ finally {
131
+ s.limpar();
132
+ }
133
+ },
134
+ };
135
+ /**
136
+ * fx-modo-aposentado-escritor: o lado que precisa RECUSAR, e recusar falando.
137
+ *
138
+ * Ignorar em silencio e o pecado que o produto inteiro combate, e seria o pior
139
+ * resultado desta aposentadoria: o builder escreve `#Look` no pedido e recebe uma
140
+ * thread em `#Auto` sem saber que trocou de regime de supervisao.
141
+ *
142
+ * O canario cobra as tres coisas juntas: a recusa acontece, ela e TIPADA, e ela nomeia
143
+ * um substituto que EXISTE. Toda #TAG do texto e um modo da matriz, e o substituto e
144
+ * sempre de ciclo completo: com a I-42, o `#Fast` existe, mas nao substitui modo de
145
+ * vigilancia maxima.
146
+ */
147
+ const fxModoAposentadoEscritor = {
148
+ id: 'fx-modo-aposentado-escritor',
149
+ sobre: 'modo aposentado escrito em qualquer entrada recebe recusa tipada, nunca silencio',
150
+ precisaDeGit: true,
151
+ rodar: () => {
152
+ const s = (0, sandbox_1.sandboxGit)('modo-aposentado-escritor');
153
+ try {
154
+ let recusasNaCriacao = 0, recusasNoParse = 0, tagsReconhecidas = 0;
155
+ const mensagens = [];
156
+ for (const morto of modos_1.MODOS_APOSENTADOS) {
157
+ // 1. O portao de escrita recusa, e nao confunde aposentado com inexistente.
158
+ if ((0, modos_1.parseModo)(morto) === null)
159
+ recusasNoParse++;
160
+ try {
161
+ (0, thread_1.novaThread)(s.carregado, { nome: 'proibida', modo: morto });
162
+ }
163
+ catch {
164
+ recusasNaCriacao++;
165
+ }
166
+ // 2. A #TAG no texto livre do pedido e RECONHECIDA, e nao cai no default.
167
+ const pedido = `Migracao de risco #${morto} agora`;
168
+ if ((0, modos_1.extrairTagDoPedido)(pedido) === null && (0, modos_1.extrairTagAposentadaDoPedido)(pedido) === morto) {
169
+ tagsReconhecidas++;
170
+ }
171
+ mensagens.push((0, modos_1.recusaDeModoAposentado)(morto));
172
+ }
173
+ const substitutos = (0, modos_1.substitutosVivos)();
174
+ const texto = mensagens.join(' | ');
175
+ return {
176
+ recusasNoParse,
177
+ recusasNaCriacao,
178
+ tagsReconhecidas,
179
+ // Toda mensagem e tipada e nomeia o modo pedido.
180
+ todasTipadas: mensagens.every((m) => m.startsWith('modo.aposentado:')),
181
+ nomeiaOModoPedido: mensagens.every((m, i) => m.includes(`#${modos_1.MODOS_APOSENTADOS[i][0].toUpperCase()}${modos_1.MODOS_APOSENTADOS[i].slice(1)}`)),
182
+ // E todo substituto oferecido e um modo que EXISTE hoje.
183
+ substitutosVivos: substitutos.every((tag) => modos_1.ORDEM_DOS_MODOS.some((m) => (0, modos_1.tagDoModo)(m) === tag)),
184
+ // `#Maestro` nao e substituto: ele e o modo de gate, de outra natureza.
185
+ semMaestroNaOferta: !texto.includes('#Maestro'),
186
+ // Nenhum modo inexistente e prometido: toda #TAG do texto e um modo da matriz.
187
+ semModoInexistente: (texto.match(/#[A-Za-z]+/g) ?? []).every((tag) => modos_1.MODOS_LEGADOS.some((m) => (0, modos_1.tagDoModo)(m) === tag)),
188
+ // I-42: o substituto de um modo de vigilancia maxima e de ciclo completo; o #Fast nao entra.
189
+ semCicloParcialNaOferta: substitutos.length > 0 && modos_1.ORDEM_DOS_MODOS.every((m) => (0, modos_1.cicloCompleto)(m) || !substitutos.includes((0, modos_1.tagDoModo)(m))),
190
+ // O manifesto do proprio sandbox nasce so com os vivos. Relacao, nao numero:
191
+ // quando a I-42 acrescentar `fast`, isto continua verdadeiro sozinho.
192
+ initSoComVivos: ((0, manifest_1.carregarManifesto)(s.dir)?.manifesto.conduction.allowed_modes ?? [])
193
+ .every((m) => modos_1.ORDEM_DOS_MODOS.includes(m)),
194
+ initTemTodosOsVivos: modos_1.ORDEM_DOS_MODOS.every((m) => ((0, manifest_1.carregarManifesto)(s.dir)?.manifesto.conduction.allowed_modes ?? []).includes(m)),
195
+ };
196
+ }
197
+ finally {
198
+ s.limpar();
199
+ }
200
+ },
201
+ };
202
+ /**
203
+ * fx-listagem-abertas: o default para de mostrar o que ninguem pediu para ver.
204
+ *
205
+ * O custo medido era o DEFAULT, nao a falta de flag: `ork thread list` imprimia 137
206
+ * linhas para as 31 que interessavam, e 71 delas (52 por cento) eram threads
207
+ * `Sessao adotada claude-bg <uuid>`, lixo do mecanismo de adocao de 07 a 14/09. Quem
208
+ * pagava era quem nao sabia que existia flag, porque flag nenhuma existia.
209
+ *
210
+ * O canario roda em SANDBOX e nunca contra o board vivo, e isso nao e detalhe: M8 do
211
+ * PLAN mediu que `ork thread list` rodado DENTRO desta worktree lista as 137 threads
212
+ * da arvore principal, porque `raizDoEstado` resolve o estado pelo `git-common-dir`.
213
+ * Conferir "no projeto" seria comparar 137 com 10 e afirmar contagem de artefato vivo,
214
+ * que reprova sozinha quando a branch cresce. Aqui as contagens sao 1 e 2, fixadas
215
+ * pelo proprio canario.
216
+ *
217
+ * A thread PAUSADA e a razao de o default ser "nao fechadas" e nao "so abertas", que
218
+ * era o texto do GOAL: esconder a pausada seria esconder a que mais pede atencao.
219
+ */
220
+ const fxListagemAbertas = {
221
+ id: 'fx-listagem-abertas',
222
+ sobre: 'o default de ork thread list mostra o que ainda pede atencao, e --todas abre o resto',
223
+ precisaDeGit: true,
224
+ rodar: () => {
225
+ const s = (0, sandbox_1.sandboxGit)('listagem-abertas');
226
+ try {
227
+ const aberta = (0, thread_1.novaThread)(s.carregado, { nome: 'aberta', modo: 'classic' }).thread;
228
+ const pausada = (0, thread_1.novaThread)(s.carregado, { nome: 'pausada', modo: 'classic' }).thread;
229
+ const fechada = (0, thread_1.novaThread)(s.carregado, { nome: 'fechada', modo: 'classic' }).thread;
230
+ const p = (0, thread_1.lerThread)(s.dir, pausada.id);
231
+ p.status = 'pausada';
232
+ (0, thread_1.gravarThread)(s.dir, p);
233
+ const f = (0, thread_1.lerThread)(s.dir, fechada.id);
234
+ f.status = 'fechada';
235
+ (0, thread_1.gravarThread)(s.dir, f);
236
+ const padrao = (0, thread_1.threadsDaListagem)(s.dir);
237
+ const todas = (0, thread_1.threadsDaListagem)(s.dir, { todas: true });
238
+ const texto = (0, thread_1.tabelaDeThreads)(s.dir);
239
+ return {
240
+ // O default traz a aberta E a pausada, e deixa a fechada de fora.
241
+ noDefault: padrao.map((l) => l.status).sort(),
242
+ defaultTemAAberta: padrao.some((l) => l.id === aberta.id),
243
+ defaultTemAPausada: padrao.some((l) => l.id === pausada.id),
244
+ defaultEscondeAFechada: !padrao.some((l) => l.id === fechada.id),
245
+ // `--todas` traz as tres.
246
+ comTodas: todas.length,
247
+ todasTemAFechada: todas.some((l) => l.id === fechada.id),
248
+ // A soma bate: default + fechadas = tudo. Sem afirmar numero de artefato vivo,
249
+ // porque as tres threads sao criadas por este canario.
250
+ somaBate: padrao.length + todas.filter((l) => l.status === 'fechada').length === todas.length,
251
+ // E o texto avisa que escondeu algo, em vez de esconder em silencio.
252
+ avisaQueEscondeu: texto.includes('fechada(s) omitida(s)'),
253
+ };
254
+ }
255
+ finally {
256
+ s.limpar();
257
+ }
258
+ },
259
+ };
260
+ /**
261
+ * fx-indice-reversao: a entrega revertida se rebaixa SOZINHA, pelo caminho que o
262
+ * produto percorre de verdade.
263
+ *
264
+ * E o canario que libera a saida da fila de ratificacao de score, e ele prova a
265
+ * propriedade exata que a fila nao entregava: a fila tinha 13 entradas esperando nota
266
+ * humana justamente porque lembrete nao converte em nota, e nenhuma delas dizia se a
267
+ * entrega tinha sido desfeita depois.
268
+ *
269
+ * ELE NAO CHAMA A DETECCAO A MAO, e essa e a mudanca do GO-FIX 1. Na primeira versao
270
+ * ele chamava `registrarReversaoDaEntrega` direto, que era justamente o passo que no
271
+ * produto ninguem executava: o unico chamador era o COMECO de um `ork ship` seguinte
272
+ * da mesma thread, e depois do MASTER nao ha ship seguinte. O canario ficava verde com
273
+ * a propriedade quebrada, e o CHECK provou com `git revert` real que o produto gravava
274
+ * score 5 e a justificativa "sem reversao" numa entrega desfeita.
275
+ *
276
+ * Agora o que roda aqui e o que `ork master` roda: `tabelaDeEntregas` (o que o dono le)
277
+ * e `aceitarPorOmissao` (o que `--aceitar-omissao` faz). A reversao tem de alcancar o
278
+ * texto, o indice, o `score` gravado e o MASTER log sem ninguem chamar nada a mao.
279
+ *
280
+ * O caminho exercitado, do comeco ao fim:
281
+ * 1. a thread entrega, e `ship_done` grava o `mergeSha` e o destino;
282
+ * 2. alguem faz `git revert` na base, como faria de verdade;
283
+ * 3. o dono roda `ork master`, e a tabela ja mostra a reversao em vez de "sem tropeco";
284
+ * 4. a aceitacao por omissao grava score 2, e a justificativa NAO diz "sem reversao".
285
+ *
286
+ * A deteccao ancora em "This reverts commit <sha>" e nao em diff de arvore: um arquivo
287
+ * que voltou ao estado anterior pode ser trabalho de outra thread, e chamar isso de
288
+ * reversao rebaixaria entrega alheia por coincidencia.
289
+ *
290
+ * Tambem se prova a IDEMPOTENCIA: o caminho roda em todo `ork master`, entao rodar de
291
+ * novo nao pode rebaixar duas vezes. Sem isso, consultar a tabela afundaria a nota.
292
+ */
293
+ const fxIndiceReversao = {
294
+ id: 'fx-indice-reversao',
295
+ sobre: 'entrega revertida depois do ship se rebaixa sozinha no caminho real do ork master, sem ninguem pontuar',
296
+ precisaDeGit: true,
297
+ rodar: () => {
298
+ const s = (0, sandbox_1.sandboxGit)('indice-reversao');
299
+ try {
300
+ const t = (0, thread_1.novaThread)(s.carregado, { nome: 'entrega', modo: 'auto' }).thread;
301
+ const dir = (0, thread_1.dirThread)(s.dir, t.id);
302
+ // Antes de qualquer tropeco, a entrega vale o teto: entregue e aceito.
303
+ const antesDeTudo = (0, master_1.indiceDaThread)(s.dir, t.id).valor;
304
+ // 1. A entrega acontece de verdade no git da sandbox.
305
+ const merge = (0, sandbox_2.commitar)(s.dir, 'entrega.md', '# entrega da thread\n', 'feat: entrega');
306
+ (0, ledger_1.registrar)(dir, t.id, 'ship_done', { fase: 'SHIP', de: 'ork/entrega', para: 'main',
307
+ mergeSha: merge, pushVerificado: true });
308
+ // Com git presente e nenhuma reversao, o caminho do produto nao inventa tropeco.
309
+ const depoisDoShip = (0, master_1.indiceDaThread)(s.dir, t.id).valor;
310
+ // 2. O dono reverte na base, como reverteria de verdade.
311
+ (0, util_1.exec)('git', ['revert', '--no-edit', merge], s.dir);
312
+ // 3. O dono roda `ork master`. NINGUEM chamou a deteccao: quem a chama e o produto.
313
+ const tabela = (0, master_1.tabelaDeEntregas)(s.dir);
314
+ const depoisDaReversao = (0, master_1.indiceDaThread)(s.dir, t.id).valor;
315
+ // 4. E a aceitacao por omissao, que e o que carimbava 5 em coisa revertida.
316
+ const aceite = (0, master_1.aceitarPorOmissao)(s.dir, t.id);
317
+ const gravado = (0, thread_1.lerThread)(s.dir, t.id).score;
318
+ const masterLog = (0, master_1.lerMasterLog)(s.dir, t.id);
319
+ // 5. De novo: o caminho roda em toda consulta, e nao pode rebaixar duas vezes.
320
+ (0, master_1.tabelaDeEntregas)(s.dir);
321
+ const depoisDeRepetir = (0, master_1.indiceDaThread)(s.dir, t.id).valor;
322
+ const rollbacks = (0, ledger_1.lerLedger)(dir).filter((e) => e.tipo === 'rollback_done').length;
323
+ return {
324
+ antesDeTudo,
325
+ depoisDoShip,
326
+ // O texto que o dono le: a reversao aparece, e "sem tropeco" some.
327
+ depoisDaReversao,
328
+ tabelaMostraAReversao: tabela.includes('rollback_done x1'),
329
+ tabelaDizSemTropeco: tabela.includes('sem tropeco'),
330
+ // O indice e o score que o MASTER consome.
331
+ indiceDoAceite: aceite.indice.valor,
332
+ scoreGravado: gravado?.valor ?? null,
333
+ regimeGravado: gravado?.regime ?? null,
334
+ masterLogScore: masterLog?.score ?? null,
335
+ // A justificativa gravada dizia "sem reversao" sobre uma entrega desfeita.
336
+ justificativaDizSemReversao: (gravado?.justificativa ?? '').includes('sem reversao'),
337
+ justificativaCitaAReversao: (gravado?.justificativa ?? '').includes('rollback_done'),
338
+ // Ninguem HUMANO pontuou: quem decidiu foi o nucleo, e isso fica legivel.
339
+ avaliadoPor: gravado?.avaliadoPor ?? null,
340
+ depoisDeRepetir,
341
+ rollbacks,
342
+ // O evento e do catalogo do nucleo, nao string livre.
343
+ eventoNoCatalogo: ledger_1.TIPOS_DE_EVENTO.rollbackConcluido === 'rollback_done',
344
+ };
345
+ }
346
+ finally {
347
+ s.limpar();
348
+ }
349
+ },
350
+ };
351
+ /**
352
+ * fx-check-runtime-cruzado: quem valida nao pode ser quem executou.
353
+ *
354
+ * Esta e a VIGA (a) do Objective Envelope, a unica regra do produto que dizia isso, e
355
+ * ela estava presa dentro de um mecanismo que nunca rodou: valia na criacao do
356
+ * envelope, para tres threads com zero sessoes, e `validationRuntimes` nao aparecia em
357
+ * nenhum arquivo alem de `objective.ts` e `index.ts`.
358
+ *
359
+ * O regime que ela combate esta medido: das 137 threads, 16 registram sessoes de GO e
360
+ * de CHECK, e em 11 delas o CHECK rodou apenas em runtime que o GO tambem usou. As
361
+ * quatro threads mais recentes sao todas `claude-bg` conferindo `claude-bg`.
362
+ *
363
+ * O canario prova os TRES lados, porque so o positivo nao provaria nada:
364
+ * - a thread que EXIGE recusa o CHECK no runtime do GO, com motivo tipado;
365
+ * - a mesma thread ACEITA o CHECK em outro runtime;
366
+ * - a thread que NAO exige despacha normalmente, entao a regra nao vazou para quem
367
+ * nao pediu por ela.
368
+ */
369
+ const fxCheckRuntimeCruzado = {
370
+ id: 'fx-check-runtime-cruzado',
371
+ sobre: 'thread que exige validacao cruzada recusa o CHECK no mesmo runtime que entregou',
372
+ precisaDeGit: true,
373
+ rodar: () => {
374
+ const s = (0, sandbox_1.sandboxGit)('check-runtime-cruzado');
375
+ try {
376
+ /** Uma thread com uma sessao de GO ja registrada no runtime informado. */
377
+ const comGoEm = (nome, runtime, exige) => {
378
+ const t = (0, thread_1.novaThread)(s.carregado, { nome, modo: 'auto', exigeRuntimeDiferente: exige }).thread;
379
+ const emDisco = (0, thread_1.lerThread)(s.dir, t.id);
380
+ emDisco.faseAtual = 'CHECK';
381
+ emDisco.sessoes.push({ sessionId: `11111111-2222-3333-4444-${nome.padEnd(12, '0').slice(0, 12)}`,
382
+ slug: emDisco.slug, fase: 'GO', bloco: 'GO', runtime, despachadaEm: '2026-09-20T12:00:00.000Z',
383
+ promptPath: '', promptSha256: '', verificada: true });
384
+ (0, thread_1.gravarThread)(s.dir, emDisco);
385
+ return (0, thread_1.lerThread)(s.dir, emDisco.id);
386
+ };
387
+ const exigente = comGoEm('exigente', 'claude-bg', true);
388
+ const solta = comGoEm('solta', 'claude-bg', false);
389
+ const mesmoRuntime = (0, phase_1.runtimeCruzadoParaDespacho)(exigente, 'CHECK', 'claude-bg');
390
+ const outroRuntime = (0, phase_1.runtimeCruzadoParaDespacho)(exigente, 'CHECK', 'codex');
391
+ const semExigencia = (0, phase_1.runtimeCruzadoParaDespacho)(solta, 'CHECK', 'claude-bg');
392
+ // A regra vale no CHECK e so no CHECK: ela e sobre VALIDACAO.
393
+ const noGo = (0, phase_1.runtimeCruzadoParaDespacho)(exigente, 'GO', 'claude-bg');
394
+ return {
395
+ recusaMesmoRuntime: mesmoRuntime !== null,
396
+ // A recusa DIZ o que esta errado e o que destrava, com motivo tipado.
397
+ recusaTipada: (mesmoRuntime ?? '').startsWith('runtime.autoconferencia:'),
398
+ recusaNomeiaORuntimeDoGo: (mesmoRuntime ?? '').includes('claude-bg'),
399
+ recusaDizOQueDestrava: (mesmoRuntime ?? '').includes('outro runtime'),
400
+ aceitaOutroRuntime: outroRuntime === null,
401
+ semExigenciaDespacha: semExigencia === null,
402
+ naoVazaParaOGo: noGo === null,
403
+ // O motivo esta no catalogo e tem politica de retry declarada.
404
+ motivoNoCatalogo: gates_1.DESCRICAO_DO_MOTIVO['runtime.autoconferencia'] !== undefined,
405
+ semRetryAutomatico: retry_1.POLITICA_DE_RETRY['runtime.autoconferencia'].automatica === false,
406
+ escalaParaHumano: retry_1.POLITICA_DE_RETRY['runtime.autoconferencia'].acao === 'escalar-humano',
407
+ };
408
+ }
409
+ finally {
410
+ s.limpar();
411
+ }
412
+ },
413
+ };
414
+ /**
415
+ * fx-donewhen-executavel: criterio de pronto que FALHA reprova, e o veredito o nomeia.
416
+ *
417
+ * Esta e a VIGA (b) do Objective Envelope, e salva-la nao foi mover codigo: foi criar
418
+ * capacidade. Dentro do envelope, `doneWhen` era PROSA. `objective.ts:205` despejava
419
+ * os itens como lista no `SPEC.md` e NENHUM codigo os executava; os criterios do
420
+ * envelope real eram frases do tipo "D1: ork phase run recusa o despacho quando o
421
+ * objective da thread nao esta approved, com teste que cobre a recusa". Bonito, e
422
+ * impossivel de reprovar.
423
+ *
424
+ * O canario prova as duas metades, porque criterio que so passa nao prova nada:
425
+ * - o criterio que o comando SUSTENTA passa e a thread verifica;
426
+ * - o criterio que o comando NAO sustenta reprova, e o veredito diz QUAL criterio
427
+ * falhou, pela alegacao que a claim carrega.
428
+ *
429
+ * E prova a IDEMPOTENCIA: `ork verify` roda em toda fase, e uma claim por criterio
430
+ * por rodada transformaria a lista num acumulador em vez de uma verificacao.
431
+ */
432
+ const fxDoneWhenExecutavel = {
433
+ id: 'fx-donewhen-executavel',
434
+ sobre: 'criterio de pronto executavel reprova quando o comando falha, e o veredito o nomeia',
435
+ precisaDeGit: true,
436
+ rodar: () => {
437
+ const s = (0, sandbox_1.sandboxGit)('donewhen-executavel');
438
+ try {
439
+ const t = (0, thread_1.novaThread)(s.carregado, { nome: 'com criterio', modo: 'auto', doneWhen: [
440
+ { criterio: 'o README do projeto existe', comando: 'test -f README.md' },
441
+ { criterio: 'o arquivo prometido pela entrega existe', comando: 'test -f ENTREGA-QUE-NAO-EXISTE.md' },
442
+ ] }).thread;
443
+ // O verify roda os criterios como claims do nucleo, pela maquina que ja existe.
444
+ const antes = (0, verify_1.verificar)(s.carregado, t.id, { soClaims: true });
445
+ const claims = (0, claims_1.lerClaims)(s.dir, t.id);
446
+ const doNucleo = claims.filter((c) => c.origem === 'nucleo.doneWhen');
447
+ const reprovada = antes.claims.find((c) => !c.verificado);
448
+ // Idempotente: verificar de novo nao cria claim nova.
449
+ (0, verify_1.verificar)(s.carregado, t.id, { soClaims: true });
450
+ const depoisDeRepetir = (0, claims_1.lerClaims)(s.dir, t.id).filter((c) => c.origem === 'nucleo.doneWhen').length;
451
+ // A metade que passa: o criterio sustentado pelo comando verifica.
452
+ const passou = antes.claims.find((c) => c.claim.alegacao.includes('README do projeto existe'));
453
+ return {
454
+ criteriosViraramClaim: doNucleo.length,
455
+ naoDuplicaAoRepetir: depoisDeRepetir === doNucleo.length,
456
+ // A thread REPROVA quando um criterio nao se sustenta.
457
+ verifyReprovou: antes.ok === false,
458
+ motivoTipado: antes.motivos.includes('claims.failed'),
459
+ // E o veredito NOMEIA o criterio, porque a claim carrega o texto dele.
460
+ vereditoNomeiaOCriterio: (reprovada?.claim.alegacao ?? '').includes('o arquivo prometido pela entrega existe'),
461
+ // A metade que passa continua passando: a regra nao reprova por reprovar.
462
+ criterioSustentadoPassa: passou?.verificado === true,
463
+ // A claim do nucleo e distinguivel de auto-relato de agente.
464
+ marcadaComoDoNucleo: doNucleo.every((c) => c.origem === 'nucleo.doneWhen'),
465
+ };
466
+ }
467
+ finally {
468
+ s.limpar();
469
+ }
470
+ },
471
+ };
472
+ /**
473
+ * fx-adapter-editado-detectado: a copia editada a mao continua sendo PEGA.
474
+ *
475
+ * R1 do GOAL chama esta de a remocao com maior risco, e pelo motivo certo: a cerimonia
476
+ * de instalacao e o unico mecanismo que pega uma copia instalada editada a mao, e
477
+ * nenhum teste da suite alcanca isso, porque a suite roda sobre o CATALOGO e nao sobre
478
+ * a copia. Trocar uma recusa barulhenta por nada seria trocar investigacao de
479
+ * madrugada por defeito que ninguem ve.
480
+ *
481
+ * O que muda e o que BARRA, nao o que DETECTA. O canario cobra os dois lados:
482
+ * - a copia editada e detectada, NOMEADA, e classificada como `copia-editada`;
483
+ * - a divergencia segura (`catalogo-andou`) resolve sozinha e nao vira decisao;
484
+ * - a saida traz o `diff` do arquivo e um caminho de UM comando, com o `--dir` em
485
+ * uso repetido. A linha antiga mandava rodar `--force` SEM o `--dir`, e rodar o
486
+ * que estava na tela instalaria no lugar errado.
487
+ */
488
+ const fxAdapterEditadoDetectado = {
489
+ id: 'fx-adapter-editado-detectado',
490
+ sobre: 'copia de adapter editada fora do catalogo continua detectada e nomeada, com saida de um comando',
491
+ precisaDeGit: false,
492
+ rodar: (ctx) => {
493
+ const destino = (0, sandbox_1.dirTemporario)('adapter-editado');
494
+ try {
495
+ const comum = { projeto: destino, dir: '.', catalogo: ctx.catalogo, versao: '0.0.0-canario' };
496
+ // 1. Instalacao limpa: nasce o recibo com o sha de cada arquivo.
497
+ const primeira = (0, hosts_1.instalarAdaptador)('hermes', comum);
498
+ const recibo = (0, hosts_1.lerRecibo)(destino);
499
+ // 2. Reinstalar sem mexer em nada nao acusa divergencia nenhuma.
500
+ const semMexer = (0, hosts_1.instalarAdaptador)('hermes', { ...comum, dryRun: true });
501
+ // 3. Alguem edita a COPIA instalada, que e o defeito que a suite nao alcanca.
502
+ const alvo = primeira.arquivos.find((a) => a.relativo.endsWith('README.md'));
503
+ fs.writeFileSync(alvo.destino, fs.readFileSync(alvo.destino, 'utf8') + '\n<!-- editado a mao -->\n');
504
+ const depois = (0, hosts_1.instalarAdaptador)('hermes', { ...comum, dryRun: true });
505
+ const achado = depois.conflitos.find((a) => a.relativo === alvo.relativo);
506
+ const texto = (0, hosts_1.textoDaInstalacao)(depois);
507
+ // 4. E a resolucao e de UM comando, por arquivo.
508
+ const resolvido = (0, hosts_1.instalarAdaptador)('hermes', {
509
+ ...comum, dryRun: true, aceitarCatalogo: [alvo.relativo],
510
+ });
511
+ return {
512
+ // A instalacao limpa nao inventa divergencia.
513
+ semDivergenciaAoInstalar: primeira.conflitos.length === 0,
514
+ reciboGravado: (recibo?.arquivos.length ?? 0) > 0,
515
+ reinstalarNaoAcusa: semMexer.conflitos.length === 0 && semMexer.ok,
516
+ // A copia editada e DETECTADA, NOMEADA e CLASSIFICADA.
517
+ detectouAEdicao: achado !== undefined,
518
+ nomeiaOArquivo: texto.includes(alvo.relativo),
519
+ classificouComoCopiaEditada: achado?.divergencia === 'copia-editada',
520
+ // E ela BARRA, porque `copia-editada` e justamente o que nao se resolve sozinho.
521
+ barrouSemDecisao: depois.ok === false,
522
+ // A saida traz o diff e o caminho de um comando, com o --dir em uso.
523
+ temDiffNaSaida: texto.includes('$ diff -u'),
524
+ temUmComando: texto.includes('--aceitar-catalogo') && texto.includes('--manter-copia'),
525
+ naoOfereceForce: !texto.includes('--force'),
526
+ // Decidido o arquivo, o comando deixa de barrar.
527
+ umComandoResolve: resolvido.ok === true,
528
+ };
529
+ }
530
+ finally {
531
+ fs.rmSync(destino, { recursive: true, force: true });
532
+ }
533
+ },
534
+ };
535
+ exports.CANARIOS_I43 = [
536
+ fxModoAposentadoLeitor,
537
+ fxModoAposentadoEscritor,
538
+ fxListagemAbertas,
539
+ fxIndiceReversao,
540
+ fxCheckRuntimeCruzado,
541
+ fxDoneWhenExecutavel,
542
+ fxAdapterEditadoDetectado,
543
+ ];