@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,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fingerprintCapacidade = fingerprintCapacidade;
4
+ exports.validarReciboCapacidade = validarReciboCapacidade;
5
+ exports.avaliarCapacidades = avaliarCapacidades;
6
+ exports.exigirCapacidadesRequeridas = exigirCapacidadesRequeridas;
7
+ /** Matriz I09 sem transporte, spawn, persistencia ou ativacao. */
8
+ const playbook_contracts_1 = require("./playbook-contracts");
9
+ const niveis = ['help', 'transporte', 'teste', 'homologacao'];
10
+ const versao = { type: 'integer', const: playbook_contracts_1.PLAYBOOK_VERSION };
11
+ const schemaContexto = (0, playbook_contracts_1.objetoFechado)({
12
+ runtime: { type: 'string', enum: ['codex', 'claude'] },
13
+ versaoRuntime: playbook_contracts_1.textoPlaybook, binarioSha256: playbook_contracts_1.textoPlaybook, transporte: playbook_contracts_1.textoPlaybook,
14
+ configSha256: playbook_contracts_1.textoPlaybook, schemaSha256: playbook_contracts_1.textoPlaybook, codigoSha256: playbook_contracts_1.textoPlaybook,
15
+ escopo: (0, playbook_contracts_1.objetoFechado)({
16
+ projeto: playbook_contracts_1.textoPlaybook, thread: playbook_contracts_1.textoPlaybook,
17
+ fase: { type: 'string', enum: ['GOAL', 'PLAN', 'GO', 'CHECK', 'SHIP', 'MASTER'] },
18
+ dispatchId: playbook_contracts_1.textoPlaybook, sessionId: playbook_contracts_1.textoPlaybook, base: playbook_contracts_1.textoPlaybook, head: playbook_contracts_1.textoPlaybook, prova: playbook_contracts_1.textoPlaybook,
19
+ }),
20
+ });
21
+ const schemaMatriz = (0, playbook_contracts_1.objetoFechado)({
22
+ schemaVersion: versao, contexto: schemaContexto,
23
+ capacidades: (0, playbook_contracts_1.listaPlaybook)((0, playbook_contracts_1.objetoFechado)({
24
+ id: playbook_contracts_1.textoPlaybook,
25
+ evidencias: (0, playbook_contracts_1.objetoFechado)(Object.fromEntries(niveis.map(n => [n, playbook_contracts_1.textoPlaybook])), []),
26
+ })),
27
+ });
28
+ const schemaRecibo = (0, playbook_contracts_1.objetoFechado)({
29
+ schemaVersion: versao, id: playbook_contracts_1.textoPlaybook, fingerprint: playbook_contracts_1.textoPlaybook, capacidade: playbook_contracts_1.textoPlaybook,
30
+ nivel: { type: 'string', enum: niveis },
31
+ origem: { type: 'string', enum: ['help', 'transporte', 'deterministica', 'nativa'] },
32
+ fonte: (0, playbook_contracts_1.objetoFechado)({ id: playbook_contracts_1.textoPlaybook, sha256: playbook_contracts_1.textoPlaybook }),
33
+ comando: (0, playbook_contracts_1.listaPlaybook)(playbook_contracts_1.textoPlaybook, 1), saida: { type: 'string', maxLength: 131072 },
34
+ inicio: playbook_contracts_1.textoPlaybook, fim: playbook_contracts_1.textoPlaybook,
35
+ resultado: (0, playbook_contracts_1.objetoFechado)({
36
+ estado: { type: 'string', enum: ['aprovado', 'reprovado', 'unavailable'] },
37
+ exitCode: { type: 'integer' }, esperados: (0, playbook_contracts_1.listaPlaybook)(playbook_contracts_1.textoPlaybook),
38
+ executados: (0, playbook_contracts_1.listaPlaybook)(playbook_contracts_1.textoPlaybook), aprovados: (0, playbook_contracts_1.listaPlaybook)(playbook_contracts_1.textoPlaybook),
39
+ skipped: { type: 'integer' }, todo: { type: 'integer' },
40
+ }),
41
+ });
42
+ function exigir(condicao, campo, detalhe) {
43
+ if (!condicao)
44
+ throw new playbook_contracts_1.ContratoPlaybookInvalido(campo, detalhe);
45
+ }
46
+ function sha256(valor, campo) {
47
+ exigir(/^[a-f0-9]{64}$/.test(valor), campo, 'SHA-256 invalido');
48
+ }
49
+ function nomesUnicos(valores, campo) {
50
+ exigir(valores.every(v => v.trim().length > 0), campo, 'nome vazio');
51
+ exigir(new Set(valores).size === valores.length, campo, 'nome repetido');
52
+ }
53
+ function fingerprintCapacidade(contexto) {
54
+ (0, playbook_contracts_1.validarContratoPlaybook)(contexto, schemaContexto);
55
+ for (const k of ['binarioSha256', 'configSha256', 'schemaSha256', 'codigoSha256'])
56
+ sha256(contexto[k], k);
57
+ for (const k of ['base', 'head'])
58
+ exigir(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(contexto.escopo[k]), k, 'commit invalido');
59
+ exigir(Object.values(contexto.escopo).every(v => v.trim().length > 0) &&
60
+ contexto.versaoRuntime.trim().length > 0 && contexto.transporte.trim().length > 0, 'contexto', 'identidade vazia');
61
+ return (0, playbook_contracts_1.hashJsonPlaybook)({ schemaVersion: playbook_contracts_1.PLAYBOOK_VERSION, contexto });
62
+ }
63
+ function validarReciboCapacidade(valor) {
64
+ (0, playbook_contracts_1.validarContratoPlaybook)(valor, schemaRecibo);
65
+ const r = valor;
66
+ sha256(r.fingerprint, 'fingerprint');
67
+ sha256(r.fonte.sha256, 'fonte.sha256');
68
+ for (const campo of ['inicio', 'fim']) {
69
+ const instante = Date.parse(r[campo]);
70
+ exigir(Number.isFinite(instante) && new Date(instante).toISOString() === r[campo], campo, 'instante UTC invalido');
71
+ }
72
+ exigir(Date.parse(r.fim) >= Date.parse(r.inicio), 'fim', 'recibo termina antes de iniciar');
73
+ nomesUnicos([r.id], 'id');
74
+ nomesUnicos([r.capacidade], 'capacidade');
75
+ nomesUnicos([r.fonte.id], 'fonte.id');
76
+ const resultado = r.resultado;
77
+ for (const k of ['esperados', 'executados', 'aprovados'])
78
+ nomesUnicos(resultado[k], `resultado.${k}`);
79
+ exigir(resultado.exitCode >= 0 && resultado.skipped >= 0 && resultado.todo >= 0, 'resultado', 'contagem negativa');
80
+ exigir(resultado.aprovados.every(c => resultado.executados.includes(c)) &&
81
+ resultado.executados.every(c => resultado.esperados.includes(c)), 'resultado', 'casos sem correspondencia');
82
+ const origens = {
83
+ help: ['help'], transporte: ['transporte'], teste: ['deterministica', 'nativa'], homologacao: ['nativa'],
84
+ };
85
+ exigir(origens[r.nivel].includes(r.origem), 'origem', 'origem incompativel com nivel');
86
+ return r;
87
+ }
88
+ /**
89
+ * O consumidor Ork fornece contexto ATUAL e resolve fontes externas exatas, verificadas
90
+ * independentemente. Nunca construir resolverRecibo a partir do JSON do candidato.
91
+ * Ausencia de resolver ou de fonte nao concede selo. T07/T20 implementarao essa fronteira.
92
+ */
93
+ function avaliarCapacidades(candidato, contextoAtual, requeridas, resolverRecibo) {
94
+ (0, playbook_contracts_1.validarContratoPlaybook)(candidato, schemaMatriz);
95
+ const matriz = candidato;
96
+ const fingerprint = fingerprintCapacidade(contextoAtual);
97
+ exigir(fingerprintCapacidade(matriz.contexto) === fingerprint, 'contexto', 'fingerprint atual divergente');
98
+ (0, playbook_contracts_1.validarContratoPlaybook)(requeridas, (0, playbook_contracts_1.listaPlaybook)(playbook_contracts_1.textoPlaybook));
99
+ nomesUnicos(requeridas, 'requeridas');
100
+ nomesUnicos(matriz.capacidades.map(c => c.id), 'capacidades');
101
+ const capacidades = matriz.capacidades.map(c => {
102
+ const provas = {};
103
+ const motivos = [];
104
+ let reprovada = false;
105
+ let unavailable = false;
106
+ for (const nivel of niveis) {
107
+ const id = c.evidencias[nivel];
108
+ if (id === undefined)
109
+ continue;
110
+ const fonte = resolverRecibo?.(id);
111
+ if (fonte === undefined || fonte === null) {
112
+ motivos.push(`${nivel}: fonte externa ausente`);
113
+ unavailable = true;
114
+ continue;
115
+ }
116
+ const recibo = validarReciboCapacidade(fonte);
117
+ exigir(recibo.id === id && recibo.capacidade === c.id && recibo.nivel === nivel, nivel, 'recibo de outra capacidade ou nivel');
118
+ exigir(recibo.fingerprint === fingerprint, nivel, 'recibo de outro fingerprint');
119
+ const r = recibo.resultado;
120
+ const casosCompletos = r.esperados.length > 0 && r.esperados.length === r.executados.length &&
121
+ r.executados.length === r.aprovados.length && r.skipped === 0 && r.todo === 0;
122
+ provas[nivel] = r.estado === 'aprovado' && r.exitCode === 0 && casosCompletos;
123
+ if (!provas[nivel]) {
124
+ motivos.push(`${nivel}: ${r.estado}, casos completos=${casosCompletos}, exitCode=${r.exitCode}`);
125
+ if (r.estado === 'unavailable')
126
+ unavailable = true;
127
+ else
128
+ reprovada = true;
129
+ }
130
+ }
131
+ const homologada = provas.transporte === true && provas.teste === true && provas.homologacao === true &&
132
+ !reprovada && !unavailable;
133
+ return {
134
+ id: c.id, observadaNoHelp: provas.help === true, disponivelNoTransporte: provas.transporte === true,
135
+ testada: provas.teste === true, homologada,
136
+ estado: reprovada ? 'reprovada' : unavailable ? 'unavailable' :
137
+ homologada ? 'homologada' : 'pendente',
138
+ motivos,
139
+ };
140
+ });
141
+ const requeridasSemDemonstracao = requeridas.filter(id => !capacidades.some(c => c.id === id && c.homologada));
142
+ return { schemaVersion: playbook_contracts_1.PLAYBOOK_VERSION, fingerprint, capacidades,
143
+ requeridasAtendidas: requeridas.length > 0 && requeridasSemDemonstracao.length === 0,
144
+ requeridasSemDemonstracao };
145
+ }
146
+ function exigirCapacidadesRequeridas(...parametros) {
147
+ const matriz = avaliarCapacidades(...parametros);
148
+ exigir(matriz.requeridasAtendidas, 'requeridas', `sem demonstracao: ${matriz.requeridasSemDemonstracao.join(', ') || 'coorte vazia'}`);
149
+ return matriz;
150
+ }
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.textoPlaybook = exports.ContratoPlaybookInvalido = exports.MAX_RESULT_BYTES = exports.JSON_SCHEMA_DIALECT = exports.PLAYBOOK_VERSION = void 0;
4
+ exports.validarSchemaPlaybook = validarSchemaPlaybook;
5
+ exports.validarContratoPlaybook = validarContratoPlaybook;
6
+ exports.hashJsonPlaybook = hashJsonPlaybook;
7
+ exports.objetoFechado = objetoFechado;
8
+ exports.listaPlaybook = listaPlaybook;
9
+ exports.validarResultadoFasePlaybook = validarResultadoFasePlaybook;
10
+ /** Contratos puros I09. Validar formato nao concede autoridade nem executa verify. */
11
+ const node_crypto_1 = require("node:crypto");
12
+ exports.PLAYBOOK_VERSION = 1;
13
+ exports.JSON_SCHEMA_DIALECT = 'https://json-schema.org/draft/2020-12/schema';
14
+ exports.MAX_RESULT_BYTES = 256 * 1024;
15
+ class ContratoPlaybookInvalido extends Error {
16
+ campo;
17
+ constructor(campo, detalhe) {
18
+ super(`${campo}: ${detalhe}`);
19
+ this.campo = campo;
20
+ this.name = 'ContratoPlaybookInvalido';
21
+ }
22
+ }
23
+ exports.ContratoPlaybookInvalido = ContratoPlaybookInvalido;
24
+ function exigir(condicao, campo, detalhe) {
25
+ if (!condicao)
26
+ throw new ContratoPlaybookInvalido(campo, detalhe);
27
+ }
28
+ function objeto(valor) {
29
+ return valor !== null && typeof valor === 'object' && !Array.isArray(valor) &&
30
+ [Object.prototype, null].includes(Object.getPrototypeOf(valor));
31
+ }
32
+ /** Somente dados JSON, sem getters, prototipos customizados, ciclos ou arrays esparsos. */
33
+ function exigirJson(valor) {
34
+ const ativos = new Set();
35
+ let nos = 0;
36
+ function visitar(v, profundidade) {
37
+ exigir(++nos <= exports.MAX_RESULT_BYTES && profundidade <= 32, '$', 'JSON excede limite estrutural');
38
+ if (v === null || typeof v === 'string' || typeof v === 'boolean')
39
+ return;
40
+ if (typeof v === 'number') {
41
+ exigir(Number.isFinite(v), '$', 'numero JSON invalido');
42
+ return;
43
+ }
44
+ exigir(Array.isArray(v) || objeto(v), '$', 'esperado dado JSON simples');
45
+ exigir(!ativos.has(v), '$', 'ciclo JSON');
46
+ ativos.add(v);
47
+ const chaves = Reflect.ownKeys(v);
48
+ if (Array.isArray(v)) {
49
+ exigir(chaves.length === v.length + 1, '$', 'array esparso ou com campos extras');
50
+ }
51
+ for (const chave of chaves) {
52
+ if (Array.isArray(v) && chave === 'length')
53
+ continue;
54
+ exigir(typeof chave === 'string', '$', 'chave nao JSON');
55
+ const d = Object.getOwnPropertyDescriptor(v, chave);
56
+ exigir(d.enumerable && 'value' in d, '$', 'campo nao JSON');
57
+ if (Array.isArray(v))
58
+ exigir(/^(0|[1-9][0-9]*)$/.test(chave) && Number(chave) < v.length, '$', 'indice invalido');
59
+ visitar(d.value, profundidade + 1);
60
+ }
61
+ ativos.delete(v);
62
+ }
63
+ visitar(valor, 0);
64
+ exigir(Buffer.byteLength(JSON.stringify(valor), 'utf8') <= exports.MAX_RESULT_BYTES, '$', 'JSON excede 256 KiB');
65
+ }
66
+ function primitivo(v) {
67
+ return v === null || typeof v === 'string' || typeof v === 'boolean' ||
68
+ (typeof v === 'number' && Number.isSafeInteger(v));
69
+ }
70
+ /** Subconjunto fechado. $ref, combinadores, pattern e keywords desconhecidas falham. */
71
+ function validarSchemaPlaybook(schema) {
72
+ exigirJson(schema);
73
+ function visitar(s, campo, nivel) {
74
+ exigir(objeto(s), campo, 'schema deve ser objeto');
75
+ exigir(nivel <= 24, campo, 'schema profundo demais');
76
+ const porTipo = {
77
+ object: ['properties', 'required', 'additionalProperties'],
78
+ array: ['items', 'minItems', 'maxItems'],
79
+ string: ['minLength', 'maxLength'],
80
+ integer: [], boolean: [], null: [],
81
+ };
82
+ exigir(typeof s.type === 'string' && Object.hasOwn(porTipo, s.type), campo, 'tipo nao suportado');
83
+ const permitidas = ['type', 'const', 'enum', ...porTipo[s.type]];
84
+ if (nivel === 0)
85
+ permitidas.push('$schema');
86
+ for (const chave of Object.keys(s))
87
+ exigir(permitidas.includes(chave), `${campo}.${chave}`, 'keyword nao suportada');
88
+ if (Object.hasOwn(s, '$schema'))
89
+ exigir(s.$schema === exports.JSON_SCHEMA_DIALECT, campo, 'dialeto nao suportado');
90
+ if (Object.hasOwn(s, 'const'))
91
+ exigir(primitivo(s.const), campo, 'const deve ser primitivo');
92
+ if (Object.hasOwn(s, 'enum')) {
93
+ exigir(Array.isArray(s.enum) && s.enum.length > 0 && s.enum.every(primitivo), campo, 'enum invalido');
94
+ exigir(new Set(s.enum).size === s.enum.length, campo, 'enum repetido');
95
+ }
96
+ for (const [min, max] of [['minLength', 'maxLength'], ['minItems', 'maxItems']]) {
97
+ for (const k of [min, max])
98
+ if (Object.hasOwn(s, k)) {
99
+ exigir(Number.isSafeInteger(s[k]) && s[k] >= 0, campo, `${k} invalido`);
100
+ }
101
+ if (Object.hasOwn(s, min) && Object.hasOwn(s, max))
102
+ exigir(s[min] <= s[max], campo, 'limites invertidos');
103
+ }
104
+ if (s.type === 'object') {
105
+ exigir(objeto(s.properties) && s.additionalProperties === false && Array.isArray(s.required), campo, 'objeto deve ser fechado');
106
+ exigir(s.required.every(k => typeof k === 'string' && Object.hasOwn(s.properties, k)), campo, 'required desconhecido');
107
+ exigir(new Set(s.required).size === s.required.length, campo, 'required repetido');
108
+ for (const [k, filho] of Object.entries(s.properties))
109
+ visitar(filho, `${campo}.properties.${k}`, nivel + 1);
110
+ }
111
+ if (s.type === 'array')
112
+ visitar(s.items, `${campo}.items`, nivel + 1);
113
+ // Nao aceitar restricoes impossiveis como const de outro tipo ou fora do enum.
114
+ const valores = Object.hasOwn(s, 'const') ? [s.const] : s.enum ?? [];
115
+ for (const v of valores)
116
+ validarValor(v, s, campo);
117
+ }
118
+ visitar(schema, '$schema', 0);
119
+ }
120
+ function validarValor(v, s, campo) {
121
+ const tipoOk = s.type === 'object' ? objeto(v) : s.type === 'array' ? Array.isArray(v) :
122
+ s.type === 'null' ? v === null : s.type === 'integer' ? Number.isSafeInteger(v) : typeof v === s.type;
123
+ exigir(tipoOk, campo, `tipo esperado: ${s.type}`);
124
+ if (Object.hasOwn(s, 'const'))
125
+ exigir(v === s.const, campo, 'const divergente');
126
+ if (Array.isArray(s.enum))
127
+ exigir(s.enum.includes(v), campo, 'valor fora do enum');
128
+ if (typeof v === 'string' || Array.isArray(v)) {
129
+ const tamanho = typeof v === 'string' ? [...v].length : v.length;
130
+ const min = s[typeof v === 'string' ? 'minLength' : 'minItems'];
131
+ const max = s[typeof v === 'string' ? 'maxLength' : 'maxItems'];
132
+ exigir(min === undefined || tamanho >= min, campo, 'tamanho abaixo do minimo');
133
+ exigir(max === undefined || tamanho <= max, campo, 'tamanho acima do maximo');
134
+ }
135
+ if (objeto(v)) {
136
+ const props = s.properties;
137
+ for (const k of s.required)
138
+ exigir(Object.hasOwn(v, k), `${campo}.${k}`, 'campo obrigatorio ausente');
139
+ for (const k of Object.keys(v)) {
140
+ exigir(Object.hasOwn(props, k), `${campo}.${k}`, 'campo desconhecido');
141
+ validarValor(v[k], props[k], `${campo}.${k}`);
142
+ }
143
+ }
144
+ if (Array.isArray(v))
145
+ v.forEach((item, i) => validarValor(item, s.items, `${campo}[${i}]`));
146
+ }
147
+ function validarContratoPlaybook(valor, schema) {
148
+ validarSchemaPlaybook(schema);
149
+ exigirJson(valor);
150
+ validarValor(valor, schema, '$');
151
+ }
152
+ /** Canonizacao independente da ordem de propriedades; arrays preservam sua ordem. */
153
+ function hashJsonPlaybook(valor) {
154
+ exigirJson(valor);
155
+ function canonico(v) {
156
+ if (Array.isArray(v))
157
+ return `[${v.map(canonico).join(',')}]`;
158
+ if (objeto(v))
159
+ return `{${Object.keys(v).sort().map(k => `${JSON.stringify(k)}:${canonico(v[k])}`).join(',')}}`;
160
+ return JSON.stringify(v);
161
+ }
162
+ return (0, node_crypto_1.createHash)('sha256').update(canonico(valor)).digest('hex');
163
+ }
164
+ exports.textoPlaybook = { type: 'string', minLength: 1, maxLength: 4096 };
165
+ function objetoFechado(properties, required = Object.keys(properties)) {
166
+ return { type: 'object', properties, required, additionalProperties: false };
167
+ }
168
+ function listaPlaybook(items, minItems = 0) {
169
+ return { type: 'array', items, minItems, maxItems: 256 };
170
+ }
171
+ const schemaFase = objetoFechado({
172
+ schemaVersion: { type: 'integer', const: exports.PLAYBOOK_VERSION },
173
+ fase: { type: 'string', enum: ['GOAL', 'PLAN', 'GO', 'CHECK', 'SHIP', 'MASTER'] },
174
+ slug: exports.textoPlaybook, sessionId: exports.textoPlaybook, dispatchId: exports.textoPlaybook,
175
+ estado: { type: 'string', enum: ['concluida', 'falhou', 'interrompida'] },
176
+ reciboId: exports.textoPlaybook,
177
+ resultado: objetoFechado({
178
+ produtoHomologado: { type: 'boolean' }, GOIntegralConcluido: { type: 'boolean' }, checkpoint: exports.textoPlaybook,
179
+ }),
180
+ });
181
+ /** Apenas contrato e correlacao. T06 consumira a prova terminal externa de I04. */
182
+ function validarResultadoFasePlaybook(valor, esperado) {
183
+ validarContratoPlaybook(valor, schemaFase);
184
+ const r = valor;
185
+ for (const k of ['fase', 'slug', 'sessionId', 'dispatchId'])
186
+ exigir(r[k] === esperado[k], k, 'despacho divergente');
187
+ return r;
188
+ }
package/dist/policies.js CHANGED
@@ -15,8 +15,10 @@ exports.POLICIES_CONHECIDAS = void 0;
15
15
  exports.procurarSegredos = procurarSegredos;
