@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/ship.js CHANGED
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * A ordem dos passos e o contrato, e ela nao muda por modo de conducao:
6
6
  *
7
- * 1. autorizacao de push, pelo gate do modo (#Look/#Ork pausam; #Classic usa a
7
+ * 1. autorizacao de push, pelo gate do modo (#Classic usa a
8
8
  * autorizacao antecipada registrada no ledger; #Maestro/#Auto usam a propria #TAG);
9
9
  * 2. policies do manifesto no gate `ship` (push_direto_na_base e provider);
10
10
  * 3. verificacao independente: `ork verify` reexecuta claims e comandos no HEAD real;
@@ -56,6 +56,8 @@ exports.prepararArvore = prepararArvore;
56
56
  exports.shaDaRef = shaDaRef;
57
57
  exports.shaNoRemoto = shaNoRemoto;
58
58
  exports.remotoConfigurado = remotoConfigurado;
59
+ exports.detectarReversaoDaEntrega = detectarReversaoDaEntrega;
60
+ exports.registrarReversaoDaEntrega = registrarReversaoDaEntrega;
59
61
  exports.ship = ship;
60
62
  exports.textoDoShip = textoDoShip;
61
63
  const fs = __importStar(require("node:fs"));
@@ -69,14 +71,31 @@ const policies_1 = require("./policies");
69
71
  const thread_1 = require("./thread");
70
72
  const util_1 = require("./util");
71
73
  const verify_1 = require("./verify");
74
+ const ci_1 = require("./ci");
75
+ const contrato_publico_1 = require("./contrato-publico");
76
+ const prova_minima_1 = require("./prova-minima");
77
+ const horario_1 = require("./horario");
78
+ const fabrica_publicar_1 = require("./fabrica-publicar");
79
+ /** Os caminhos de contrato publico que a entrega traz sobre a base (diff desde o merge-base). */
80
+ function contratosDaEntrega(raiz, shaPara, shaDe) {
81
+ const base = (0, util_1.exec)('git', ['merge-base', shaPara, shaDe], raiz);
82
+ if (!base.ok)
83
+ return [];
84
+ const diff = (0, util_1.exec)('git', ['diff', '--name-only', '--no-renames', base.stdout.trim(), shaDe], raiz);
85
+ return diff.ok ? (0, contrato_publico_1.contratosTocados)(diff.stdout.split('\n').map((l) => l.trim()).filter(Boolean)) : [];
86
+ }
72
87
  /** Modos em que a propria #TAG do pedido autoriza o push antecipadamente. */
73
88
  const MODOS_QUE_AUTORIZAM_PUSH = ['maestro', 'auto'];
74
89
  /**
75
90
  * Quem autoriza o push desta thread.
76
91
  *
77
- * `#Look` e `#Ork` pausam no proprio SHIP e esperam o humano. `#Classic` pausa antes,
78
- * no gate de evidencias, com autorizacao ANTECIPADA de push: aqui isso e conferido no
79
- * ledger, nao presumido. `#Maestro` e `#Auto` seguem pela #TAG, que fica registrada.
92
+ * `#Classic` pausa no gate de evidencias, com autorizacao ANTECIPADA de push: aqui isso
93
+ * e conferido no ledger, nao presumido. `#Maestro` e `#Auto` seguem pela #TAG, que fica
94
+ * registrada.
95
+ *
96
+ * I-43: thread LEGADA em `#Look` ou `#Ork` pausava no proprio SHIP. Ela continua caindo
97
+ * neste mesmo caminho (nao esta em `MODOS_QUE_AUTORIZAM_PUSH`, entao exige autorizacao
98
+ * registrada), e por isso a regra nao precisou de um ramo so para ela.
80
99
  */
81
100
  function autorizacaoDePush(raiz, thread, opcoes) {
82
101
  const tag = (0, modos_1.tagDoModo)(thread.modo);
@@ -112,8 +131,7 @@ function autorizacaoDePush(raiz, thread, opcoes) {
112
131
  tipo: 'pendente',
113
132
  por: '',
114
133
  razao: `o modo ${tag} pausa no push e ainda nao ha autorizacao humana registrada. ` +
115
- `Autorize com: ork gate approve ${thread.id} push --por <quem> ` +
116
- `ou rode: ork ship ${thread.id} --para <branch> --autorizar-push <quem>`,
134
+ `Autorize na entrega: ork ship ${thread.id} --para <branch> --autorizar-push <quem>`,
117
135
  };
118
136
  }
119
137
  /** Diretorio temporario onde a arvore de merge e montada quando preciso. */
@@ -225,6 +243,7 @@ function baseDoResultado(thread, de, opcoes) {
225
243
  pushVerificado: false,
226
244
  autorizacao: { autorizado: false, tipo: 'pendente', por: '', razao: '' },
227
245
  verificacao: null,
246
+ ci: null,
228
247
  violacoes: [],
229
248
  lease: null,
230
249
  leaseOcupadoPor: null,
@@ -232,7 +251,78 @@ function baseDoResultado(thread, de, opcoes) {
232
251
  dryRun: opcoes.dryRun === true,
233
252
  };
234
253
  }
235
- /** Executa o SHIP da thread. Nunca lanca por reprovacao: reprovacao volta tipada. */
254
+ /**
255
+ * A entrega ja feita por esta thread foi REVERTIDA na base? (I-43, D3, T7)
256
+ *
257
+ * Este era o buraco que tornava o indice de qualidade um numero que nunca muda:
258
+ * `rollback_done` existia na allowlist do ciclo e NAO era escrito por ninguem, e ele
259
+ * e o insumo de maior peso. Sem escritor, 23 das 29 threads entregues ficariam
260
+ * coladas no teto para sempre.
261
+ *
262
+ * A deteccao ancora no marcador que o PROPRIO git escreve. `git revert -m 1 <sha>`
263
+ * poe "This reverts commit <sha>" no corpo do commit, e e isso que se procura no
264
+ * historico da base DEPOIS do merge. Nao se infere reversao por diff de arvore: um
265
+ * arquivo que voltou ao estado anterior pode ser trabalho de outra thread, e chamar
266
+ * isso de reversao seria rebaixar entrega alheia por coincidencia.
267
+ *
268
+ * `para` e OPCIONAL, e isso e o que permite perguntar fora do ship (GO-FIX 1, A1):
269
+ * sem ele, o destino sai do proprio `ship_done`, que ja grava para onde entregou. Quem
270
+ * calcula o indice depois do MASTER nao tem branch de destino na mao, e inventar uma
271
+ * seria pior que nao perguntar.
272
+ *
273
+ * So le git; nao escreve nada. Quem grava o evento e `registrarReversaoDaEntrega`.
274
+ */
275
+ function detectarReversaoDaEntrega(raiz, thread, para) {
276
+ const dir = (0, thread_1.dirThread)(raiz, thread.id);
277
+ const entregas = (0, ledger_1.lerLedger)(dir)
278
+ .filter((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.shipConcluido && typeof e.mergeSha === 'string')
279
+ .map((e) => ({ mergeSha: String(e.mergeSha), para: para ?? String(e.para ?? '') }))
280
+ .filter((e) => e.para.length > 0);
281
+ if (entregas.length === 0)
282
+ return null;
283
+ const perguntados = new Set();
284
+ for (const entrega of [...entregas].reverse()) {
285
+ const intervalo = `${entrega.mergeSha}..${entrega.para}`;
286
+ if (perguntados.has(intervalo))
287
+ continue;
288
+ perguntados.add(intervalo);
289
+ // O historico e append-only: o merge continua la, e o revert vem DEPOIS dele.
290
+ const log = (0, util_1.exec)('git', ['log', '--format=%H%x1f%B%x1e', intervalo], raiz, 60000);
291
+ if (!log.ok)
292
+ continue;
293
+ for (const bruto of log.stdout.split('\x1e')) {
294
+ const [sha, corpo] = bruto.split('\x1f');
295
+ if (!sha || !corpo)
296
+ continue;
297
+ if (corpo.includes(`This reverts commit ${entrega.mergeSha}`)) {
298
+ return { mergeSha: entrega.mergeSha, revertSha: sha.trim(), para: entrega.para };
299
+ }
300
+ }
301
+ }
302
+ return null;
303
+ }
304
+ /**
305
+ * Grava `rollback_done` quando a reversao e nova, e devolve o que encontrou.
306
+ *
307
+ * IDEMPOTENTE por `revertSha`: o ledger e append-only e o mesmo revert nao pode
308
+ * rebaixar a thread duas vezes so porque alguem rodou o comando de novo.
309
+ */
310
+ function registrarReversaoDaEntrega(raiz, thread, para) {
311
+ const achada = detectarReversaoDaEntrega(raiz, thread, para);
312
+ if (!achada)
313
+ return null;
314
+ const dir = (0, thread_1.dirThread)(raiz, thread.id);
315
+ const jaRegistrada = (0, ledger_1.lerLedger)(dir).some((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.rollbackConcluido && e.revertSha === achada.revertSha);
316
+ if (jaRegistrada)
317
+ return achada;
318
+ (0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.rollbackConcluido, {
319
+ fase: 'SHIP',
320
+ ...achada,
321
+ prova: `git log ${achada.mergeSha.slice(0, 8)}..${achada.para} traz "This reverts commit ${achada.mergeSha}" em ${achada.revertSha.slice(0, 8)}`,
322
+ razao: 'I-43: a entrega foi desfeita na base; e o insumo de maior peso do indice de qualidade',
323
+ });
324
+ return achada;
325
+ }
236
326
  function ship(carregado, threadId, opcoes) {
237
327
  const { raiz, manifesto } = carregado;
238
328
  const thread = (0, thread_1.lerThread)(raiz, threadId);
@@ -241,6 +331,14 @@ function ship(carregado, threadId, opcoes) {
241
331
  const para = opcoes.para;
242
332
  const remoto = opcoes.remoto ?? 'origin';
243
333
  const r = baseDoResultado(thread, de, opcoes);
334
+ // I-43 (T7): antes de qualquer coisa, se a entrega ANTERIOR desta thread foi
335
+ // revertida na base, isso vira `rollback_done`. E o insumo de maior peso do indice
336
+ // de qualidade, e o unico fato que diz sem interpretacao que a entrega nao servia.
337
+ // Idempotente: o mesmo revert nao rebaixa a thread duas vezes.
338
+ try {
339
+ registrarReversaoDaEntrega(raiz, thread, para);
340
+ }
341
+ catch { /* git indisponivel nao barra o ship */ }
244
342
  const bloquear = (motivo, detalhe, correcao) => {
245
343
  (0, gates_1.registrarGateBloqueado)(dir, threadId, {
246
344
  gate: 'ship',
@@ -266,22 +364,36 @@ function ship(carregado, threadId, opcoes) {
266
364
  const autorizacao = autorizacaoDePush(raiz, thread, opcoes);
267
365
  r.autorizacao = autorizacao;
268
366
  if (!autorizacao.autorizado) {
269
- return bloquear('human.pending', autorizacao.razao, `ork gate approve ${threadId} push --por <quem>`);
367
+ return bloquear('human.pending', autorizacao.razao, `ork ship ${threadId} --para <branch> --autorizar-push <quem>`);
270
368
  }
271
- // 2. Policies do manifesto que valem no gate `ship`.
369
+ // 2. Policies do manifesto que valem no gate `ship`. RM-008 (fatia 3): a branch da thread
370
+ // atras da base e fato do git, calculado aqui (a ponta da base nao esta contida na branch).
371
+ const pontaDe = shaDaRef(raiz, `refs/heads/${de}`);
372
+ const pontaPara = shaDaRef(raiz, `refs/heads/${para}`);
373
+ const branchAtrasDaBase = pontaDe && pontaPara && de !== para
374
+ ? !(0, util_1.exec)('git', ['merge-base', '--is-ancestor', pontaPara, pontaDe], raiz).ok
375
+ : undefined;
272
376
  const violacoes = (0, policies_1.avaliarPolicies)(manifesto, {
273
377
  gate: 'ship',
274
378
  de,
275
379
  para,
276
380
  baseBranch: manifesto.worktree.base_branch,
381
+ threadId,
382
+ branchAtrasDaBase,
277
383
  });
278
384
  r.violacoes = violacoes;
385
+ if (!r.dryRun) {
386
+ for (const v of (0, policies_1.avisos)(violacoes)) {
387
+ (0, ledger_1.registrar)(dir, threadId, ledger_1.TIPOS_DE_EVENTO.politicaAviso, { gate: 'ship', de, para,
388
+ policy: v.policy, detalhe: v.detalhe, correcao: v.correcao, modo: thread.modo });
389
+ }
390
+ }
279
391
  const bloqueiam = (0, policies_1.bloqueantes)(violacoes);
280
392
  if (bloqueiam.length > 0) {
281
393
  return bloquear('policy.violation', bloqueiam.map((v) => `${v.policy}: ${v.detalhe}`).join('; '), bloqueiam.map((v) => v.correcao).join('; '));
282
394
  }
283
395
  // 3. Verificacao independente: reexecuta claims e comandos no HEAD real da thread.
284
- const verificacao = (0, verify_1.verificar)(carregado, threadId);
396
+ const verificacao = (0, verify_1.verificar)(carregado, threadId, { executor: opcoes.executorVerify });
285
397
  r.verificacao = verificacao;
286
398
  if (!verificacao.ok) {
287
399
  const motivo = verificacao.motivos.find((m) => m !== 'claims.unverifiable');
@@ -298,6 +410,19 @@ function ship(carregado, threadId, opcoes) {
298
410
  }
299
411
  r.shaDe = shaDe;
300
412
  r.shaParaAntes = shaPara;
413
+ // I-42 (D7): a fronteira do commit MCP vale tambem na entrega, onde aparece o commit feito
414
+ // por git direto. Ciclo sem PLAN nem CHECK nao entrega contrato publico.
415
+ const tocados = (0, prova_minima_1.cicloSemCheck)(thread) ? contratosDaEntrega(raiz, shaPara, shaDe) : [];
416
+ if (tocados.length > 0) {
417
+ return bloquear('policy.violation', `contrato publico em ciclo sem PLAN nem CHECK: ${tocados.join(', ')}`, 'refaca a mudanca numa thread #Classic, #Maestro ou #Auto');
418
+ }
419
+ // O recibo vem do provedor e pertence ao SHA exato da candidata. Teste local
420
+ // verde ou status de outro commit não libera a entrega.
421
+ const ci = (0, ci_1.consultarCi)(carregado, shaDe, remoto, opcoes.executorCi);
422
+ r.ci = ci;
423
+ if (!ci.ok) {
424
+ return bloquear('ci.failed', `${ci.detail} (commit ${shaDe}, contexto ${ci.context})`, `publique a branch, aguarde o check ${ci.context} verde no GitHub e repita o SHIP`);
425
+ }
301
426
  // 4. Lease `main-tree`: so uma thread mergeia por vez.
302
427
  if (r.dryRun) {
303
428
  const ocupado = (0, leases_1.lerLease)(raiz, leases_1.LEASE_MAIN_TREE);
@@ -334,6 +459,7 @@ function ship(carregado, threadId, opcoes) {
334
459
  thread: threadId,
335
460
  motivo: `ship de ${de} para ${para}`,
336
461
  ttlMs: opcoes.ttlLeaseMs,
462
+ retomarVencido: opcoes.retomarLeaseVencido,
337
463
  });
338
464
  if (!aquisicao.ok) {
339
465
  r.leaseOcupadoPor = aquisicao.ocupadoPor;
@@ -369,6 +495,7 @@ function ship(carregado, threadId, opcoes) {
369
495
  let arvore = null;
370
496
  try {
371
497
  try {
498
+ opcoes.revalidarGit?.('preparar');
372
499
  arvore = prepararArvore(raiz, para);
373
500
  }
374
501
  catch (e) {
@@ -376,6 +503,7 @@ function ship(carregado, threadId, opcoes) {
376
503
  return bloquear('tree.blocked', e.message, 'deixe a arvore da branch de destino limpa (ou libere a branch) e rode o ship de novo');
377
504
  }
378
505
  const passos = [];
506
+ opcoes.revalidarGit?.('merge', arvore.dir);
379
507
  // 5. Merge --no-ff, conferido no proprio git.
380
508
  const jaIncorporado = (0, util_1.exec)('git', ['merge-base', '--is-ancestor', shaDe, shaPara], raiz).ok;
381
509
  r.jaIncorporado = jaIncorporado;
@@ -410,6 +538,7 @@ function ship(carregado, threadId, opcoes) {
410
538
  passos.push(`(nada a mergear: ${de} ja e ancestral de ${para})`);
411
539
  }
412
540
  r.mergeSha = mergeSha;
541
+ opcoes.revalidarGit?.('push', arvore.dir);
413
542
  // 6. Push PROVADO por ls-remote.
414
543
  const temRemoto = remotoConfigurado(arvore.dir, remoto);
415
544
  r.remoto = temRemoto ? remoto : null;
@@ -468,12 +597,18 @@ function ship(carregado, threadId, opcoes) {
468
597
  evidencia: {
469
598
  verificadoNoCommit: verificacao.commit,
470
599
  claimsVerificadas: verificacao.claims.filter((c) => c.verificado).map((c) => c.claim.id),
471
- comandos: verificacao.comandos.map((c) => ({ nome: c.nome, ok: c.ok })),
600
+ // I-37 (T9): a mesma evidencia do `verify_run`, com causa, prazo e o teste que caiu.
601
+ comandos: verificacao.comandos.map(verify_1.comandoNoLedger),
602
+ ci,
472
603
  passos,
473
604
  },
474
605
  });
606
+ (0, fabrica_publicar_1.publicarEmSegundoPlano)(raiz);
475
607
  const atualizada = (0, thread_1.lerThread)(raiz, threadId);
476
- atualizada.faseAtual = 'SHIP';
608
+ // I-42: ciclo sem SHIP (o `#Fast`) entrega sem trocar de fase; `faseAtual` fica sempre
609
+ // dentro do ciclo, porque board, pulse e prompt resolvem o bloco a partir dela.
610
+ if (!atualizada.fases?.length || atualizada.fases.includes('SHIP'))
611
+ atualizada.faseAtual = 'SHIP';
477
612
  atualizada.leases = [
478
613
  ...(atualizada.leases ?? []),
479
614
  { nome: leases_1.LEASE_MAIN_TREE, adquiridoEm: aquisicao.lease?.adquiridoEm ?? (0, util_1.agora)(), liberadoEm: (0, util_1.agora)() },
@@ -495,20 +630,34 @@ function ship(carregado, threadId, opcoes) {
495
630
  /** Texto de `ork ship` para o CLI. */
496
631
  function textoDoShip(r) {
497
632
  const linhas = [];
633
+ // I-35: horários no fuso do dono, sem rótulo por linha; o fuso é dito uma vez, no fim.
634
+ let comHorario = false;
635
+ const local = (texto) => {
636
+ const localizado = (0, horario_1.localizarTexto)(texto);
637
+ if (localizado !== texto)
638
+ comHorario = true;
639
+ return localizado;
640
+ };
641
+ const fechar = () => (comHorario ? [...linhas, (0, horario_1.legendaDoFuso)()] : linhas).join('\n');
498
642
  const cabecalho = r.dryRun ? 'ork ship (--dry-run, nada foi executado)' : 'ork ship';
499
643
  linhas.push(`${cabecalho}: thread ${r.thread}`);
500
644
  linhas.push(` de ${r.de}${r.shaDe ? ` @ ${r.shaDe.slice(0, 8)}` : ''}`);
501
645
  linhas.push(` para ${r.para}${r.shaParaAntes ? ` @ ${r.shaParaAntes.slice(0, 8)}` : ''}`);
502
646
  linhas.push(` autorizacao ${r.autorizacao.autorizado ? `AUTORIZADO por ${r.autorizacao.por} (${r.autorizacao.tipo})` : 'AGUARDANDO AUTORIZACAO HUMANA'}`);
503
- linhas.push(` ${r.autorizacao.razao}`);
647
+ linhas.push(` ${local(r.autorizacao.razao)}`);
504
648
  if (r.verificacao) {
505
649
  const v = r.verificacao;
506
650
  linhas.push(` verificacao ${v.ok ? 'passou' : 'REPROVOU'} no HEAD ${v.commit.slice(0, 8)} ` +
507
651
  `(${v.claims.filter((c) => c.verificado).length}/${v.claims.length} claims, ` +
508
652
  `${v.comandos.filter((c) => c.ok).length}/${v.comandos.length} comandos)`);
509
653
  }
654
+ if (r.ci) {
655
+ linhas.push(` ci ${r.ci.required ? `${r.ci.state.toUpperCase()} ${r.ci.context} em ${r.ci.sha.slice(0, 8)}` : 'não exigido'}`);
656
+ }
657
+ linhas.push(...(0, policies_1.linhasDeAviso)(r.violacoes ?? []));
510
658
  if (r.leaseOcupadoPor) {
511
- linhas.push(` lease ${leases_1.LEASE_MAIN_TREE} OCUPADO pela thread ${r.leaseOcupadoPor.thread} (desde ${r.leaseOcupadoPor.adquiridoEm})`);
659
+ comHorario = true;
660
+ linhas.push(` lease ${leases_1.LEASE_MAIN_TREE} OCUPADO pela thread ${r.leaseOcupadoPor.thread} (desde ${(0, horario_1.formatarDataHora)(r.leaseOcupadoPor.adquiridoEm)})`);
512
661
  }
513
662
  else if (r.lease) {
514
663
  linhas.push(` lease ${leases_1.LEASE_MAIN_TREE} tomado por ${r.thread} e liberado ao fim`);
@@ -519,16 +668,16 @@ function textoDoShip(r) {
519
668
  if (r.bloqueado) {
520
669
  linhas.push('');
521
670
  linhas.push(`BLOQUEADO. motivo tipado: ${r.motivo}`);
522
- linhas.push(` detalhe ${r.detalhe}`);
671
+ linhas.push(` detalhe ${local(r.detalhe)}`);
523
672
  linhas.push(` correcao ${r.correcao}`);
524
- return linhas.join('\n');
673
+ return fechar();
525
674
  }
526
675
  if (r.dryRun) {
527
676
  linhas.push('');
528
677
  linhas.push('Passos que o ship real executaria, nesta ordem:');
529
678
  for (const p of r.passos)
530
679
  linhas.push(` ${p}`);
531
- return linhas.join('\n');
680
+ return fechar();
532
681
  }
533
682
  linhas.push('');
534
683
  linhas.push(r.jaIncorporado
@@ -539,7 +688,7 @@ function textoDoShip(r) {
539
688
  linhas.push(` e o destino local esta no mesmo sha: ${r.mergeSha}`);
540
689
  }
541
690
  else {
542
- linhas.push(`Push nao provado: ${r.detalhe || 'sem remoto configurado'}`);
691
+ linhas.push(`Push nao provado: ${local(r.detalhe) || 'sem remoto configurado'}`);
543
692
  }
544
693
  linhas.push('');
545
694
  linhas.push('Evidencia (comandos executados):');
@@ -547,5 +696,5 @@ function textoDoShip(r) {
547
696
  linhas.push(` ${p}`);
548
697
  linhas.push('');
549
698
  linhas.push(`Ledger: ork phase list ${r.thread} (evento ship_done)`);
550
- return linhas.join('\n');
699
+ return fechar();
551
700
  }
package/dist/slug.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * Slug de sessao em 3 partes (visao unificada, secao 3.4).
3
+ * Slug de sessao em 3 partes (conceitos: docs/conceitos/visao-geral.md).
4
4
  *
5
5
  * <produto ate 3 letras>-<assunto ate 12 chars>-<fases>[-<rotacao>]
6
6
  *
@@ -0,0 +1,115 @@
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.validarArtefato = validarArtefato;
37
+ exports.provaDeEntrega = provaDeEntrega;
38
+ exports.exigirEntrega = exigirEntrega;
39
+ exports.registrarArtefato = registrarArtefato;
40
+ exports.fecharAdministrativamente = fecharAdministrativamente;
41
+ /** Encerramento administrativo não representa uma entrega nem um score humano. */
42
+ const fs = __importStar(require("node:fs"));
43
+ const path = __importStar(require("node:path"));
44
+ const node_crypto_1 = require("node:crypto");
45
+ const thread_1 = require("./thread");
46
+ const ledger_1 = require("./ledger");
47
+ const estado_thread_1 = require("./estado-thread");
48
+ const util_1 = require("./util");
49
+ const fabrica_publicar_1 = require("./fabrica-publicar");
50
+ function validarArtefato(raiz, arquivo, sha256) {
51
+ if (!/^[a-f0-9]{64}$/.test(sha256))
52
+ throw new Error('sha256 inválido');
53
+ const root = fs.realpathSync((0, estado_thread_1.raizDoEstado)(raiz));
54
+ const destino = fs.realpathSync(path.resolve(root, arquivo));
55
+ const relativo = path.relative(root, destino);
56
+ if (!relativo || relativo === '..' || relativo.startsWith(`..${path.sep}`) || path.isAbsolute(relativo)) {
57
+ throw new Error('artefato deve estar dentro do projeto');
58
+ }
59
+ if (!fs.statSync(destino).isFile())
60
+ throw new Error('artefato deve ser arquivo regular');
61
+ if ((0, node_crypto_1.createHash)('sha256').update(fs.readFileSync(destino)).digest('hex') !== sha256) {
62
+ throw new Error('hash do artefato diverge');
63
+ }
64
+ return { tipo: 'artefato', arquivo: relativo, sha256 };
65
+ }
66
+ function provaDeEntrega(raiz, id) {
67
+ const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id));
68
+ const ship = [...eventos].reverse().find(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.shipConcluido);
69
+ if (ship)
70
+ return { tipo: 'ship', ts: ship.ts, mergeSha: String(ship.mergeSha ?? '') };
71
+ for (const e of eventos.filter(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.artefatoEntregue).reverse()) {
72
+ try {
73
+ return validarArtefato(raiz, String(e.arquivo), String(e.sha256));
74
+ }
75
+ catch { /* prova precisa continuar válida */ }
76
+ }
77
+ return null;
78
+ }
79
+ function exigirEntrega(raiz, id) {
80
+ const t = (0, thread_1.lerThread)(raiz, id);
81
+ if (t.fechamentoAdmin)
82
+ throw new Error('thread encerrada administrativamente não pode receber MASTER');
83
+ const prova = provaDeEntrega(raiz, id);
84
+ if (!prova)
85
+ throw new Error('MASTER exige entrega: ship_done ou artefato existente com hash verificado');
86
+ return prova;
87
+ }
88
+ function registrarArtefato(raiz, id, arquivo, sha256, por) {
89
+ const t = (0, thread_1.lerThread)(raiz, id);
90
+ if (t.status === 'fechada' || !por.trim())
91
+ throw new Error('artefato exige thread aberta e autoria explícita');
92
+ const prova = validarArtefato(raiz, arquivo, sha256);
93
+ (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, id), id, ledger_1.TIPOS_DE_EVENTO.artefatoEntregue, { arquivo, sha256, fase: 'SHIP', por: por.trim() });
94
+ return prova;
95
+ }
96
+ function fecharAdministrativamente(raiz, id, opcoes) {
97
+ if (!['orfa', 'engano', 'superada'].includes(opcoes.motivo))
98
+ throw new Error('motivo deve ser orfa, engano ou superada');
99
+ if (!opcoes.por.trim() || opcoes.justificativa.trim().length < 3)
100
+ throw new Error('fechamento exige autoria e justificativa');
101
+ const t = (0, thread_1.lerThread)(raiz, id);
102
+ if (t.fechamentoAdmin) {
103
+ if (t.fechamentoAdmin.motivo !== opcoes.motivo)
104
+ throw new Error('thread já encerrada por outro motivo');
105
+ return t;
106
+ }
107
+ if (provaDeEntrega(raiz, id) || t.score)
108
+ throw new Error('thread entregue ou pontuada exige MASTER, não fechamento administrativo');
109
+ t.fechamentoAdmin = { motivo: opcoes.motivo, por: opcoes.por.trim(), justificativa: opcoes.justificativa.trim(), fechadoEm: (0, util_1.agora)() };
110
+ (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, id), id, ledger_1.TIPOS_DE_EVENTO.threadFechadaAdmin, t.fechamentoAdmin);
111
+ t.status = 'fechada';
112
+ (0, thread_1.gravarThread)(raiz, t);
113
+ (0, fabrica_publicar_1.publicarEmSegundoPlano)(raiz);
114
+ return t;
115
+ }