@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
package/dist/verify.js CHANGED
@@ -13,8 +13,13 @@
13
13
  * declarada como `verify.failed`, e nao como regressao que nao da para provar.
14
14
  */
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.TIMEOUT_VERIFY_MS = void 0;
16
+ exports.PREFIXO_BLOQUEADO_NO_VERIFY = exports.TIMEOUT_VERIFY_MS = void 0;
17
+ exports.ambienteDoVerify = ambienteDoVerify;
18
+ exports.prazoDoComando = prazoDoComando;
17
19
  exports.executar = executar;
20
+ exports.identidadeDoProduto = identidadeDoProduto;
21
+ exports.causaDoEncerramento = causaDoEncerramento;
22
+ exports.comandoNoLedger = comandoNoLedger;
18
23
  exports.comandosDoManifesto = comandosDoManifesto;
19
24
  exports.cwdDaThread = cwdDaThread;
20
25
  exports.commitReal = commitReal;
@@ -26,7 +31,14 @@ const claims_1 = require("./claims");
26
31
  const gates_1 = require("./gates");
27
32
  const ledger_1 = require("./ledger");
28
33
  const thread_1 = require("./thread");
34
+ const node_fs_1 = require("node:fs");
35
+ const node_path_1 = require("node:path");
36
+ const node_crypto_1 = require("node:crypto");
29
37
  const util_1 = require("./util");
38
+ const horario_1 = require("./horario");
39
+ const redacao_saida_1 = require("./redacao-saida");
40
+ const redacao_url_1 = require("./redacao-url");
41
+ const conducao_1 = require("./conducao");
30
42
  /** Teto de tempo de um comando de verificacao (build e suite completa cabem). */
31
43
  exports.TIMEOUT_VERIFY_MS = 10 * 60 * 1000;
32
44
  /** Ultimas linhas da saida real, o suficiente para servir de evidencia no ledger. */
@@ -35,15 +47,123 @@ function resumirSaida(stdout, stderr) {
35
47
  const linhas = bruto.split('\n').filter((l) => l.trim() !== '');
36
48
  return linhas.slice(-10).join('\n').slice(-800);
37
49
  }