16
16
  exports.policiesDesconhecidas = policiesDesconhecidas;
17
17
  exports.avaliarPolicies = avaliarPolicies;
18
+ exports.avisos = avisos;
18
19
  exports.bloqueantes = bloqueantes;
19
20
  exports.motivoDominante = motivoDominante;
21
+ exports.linhasDeAviso = linhasDeAviso;
20
22
  exports.textoDeViolacoes = textoDeViolacoes;
21
23
  /**
22
24
  * Variaveis que REDIRECIONAM o despacho do `claude` para um provider pago.
@@ -73,6 +75,24 @@ exports.POLICIES_CONHECIDAS = {
73
75
  quando: ['ship'],
74
76
  descricao: 'proibe entregar sem branch de thread (push direto na base)',
75
77
  },
78
+ // RM-008 (fatia 3): licoes do loop de aprendizado que o `ork` sabe conferir sem ambiguidade.
79
+ // O nome e o mesmo que o `ork licoes` propoe, para a proposta ser declarada como veio.
80
+ verify_regression: {
81
+ quando: ['phase.dispatch'],
82
+ descricao: 'avisa quando o bloco que contem GO sai sem baseline gravada',
83
+ },
84
+ verify_failed: {
85
+ quando: ['phase.dispatch'],
86
+ descricao: 'avisa quando o bloco que contem GO sai sem baseline gravada (mesma conferencia de verify_regression)',
87
+ },
88
+ runtime_unavailable: {
89
+ quando: ['phase.dispatch'],
90
+ descricao: 'avisa quando o bloco despachado nao declara runtime de fallback',
91
+ },
92
+ tree_blocked: {
93
+ quando: ['ship'],
94
+ descricao: 'avisa quando a branch da thread esta atras da base',
95
+ },
76
96
  };
77
97
  function severidade(bruta) {
78
98
  if (bruta === 'block' || bruta === 'warn' || bruta === 'off')
@@ -87,6 +107,8 @@ function policiesDesconhecidas(manifesto) {
87
107
  function avaliarPolicies(manifesto, ctx) {
88
108
  const declaradas = manifesto.policies ?? {};
89
109
  const violacoes = [];
110
+ // verify_regression e verify_failed conferem a mesma coisa: um aviso so, com o nome da primeira declarada.
111
+ let baselineJaAvaliada = false;
90
112
  for (const [nome, bruta] of Object.entries(declaradas)) {
91
113
  const conhecida = exports.POLICIES_CONHECIDAS[nome];
92
114
  if (!conhecida || !conhecida.quando.includes(ctx.gate))
@@ -148,9 +170,52 @@ function avaliarPolicies(manifesto, ctx) {
148
170
  }
149
171
  continue;
150
172
  }
173
+ if (nome === 'verify_regression' || nome === 'verify_failed') {
174
+ if (baselineJaAvaliada)
175
+ continue;
176
+ baselineJaAvaliada = true;
177
+ if (ctx.blocoComGo === true && ctx.temBaseline === false) {
178
+ violacoes.push({
179
+ policy: nome,
180
+ severidade: sev,
181
+ motivo: 'policy.violation',
182
+ detalhe: 'o bloco que contem GO vai sair sem baseline: uma falha que ja existia passaria por regressao desta thread',
183
+ correcao: `ork verify ${ctx.threadId ?? '<thread>'} --baseline`,
184
+ });
185
+ }
186
+ continue;
187
+ }
188
+ if (nome === 'runtime_unavailable') {
189
+ if (Array.isArray(ctx.fallbackDoBloco) && ctx.fallbackDoBloco.length === 0) {
190
+ violacoes.push({
191
+ policy: nome,
192
+ severidade: sev,
193
+ motivo: 'policy.violation',
194
+ detalhe: 'o bloco nao declara runtime de fallback: se o runtime cair, a fase para ate alguem trocar a mao',
195
+ correcao: `ork setup ${ctx.modo ?? '<modo>'} --bloco ${ctx.bloco ?? 'N'} --fallback <runtime:modelo>`,
196
+ });
197
+ }
198
+ continue;
199
+ }
200
+ if (nome === 'tree_blocked') {
201
+ if (ctx.branchAtrasDaBase === true) {
202
+ violacoes.push({
203
+ policy: nome,
204
+ severidade: sev,
205
+ motivo: 'policy.violation',
206
+ detalhe: `a branch "${ctx.de ?? 'da thread'}" esta atras de "${ctx.para ?? ctx.baseBranch ?? 'base'}": a entrega mistura a mudanca com o que a base ja andou`,
207
+ correcao: `ork worktree sync ${ctx.threadId ?? '<thread>'}`,
208
+ });
209
+ }
210
+ continue;
211
+ }
151
212
  }
152
213
  return violacoes;
153
214
  }
215
+ /** So as violacoes com severidade `warn` (as que registram e seguem). */
216
+ function avisos(violacoes) {
217
+ return violacoes.filter((v) => v.severidade === 'warn');
218
+ }
154
219
  /** So as violacoes com severidade `block` (as que reprovam em qualquer modo). */
