@orkastery/cli 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/adapters/README.md +11 -0
  2. package/adapters/claude-code/.claude-plugin/plugin.json +3 -1
  3. package/adapters/claude-code/agents/ork-check.md +1 -1
  4. package/adapters/claude-code/agents/ork-go.md +2 -2
  5. package/adapters/claude-code/agents/ork-goal.md +1 -1
  6. package/adapters/claude-code/agents/ork-master.md +1 -1
  7. package/adapters/claude-code/agents/ork-plan.md +1 -1
  8. package/adapters/claude-code/agents/ork-ship.md +1 -1
  9. package/adapters/claude-code/commands/master.md +11 -8
  10. package/adapters/claude-code/commands/ork.md +8 -0
  11. package/adapters/claude-code/commands/ship.md +2 -2
  12. package/adapters/codex/skills/ork/SKILL.md +12 -1
  13. package/adapters/hermes/README.md +3 -0
  14. package/adapters/hermes/bin/ork-abrir-thread.sh +17 -2
  15. package/adapters/hermes/bin/ork-brain.sh +3 -0
  16. package/adapters/hermes/bin/ork-maestro.sh +4 -1
  17. package/adapters/hermes/bin/ork-network-roadmap.sh +11 -0
  18. package/adapters/hermes/bin/ork-roadmap-status.sh +9 -0
  19. package/adapters/hermes/hermes.plugin.json +2 -0
  20. package/adapters/hermes/hitl-ingress/__init__.py +36 -3
  21. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +19 -20
  22. package/adapters/openclaw/README.md +34 -2
  23. package/adapters/openclaw/dist/hitl-ingress.js +37 -3
  24. package/adapters/openclaw/dist/index.js +92 -20
  25. package/adapters/openclaw/openclaw.plugin.json +10 -1
  26. package/adapters/openclaw/package.json +2 -2
  27. package/adapters/openclaw/src/hitl-ingress.ts +32 -3
  28. package/adapters/openclaw/src/index.ts +108 -20
  29. package/assets/docs/padroes/documentacao-de-produto.md +2 -2
  30. package/assets/docs/padroes/roadmap-de-produto.md +1 -1
  31. package/assets/docs/produto/_modelo-feature.md +2 -0
  32. package/assets/orkmind_bridge.py +214 -1
  33. package/dist/adapters/claude-bg.js +6 -3
  34. package/dist/board.js +74 -0
  35. package/dist/branch-de-estado.js +5 -4
  36. package/dist/busca-semantica.js +161 -0
  37. package/dist/ci.js +141 -10
  38. package/dist/company-brain-cli.js +27 -2
  39. package/dist/company-brain-context.js +132 -0
  40. package/dist/company-brain-dossie.js +376 -0
  41. package/dist/company-brain-mcp.js +4 -1
  42. package/dist/conducao.js +71 -18
  43. package/dist/decisao-autonoma.js +42 -0
  44. package/dist/docs.js +64 -22
  45. package/dist/doctor.js +33 -0
  46. package/dist/entrega-pr.js +109 -5
  47. package/dist/experiencia-instalacao.js +256 -0
  48. package/dist/experiencia.js +72 -0
  49. package/dist/fabrica-estado.js +43 -10
  50. package/dist/fechamento.js +105 -0
  51. package/dist/forja.js +435 -0
  52. package/dist/gates.js +9 -1
  53. package/dist/hitl-classificacao.js +11 -1
  54. package/dist/hitl-contract.js +50 -7
  55. package/dist/hitl-curto.js +158 -0
  56. package/dist/hitl-gates.js +67 -1
  57. package/dist/hitl-lote.js +30 -15
  58. package/dist/hitl-presentation.js +10 -7
  59. package/dist/hitl-resumo.js +33 -12
  60. package/dist/hitl-texto-livre.js +150 -0
  61. package/dist/hosts.js +86 -1
  62. package/dist/index.js +602 -38
  63. package/dist/indice-vetorial.js +317 -0
  64. package/dist/init.js +13 -0
  65. package/dist/integracoes-locais.js +1 -1
  66. package/dist/intelligence-benchmark-contract.js +570 -0
  67. package/dist/intelligence-graph-cli.js +430 -0
  68. package/dist/intelligence-graph-contract.js +577 -0
  69. package/dist/intelligence-graph-extract-md.js +469 -0
  70. package/dist/intelligence-graph-extract-ts.js +810 -0
  71. package/dist/intelligence-graph-extract.js +369 -0
  72. package/dist/intelligence-graph-index.js +512 -0
  73. package/dist/intelligence-graph-parsers.js +327 -0
  74. package/dist/intelligence-graph-query.js +344 -0
  75. package/dist/intelligence-graph-repo.js +187 -0
  76. package/dist/leases.js +84 -0
  77. package/dist/ledger.js +14 -0
  78. package/dist/maestro-cli.js +10 -1
  79. package/dist/maestro-contract.js +5 -1
  80. package/dist/maestro-discovery.js +16 -2
  81. package/dist/maestro-snapshot.js +6 -2
  82. package/dist/manifest.js +142 -5
  83. package/dist/master-batch.js +3 -2
  84. package/dist/master-digest.js +2 -2
  85. package/dist/master-nota.js +203 -0
  86. package/dist/master.js +4 -0
  87. package/dist/mcp-experiencia.js +164 -0
  88. package/dist/mcp-git.js +4 -0
  89. package/dist/mcp-install.js +3 -1
  90. package/dist/mcp-maestro.js +3 -2
  91. package/dist/mcp-server.js +84 -5
  92. package/dist/memoria.js +147 -1
  93. package/dist/network-roadmap.js +907 -0
  94. package/dist/ocupacao.js +38 -2
  95. package/dist/onboarding.js +113 -7
  96. package/dist/orkmind.js +165 -9
  97. package/dist/phase.js +166 -13
  98. package/dist/policies.js +2 -0
  99. package/dist/projeto-alvo.js +551 -0
  100. package/dist/prompts.js +1 -1
  101. package/dist/pulse-consentimento.js +4 -2
  102. package/dist/pulse-delivery.js +5 -0
  103. package/dist/pulse-resposta.js +674 -49
  104. package/dist/pulse.js +21 -0
  105. package/dist/retry.js +51 -8
  106. package/dist/roadmap-reservas.js +262 -20
  107. package/dist/roadmap-status.js +213 -0
  108. package/dist/thread-close.js +3 -0
  109. package/dist/verify.js +4 -3
  110. package/eval/casos/orchestration-experience-pt-br.json +48 -0
  111. package/eval/casos/orchestration-experience.json +48 -0
  112. package/package.json +1 -1
  113. package/schemas/code-artifact-graph.v1.schema.json +581 -0
  114. package/schemas/graph-benchmark.v1.schema.json +2240 -0
  115. package/schemas/maestro-snapshot.schema.json +23 -0
  116. package/skills/README.md +7 -5
  117. package/skills/core/onboarding/SKILL.md +7 -0
  118. package/skills/core/orchestration-experience/SKILL.md +113 -0
  119. package/skills/core/orchestration-experience-pt-br/SKILL.md +112 -0
  120. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  121. package/skills/phases/go-implementation/SKILL.md +2 -0