38
- /** Executa um comando de verificacao pelo shell, no diretorio de trabalho da thread. */
39
- function executar(nome, comando, cwd) {
40
- const r = (0, util_1.exec)('bash', ['-c', comando], cwd, exports.TIMEOUT_VERIFY_MS);
41
- return {
50
+ /** `timeout(1)` (GNU coreutils ou uutils): no estouro sinaliza o GRUPO de processos
51
+ * inteiro, nao so o filho direto. Os dois se poem no proprio grupo e devolvem 124. */
52
+ const TIMEOUT_BIN = '/usr/bin/timeout';
53
+ /**
54
+ * I-37 (D5, D6, D7): o comando de verificacao nunca herda a autoridade HITL.
55
+ *
56
+ * Um comando que prova uma alegacao nao pode agir como o dono: com a chave de ingresso e os
57
+ * ids do canal no ambiente, ele conseguiria responder um gate. Sai todo `ORK_HITL_*` (as seis
58
+ * variaveis do PLAN mais as do OpenClaw, que vieram depois), so no executor de verify, e sem
59
+ * valvula de escape: comando que precise delas vira escalacao para humano.
60
+ */
61
+ exports.PREFIXO_BLOQUEADO_NO_VERIFY = 'ORK_HITL_';
62
+ function ambienteDoVerify(base = process.env) {
63
+ return Object.fromEntries(Object.entries(base).filter(([chave]) => !chave.startsWith(exports.PREFIXO_BLOQUEADO_NO_VERIFY)));
64
+ }
65
+ /** I-37 (D2): o prazo de um comando, resolvido uma vez por rodada (D3). */
66
+ function prazoDoComando(manifesto, nome) {
67
+ const porComando = manifesto.verify.timeout_ms_por_comando;
68
+ return porComando?.[nome] ?? manifesto.verify.timeout_ms ?? exports.TIMEOUT_VERIFY_MS;
69
+ }
70
+ /**
71
+ * Executa um comando de verificacao pelo shell, no diretorio de trabalho da thread.
72
+ *
73
+ * O `exec` sozinho mata so o `bash` quando estoura o teto: npm, tsc e node --test
74
+ * ficavam orfaos, rodando sem dono. Em 21/09/2026 isso acumulou ate 38 builds de teste
75
+ * presos e travou a VPS. Com o `timeout` na frente, o estouro leva a arvore inteira; e se
76
+ * o proprio `ork` morrer no meio, o `timeout` segue de pe e encerra o grupo no prazo.
77
+ * O estouro continua saindo como `code: -1`, o contrato de antes.
78
+ */
79
+ function executar(nome, comando, cwd, tetoMs = exports.TIMEOUT_VERIFY_MS) {
80
+ const comGrupo = (0, node_fs_1.existsSync)(TIMEOUT_BIN);
81
+ const inicio = Date.now();
82
+ const ambiente = ambienteDoVerify();
83
+ const r = comGrupo
84
+ ? (0, util_1.exec)(TIMEOUT_BIN, ['--kill-after=15', `${Math.ceil(tetoMs / 1000)}`, 'bash', '-c', comando], cwd, tetoMs + 30_000, ambiente)
85
+ : (0, util_1.exec)('bash', ['-c', comando], cwd, tetoMs, ambiente);
86
+ const duracaoMs = Date.now() - inicio;
87
+ const causa = causaDoEncerramento({ code: r.code, signal: r.signal ?? null, error: r.error, comGrupo, duracaoMs, tetoMs });
88
+ const estourou = causa === 'timeout';
89
+ const resultado = {
42
90
  nome,
43
91
  comando,
44
92
  ok: r.ok,
45
- code: r.code,
93
+ code: estourou ? -1 : r.code,
46
94
  resumo: resumirSaida(r.stdout, r.stderr),
95
+ causa,
96
+ prazoMs: tetoMs,
97
+ duracaoMs,
98
+ // I-54 (D11): so nao rodou o que o sistema recusou lancar; estouro e sinal rodaram e acabaram.
99
+ executado: !(r.error && NAO_LANCADO.has(r.error)),
100
+ };
101
+ if (!r.ok) {
102
+ const saida = r.stdout + (r.stderr ? '\n' + r.stderr : '');
103
+ const testes = (0, redacao_saida_1.testesQueCairam)(saida);
104
+ if (testes.length > 0)
105
+ resultado.testeQueCaiu = testes;
106
+ resultado.trecho = (0, redacao_saida_1.redigirSaida)(saida);
107
+ }
108
+ return resultado;
109
+ }
110
+ /** I-54 (D11): erros de spawn em que o processo nem chegou a existir. */
111
+ const NAO_LANCADO = new Set(['ENOENT', 'EACCES', 'EAGAIN', 'ENOMEM', 'EPERM', 'EMFILE']);
112
+ /**
113
+ * I-54 (RM-037, D11): a identidade do produto que a rodada verifica. HEAD, o diff contra ele e o
114
+ * conteudo dos arquivos nao rastreados (o que o `.gitignore` exclui, como `dist/`, fica fora). O
115
+ * mtime nao entra: `touch` o engana, e identidade e conteudo. O `.orkastery/` fica fora sempre: e
116
+ * o estado do proprio `ork` (ledger, claims), que a rodada escreve enquanto verifica.
117
+ */
118
+ const FORA_DO_PRODUTO = [':(exclude).orkastery'];
119
+ function identidadeDoProduto(cwd) {
120
+ const h = (0, node_crypto_1.createHash)('sha256');
121
+ h.update((0, util_1.exec)('git', ['rev-parse', 'HEAD'], cwd).stdout);
122
+ h.update((0, util_1.exec)('git', ['diff', 'HEAD', '--no-ext-diff', '--binary', '--', '.', ...FORA_DO_PRODUTO], cwd).stdout);
123
+ const soltos = (0, util_1.exec)('git', ['ls-files', '--others', '--exclude-standard', '-z', '--', '.', ...FORA_DO_PRODUTO], cwd).stdout
124
+ .split('\0').filter(Boolean).sort();
125
+ for (const arquivo of soltos) {
126
+ h.update(arquivo + '\0');
127
+ try {
128
+ h.update((0, node_fs_1.readFileSync)((0, node_path_1.join)(cwd, arquivo)));
129
+ }
130
+ catch {
131
+ h.update('<ilegivel>');
132
+ }
133
+ }
134
+ return h.digest('hex');
135
+ }
136
+ /**
137
+ * I-37 (T3): por que o comando terminou, a partir do que o processo devolveu.
138
+ *
139
+ * Pelo `timeout(1)`, 124 e o estouro e 137 o SIGKILL do `--kill-after`, e so contam como
140
+ * estouro quando o tempo corrido chegou ao prazo. Sem ele, o proprio spawnSync mata por prazo e
141
+ * devolve `ETIMEDOUT`. Comando que o shell nao achou sai 127. Morte por sinal aparece no
142
+ * `signal` do processo ou, no GNU `timeout`, como 128 + sinal (o uutils devolve so o numero,
143
+ * que fica indistinguivel de um `exit` e e tratado como tal).
144
+ */
145
+ function causaDoEncerramento(r) {
146
+ const estourou = (r.comGrupo && (r.code === 124 || r.code === 137) && r.duracaoMs >= r.tetoMs - 1000)
147
+ || (!r.comGrupo && r.error === 'ETIMEDOUT');
148
+ if (estourou)
149
+ return 'timeout';
150
+ if (r.error === 'ENOENT' || r.code === 127)
151
+ return 'nao-encontrado';
152
+ if (r.signal || (r.comGrupo && r.code > 128 && r.code < 160))
153
+ return 'sinal';
154
+ return 'exit';
155
+ }
156
+ /** I-37 (D8): o que o ledger grava de um comando. Sucesso e o codigo 0; falha leva a evidencia. */
157
+ function comandoNoLedger(c) {
158
+ if (c.ok)
159
+ return { nome: c.nome, ok: true, code: c.code };
160
+ return {
161
+ nome: c.nome, comando: (0, redacao_url_1.redigirCredenciaisUrl)(c.comando), ok: false, code: c.code,
162
+ ...(c.causa ? { causa: c.causa } : {}),
163
+ ...(c.prazoMs !== undefined ? { prazoMs: c.prazoMs } : {}),
164
+ ...(c.duracaoMs !== undefined ? { duracaoMs: c.duracaoMs } : {}),
165
+ ...(c.testeQueCaiu?.length ? { testeQueCaiu: c.testeQueCaiu } : {}),
166
+ ...(c.trecho !== undefined ? { trecho: c.trecho } : {}),
47
167
  };
48
168
  }
49
169
  /** Comandos declarados em `verify:` no manifesto, na ordem canonica. */
@@ -65,12 +185,34 @@ function commitReal(cwd) {
65
185
  const r = (0, util_1.exec)('git', ['rev-parse', 'HEAD'], cwd);
66
186
  return r.ok ? r.stdout.trim() : 'desconhecido';
67
187
  }
188
+ /** O pedido de conducao de uma verificacao, com o prazo derivado dos comandos que ela vai rodar (D3). */
189
+ function pedidoDoVerify(carregado, threadId, operacao, comandos, conducao) {
190
+ return {
191
+ canal: conducao.canal ?? (0, conducao_1.canalDoProcesso)(),
192
+ correlacao: conducao.correlacao ?? null,
193
+ operacao,
194
+ identidade: conducao.identidade ?? (0, conducao_1.identidadeDoAmbiente)(threadId),
195
+ prazoMs: (0, conducao_1.prazoDaVerificacao)(carregado.manifesto.verify.timeout_ms ?? exports.TIMEOUT_VERIFY_MS, comandos),
196
+ esperarMs: conducao.esperarMs,
197
+ };
198
+ }
199
+ /** O executor que renova o prazo da conducao antes de cada comando (D3). */
200
+ function executorSobConducao(base, manifesto, conducao) {
201
+ return (nome, comando, cwd) => {
202
+ conducao.renovar(prazoDoComando(manifesto, nome));
203
+ return base(nome, comando, cwd);
204
+ };
205
+ }
68
206
  /** `ork verify --baseline`: grava o estado do mundo ANTES do GO. */
69
- function gravarBaseline(carregado, threadId) {
207
+ function gravarBaseline(carregado, threadId, executor = executar, conducao = {}) {
208
+ const pedido = pedidoDoVerify(carregado, threadId, 'baseline', comandosDoManifesto(carregado.manifesto).length, conducao);
209
+ return (0, conducao_1.comConducao)(carregado.raiz, threadId, pedido, (tomada) => gravarBaselineSobConducao(carregado, threadId, executorSobConducao(executor, carregado.manifesto, tomada)));
210
+ }
211
+ function gravarBaselineSobConducao(carregado, threadId, executor) {
70
212
  const { raiz, manifesto } = carregado;
71
213
  const thread = (0, thread_1.lerThread)(raiz, threadId);
72
214
  const cwd = cwdDaThread(raiz, thread);
73
- const comandos = comandosDoManifesto(manifesto).map((c) => executar(c.nome, c.comando, cwd));
215
+ const comandos = comandosDoManifesto(manifesto).map((c) => executor(c.nome, c.comando, cwd));
74
216
  const baseline = { commit: commitReal(cwd), gravadaEm: (0, util_1.agora)(), comandos };
75
217
  thread.baseline = baseline;
76
218
  (0, thread_1.gravarThread)(raiz, thread);
@@ -88,7 +230,7 @@ function gravarBaseline(carregado, threadId) {
88
230
  * Exportada para o bloco B5: as claims dos ACHADOS de auditoria passam por este mesmo
89
231
  * julgamento, sem uma segunda regra paralela que pudesse ser mais frouxa.
90
232
  */
91
- function verificarClaim(claim, cwd) {
233
+ function verificarClaim(claim, cwd, executor = executar) {
92
234
  if (claim.verificar.length === 0) {
93
235
  const negativa = claim.negativa;
94
236
  return {
@@ -102,14 +244,29 @@ function verificarClaim(claim, cwd) {
102
244
  execucoes: [],
103
245
  };
104
246
  }
105
- const execucoes = claim.verificar.map((c, i) => executar(`${claim.id}.${i + 1}`, c, cwd));
247
+ const execucoes = claim.verificar.map((c, i) => executor(`${claim.id}.${i + 1}`, c, cwd));
248
+ // I-54 (D11): comando que nao rodou nao tem veredito, e lista vazia de execucao nunca aprova.
249
+ const naoRodou = execucoes.find((e) => e.executado === false);
250
+ if (naoRodou) {
251
+ return {
252
+ claim,
253
+ verificado: false,
254
+ motivo: 'verify.sem-veredito',
255
+ detalhe: `comando "${(0, redacao_url_1.redigirCredenciaisUrl)(naoRodou.comando)}" nao foi executado: ${naoRodou.resumo}`,
256
+ execucoes,
257
+ };
258
+ }
106
259
  const falhou = execucoes.find((e) => !e.ok);
260
+ // I-37 (D1): estouro de prazo nao desmente a alegacao; a prova so nao chegou ao fim.
261
+ const estourou = falhou?.causa === 'timeout';
107
262
  return {
108
263
  claim,
109
264
  verificado: !falhou,
110
- motivo: falhou ? 'claims.failed' : null,
265
+ motivo: falhou ? (estourou ? 'verify.timeout' : 'claims.failed') : null,
111
266
  detalhe: falhou
112
- ? `comando "${falhou.comando}" saiu com codigo ${falhou.code}`
267
+ ? estourou
268
+ ? `comando "${falhou.comando}" estourou o prazo de ${Math.round((falhou.prazoMs ?? 0) / 1000)} s sem terminar`
269
+ : `comando "${(0, redacao_url_1.redigirCredenciaisUrl)(falhou.comando)}" saiu com codigo ${falhou.code}`
113
270
  : `${execucoes.length} comando(s) reexecutado(s) com sucesso`,
114
271
  execucoes,
115
272
  };
@@ -119,16 +276,42 @@ function verificarClaim(claim, cwd) {
119
276
  * Nao decide pausa, decide VERDADE: quem pausa e o gate do modo de conducao.
120
277
  */
121
278
  function verificar(carregado, threadId, opcoes = {}) {
279
+ // I-36 (T4): sem a conducao da thread, nenhum comando roda; a recusa sai tipada, com quem conduz.
280
+ const planejados = (0, claims_1.lerClaims)(carregado.raiz, threadId).filter((c) => c.estado !== 'retirada')
281
+ .reduce((n, c) => n + c.verificar.length, 0) + (opcoes.soClaims ? 0 : comandosDoManifesto(carregado.manifesto).length) + 1;
282
+ const pedido = pedidoDoVerify(carregado, threadId, opcoes.operacao ?? 'verify', planejados, opcoes.conducao ?? {});
283
+ return (0, conducao_1.comConducao)(carregado.raiz, threadId, pedido, (tomada) => verificarSobConducao(carregado, threadId, opcoes, tomada, pedido.canal));
284
+ }
285
+ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal) {
122
286
  const { raiz, manifesto } = carregado;
123
287
  const thread = (0, thread_1.lerThread)(raiz, threadId);
124
288
  const cwd = cwdDaThread(raiz, thread);
125
289
  const commit = commitReal(cwd);
126
290
  const dir = (0, thread_1.dirThread)(raiz, threadId);
291
+ // I-43 (D4, viga b): os criterios de pronto da thread viram claims do nucleo ANTES
292
+ // da reexecucao, para entrarem no MESMO veredito das demais alegacoes. Idempotente:
293
+ // `ork verify` roda em toda fase, e uma claim por criterio por rodada viraria
294
+ // acumulador em vez de verificacao.
295
+ (0, claims_1.registrarCriteriosDePronto)(raiz, threadId);
296
+ // I-37 (D2, D3): o prazo de cada comando sai do manifesto carregado no inicio da rodada;
297
+ // editar o manifesto no meio dela nao muda o teto de quem ainda vai rodar.
298
+ const executor = executorSobConducao(opcoes.executor
299
+ ?? ((nome, comando, dirDeTrabalho) => executar(nome, comando, dirDeTrabalho, prazoDoComando(manifesto, nome))), manifesto, conducao);
300
+ // I-54 (D10): o preparo roda UMA vez, antes das claims. Ele nunca e condicao para uma claim
301
+ // passar (cada uma roda o proprio comando inteiro); ele so deixa pronta a compilacao. A
302
+ // identidade do produto e tomada logo depois dele e conferida no fim da rodada.
303
+ const preparo = manifesto.verify.preparo ? (() => {
304
+ const resultado = executor('preparo', manifesto.verify.preparo, cwd);
305
+ return { resultado, identidade: identidadeDoProduto(cwd) };
306
+ })() : null;
127
307
  // Claim retirada sai do gate: o historico guarda a alegacao e o motivo da retirada.
128
308
  const claims = (0, claims_1.lerClaims)(raiz, threadId)
129
309
  .filter((c) => c.estado !== 'retirada')
130
- .map((c) => verificarClaim(c, cwd));
310
+ .map((c) => verificarClaim(c, cwd, executor));
131
311
  for (const r of claims) {
312
+ // Estouro de prazo e comando que nao rodou nao julgam a alegacao: o estado anterior vale.
313
+ if (r.motivo === 'verify.timeout' || r.motivo === 'verify.sem-veredito')
314
+ continue;
132
315
  const estado = r.verificado
133
316
  ? 'verificado'
134
317
  : r.motivo === 'claims.unverifiable'
@@ -139,14 +322,19 @@ function verificar(carregado, threadId, opcoes = {}) {
139
322
  }
140
323
  const comandos = opcoes.soClaims
141
324
  ? []
142
- : comandosDoManifesto(manifesto).map((c) => executar(c.nome, c.comando, cwd));
325
+ : comandosDoManifesto(manifesto).map((c) => executor(c.nome, c.comando, cwd));
143
326
  const baseline = thread.baseline ?? null;
144
327
  const regressoes = [];
145
328
  const preExistentes = [];
146
329
  const falhasSemBaseline = [];
330
+ const estouros = [];
147
331
  for (const atual of comandos) {
148
332
  if (atual.ok)
149
333
  continue;
334
+ if (atual.causa === 'timeout') {
335
+ estouros.push(atual);
336
+ continue;
337
+ }
150
338
  const antes = baseline?.comandos.find((c) => c.nome === atual.nome);
151
339
  if (!antes)
152
340
  falhasSemBaseline.push(atual);
@@ -155,6 +343,10 @@ function verificar(carregado, threadId, opcoes = {}) {
155
343
  else
156
344
  preExistentes.push(atual);
157
345
  }
346
+ // I-54 (D11): o produto mudou entre o preparo e o fim da rodada? Entao nenhum veredito vale.
347
+ const identidadeFinal = preparo ? identidadeDoProduto(cwd) : null;
348
+ const produtoAlterado = !!preparo && identidadeFinal !== preparo.identidade;
349
+ const naoExecutados = comandos.filter((c) => c.executado === false);
158
350
  const motivos = [];
159
351
  if (claims.some((c) => c.motivo === 'claims.failed'))
160
352
  motivos.push('claims.failed');
@@ -164,24 +356,40 @@ function verificar(carregado, threadId, opcoes = {}) {
164
356
  motivos.push('verify.regression');
165
357
  if (falhasSemBaseline.length > 0)
166
358
  motivos.push('verify.failed');
359
+ if (estouros.length > 0 || claims.some((c) => c.motivo === 'verify.timeout'))
360
+ motivos.push('verify.timeout');
361
+ if (produtoAlterado || naoExecutados.length > 0 || claims.some((c) => c.motivo === 'verify.sem-veredito')) {
362
+ motivos.push('verify.sem-veredito');
363
+ }
167
364
  const bloqueantes = motivos.filter((m) => m !== 'claims.unverifiable');
168
365
  const ok = bloqueantes.length === 0;
169
366
  (0, ledger_1.registrar)(dir, threadId, ledger_1.TIPOS_DE_EVENTO.verificacao, {
170
367
  commit,
171
368
  cwd,
172
- claims: claims.map((c) => ({
173
- id: c.claim.id,
174
- verificado: c.verificado,
175
- motivo: c.motivo,
176
- detalhe: c.detalhe,
177
- })),
178
- comandos: comandos.map((c) => ({ nome: c.nome, ok: c.ok, code: c.code })),
369
+ claims: claims.map((c) => {
370
+ const falhou = c.execucoes.find((e) => !e.ok);
371
+ return {
372
+ id: c.claim.id,
373
+ verificado: c.verificado,
374
+ motivo: c.motivo,
375
+ detalhe: c.detalhe,
376
+ ...(falhou ? { execucao: comandoNoLedger(falhou) } : {}),
377
+ };
378
+ }),
379
+ comandos: comandos.map(comandoNoLedger),
179
380
  baseline: baseline ? { commit: baseline.commit, gravadaEm: baseline.gravadaEm } : null,
180
381
  regressoes: regressoes.map((r) => r.nome),
181
382
  preExistentes: preExistentes.map((r) => r.nome),
182
383
  falhasSemBaseline: falhasSemBaseline.map((r) => r.nome),
384
+ estouros: estouros.map((r) => r.nome),
385
+ prazoMs: manifesto.verify.timeout_ms ?? exports.TIMEOUT_VERIFY_MS,
386
+ ...(preparo ? { preparo: { ...comandoNoLedger(preparo.resultado), duracaoMs: preparo.resultado.duracaoMs,
387
+ identidade: preparo.identidade.slice(0, 16), identidadeFinal: identidadeFinal.slice(0, 16), produtoAlterado } } : {}),
183
388
  motivos,
184
389
  veredito: ok ? 'verdade sustentada' : 'reprovado',
390
+ // I-36: por qual canal a verificacao chegou; a reentrada da sessao que conduz aparece aqui.
391
+ canal,
392
+ conducao: { identidade: conducao.identidade, reentrada: conducao.reentrada },
185
393
  });
186
394
  for (const motivo of bloqueantes) {
187
395
  (0, gates_1.registrarGateBloqueado)(dir, threadId, {
@@ -195,11 +403,23 @@ function verificar(carregado, threadId, opcoes = {}) {
195
403
  .join('; ')
196
404
  : motivo === 'verify.regression'
197
405
  ? `regressao em: ${regressoes.map((r) => r.nome).join(', ')}`
198
- : `falha sem baseline em: ${falhasSemBaseline.map((r) => r.nome).join(', ')}`,
406
+ : motivo === 'verify.timeout'
407
+ ? `estourou o prazo sem terminar: ${[...estouros.map((r) => r.nome),
408
+ ...claims.filter((c) => c.motivo === 'verify.timeout').map((c) => c.claim.id)].join(', ')}`
409
+ : motivo === 'verify.sem-veredito'
410
+ ? [produtoAlterado ? 'o produto mudou entre o preparo e o fim da rodada' : '',
411
+ ...naoExecutados.map((c) => `${c.nome} nao foi executado`),
412
+ ...claims.filter((c) => c.motivo === 'verify.sem-veredito').map((c) => `${c.claim.id}: ${c.detalhe}`)]
413
+ .filter(Boolean).join('; ')
414
+ : `falha sem baseline em: ${falhasSemBaseline.map((r) => r.nome).join(', ')}`,
199
415
  evidencia: `reexecucao no HEAD ${commit} em ${cwd}`,
200
416
  correcao: motivo === 'claims.failed'
201
417
  ? 'corrija o artefato ou a alegacao e rode `ork verify` de novo'
202
- : 'corrija a regressao, ou grave a baseline antes do GO com `ork verify <thread> --baseline`',
418
+ : motivo === 'verify.timeout'
419
+ ? 'rode `ork verify` de novo; se estourar sempre, suba verify.timeout_ms no manifesto ou divida o comando'
420
+ : motivo === 'verify.sem-veredito'
421
+ ? 'rode `ork verify` de novo, sem editar a worktree durante a rodada'
422
+ : 'corrija a regressao, ou grave a baseline antes do GO com `ork verify <thread> --baseline`',
203
423
  });
204
424
  }
205
425
  return {
@@ -212,17 +432,36 @@ function verificar(carregado, threadId, opcoes = {}) {
212
432
  regressoes,
213
433
  preExistentes,
214
434
  falhasSemBaseline,
435
+ estouros,
436
+ preparo: preparo ? { ...preparo, identidadeFinal: identidadeFinal, produtoAlterado } : null,
215
437
  motivos,
216
438
  ok,
217
439
  };
218
440
  }
441
+ /** `FALHOU (codigo 1)`, ou `ESTOUROU O PRAZO (600 s, rodou 612 s)`: a causa e dita pelo nome. */
442
+ function situacaoDoComando(c) {
443
+ const s = (ms) => `${Math.round((ms ?? 0) / 1000)} s`;
444
+ if (c.causa === 'timeout')
445
+ return `ESTOUROU O PRAZO (${s(c.prazoMs)}, rodou ${s(c.duracaoMs)})`;
446
+ if (c.causa === 'nao-encontrado')
447
+ return `NAO EXECUTOU (comando nao encontrado, codigo ${c.code})`;
448
+ if (c.causa === 'sinal')
449
+ return `MORTO POR SINAL (codigo ${c.code})`;
450
+ return `FALHOU (codigo ${c.code})`;
451
+ }
219
452
  /** Texto de `ork verify`. */
220
453
  function textoDoVerify(r) {
221
454
  const linhas = [];
222
455
  linhas.push(`ork verify da thread ${r.thread}`);
223
456
  linhas.push(` HEAD real ${r.commit}`);
224
457
  linhas.push(` diretorio ${r.cwd}`);
225
- linhas.push(` baseline ${r.baseline ? `${r.baseline.commit.slice(0, 8)} de ${r.baseline.gravadaEm}` : '(nao gravada: falha nao pode ser chamada de regressao)'}`);
458
+ linhas.push(` baseline ${r.baseline ? `${r.baseline.commit.slice(0, 8)} de ${(0, horario_1.formatarDataHoraRotulada)(r.baseline.gravadaEm)}` : '(nao gravada: falha nao pode ser chamada de regressao)'}`);
459
+ if (r.preparo) {
460
+ const p = r.preparo;
461
+ linhas.push(` preparo ${p.resultado.ok ? 'ok' : situacaoDoComando(p.resultado)} em ` +
462
+ `${Math.round((p.resultado.duracaoMs ?? 0) / 1000)} s, uma vez para a rodada; produto ` +
463
+ `${p.produtoAlterado ? 'MUDOU no meio da rodada: nenhum veredito vale' : 'conferido do preparo ao fim'}`);
464
+ }
226
465
  linhas.push('');
227
466
  linhas.push('Claims reexecutadas no HEAD real:');
228
467
  if (r.claims.length === 0) {
@@ -239,9 +478,15 @@ function textoDoVerify(r) {
239
478
  linhas.push('');
240
479
  linhas.push('Comandos de verify do manifesto:');
241
480
  for (const c of r.comandos) {
242
- linhas.push(` ${c.nome.padEnd(10)} ${c.ok ? 'ok' : `FALHOU (codigo ${c.code})`} ${c.comando}`);
481
+ linhas.push(` ${c.nome.padEnd(10)} ${c.ok ? 'ok' : situacaoDoComando(c)} ${c.comando}`);
482
+ if (!c.ok && c.testeQueCaiu?.length)
483
+ linhas.push(` teste(s) que caiu(ram): ${c.testeQueCaiu.join('; ')}`);
243
484
  }
244
485
  }
486
+ if (r.estouros.length > 0) {
487
+ linhas.push('');
488
+ linhas.push(`Estouro de prazo (nao e reprovacao, a prova nao terminou): ${r.estouros.map((c) => c.nome).join(', ')}`);
489
+ }
245
490
  if (r.regressoes.length > 0 || r.preExistentes.length > 0 || r.falhasSemBaseline.length > 0) {
246
491
  linhas.push('');
247
492
  linhas.push(`Classificacao: ${r.regressoes.length} regressao(oes), ` +
package/dist/versao.js ADDED
@@ -0,0 +1,60 @@
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.VERSAO_DO_ORK = exports.NOME_DO_PACOTE = void 0;
37
+ /**
38
+ * A versao do `ork`, lida do package.json que viaja com o pacote.
39
+ *
40
+ * Havia um literal por superficie (CLI, servidor MCP, recibo de instalacao de adaptador), e cada
41
+ * um precisava lembrar da publicacao seguinte. O package.json e a unica fonte: no repositorio ele
42
+ * fica em `core/`, e no pacote npm ao lado de `dist/`, sempre um nivel acima do arquivo compilado.
43
+ * A arvore de teste (`dist-test/src/`) fica dois niveis abaixo, por isso o segundo candidato.
44
+ */
45
+ const fs = __importStar(require("node:fs"));
46
+ const path = __importStar(require("node:path"));
47
+ exports.NOME_DO_PACOTE = '@orkastery/cli';
48
+ function lerVersao() {
49
+ for (const candidato of [path.join(__dirname, '..', 'package.json'), path.join(__dirname, '..', '..', 'package.json')]) {
50
+ try {
51
+ const pacote = JSON.parse(fs.readFileSync(candidato, 'utf8'));
52
+ if (pacote.name === exports.NOME_DO_PACOTE && typeof pacote.version === 'string')
53
+ return pacote.version;
54
+ }
55
+ catch { /* tenta o proximo candidato */ }
56
+ }
57
+ return '0.0.0-desconhecida';
58
+ }
59
+ /** A versao publicada em `@orkastery/cli`, a mesma do `version` do package.json. */
60
+ exports.VERSAO_DO_ORK = lerVersao();
package/dist/worktree.js CHANGED
@@ -62,6 +62,7 @@ const ledger_1 = require("./ledger");
62
62
  const leases_1 = require("./leases");
63
63
  const thread_1 = require("./thread");
64
64
  const util_1 = require("./util");
65
+ const estado_thread_1 = require("./estado-thread");
65
66
  /** Diretorio canonico da worktree de uma thread, resolvido pelo `ork`. */
66
67
  function dirDaWorktree(carregado, id) {
67
68
  return path.resolve(carregado.raiz, carregado.manifesto.worktree.dir, id);
@@ -130,6 +131,13 @@ function garantirWorktree(carregado, id) {
130
131
  correcao: `remova o diretorio ou registre a worktree; depois rode: ork worktree ensure ${id}`,
131
132
  };
132
133
  }
134
+ try {
135
+ (0, estado_thread_1.vincularEstado)(raiz, id, dir);
136
+ }
137
+ catch (e) {
138
+ return { ok: false, criada: false, dir, branch, base, motivo: 'tree.blocked',
139
+ detalhe: e.message, correcao: `reconcilie o estado e rode ork worktree sync ${id}` };
140
+ }
133
141
  if (thread.worktree !== dir) {
134
142
  thread.worktree = dir;
135
143
  (0, thread_1.gravarThread)(raiz, thread);
@@ -229,6 +237,13 @@ function sincronizarWorktree(carregado, id, opcoes = {}) {
229
237
  correcao: `commite ou guarde as alteracoes em ${dir} e rode de novo: ork worktree sync ${id}`,
230
238
  };
231
239
  }
240
+ try {
241
+ (0, estado_thread_1.vincularEstado)(raiz, id, dir, opcoes.dryRun);
242
+ }
243
+ catch (e) {
244
+ return { ...vazio, ok: false, jaAtualizada: false, rebaseFeito: false,
245
+ motivo: 'tree.blocked', detalhe: e.message, correcao: 'reconcilie as duas cópias sem descartar evidências' };
246
+ }
232
247
  const refBase = (0, util_1.exec)('git', ['rev-parse', '--verify', base], raiz);
233
248
  if (!refBase.ok) {
234
249
  return {
@@ -287,10 +302,22 @@ function sincronizarWorktree(carregado, id, opcoes = {}) {
287
302
  correcao: '',
288
303
  };
289
304
  }
290
- const rebase = (0, util_1.exec)('git', ['rebase', shaBase], dir);
305
+ let rebase;
306
+ try {
307
+ rebase = (0, estado_thread_1.comEstadoParaGit)(raiz, id, dir, () => {
308
+ const resultado = (0, util_1.exec)('git', ['rebase', shaBase], dir);
309
+ if (!resultado.ok)
310
+ (0, util_1.exec)('git', ['rebase', '--abort'], dir);
311
+ return resultado;
312
+ });
313
+ }
314
+ catch (e) {
315
+ return { ...vazio, shaBase, shaAntes, ok: false, jaAtualizada: false, rebaseFeito: false,
316
+ motivo: 'tree.blocked', detalhe: e.message,
317
+ correcao: 'inspecione a cópia local e a fonte canônica preservadas antes de repetir o sync' };
318
+ }
291
319
  passos.push(`git rebase ${shaBase}`);
292
320
  if (!rebase.ok) {
293
- (0, util_1.exec)('git', ['rebase', '--abort'], dir);
294
321
  passos.push('git rebase --abort');
295
322
  const detalhe = (rebase.stderr || rebase.stdout).trim().split('\n').slice(-4).join(' | ');
296
323
  (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, id), id, ledger_1.TIPOS_DE_EVENTO.worktreeSincronizada, {
@@ -431,6 +458,8 @@ function auditarWorktree(carregado, id) {
431
458
  nivel: 'ok',
432
459
  detalhe: `${path.relative(raiz, dirArtefatos)} fica fora da worktree`,
433
460
  });
461
+ if (existe)
462
+ checks.push((0, estado_thread_1.auditarEstado)(raiz, id, dir));
434
463
  const divergencias = checks.filter((c) => c.nivel === 'fail').length;
435
464
  (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, id), id, ledger_1.TIPOS_DE_EVENTO.worktreeAuditada, {
436
465
  dir,