155
220
  function bloqueantes(violacoes) {
156
221
  return violacoes.filter((v) => v.severidade === 'block');
@@ -168,6 +233,13 @@ function motivoDominante(violacoes) {
168
233
  ? 'cost.violation'
169
234
  : 'policy.violation';
170
235
  }
236
+ /** RM-008 (fatia 3): as linhas de aviso (policies em warn) para a saida do CLI. Nada quando nao ha aviso. */
237
+ function linhasDeAviso(violacoes, recuo = ' ') {
238
+ return avisos(violacoes).flatMap((v) => [
239
+ `${recuo}aviso da policy ${v.policy}: ${v.detalhe}`,
240
+ `${recuo} correcao: ${v.correcao}`,
241
+ ]);
242
+ }
171
243
  /** Texto das violacoes para a saida do CLI. */
172
244
  function textoDeViolacoes(violacoes) {
173
245
  return violacoes
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.inspectPortfolio = inspectPortfolio;
4
+ /** Inspeção por identidade: o estado do catálogo não é inferido de ciclos. */
5
+ const portfolio_1 = require("./portfolio");
6
+ const objective_1 = require("./objective");
7
+ const statusLabels = {
8
+ awaiting_approval: 'Aguardando aprovação', running: 'Em andamento', paused: 'Pausado', validated: 'Validado no ciclo', stopped: 'Interrompido',
9
+ };
10
+ function inspectPortfolio(root, id, readCycles = objective_1.listObjectives) {
11
+ if (!/^(prod|proj|init)-[a-z0-9][a-z0-9-]{2,47}$/.test(id))
12
+ throw new Error('portfolio.id: identidade inválida');
13
+ const entity = (0, portfolio_1.findEntity)(root, id);
14
+ if (!entity)
15
+ throw new Error('portfolio.unavailable: entidade indisponível');
16
+ const portfolio = (0, portfolio_1.readPortfolio)(root);
17
+ const parentId = entity.kind === 'project' ? entity.productId : entity.kind === 'initiative' ? entity.projectId : null;
18
+ const parent = parentId ? (0, portfolio_1.findEntity)(root, parentId) : null;
19
+ const result = {
20
+ schema: 'ork.portfolio-context/v1', entity, parent,
21
+ origin: { authority: 'ork.portfolio', schema: portfolio.schema, reference: `portfolio:${entity.id}`, catalogUpdatedAt: portfolio.updatedAt, observedAt: new Date().toISOString(), creationOperationId: entity.creationOperationId ?? null },
22
+ cycles: [], cyclesState: 'available', cyclesMessage: 'Nenhum ciclo vinculado',
23
+ gaps: ['delivery.receipt_not_loaded'], conflicts: [], references: parentId ? [{ kind: 'entity', id: parentId }] : [],
24
+ };
25
+ if (!entity.creationOperationId)
26
+ result.gaps.push('origin.legacy');
27
+ if (parentId && !parent)
28
+ result.gaps.push('parent.unavailable');
29
+ try {
30
+ for (const cycle of readCycles(root)) {
31
+ const scope = cycle.envelope.portfolio;
32
+ if (!scope)
33
+ continue;
34
+ const matches = entity.kind === 'product' ? scope.productId === entity.id
35
+ : entity.kind === 'project' ? scope.projectId === entity.id
36
+ : scope.projectId === entity.projectId && (scope.delivery === 'project' || scope.initiativeIds.includes(entity.id));
37
+ if (!matches)
38
+ continue;
39
+ const relation = entity.kind === 'product' || (entity.kind === 'initiative' && scope.delivery === 'project') ? 'project_context'
40
+ : scope.delivery === 'project' ? 'project_delivery' : 'initiative_delivery';
41
+ result.cycles.push({ id: cycle.id, title: cycle.title, status: cycle.status, statusLabel: statusLabels[cycle.status] ?? 'Estado não confirmado', relation,
42
+ projectId: scope.projectId, initiativeIds: [...scope.initiativeIds], updatedAt: cycle.updatedAt, envelopeHash: cycle.envelope.hash, entityDeliveryProven: false });
43
+ result.references.push({ kind: 'objective', id: cycle.id });
44
+ if (entity.status === 'delivered' && ['running', 'paused', 'awaiting_approval'].includes(cycle.status)) {
45
+ result.conflicts.push({ code: 'entity.delivered_cycle_open', cycleId: cycle.id });
46
+ }
47
+ }
48
+ result.cycles.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt) || a.id.localeCompare(b.id));
49
+ if (result.cycles.length)
50
+ result.cyclesMessage = 'Ciclos vinculados; escopo e estado independentes do catálogo';
51
+ }
52
+ catch {
53
+ result.cycles = [];
54
+ result.conflicts = [];
55
+ result.references = result.references.filter((reference) => reference.kind === 'entity');
56
+ result.cyclesState = 'unavailable';
57
+ result.cyclesMessage = 'Consulta de ciclos indisponível';
58
+ result.gaps.push('cycles.unavailable');
59
+ }
60
+ return result;
61
+ }