@@ -0,0 +1,570 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.digestDoConjuntoDeArestas = exports.benchmarkSchema = exports.execucaoSchema = exports.auditoriaSchema = exports.protocoloSchema = exports.parSchema = exports.tarefaSchema = exports.controlesSchema = exports.requisicaoSchema = exports.metricasSchema = exports.medidaDeCustoSchema = exports.medidaDeContextoSchema = exports.medidaDeLatenciaSchema = exports.medidaDeChamadasSchema = exports.medidaDeTokensSchema = exports.MOTIVOS_DE_LACUNA = exports.MOTIVOS_DE_FALHA = exports.METODO_DE_LATENCIA = exports.METRICAS_REQUERIVEIS = exports.DESFECHOS_COM_RETRY = exports.DESFECHOS = exports.ORIGENS_DE_CONSUMO_MEDIDO = exports.ORIGENS_DE_MEDIDA = exports.PROTOCOLO_KG1 = exports.BENCHMARK_SCHEMA = void 0;
4
+ exports.validarBenchmark = validarBenchmark;
5
+ exports.mediana = mediana;
6
+ exports.avaliarBenchmark = avaliarBenchmark;
7
+ /**
8
+ * I-31 KG1 (D1, D6 a D8, D10): contrato `ork.graph-benchmark/v1` do experimento A/B do grafo.
9
+ *
10
+ * A e o fluxo de leitura existente, B e o mesmo fluxo com o grafo deterministico; o resto do
11
+ * par fica fixo no protocolo. Validacao do registro e avaliacao do resultado sao funcoes
12
+ * separadas: estrutura invalida e erro de contrato, e so um registro valido recebe veredito.
13
+ * Modulo puro (D10): nao executa modelo, nao le telemetria nem arquivo. Avalia o que recebe.
14
+ * O KG1 nao traz medicao real: registro sintetico nunca e publicavel como economia medida.
15
+ */
16
+ const zod_1 = require("zod");
17
+ const intelligence_graph_contract_1 = require("./intelligence-graph-contract");
18
+ exports.BENCHMARK_SCHEMA = 'ork.graph-benchmark/v1';
19
+ exports.PROTOCOLO_KG1 = 'kg1-ab/1';
20
+ /** D7: de onde veio a medida. So as duas primeiras demonstram consumo. */
21
+ exports.ORIGENS_DE_MEDIDA = ['runtime_reported', 'tokenizer_exact', 'estimated', 'unavailable'];
22
+ exports.ORIGENS_DE_CONSUMO_MEDIDO = ['runtime_reported', 'tokenizer_exact'];
23
+ exports.DESFECHOS = ['completed', 'task-failed', 'timeout', 'cancelled', 'error', 'instrumentation-failed'];
24
+ /** Desfechos que admitem nova tentativa; a tentativa conta no consumo do par. */
25
+ exports.DESFECHOS_COM_RETRY = ['task-failed', 'timeout', 'error', 'instrumentation-failed'];
26
+ exports.METRICAS_REQUERIVEIS = ['logical_total_tokens', 'residual_context_tokens', 'tool_calls', 'latency_ms', 'cost', 'index_preparation'];
27
+ exports.METODO_DE_LATENCIA = 'monotonic-clock';
28
+ /** D8: motivos de `fail` (rigor violado ou mediana sem ganho com dados completos). */
29
+ exports.MOTIVOS_DE_FALHA = [
30
+ 'fato-perdido', 'claim-nao-preservada', 'verify-falhou', 'verify-nao-preservado', 'aresta-falsa',
31
+ 'tarefa-nao-concluida', 'mediana-nao-menor',
32
+ ];
33
+ /** D8: motivos de `inconclusive` (dado, controle ou auditoria insuficiente). */
34
+ exports.MOTIVOS_DE_LACUNA = [
35
+ 'amostra-incompleta', 'aquecimento-divergente', 'controles-divergentes', 'pergunta-divergente', 'ordem-divergente', 'falha-de-instrumentacao',
36
+ 'tarefa-cancelada', 'metrica-primaria-ausente', 'metrica-primaria-sem-consumo-medido', 'origens-nao-equivalentes',
37
+ 'metrica-requerida-ausente', 'metrica-requerida-estimada', 'auditoria-incompleta',
38
+ ];
39
+ const MAX = Number.MAX_SAFE_INTEGER;
40
+ const inteiro = zod_1.z.number().int().min(0).max(MAX);
41
+ const positivo = zod_1.z.number().int().min(1).max(100_000);
42
+ const sha256 = zod_1.z.string().regex(/^[a-f0-9]{64}$/);
43
+ const id = zod_1.z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/);
44
+ const texto = zod_1.z.string().min(1).max(512);
45
+ const instante = zod_1.z.string().datetime({ offset: true });
46
+ const idDeAresta = zod_1.z.string().regex(/^edge-[a-f0-9]{64}$/);
47
+ const idDeSnapshot = zod_1.z.string().regex(/^snap-[a-f0-9]{64}$/);
48
+ const referencia = zod_1.z.object({ ref: texto, sha256 }).strict();
49
+ const baseDaMedida = {
50
+ value: zod_1.z.number().finite().min(0).nullable(),
51
+ source: zod_1.z.enum(exports.ORIGENS_DE_MEDIDA),
52
+ method: texto,
53
+ method_version: texto,
54
+ evidence_ref: referencia.nullable(),
55
+ unavailable_reason: texto.nullable(),
56
+ };
57
+ exports.medidaDeTokensSchema = zod_1.z.object({ ...baseDaMedida, unit: zod_1.z.literal('tokens') }).strict();
58
+ exports.medidaDeChamadasSchema = zod_1.z.object({ ...baseDaMedida, unit: zod_1.z.literal('calls') }).strict();
59
+ exports.medidaDeLatenciaSchema = zod_1.z.object({ ...baseDaMedida, unit: zod_1.z.literal('ms') }).strict();
60
+ /** D7: contexto residual com a janela e o ponto de leitura. */
61
+ exports.medidaDeContextoSchema = zod_1.z.object({
62
+ ...baseDaMedida, unit: zod_1.z.literal('tokens'), window_tokens: inteiro.nullable(), read_point: zod_1.z.enum(['task-end']),
63
+ }).strict();
64
+ /** D7: custo com moeda, natureza e tabela; assinatura nao atribuivel e `null` com motivo. */
65
+ exports.medidaDeCustoSchema = zod_1.z.object({
66
+ ...baseDaMedida, unit: zod_1.z.string().regex(/^[A-Z]{3}$/),
67
+ cost_kind: zod_1.z.enum(['paid', 'marginal', 'attributed']).nullable(),
68
+ rate_card: zod_1.z.object({ id, version: texto }).strict().nullable(),
69
+ }).strict();
70
+ exports.metricasSchema = zod_1.z.object({
71
+ logical_total_tokens: exports.medidaDeTokensSchema,
72
+ input_total_tokens: exports.medidaDeTokensSchema,
73
+ output_total_tokens: exports.medidaDeTokensSchema,
74
+ cached_input_tokens: exports.medidaDeTokensSchema,
75
+ reasoning_tokens: exports.medidaDeTokensSchema,
76
+ residual_context_tokens: exports.medidaDeContextoSchema,
77
+ tool_calls: exports.medidaDeChamadasSchema,
78
+ latency_ms: exports.medidaDeLatenciaSchema,
79
+ cost: exports.medidaDeCustoSchema,
80
+ }).strict();
81
+ /**
82
+ * Uma requisicao ao modelo, em delta: telemetria cumulativa chega aqui ja convertida. Toda
83
+ * requisicao real envia ao menos um token; requisicao zerada nao sustenta consumo medido.
84
+ */
85
+ exports.requisicaoSchema = zod_1.z.object({
86
+ request_id: id, input_total_tokens: zod_1.z.number().int().min(1).max(MAX), output_total_tokens: inteiro, cached_input_tokens: inteiro, reasoning_tokens: inteiro,
87
+ }).strict();
88
+ /** D6: tudo o que fica igual nos dois bracos do par. */
89
+ exports.controlesSchema = zod_1.z.object({
90
+ model: texto, model_revision: texto, provider: texto, runtime: texto, runtime_version: texto, effort: texto,
91
+ sampling: zod_1.z.object({
92
+ temperature: zod_1.z.number().finite().min(0).max(10).nullable(),
93
+ top_p: zod_1.z.number().finite().min(0).max(1).nullable(),
94
+ seed: zod_1.z.number().int().min(0).max(MAX).nullable(),
95
+ seed_unavailable_reason: texto.nullable(),
96
+ }).strict(),
97
+ base_prompt_hash: sha256, tools_hash: sha256, stop_rules_hash: sha256,
98
+ budget: zod_1.z.object({ max_total_tokens: inteiro, max_context_tokens: inteiro, max_wall_ms: inteiro }).strict(),
99
+ snapshot_id: idDeSnapshot,
100
+ tenant_id: zod_1.z.string().regex(/^[a-z0-9][a-z0-9._-]{0,63}$/),
101
+ acl_policy_hash: sha256,
102
+ }).strict();
103
+ exports.tarefaSchema = zod_1.z.object({
104
+ task_id: id, question_hash: sha256,
105
+ mandatory_fact_ids: zod_1.z.array(id).min(1).max(1000),
106
+ claim_ids: zod_1.z.array(id).max(1000),
107
+ verifiers: zod_1.z.array(zod_1.z.object({ verify_id: id, command_hash: sha256 }).strict()).max(1000),
108
+ }).strict();
109
+ exports.parSchema = zod_1.z.object({ pair_id: id, task_id: id, repetition: positivo, order: zod_1.z.enum(['AB', 'BA']) }).strict();
110
+ /** D6: fixado antes da primeira execucao. */
111
+ exports.protocoloSchema = zod_1.z.object({
112
+ protocol_version: zod_1.z.literal(exports.PROTOCOLO_KG1),
113
+ corpus: zod_1.z.object({ corpus_id: id, corpus_version: texto, corpus_hash: sha256 }).strict(),
114
+ tasks: zod_1.z.array(exports.tarefaSchema).min(1).max(1000),
115
+ repetitions_per_task: positivo,
116
+ pairs: zod_1.z.array(exports.parSchema).min(1).max(100_000),
117
+ order_seed: texto,
118
+ controls: exports.controlesSchema,
119
+ treatment: zod_1.z.object({
120
+ graph_schema: zod_1.z.literal(intelligence_graph_contract_1.GRAFO_SCHEMA), graph_digest: sha256, snapshot_id: idDeSnapshot, edge_count: inteiro,
121
+ /** D8: digest do conjunto de `edge_id` do grafo, que ancora o universo da auditoria. */
122
+ edge_set_digest: sha256,
123
+ }).strict(),
124
+ environment_hash: sha256,
125
+ cache_policy: zod_1.z.enum(['cold', 'warm']),
126
+ warmup_runs_per_arm: zod_1.z.number().int().min(0).max(100),
127
+ retry_policy: zod_1.z.object({ max_attempts: zod_1.z.number().int().min(1).max(100) }).strict(),
128
+ tool_call_convention: zod_1.z.enum(['model-requested', 'executed']),
129
+ latency_boundary: zod_1.z.literal('end-to-end'),
130
+ primary_metric: zod_1.z.literal('logical_total_tokens'),
131
+ required_metrics: zod_1.z.array(zod_1.z.enum(exports.METRICAS_REQUERIVEIS)).min(1).max(exports.METRICAS_REQUERIVEIS.length),
132
+ }).strict();
133
+ /** D8: auditoria de arestas do grafo usado pelo braco B. */
134
+ exports.auditoriaSchema = zod_1.z.object({
135
+ graph_digest: sha256,
136
+ universe_edge_ids: zod_1.z.array(idDeAresta).max(500_000),
137
+ examined: zod_1.z.array(zod_1.z.object({
138
+ edge_id: idDeAresta, result: zod_1.z.enum(['supported', 'false', 'unverified']), source_refs: zod_1.z.array(referencia).max(64),
139
+ }).strict()).max(500_000),
140
+ method: texto,
141
+ method_version: texto,
142
+ }).strict();
143
+ exports.execucaoSchema = zod_1.z.object({
144
+ run_id: id, session_id: id, pair_id: id.nullable(), arm: zod_1.z.enum(['A', 'B']), task_id: id,
145
+ repetition: positivo.nullable(), attempt: zod_1.z.number().int().min(1).max(100), warmup: zod_1.z.boolean(),
146
+ started_at: instante, ended_at: instante, outcome: zod_1.z.enum(exports.DESFECHOS),
147
+ controls: exports.controlesSchema, question_hash: sha256,
148
+ metrics: exports.metricasSchema,
149
+ requests: zod_1.z.array(exports.requisicaoSchema).max(10_000),
150
+ mandatory_fact_results: zod_1.z.array(zod_1.z.object({ fact_id: id, result: zod_1.z.enum(['present', 'missing']) }).strict()).max(1000),
151
+ claim_results: zod_1.z.array(zod_1.z.object({ claim_id: id, result: zod_1.z.enum(['verified', 'failed', 'removed']) }).strict()).max(1000),
152
+ verify_results: zod_1.z.array(zod_1.z.object({
153
+ verify_id: id, command_hash: sha256, exit_code: zod_1.z.number().int().nullable(), result: zod_1.z.enum(['pass', 'fail']),
154
+ }).strict()).max(1000),
155
+ edge_audit: exports.auditoriaSchema.nullable(),
156
+ artifacts: zod_1.z.array(referencia).max(1000),
157
+ }).strict();
158
+ exports.benchmarkSchema = zod_1.z.object({
159
+ schema: zod_1.z.literal(exports.BENCHMARK_SCHEMA),
160
+ experiment_id: id,
161
+ data_class: zod_1.z.enum(['synthetic', 'measured']),
162
+ status: zod_1.z.enum(['not-run', 'partial', 'complete']),
163
+ protocol: exports.protocoloSchema,
164
+ /** D6: preparo do indice fica separado da consulta, nunca escondido nela. */
165
+ index_preparation: zod_1.z.object({
166
+ scenario: zod_1.z.enum(['cold', 'warm']), amortization_hypothesis: texto,
167
+ logical_total_tokens: exports.medidaDeTokensSchema, latency_ms: exports.medidaDeLatenciaSchema, cost: exports.medidaDeCustoSchema,
168
+ }).strict(),
169
+ runs: zod_1.z.array(exports.execucaoSchema).max(200_000),
170
+ receipts_review: zod_1.z.object({ state: zod_1.z.enum(['pending', 'reviewed']), receipt_ref: referencia.nullable() }).strict(),
171
+ evidence_refs: zod_1.z.array(referencia).max(10_000),
172
+ }).strict();
173
+ /** D8: digest do conjunto de arestas, na ordem dos bytes UTF-8, para ancorar a auditoria ao grafo. */
174
+ const digestDoConjuntoDeArestas = (ids) => (0, intelligence_graph_contract_1.sha256DoCanonico)([...ids].sort(intelligence_graph_contract_1.compararUtf8));
175
+ exports.digestDoConjuntoDeArestas = digestDoConjuntoDeArestas;
176
+ function falha(codigo, onde) {
177
+ throw new Error(onde ? `${codigo} em ${onde}` : codigo);
178
+ }
179
+ function semRepeticao(valores, codigo, onde) {
180
+ const s = new Set(valores);
181
+ if (s.size !== valores.length)
182
+ falha(codigo, onde);
183
+ return s;
184
+ }
185
+ /** D7: ausente e explicito. Nunca zero no lugar de desconhecido, nunca valor sem evidencia. */
186
+ function conferirMedida(m, inteira, onde) {
187
+ const ausente = m.value === null;
188
+ if (ausente !== (m.source === 'unavailable') || ausente !== (m.unavailable_reason !== null))
189
+ falha('benchmark.metrica.ausencia-inconsistente', onde);
190
+ if (ausente)
191
+ return;
192
+ if (m.evidence_ref === null)
193
+ falha('benchmark.metrica.sem-evidencia', onde);
194
+ if (inteira && !Number.isSafeInteger(m.value))
195
+ falha('benchmark.metrica.nao-inteiro', onde);
196
+ }
197
+ function conferirCusto(m, onde) {
198
+ conferirMedida(m, false, onde);
199
+ if (m.value === null) {
200
+ if (m.cost_kind !== null)
201
+ falha('benchmark.metrica.custo-sem-origem', onde);
202
+ return;
203
+ }
204
+ if (m.cost_kind === null || (m.source !== 'runtime_reported' && m.rate_card === null))
205
+ falha('benchmark.metrica.custo-sem-origem', onde);
206
+ }
207
+ function conferirLatencia(m, onde) {
208
+ conferirMedida(m, false, onde);
209
+ if (m.value !== null && m.method !== exports.METODO_DE_LATENCIA)
210
+ falha('benchmark.metrica.latencia-sem-relogio-monotonico', onde);
211
+ // Tokenizador nao mede tempo: latencia medida vem do executor.
212
+ if (m.source === 'tokenizer_exact')
213
+ falha('benchmark.metrica.origem-invalida', onde);
214
+ }
215
+ /** Custo por tabela herda a origem dos tokens que ele multiplica. */
216
+ function conferirOrigemDoCusto(custo, tokens, onde) {
217
+ if (custo.value !== null && custo.rate_card !== null && exports.ORIGENS_DE_CONSUMO_MEDIDO.includes(custo.source) && custo.source !== tokens.source) {
218
+ falha('benchmark.metrica.origem-invalida', onde);
219
+ }
220
+ }
221
+ function conferirSeed(c, onde) {
222
+ if ((c.sampling.seed === null) === (c.sampling.seed_unavailable_reason === null))
223
+ falha('benchmark.controle.seed-sem-motivo', onde);
224
+ }
225
+ const TOKENS = ['input_total_tokens', 'output_total_tokens', 'cached_input_tokens', 'reasoning_tokens'];
226
+ /** O que cada medida de tokens soma nas requisicoes; o total logico e entrada mais saida. */
227
+ const PARCELAS = {
228
+ logical_total_tokens: (q) => q.input_total_tokens + q.output_total_tokens,
229
+ input_total_tokens: (q) => q.input_total_tokens,
230
+ output_total_tokens: (q) => q.output_total_tokens,
231
+ cached_input_tokens: (q) => q.cached_input_tokens,
232
+ reasoning_tokens: (q) => q.reasoning_tokens,
233
+ };
234
+ /** D7: subconjuntos reportados, nunca somados duas vezes; requisicao contada uma vez so. */
235
+ function conferirTokens(r, requisicoes, onde) {
236
+ const m = r.metrics;
237
+ for (const k of ['logical_total_tokens', ...TOKENS])
238
+ conferirMedida(m[k], true, `${onde}.metrics.${k}`);
239
+ const [total, entrada, saida, cache, raciocinio] = [m.logical_total_tokens, ...TOKENS.map((k) => m[k])].map((x) => x.value);
240
+ if (total !== null && entrada !== null && saida !== null && total !== entrada + saida)
241
+ falha('benchmark.metrica.total-inconsistente', onde);
242
+ if ((cache !== null && entrada !== null && cache > entrada) || (raciocinio !== null && saida !== null && raciocinio > saida)) {
243
+ falha('benchmark.metrica.subconjunto-inconsistente', onde);
244
+ }
245
+ r.requests.forEach((q, i) => {
246
+ if (requisicoes.has(q.request_id))
247
+ falha('benchmark.metrica.requisicao-recontada', `${onde}.requests.${i}`);
248
+ requisicoes.add(q.request_id);
249
+ if (q.cached_input_tokens > q.input_total_tokens || q.reasoning_tokens > q.output_total_tokens) {
250
+ falha('benchmark.metrica.subconjunto-inconsistente', `${onde}.requests.${i}`);
251
+ }
252
+ });
253
+ // A metrica primaria tambem se concilia: total declarado sem as requisicoes que o somam nao vale.
254
+ // So a tentativa nao concluida que caiu antes da primeira requisicao mede zero sem requisicoes.
255
+ const caiuAntes = r.outcome !== 'completed' && r.requests.length === 0;
256
+ for (const k of ['logical_total_tokens', ...TOKENS]) {
257
+ const medida = m[k];
258
+ if (medida.value === null)
259
+ continue;
260
+ if (exports.ORIGENS_DE_CONSUMO_MEDIDO.includes(medida.source) && r.requests.length === 0 && !(caiuAntes && medida.value === 0)) {
261
+ falha('benchmark.metrica.sem-requisicoes', onde);
262
+ }
263
+ if (r.requests.length && medida.value !== r.requests.reduce((s, q) => s + PARCELAS[k](q), 0))
264
+ falha('benchmark.metrica.requisicoes-divergentes', onde);
265
+ }
266
+ }
267
+ function conferirProtocolo(p) {
268
+ conferirSeed(p.controls, 'protocol.controls');
269
+ if (p.treatment.snapshot_id !== p.controls.snapshot_id)
270
+ falha('benchmark.protocolo.tratamento-divergente');
271
+ semRepeticao(p.tasks.map((t) => t.task_id), 'benchmark.protocolo.tarefa-duplicada', 'protocol.tasks');
272
+ p.tasks.forEach((t, i) => {
273
+ const onde = `protocol.tasks.${i}`;
274
+ semRepeticao(t.mandatory_fact_ids, 'benchmark.protocolo.id-duplicado', onde);
275
+ semRepeticao(t.claim_ids, 'benchmark.protocolo.id-duplicado', onde);
276
+ semRepeticao(t.verifiers.map((v) => v.verify_id), 'benchmark.protocolo.id-duplicado', onde);
277
+ });
278
+ semRepeticao(p.pairs.map((q) => q.pair_id), 'benchmark.protocolo.par-duplicado', 'protocol.pairs');
279
+ const tarefas = new Set(p.tasks.map((t) => t.task_id)), repeticoes = new Set(), ordens = new Map();
280
+ p.pairs.forEach((q, i) => {
281
+ const onde = `protocol.pairs.${i}`;
282
+ if (!tarefas.has(q.task_id))
283
+ falha('benchmark.protocolo.tarefa-ausente', onde);
284
+ const chave = (0, intelligence_graph_contract_1.canonico)([q.task_id, q.repetition]);
285
+ if (q.repetition > p.repetitions_per_task || repeticoes.has(chave))
286
+ falha('benchmark.protocolo.repeticao-invalida', onde);
287
+ repeticoes.add(chave);
288
+ ordens.set(q.task_id, (ordens.get(q.task_id) ?? 0) + (q.order === 'AB' ? 1 : -1));
289
+ });
290
+ if (p.pairs.length !== p.tasks.length * p.repetitions_per_task)
291
+ falha('benchmark.protocolo.amostra-inconsistente');
292
+ // D6: ordem AB/BA balanceada por tarefa, segundo a seed registrada.
293
+ if ([...ordens.values()].some((saldo) => Math.abs(saldo) > 1))
294
+ falha('benchmark.protocolo.ordem-desbalanceada');
295
+ semRepeticao(p.required_metrics, 'benchmark.protocolo.id-duplicado', 'protocol.required_metrics');
296
+ if (!p.required_metrics.includes('logical_total_tokens'))
297
+ falha('benchmark.protocolo.metrica-primaria-ausente');
298
+ }
299
+ function conferirAuditoria(r, p, onde) {
300
+ const a = r.edge_audit;
301
+ if (a === null)
302
+ return;
303
+ if (r.arm === 'A')
304
+ falha('benchmark.auditoria.braco-a', onde);
305
+ if (a.graph_digest !== p.treatment.graph_digest)
306
+ falha('benchmark.auditoria.grafo-divergente', onde);
307
+ const universo = semRepeticao(a.universe_edge_ids, 'benchmark.auditoria.duplicada', onde);
308
+ semRepeticao(a.examined.map((e) => e.edge_id), 'benchmark.auditoria.duplicada', onde);
309
+ for (const e of a.examined) {
310
+ if (!universo.has(e.edge_id))
311
+ falha('benchmark.auditoria.fora-do-universo', onde);
312
+ if (e.result !== 'unverified' && e.source_refs.length === 0)
313
+ falha('benchmark.auditoria.sem-fonte', onde);
314
+ }
315
+ }
316
+ function conferirResultados(r, t, onde) {
317
+ const grupos = [
318
+ [r.mandatory_fact_results.map((x) => x.fact_id), t.mandatory_fact_ids],
319
+ [r.claim_results.map((x) => x.claim_id), t.claim_ids],
320
+ [r.verify_results.map((x) => x.verify_id), t.verifiers.map((v) => v.verify_id)],
321
+ ];
322
+ for (const [registrados, previstos] of grupos) {
323
+ const s = semRepeticao(registrados, 'benchmark.run.resultado-duplicado', onde), esperado = new Set(previstos);
324
+ if ([...s].some((x) => !esperado.has(x)))
325
+ falha('benchmark.run.resultado-desconhecido', onde);
326
+ if (r.outcome === 'completed' && s.size !== esperado.size)
327
+ falha('benchmark.run.resultados-incompletos', onde);
328
+ }
329
+ for (const v of r.verify_results) {
330
+ if ((v.result === 'pass') !== (v.exit_code === 0))
331
+ falha('benchmark.run.verify-inconsistente', onde);
332
+ }
333
+ }
334
+ /** Chave do braco de um par. */
335
+ const chaveDoBraco = (pairId, arm) => `${pairId}\u0000${arm}`;
336
+ /**
337
+ * Validacao estrutural e semantica pura do registro. Devolve o registro ou lanca `benchmark.*`.
338
+ * Nao julga o experimento: isso e `avaliarBenchmark`.
339
+ */
340
+ function validarBenchmark(entrada) {
341
+ if (entrada !== null && typeof entrada === 'object' && !Array.isArray(entrada) && 'schema' in entrada &&
342
+ entrada.schema !== exports.BENCHMARK_SCHEMA)
343
+ falha('benchmark.versao.incompativel');
344
+ const parse = exports.benchmarkSchema.safeParse(entrada);
345
+ if (!parse.success)
346
+ falha('benchmark.estrutura.invalida', parse.error.issues[0]?.path.join('.') || 'raiz');
347
+ const b = parse.data, p = b.protocol;
348
+ conferirProtocolo(p);
349
+ if (b.index_preparation.scenario !== p.cache_policy)
350
+ falha('benchmark.preparo.cenario-divergente');
351
+ conferirMedida(b.index_preparation.logical_total_tokens, true, 'index_preparation.logical_total_tokens');
352
+ conferirLatencia(b.index_preparation.latency_ms, 'index_preparation.latency_ms');
353
+ conferirCusto(b.index_preparation.cost, 'index_preparation.cost');
354
+ conferirOrigemDoCusto(b.index_preparation.cost, b.index_preparation.logical_total_tokens, 'index_preparation.cost');
355
+ if (b.receipts_review.state === 'reviewed' && b.receipts_review.receipt_ref === null)
356
+ falha('benchmark.revisao.sem-recibo');
357
+ const tarefas = new Map(p.tasks.map((t) => [t.task_id, t])), pares = new Map(p.pairs.map((q) => [q.pair_id, q]));
358
+ semRepeticao(b.runs.map((r) => r.run_id), 'benchmark.run.duplicado', 'runs');
359
+ semRepeticao(b.runs.map((r) => r.session_id), 'benchmark.run.sessao-compartilhada', 'runs');
360
+ const requisicoes = new Set(), tentativas = new Map(), aquecimento = { A: 0, B: 0 };
361
+ b.runs.forEach((r, i) => {
362
+ const onde = `runs.${i}`;
363
+ if (Date.parse(r.ended_at) < Date.parse(r.started_at))
364
+ falha('benchmark.run.tempo-invertido', onde);
365
+ const t = tarefas.get(r.task_id);
366
+ if (!t)
367
+ falha('benchmark.run.tarefa-ausente', onde);
368
+ conferirSeed(r.controls, `${onde}.controls`);
369
+ conferirTokens(r, requisicoes, onde);
370
+ conferirMedida(r.metrics.residual_context_tokens, true, `${onde}.metrics.residual_context_tokens`);
371
+ const contexto = r.metrics.residual_context_tokens;
372
+ if (contexto.value !== null && (contexto.window_tokens === null || contexto.value > contexto.window_tokens)) {
373
+ falha('benchmark.metrica.contexto-sem-janela', onde);
374
+ }
375
+ conferirMedida(r.metrics.tool_calls, true, `${onde}.metrics.tool_calls`);
376
+ if (r.metrics.tool_calls.source === 'tokenizer_exact')
377
+ falha('benchmark.metrica.origem-invalida', `${onde}.metrics.tool_calls`);
378
+ // Consumo medido zero sem requisicao e a tentativa que caiu antes da primeira: nao ha chamada pedida.
379
+ const primaria = r.metrics.logical_total_tokens;
380
+ if (r.requests.length === 0 && primaria.value === 0 && exports.ORIGENS_DE_CONSUMO_MEDIDO.includes(primaria.source) &&
381
+ r.metrics.tool_calls.value !== null && r.metrics.tool_calls.value > 0)
382
+ falha('benchmark.metrica.chamadas-sem-requisicao', `${onde}.metrics.tool_calls`);
383
+ conferirLatencia(r.metrics.latency_ms, `${onde}.metrics.latency_ms`);
384
+ conferirCusto(r.metrics.cost, `${onde}.metrics.cost`);
385
+ conferirOrigemDoCusto(r.metrics.cost, r.metrics.logical_total_tokens, `${onde}.metrics.cost`);
386
+ conferirAuditoria(r, p, onde);
387
+ if (r.warmup) {
388
+ if (r.pair_id !== null || r.repetition !== null)
389
+ falha('benchmark.warmup.com-par', onde);
390
+ aquecimento[r.arm]++;
391
+ return;
392
+ }
393
+ const par = r.pair_id === null ? undefined : pares.get(r.pair_id);
394
+ if (!par)
395
+ falha('benchmark.run.par-desconhecido', onde);
396
+ if (par.task_id !== r.task_id || par.repetition !== r.repetition)
397
+ falha('benchmark.run.tarefa-divergente', onde);
398
+ conferirResultados(r, t, onde);
399
+ const chave = chaveDoBraco(par.pair_id, r.arm), lista = tentativas.get(chave) ?? [];
400
+ if (lista.some((x) => x.attempt === r.attempt))
401
+ falha('benchmark.run.duplicado', onde);
402
+ lista.push(r);
403
+ tentativas.set(chave, lista);
404
+ });
405
+ // D6: retry e registro, nunca descarte; tentativas contiguas ate o limite do protocolo.
406
+ for (const lista of tentativas.values()) {
407
+ lista.sort((x, y) => x.attempt - y.attempt);
408
+ lista.forEach((r, i) => {
409
+ if (r.attempt !== i + 1)
410
+ falha('benchmark.run.tentativa-fora-de-ordem', `run ${r.run_id}`);
411
+ if (i < lista.length - 1 && !exports.DESFECHOS_COM_RETRY.includes(r.outcome))
412
+ falha('benchmark.run.tentativa-apos-conclusao', `run ${r.run_id}`);
413
+ });
414
+ if (lista.length > p.retry_policy.max_attempts)
415
+ falha('benchmark.run.tentativas-excedidas', `run ${lista[0].run_id}`);
416
+ }
417
+ const semRuns = b.runs.length === 0;
418
+ if (semRuns !== (b.status === 'not-run'))
419
+ falha('benchmark.status.inconsistente');
420
+ if (b.status === 'complete') {
421
+ if (p.pairs.some((q) => !tentativas.has(chaveDoBraco(q.pair_id, 'A')) || !tentativas.has(chaveDoBraco(q.pair_id, 'B')))) {
422
+ falha('benchmark.status.inconsistente');
423
+ }
424
+ if (aquecimento.A !== p.warmup_runs_per_arm || aquecimento.B !== p.warmup_runs_per_arm)
425
+ falha('benchmark.warmup.desigual');
426
+ }
427
+ return b;
428
+ }
429
+ /** D8: mediana por ordenacao numerica; amostra par usa a media dos dois centrais. */
430
+ function mediana(valores) {
431
+ if (valores.length === 0)
432
+ return null;
433
+ const v = [...valores].sort((a, b) => a - b), meio = v.length >> 1;
434
+ return v.length % 2 ? v[meio] : (v[meio - 1] + v[meio]) / 2;
435
+ }
436
+ const diferenca = (a, b) => (a === null || b === null ? null : b - a);
437
+ /**
438
+ * D8: avaliacao pura de um registro valido. Violacao de rigor observada prevalece sobre falta
439
+ * de telemetria; so dado completo e comparavel chega a comparar medianas.
440
+ */
441
+ function avaliarBenchmark(entrada) {
442
+ const b = validarBenchmark(entrada), p = b.protocol;
443
+ const vazio = {
444
+ resultado: 'not-run', motivos: ['sem-execucao'], publicavel: false, paresPlanejados: p.pairs.length, paresCompletos: 0,
445
+ medianaA: null, medianaB: null, delta: null, porTarefa: [],
446
+ };
447
+ if (b.status === 'not-run')
448
+ return vazio;
449
+ const falhas = new Set(), lacunas = new Set();
450
+ const tarefas = new Map(p.tasks.map((t) => [t.task_id, t])), controles = (0, intelligence_graph_contract_1.canonico)(p.controls);
451
+ // D8: so resultado completo e comparado; D6: aquecimento igual nos dois bracos, pela regra fixada.
452
+ if (b.status !== 'complete')
453
+ lacunas.add('amostra-incompleta');
454
+ const aquecimentos = (arm) => b.runs.filter((r) => r.warmup && r.arm === arm).length;
455
+ if (aquecimentos('A') !== p.warmup_runs_per_arm || aquecimentos('B') !== p.warmup_runs_per_arm)
456
+ lacunas.add('aquecimento-divergente');
457
+ // D8: aresta falsa e fato do grafo auditado, venha da tentativa ou do aquecimento que vier.
458
+ if (b.runs.some((r) => r.edge_audit?.examined.some((e) => e.result === 'false')))
459
+ falhas.add('aresta-falsa');
460
+ const grupos = new Map();
461
+ for (const r of b.runs) {
462
+ if (r.warmup || r.pair_id === null)
463
+ continue;
464
+ const chave = chaveDoBraco(r.pair_id, r.arm), lista = grupos.get(chave) ?? [];
465
+ lista.push(r);
466
+ grupos.set(chave, lista);
467
+ }
468
+ const exigidas = new Set(p.required_metrics), origens = new Set();
469
+ const totais = new Map();
470
+ for (const par of p.pairs) {
471
+ const tarefa = tarefas.get(par.task_id), comandos = new Map(tarefa.verifiers.map((v) => [v.verify_id, v.command_hash]));
472
+ const total = { A: null, B: null }, inicio = {};
473
+ for (const arm of ['A', 'B']) {
474
+ const lista = (grupos.get(chaveDoBraco(par.pair_id, arm)) ?? []).sort((x, y) => x.attempt - y.attempt);
475
+ if (lista.length === 0) {
476
+ lacunas.add('amostra-incompleta');
477
+ continue;
478
+ }
479
+ inicio[arm] = Date.parse(lista[0].started_at);
480
+ let soma = 0;
481
+ for (const r of lista) {
482
+ if (r.outcome === 'instrumentation-failed')
483
+ lacunas.add('falha-de-instrumentacao');
484
+ if ((0, intelligence_graph_contract_1.canonico)(r.controls) !== controles)
485
+ lacunas.add('controles-divergentes');
486
+ if (r.question_hash !== tarefa.question_hash)
487
+ lacunas.add('pergunta-divergente');
488
+ if (r.verify_results.some((v) => comandos.get(v.verify_id) !== v.command_hash))
489
+ falhas.add('verify-nao-preservado');
490
+ const primaria = r.metrics.logical_total_tokens;
491
+ if (primaria.value === null) {
492
+ lacunas.add('metrica-primaria-ausente');
493
+ soma = null;
494
+ }
495
+ else {
496
+ // D7: origem equivalente e a mesma fonte, metodo e versao nos dois bracos.
497
+ origens.add((0, intelligence_graph_contract_1.canonico)([primaria.source, primaria.method, primaria.method_version]));
498
+ if (!exports.ORIGENS_DE_CONSUMO_MEDIDO.includes(primaria.source))
499
+ lacunas.add('metrica-primaria-sem-consumo-medido');
500
+ if (soma !== null)
501
+ soma += primaria.value;
502
+ }
503
+ const m = r.metrics;
504
+ const requeridas = [['residual_context_tokens', m.residual_context_tokens], ['tool_calls', m.tool_calls],
505
+ ['latency_ms', m.latency_ms], ['cost', m.cost]];
506
+ if (requeridas.some(([nome, medida]) => exigidas.has(nome) && medida.value === null))
507
+ lacunas.add('metrica-requerida-ausente');
508
+ if (requeridas.some(([nome, medida]) => exigidas.has(nome) && medida.value !== null && !exports.ORIGENS_DE_CONSUMO_MEDIDO.includes(medida.source))) {
509
+ lacunas.add('metrica-requerida-estimada');
510
+ }
511
+ }
512
+ total[arm] = soma;
513
+ const final = lista[lista.length - 1];
514
+ if (final.outcome === 'cancelled')
515
+ lacunas.add('tarefa-cancelada');
516
+ else if (final.outcome !== 'completed' && final.outcome !== 'instrumentation-failed')
517
+ falhas.add('tarefa-nao-concluida');
518
+ if (final.outcome === 'completed') {
519
+ if (final.mandatory_fact_results.some((f) => f.result !== 'present'))
520
+ falhas.add('fato-perdido');
521
+ if (final.claim_results.some((c) => c.result !== 'verified'))
522
+ falhas.add('claim-nao-preservada');
523
+ if (final.verify_results.some((v) => v.result !== 'pass'))
524
+ falhas.add('verify-falhou');
525
+ }
526
+ if (arm === 'B') {
527
+ const a = final.edge_audit;
528
+ if (a === null)
529
+ lacunas.add('auditoria-incompleta');
530
+ else if (a.examined.some((e) => e.result === 'unverified') || a.examined.length !== a.universe_edge_ids.length ||
531
+ a.universe_edge_ids.length !== p.treatment.edge_count ||
532
+ (0, exports.digestDoConjuntoDeArestas)(a.universe_edge_ids) !== p.treatment.edge_set_digest)
533
+ lacunas.add('auditoria-incompleta');
534
+ }
535
+ }
536
+ if (inicio.A !== undefined && inicio.B !== undefined && (par.order === 'AB' ? inicio.A > inicio.B : inicio.B > inicio.A)) {
537
+ lacunas.add('ordem-divergente');
538
+ }
539
+ totais.set(par.pair_id, total);
540
+ }
541
+ if (origens.size > 1)
542
+ lacunas.add('origens-nao-equivalentes');
543
+ const preparo = b.index_preparation;
544
+ const doPreparo = [
545
+ ...(exigidas.has('index_preparation') ? [preparo.logical_total_tokens, preparo.latency_ms] : []),
546
+ ...(exigidas.has('cost') ? [preparo.cost] : []),
547
+ ];
548
+ if (doPreparo.some((m) => m.value === null))
549
+ lacunas.add('metrica-requerida-ausente');
550
+ if (doPreparo.some((m) => m.value !== null && !exports.ORIGENS_DE_CONSUMO_MEDIDO.includes(m.source)))
551
+ lacunas.add('metrica-requerida-estimada');
552
+ const completos = p.pairs.filter((q) => totais.get(q.pair_id)?.A != null && totais.get(q.pair_id)?.B != null);
553
+ const medianas = (pares) => {
554
+ const a = mediana(pares.map((q) => totais.get(q.pair_id)?.A));
555
+ const bb = mediana(pares.map((q) => totais.get(q.pair_id)?.B));
556
+ return { medianaA: a, medianaB: bb, delta: diferenca(a, bb) };
557
+ };
558
+ const geral = medianas(completos);
559
+ const porTarefa = p.tasks.map((t) => ({ task_id: t.task_id, ...medianas(completos.filter((q) => q.task_id === t.task_id)) }));
560
+ const base = { paresPlanejados: p.pairs.length, paresCompletos: completos.length, ...geral, porTarefa };
561
+ const motivos = [...exports.MOTIVOS_DE_FALHA.filter((m) => falhas.has(m)), ...exports.MOTIVOS_DE_LACUNA.filter((m) => lacunas.has(m))];
562
+ if (falhas.size)
563
+ return { ...base, resultado: 'fail', motivos, publicavel: false };
564
+ if (lacunas.size)
565
+ return { ...base, resultado: 'inconclusive', motivos, publicavel: false };
566
+ if (geral.medianaB >= geral.medianaA)
567
+ return { ...base, resultado: 'fail', motivos: ['mediana-nao-menor'], publicavel: false };
568
+ const publicavel = b.status === 'complete' && b.data_class === 'measured' && b.receipts_review.state === 'reviewed';
569
+ return { ...base, resultado: 'pass', motivos: [], publicavel };
570
+ }