@piagent/platform 1.5.5 → 1.6.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 (227) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/README.md +9 -8
  3. package/README.vi.md +9 -5
  4. package/adapters/web-frontend/profile.json +2 -4
  5. package/architecture/layers.json +18 -3
  6. package/benchmarks/deep-logic-v1/SPECIALIST_PROTOCOL.vi.md +122 -0
  7. package/benchmarks/deep-logic-v1/grade.mjs +272 -10
  8. package/benchmarks/deep-logic-v1/project/apps/admin/src/billing-summary.js +3 -0
  9. package/benchmarks/deep-logic-v1/project/benchmark-contract/public-smoke.test.js +166 -0
  10. package/benchmarks/deep-logic-v1/project/package.json +1 -1
  11. package/benchmarks/deep-logic-v1/project/packages/billing/src/close-period.js +3 -0
  12. package/benchmarks/deep-logic-v1/project/packages/billing/src/plan-timeline.js +3 -0
  13. package/benchmarks/deep-logic-v1/project/test/smoke.test.js +7 -1
  14. package/benchmarks/deep-logic-v1/prompts/budgeted-context-graph.md +2 -0
  15. package/benchmarks/deep-logic-v1/prompts/fair-dependency-scheduler.md +2 -0
  16. package/benchmarks/deep-logic-v1/prompts/layered-policy-resolution.md +2 -0
  17. package/benchmarks/deep-logic-v1/prompts/resumable-stream-assembly.md +3 -1
  18. package/benchmarks/deep-logic-v1/prompts/revision-event-reconciliation.md +2 -0
  19. package/benchmarks/deep-logic-v1/prompts/temporal-usage-billing-close.md +123 -0
  20. package/benchmarks/deep-logic-v1/prompts/transactional-config-merge.md +2 -0
  21. package/benchmarks/deep-logic-v1/suite.json +51 -3
  22. package/benchmarks/deep-logic-v1/variant.mjs +22 -1
  23. package/benchmarks/production-v1/spend-control.v1.json +68 -0
  24. package/benchmarks/production-v1/suite.json +42 -3
  25. package/catalog/capabilities.json +6 -6
  26. package/docs/command-reference-vietnamese.md +6 -6
  27. package/docs/context-engine.md +7 -1
  28. package/docs/distribution-standard.md +7 -7
  29. package/docs/en/architecture.md +1 -0
  30. package/docs/languages.json +4 -4
  31. package/docs/model-options.md +8 -5
  32. package/docs/operator-manual-vietnamese.md +13 -11
  33. package/docs/project-adapters.md +2 -2
  34. package/docs/publishing-for-teams.md +5 -0
  35. package/docs/quality-benchmark.md +271 -62
  36. package/docs/release-install-policy.md +10 -9
  37. package/docs/runtime-policy-design.md +4 -4
  38. package/docs/runtime-quality-baseline.md +13 -6
  39. package/docs/security-threat-model.md +2 -2
  40. package/docs/task-lifecycle-vietnamese.md +2 -2
  41. package/docs/team-onboarding.md +2 -2
  42. package/docs/usage-observability.md +7 -2
  43. package/docs/vi/architecture.md +1 -0
  44. package/docs-site/architecture.html +1 -1
  45. package/docs-site/benchmark.html +1 -1
  46. package/docs-site/commands.html +1 -1
  47. package/docs-site/context-engine.html +1 -1
  48. package/docs-site/en/architecture.html +1 -1
  49. package/docs-site/en/benchmark.html +1 -1
  50. package/docs-site/en/commands.html +1 -1
  51. package/docs-site/en/context-engine.html +1 -1
  52. package/docs-site/en/index.html +1 -1
  53. package/docs-site/en/mcp-approval.html +1 -1
  54. package/docs-site/en/mcp-auth.html +1 -1
  55. package/docs-site/en/mcp-servers.html +1 -1
  56. package/docs-site/en/mcp.html +1 -1
  57. package/docs-site/en/permissions.html +1 -1
  58. package/docs-site/en/profiles.html +1 -1
  59. package/docs-site/en/quickstart.html +1 -1
  60. package/docs-site/en/runtime.html +1 -1
  61. package/docs-site/en/scope.html +1 -1
  62. package/docs-site/en/security.html +1 -1
  63. package/docs-site/en/team.html +1 -1
  64. package/docs-site/en/whats-new.html +1 -1
  65. package/docs-site/en/workflows.html +1 -1
  66. package/docs-site/index.html +1 -1
  67. package/docs-site/mcp-approval.html +1 -1
  68. package/docs-site/mcp-auth.html +1 -1
  69. package/docs-site/mcp-servers.html +1 -1
  70. package/docs-site/mcp.html +1 -1
  71. package/docs-site/permissions.html +1 -1
  72. package/docs-site/profiles.html +1 -1
  73. package/docs-site/quickstart.html +1 -1
  74. package/docs-site/runtime.html +1 -1
  75. package/docs-site/scope.html +1 -1
  76. package/docs-site/security.html +1 -1
  77. package/docs-site/team.html +1 -1
  78. package/docs-site/whats-new.html +1 -1
  79. package/docs-site/workflows.html +1 -1
  80. package/evals/fixtures/benchmark-assurance-evidence.invalid.json +1 -1
  81. package/evals/fixtures/benchmark-assurance-evidence.valid.json +1 -1
  82. package/evals/fixtures/piagent-webui/session-live-state-v1.invalid.json +18 -0
  83. package/evals/fixtures/piagent-webui/session-live-state-v1.valid.json +27 -0
  84. package/evals/fs4-readiness-matrix.v1.json +2 -2
  85. package/evals/fs5-causal-arm.v1.json +2 -2
  86. package/evals/fs5-pilot-protocol.v1.json +2 -2
  87. package/evals/fs5-pilot-protocol.v4.json +6 -5
  88. package/evals/fs5-pilot-protocol.v5.json +7 -6
  89. package/evals/private-holdout-v1/public-exposure.v1.json +1 -1
  90. package/package.json +3 -1
  91. package/packages/piagent-core/benchmark/benchmark-assurance.js +4 -1
  92. package/packages/piagent-core/benchmark/benchmark-bootstrap.js +91 -9
  93. package/packages/piagent-core/benchmark/benchmark-claim-restrictions.js +38 -7
  94. package/packages/piagent-core/benchmark/benchmark-cli.js +7 -7
  95. package/packages/piagent-core/benchmark/benchmark-codex.js +3 -1
  96. package/packages/piagent-core/benchmark/benchmark-comparison.js +271 -2
  97. package/packages/piagent-core/benchmark/benchmark-core.js +732 -661
  98. package/packages/piagent-core/benchmark/benchmark-execution-guard.js +7 -5
  99. package/packages/piagent-core/benchmark/benchmark-forensics.js +439 -4
  100. package/packages/piagent-core/benchmark/benchmark-host-readiness.js +639 -0
  101. package/packages/piagent-core/benchmark/benchmark-matrix.js +22 -4
  102. package/packages/piagent-core/benchmark/benchmark-normalized-cost.js +317 -0
  103. package/packages/piagent-core/benchmark/benchmark-preflight.js +3 -1
  104. package/packages/piagent-core/benchmark/benchmark-process.js +6 -5
  105. package/packages/piagent-core/benchmark/benchmark-provider-wire.js +126 -0
  106. package/packages/piagent-core/benchmark/benchmark-record-validation.js +183 -0
  107. package/packages/piagent-core/benchmark/benchmark-report.js +116 -12
  108. package/packages/piagent-core/benchmark/benchmark-resume-recovery.js +14 -0
  109. package/packages/piagent-core/benchmark/benchmark-runner-policy.js +26 -0
  110. package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +782 -0
  111. package/packages/piagent-core/benchmark/benchmark-statistics.js +64 -0
  112. package/packages/piagent-core/benchmark/benchmark-stop-policy.js +8 -5
  113. package/packages/piagent-core/benchmark/benchmark-suite-identity.js +31 -0
  114. package/packages/piagent-core/benchmark/benchmark-suite-runtime.js +13 -9
  115. package/packages/piagent-core/benchmark/benchmark-suite.js +128 -2
  116. package/packages/piagent-core/benchmark/benchmark-summary-support.js +376 -0
  117. package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +971 -0
  118. package/packages/piagent-core/benchmark/benchmark-usage.js +311 -0
  119. package/packages/piagent-core/benchmark/benchmark-workflow.js +166 -0
  120. package/packages/piagent-core/docs/context-efficiency-improvement-plan.md +1080 -0
  121. package/packages/piagent-core/extensions/acceptance-contract-semantics.js +83 -69
  122. package/packages/piagent-core/extensions/acceptance-error-classes.js +160 -0
  123. package/packages/piagent-core/extensions/acceptance-executable-evidence.js +12 -9
  124. package/packages/piagent-core/extensions/acceptance-receipt.js +34 -11
  125. package/packages/piagent-core/extensions/acceptance-state-machine-evidence.js +518 -0
  126. package/packages/piagent-core/extensions/acceptance-test-binding-evidence.js +60 -0
  127. package/packages/piagent-core/extensions/context-efficiency-metrics.js +302 -0
  128. package/packages/piagent-core/extensions/context-efficiency-report.js +167 -0
  129. package/packages/piagent-core/extensions/context-engine.js +148 -145
  130. package/packages/piagent-core/extensions/context-evidence.js +48 -0
  131. package/packages/piagent-core/extensions/context-import-links.js +296 -0
  132. package/packages/piagent-core/extensions/context-telemetry-integrity.js +65 -0
  133. package/packages/piagent-core/extensions/criterion-context-pack.js +422 -7
  134. package/packages/piagent-core/extensions/criterion-graph.js +78 -8
  135. package/packages/piagent-core/extensions/guard-types.ts +2 -0
  136. package/packages/piagent-core/extensions/javascript-regex-evidence.js +32 -0
  137. package/packages/piagent-core/extensions/piagent-guard.ts +233 -41
  138. package/packages/piagent-core/extensions/task-contract-view.js +17 -3
  139. package/packages/piagent-core/extensions/task-lifecycle.js +7 -2
  140. package/packages/piagent-core/extensions/task-state.js +40 -134
  141. package/packages/piagent-core/extensions/verification-intelligence.js +3 -1
  142. package/packages/piagent-core/extensions/workspace-evidence-roots.js +157 -0
  143. package/packages/piagent-core/package.json +1 -1
  144. package/packages/piagent-core/policies/base-policy.json +2 -0
  145. package/packages/piagent-core/runtime/context/context-delivery.ts +103 -0
  146. package/packages/piagent-core/runtime/context/context-delta-shadow.ts +53 -0
  147. package/packages/piagent-core/runtime/context/context-efficiency-format.ts +47 -0
  148. package/packages/piagent-core/runtime/context/context-evidence-qualification.ts +32 -0
  149. package/packages/piagent-core/runtime/context/prefix-telemetry.ts +47 -0
  150. package/packages/piagent-core/runtime/context/repository-memory-hints.ts +27 -0
  151. package/packages/piagent-core/runtime/hooks/agent-prompt-telemetry.ts +56 -0
  152. package/packages/piagent-core/runtime/hooks/agent-start-hook.ts +162 -102
  153. package/packages/piagent-core/runtime/hooks/completion-hook.ts +5 -6
  154. package/packages/piagent-core/runtime/hooks/input-hook.ts +11 -1
  155. package/packages/piagent-core/runtime/hooks/session-hooks.ts +22 -2
  156. package/packages/piagent-core/runtime/hooks/session-start-hook.ts +7 -2
  157. package/packages/piagent-core/runtime/hooks/tool-result-content-guards.ts +95 -0
  158. package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +84 -102
  159. package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +4 -2
  160. package/packages/piagent-core/runtime/inspection/activity-recovery.ts +104 -0
  161. package/packages/piagent-core/runtime/inspection/task-compaction-history.ts +1 -1
  162. package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +1 -1
  163. package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +53 -0
  164. package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +34 -6
  165. package/packages/piagent-core/runtime/model/authenticated-catalog.ts +17 -9
  166. package/packages/piagent-core/runtime/model/openai-codex-reasoning.ts +83 -0
  167. package/packages/piagent-core/runtime/model/provider-wire-fingerprint.ts +238 -0
  168. package/packages/piagent-core/runtime/orchestration/role-policy.ts +1 -1
  169. package/packages/piagent-core/runtime/product/activity-inspector.ts +7 -2
  170. package/packages/piagent-core/runtime/product/efficiency-metrics.ts +4 -2
  171. package/packages/piagent-core/runtime/quality/exact-output-contract.ts +2 -1
  172. package/packages/piagent-core/runtime/quality/performance-assurance-signals.ts +23 -0
  173. package/packages/piagent-core/runtime/quality/performance-assurance.ts +6 -2
  174. package/packages/piagent-core/runtime/recovery/edit-recovery-context.ts +113 -0
  175. package/packages/piagent-core/runtime/recovery/edit-recovery-delivery.ts +42 -0
  176. package/packages/piagent-core/runtime/recovery/semantic-repair-handshake.ts +55 -2
  177. package/packages/piagent-core/runtime/recovery/semantic-repair-runtime.ts +55 -2
  178. package/packages/piagent-core/runtime/registration/context-commands.ts +66 -5
  179. package/packages/piagent-core/runtime/registration/policy-tools.ts +46 -11
  180. package/packages/piagent-core/runtime/registration/task-completion-tools.ts +49 -16
  181. package/packages/piagent-core/runtime/registration/task-start-guidance.ts +163 -0
  182. package/packages/piagent-core/runtime/registration/task-start-retry-helpers.ts +37 -0
  183. package/packages/piagent-core/runtime/registration/task-start-tool.ts +67 -62
  184. package/packages/piagent-core/runtime/session/runtime-state.ts +154 -2
  185. package/packages/piagent-core/runtime/session/system-prompt.ts +4 -4
  186. package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +500 -0
  187. package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +2 -1
  188. package/packages/piagent-core/runtime/workflows/task-intake.ts +43 -2
  189. package/packages/piagent-core/security/sensitive-data.js +13 -218
  190. package/packages/piagent-core/security/sensitive-project-file.js +42 -0
  191. package/packages/piagent-core/security/sensitive-source-expression.js +330 -0
  192. package/packages/piagent-core/security/sensitive-source-formats.js +394 -0
  193. package/packages/piagent-core/security/sensitive-text.js +234 -0
  194. package/packages/piagent-core/subagents/piagent-worker.md +1 -1
  195. package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-rD9WJKxs.js → MarkdownMessage-CxeZqTte.js} +1 -1
  196. package/packages/piagent-webui/dist/client/assets/index-DynIMe8I.js +176 -0
  197. package/packages/piagent-webui/dist/client/index.html +1 -1
  198. package/packages/piagent-webui/gateway/gateway-events.ts +109 -5
  199. package/packages/piagent-webui/gateway/gateway-service.ts +3 -0
  200. package/packages/piagent-webui/gateway/gateway-session-stream.ts +93 -7
  201. package/packages/piagent-webui/gateway/session-command-controller.ts +18 -3
  202. package/packages/piagent-webui/gateway/session-effective-options.ts +47 -0
  203. package/packages/piagent-webui/gateway/session-live-state.ts +21 -0
  204. package/packages/piagent-webui/gateway/session-operation-start.ts +5 -1
  205. package/packages/piagent-webui/gateway/session-operation-watchdog.ts +158 -0
  206. package/packages/piagent-webui/gateway/session-runtime-factory.ts +45 -0
  207. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +139 -124
  208. package/packages/piagent-webui/server/loopback-server.ts +8 -0
  209. package/packages/piagent-webui/server/transcript-projection.ts +22 -4
  210. package/packages/piagent-webui/shared/text-visibility.ts +10 -0
  211. package/schemas/piagent-webui/catalog-v1.json +9 -0
  212. package/schemas/piagent-webui/gateway-protocol-v1.schema.json +53 -3
  213. package/schemas/piagent-webui/session-live-state-v1.schema.json +76 -0
  214. package/schemas/task-contract.schema.json +12 -1
  215. package/scripts/benchmark-runner-core.mjs +355 -359
  216. package/scripts/benchmark-runner-finalization.mjs +309 -0
  217. package/scripts/benchmark-runner-host-readiness.mjs +94 -0
  218. package/scripts/benchmark-runner-support.mjs +200 -0
  219. package/scripts/benchmark-session.mjs +95 -41
  220. package/scripts/configure-model-scope.sh +4 -3
  221. package/scripts/helper-evaluation.mjs +1 -1
  222. package/scripts/install-global.sh +2 -2
  223. package/scripts/pi-usage-history.mjs +37 -10
  224. package/scripts/setup.sh +2 -2
  225. package/scripts/verify-local.sh +5 -1
  226. package/templates/global/settings.json +2 -1
  227. package/packages/piagent-webui/dist/client/assets/index-BZRFw1u6.js +0 -174
@@ -0,0 +1,782 @@
1
+ import { benchmarkProviderWireEvidenceMatchesRequest } from "./benchmark-provider-wire.js";
2
+ import {
3
+ benchmarkPricingSnapshotValidationErrors,
4
+ normalizeBenchmarkUsageCost
5
+ } from "./benchmark-normalized-cost.js";
6
+ import { summarizeBenchmarkCausalContextEvidence } from "./benchmark-record-validation.js";
7
+ import {
8
+ benchmarkHostReadinessPolicyDigest,
9
+ benchmarkHostReadinessPolicyValidationErrors,
10
+ summarizeBenchmarkHostReadinessHistory
11
+ } from "./benchmark-host-readiness.js";
12
+ import { atMostWithinFloatingPrecision, geometricMean } from "./benchmark-statistics.js";
13
+ import { pairedOutcomeFloorStop } from "./benchmark-stop-policy.js";
14
+ import { workflowContinuityEvidenceComplete } from "./benchmark-summary-support.js";
15
+ import { summarizeBenchmarkTimingDiagnostics } from "./benchmark-timing-diagnostics.js";
16
+
17
+ const TOKEN_FIELDS = Object.freeze(["input", "output", "cacheRead", "cacheWrite", "reasoning", "fresh", "total"]);
18
+ const PRODUCTION_STAGE_CONTROL_POLICY = "production-v1-provider-spend-v1";
19
+
20
+ function nonEmptyString(value) {
21
+ return typeof value === "string" && value.trim().length > 0;
22
+ }
23
+
24
+ function validStageBoundaries(stageBoundaries) {
25
+ return Array.isArray(stageBoundaries)
26
+ && stageBoundaries.length >= 2
27
+ && stageBoundaries[0] === 0
28
+ && stageBoundaries.every((value, index) => Number.isSafeInteger(value)
29
+ && value >= 0
30
+ && (index === 0 || value > stageBoundaries[index - 1]));
31
+ }
32
+
33
+ export function productionSpendControlValidationErrors(control, {
34
+ suiteId,
35
+ expectedSessions,
36
+ requireHostReadiness = control?.hostReadiness?.required === true
37
+ } = {}) {
38
+ const errors = [];
39
+ if (!control || typeof control !== "object" || Array.isArray(control)) return ["contract-must-be-an-object"];
40
+ if (control.schemaVersion !== 1) errors.push("unsupported-schema-version");
41
+ if (!nonEmptyString(control.suiteId) || (suiteId !== undefined && control.suiteId !== suiteId)) errors.push("suite-id-mismatch");
42
+ if (!nonEmptyString(control.rootSeed) || control.rootSeed.length > 200) errors.push("invalid-root-seed");
43
+
44
+ const execution = control.execution;
45
+ if (!execution || typeof execution !== "object" || Array.isArray(execution)) errors.push("missing-execution-contract");
46
+ else {
47
+ if (!Array.isArray(execution.surfaces)
48
+ || execution.surfaces.length !== 2
49
+ || new Set(execution.surfaces).size !== 2
50
+ || execution.surfaces.some((surface) => !nonEmptyString(surface))) errors.push("invalid-execution-surfaces");
51
+ if (execution.model !== null && !nonEmptyString(execution.model)) errors.push("invalid-execution-model");
52
+ if (execution.thinking !== null && !nonEmptyString(execution.thinking)) errors.push("invalid-execution-thinking");
53
+ if (!Number.isSafeInteger(execution.repeats) || execution.repeats <= 0) errors.push("invalid-execution-repeats");
54
+ if (execution.infrastructureRetries !== 0) errors.push("infrastructure-retries-must-be-zero");
55
+ if (execution.stopAfterFailedPair !== true) errors.push("stop-after-failed-pair-must-be-enabled");
56
+ }
57
+
58
+ if (requireHostReadiness) {
59
+ errors.push(...benchmarkHostReadinessPolicyValidationErrors(control.hostReadiness)
60
+ .map((error) => `host-readiness:${error}`));
61
+ } else if (control.hostReadiness !== undefined) {
62
+ errors.push(...benchmarkHostReadinessPolicyValidationErrors(control.hostReadiness)
63
+ .map((error) => `host-readiness:${error}`));
64
+ }
65
+
66
+ if (!Array.isArray(control.stages) || control.stages.length < 2) errors.push("missing-stage-boundaries");
67
+ else {
68
+ const ids = new Set();
69
+ let previous = 0;
70
+ for (const [index, stage] of control.stages.entries()) {
71
+ if (!stage || typeof stage !== "object" || Array.isArray(stage)) {
72
+ errors.push(`invalid-stage:${index}`);
73
+ continue;
74
+ }
75
+ if (!nonEmptyString(stage.id) || ids.has(stage.id)) errors.push(`invalid-stage-id:${index}`);
76
+ else ids.add(stage.id);
77
+ if (!Number.isSafeInteger(stage.cumulativeSessions) || stage.cumulativeSessions < 0
78
+ || (index > 0 && stage.cumulativeSessions <= previous)) errors.push(`invalid-stage-cumulative-sessions:${index}`);
79
+ const expectedNewSessions = index === 0 ? 0 : stage.cumulativeSessions - previous;
80
+ if (stage.newSessions !== expectedNewSessions) errors.push(`invalid-stage-new-sessions:${index}`);
81
+ if (index === 0) {
82
+ if (stage.cumulativeSessions !== 0) errors.push("initial-stage-must-start-at-zero");
83
+ if (stage.claimEligible !== false) errors.push("initial-stage-cannot-be-claim-eligible");
84
+ } else if (index === control.stages.length - 1) {
85
+ if (stage.claimEligible !== true) errors.push("final-stage-must-be-claim-eligible");
86
+ } else if (stage.claimEligible !== false) errors.push(`intermediate-stage-cannot-be-claim-eligible:${index}`);
87
+ if (Number.isSafeInteger(stage.cumulativeSessions)) previous = stage.cumulativeSessions;
88
+ }
89
+ const finalSessions = control.stages.at(-1)?.cumulativeSessions;
90
+ if (Number.isSafeInteger(expectedSessions) && finalSessions !== expectedSessions) errors.push("final-stage-session-count-mismatch");
91
+ }
92
+ return errors;
93
+ }
94
+
95
+ function sameLedgerBinding(left, right) {
96
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
97
+ }
98
+
99
+ export function createProductionStageControl({ authorizedThroughRuns, generatedAt = new Date().toISOString() }) {
100
+ return {
101
+ schemaVersion: 1,
102
+ policy: PRODUCTION_STAGE_CONTROL_POLICY,
103
+ state: "window-authorized",
104
+ approvedBoundaryRuns: 0,
105
+ authorizedThroughRuns,
106
+ pendingBoundary: null,
107
+ updatedAt: generatedAt
108
+ };
109
+ }
110
+
111
+ export function pendProductionStageControl(control, { reason, completedRuns, ledger, generatedAt = new Date().toISOString() }) {
112
+ return {
113
+ schemaVersion: 1,
114
+ policy: PRODUCTION_STAGE_CONTROL_POLICY,
115
+ state: "review-pending",
116
+ approvedBoundaryRuns: Number.isSafeInteger(control?.approvedBoundaryRuns) ? control.approvedBoundaryRuns : 0,
117
+ authorizedThroughRuns: control?.authorizedThroughRuns,
118
+ pendingBoundary: {
119
+ reason,
120
+ completedRuns,
121
+ ledger
122
+ },
123
+ updatedAt: generatedAt
124
+ };
125
+ }
126
+
127
+ export function approveProductionStageControl(control, { completedRuns, authorizedThroughRuns, generatedAt = new Date().toISOString() }) {
128
+ return {
129
+ schemaVersion: 1,
130
+ policy: PRODUCTION_STAGE_CONTROL_POLICY,
131
+ state: "window-authorized",
132
+ approvedBoundaryRuns: completedRuns,
133
+ authorizedThroughRuns,
134
+ pendingBoundary: null,
135
+ updatedAt: generatedAt
136
+ };
137
+ }
138
+
139
+ export function productionStageResumeDisposition(control, { completedRuns, ledger, stageBoundaries }) {
140
+ const errors = [];
141
+ if (control?.schemaVersion !== 1 || control?.policy !== PRODUCTION_STAGE_CONTROL_POLICY) errors.push("missing-or-unsupported-stage-control");
142
+ if (!Number.isSafeInteger(completedRuns) || completedRuns < 0) errors.push("invalid-completed-run-count");
143
+ if (!validStageBoundaries(stageBoundaries)) errors.push("invalid-frozen-stage-boundaries");
144
+ const approvedBoundaryRuns = control?.approvedBoundaryRuns;
145
+ const authorizedThroughRuns = control?.authorizedThroughRuns;
146
+ const expectedAuthorizedThroughRuns = validStageBoundaries(stageBoundaries) && Number.isSafeInteger(approvedBoundaryRuns)
147
+ ? stageBoundaries.find((boundary) => boundary > approvedBoundaryRuns)
148
+ : undefined;
149
+ if (!Number.isSafeInteger(approvedBoundaryRuns) || approvedBoundaryRuns < 0
150
+ || approvedBoundaryRuns > completedRuns
151
+ || (validStageBoundaries(stageBoundaries) && approvedBoundaryRuns >= stageBoundaries.at(-1))) errors.push("invalid-approved-boundary");
152
+ if (!Number.isSafeInteger(authorizedThroughRuns) || authorizedThroughRuns <= 0
153
+ || authorizedThroughRuns < completedRuns
154
+ || authorizedThroughRuns !== expectedAuthorizedThroughRuns) errors.push("invalid-authorized-window");
155
+ if (control?.state === "window-authorized") {
156
+ if (control.pendingBoundary !== null) errors.push("authorized-window-has-pending-boundary");
157
+ const atAuthorizedBoundary = completedRuns === authorizedThroughRuns;
158
+ return {
159
+ passed: errors.length === 0,
160
+ requiresStageGate: errors.length === 0 && atAuthorizedBoundary,
161
+ recoveryAllowed: errors.length === 0 && !atAuthorizedBoundary,
162
+ errors
163
+ };
164
+ }
165
+ if (control?.state === "review-pending") {
166
+ const pending = control.pendingBoundary;
167
+ if (!pending || typeof pending.reason !== "string") errors.push("missing-pending-boundary");
168
+ if (pending?.completedRuns !== completedRuns) errors.push("pending-boundary-run-count-mismatch");
169
+ if (Number.isSafeInteger(completedRuns) && Number.isSafeInteger(approvedBoundaryRuns)
170
+ && completedRuns <= approvedBoundaryRuns) errors.push("pending-boundary-has-no-progress");
171
+ if (!sameLedgerBinding(pending?.ledger, ledger)) errors.push("pending-boundary-ledger-mismatch");
172
+ return { passed: errors.length === 0, requiresStageGate: true, recoveryAllowed: false, errors };
173
+ }
174
+ errors.push("invalid-stage-control-state");
175
+ return { passed: false, requiresStageGate: false, recoveryAllowed: false, errors };
176
+ }
177
+
178
+ export function productionStageResumeWindow(control, { completedRuns, stageBoundaries }) {
179
+ if (!validStageBoundaries(stageBoundaries)
180
+ || !Number.isSafeInteger(completedRuns)
181
+ || completedRuns < 0
182
+ || !Number.isSafeInteger(control?.authorizedThroughRuns)) return null;
183
+ const authorizedThroughRuns = completedRuns < control.authorizedThroughRuns
184
+ ? control.authorizedThroughRuns
185
+ : stageBoundaries.find((boundary) => boundary > completedRuns);
186
+ if (!Number.isSafeInteger(authorizedThroughRuns)) {
187
+ return completedRuns === stageBoundaries.at(-1)
188
+ ? { authorizedThroughRuns: completedRuns, remainingSessions: 0 }
189
+ : null;
190
+ }
191
+ const remainingSessions = authorizedThroughRuns - completedRuns;
192
+ if (!Number.isSafeInteger(remainingSessions) || remainingSessions <= 0) return null;
193
+ return { authorizedThroughRuns, remainingSessions };
194
+ }
195
+
196
+ /**
197
+ * Replays the terminal paired-outcome rule over an accepted ledger prefix.
198
+ *
199
+ * The live runner normally evaluates this rule immediately after appending the
200
+ * second record of a pair. A process can still die after the durable append but
201
+ * before that in-memory check. Resume must therefore derive the same terminal
202
+ * result from accepted records before it performs auth, tool preflight, or any
203
+ * additional provider work.
204
+ */
205
+ export function durablePairedOutcomeFloorStop({ enabled, suite, runs, fullOrder }) {
206
+ const acceptedRuns = Array.isArray(runs) ? runs : [];
207
+ const expectedRuns = Array.isArray(fullOrder) ? fullOrder : [];
208
+ for (let index = 0; index < expectedRuns.length; index += 1) {
209
+ const terminal = pairedOutcomeFloorStop({
210
+ enabled,
211
+ suite,
212
+ runs: acceptedRuns,
213
+ current: expectedRuns[index],
214
+ next: expectedRuns[index + 1]
215
+ });
216
+ if (terminal) return terminal;
217
+ }
218
+ return null;
219
+ }
220
+
221
+ function runKey(run) {
222
+ return `${run?.scenarioId ?? run?.scenario?.id}\0${run?.surface}\0${run?.repeat}`;
223
+ }
224
+
225
+ function pairKey(value) {
226
+ return `${value?.scenarioId ?? value?.scenario?.id}\0${value?.repeat}`;
227
+ }
228
+
229
+ function publicPairId(value) {
230
+ return `${value?.scenarioId ?? value?.scenario?.id}:r${value?.repeat}`;
231
+ }
232
+
233
+ function expectedPairMap(fullOrder) {
234
+ const pairs = new Map();
235
+ for (const item of fullOrder) {
236
+ const key = pairKey(item);
237
+ const pair = pairs.get(key) ?? {
238
+ scenarioId: item?.scenarioId ?? item?.scenario?.id,
239
+ repeat: item?.repeat,
240
+ expectedSurfaces: new Set(),
241
+ expectedRunKeys: new Set()
242
+ };
243
+ pair.expectedSurfaces.add(item?.surface);
244
+ pair.expectedRunKeys.add(runKey(item));
245
+ pairs.set(key, pair);
246
+ }
247
+ return pairs;
248
+ }
249
+
250
+ function exactUsageIssues(run) {
251
+ const usage = run?.usage;
252
+ const issues = [];
253
+ if (usage?.usageCompleteness !== "exact") issues.push("usage-completeness-not-exact");
254
+ if (!Number.isSafeInteger(usage?.sessions) || usage.sessions <= 0) issues.push("invalid-session-count");
255
+ for (const field of TOKEN_FIELDS) {
256
+ if (!Number.isSafeInteger(usage?.[field]) || usage[field] < 0) issues.push(`invalid-${field}`);
257
+ }
258
+ if (Number.isSafeInteger(usage?.fresh) && Number.isSafeInteger(usage?.input) && Number.isSafeInteger(usage?.output)
259
+ && usage.fresh !== usage.input + usage.output) issues.push("fresh-token-equation-mismatch");
260
+ if ([usage?.total, usage?.input, usage?.cacheRead, usage?.cacheWrite, usage?.output].every(Number.isSafeInteger)
261
+ && usage.total !== usage.input + usage.cacheRead + usage.cacheWrite + usage.output) issues.push("total-token-equation-mismatch");
262
+ if (Number.isSafeInteger(usage?.reasoning) && Number.isSafeInteger(usage?.output) && usage.reasoning > usage.output) {
263
+ issues.push("reasoning-exceeds-output");
264
+ }
265
+ return issues;
266
+ }
267
+
268
+ function providerWireGroups(piRuns) {
269
+ const groups = new Map();
270
+ for (const run of piRuns) {
271
+ const key = `${run.scenarioId}\0${run.profile ?? "unspecified"}\0${run.lifecycle ?? "unspecified"}`;
272
+ const group = groups.get(key) ?? {
273
+ scenarioId: run.scenarioId,
274
+ profile: run.profile ?? "unspecified",
275
+ lifecycle: run.lifecycle ?? "unspecified",
276
+ runs: 0,
277
+ baseInstructionHashes: new Set(),
278
+ orderedToolSurfaceHashes: new Set()
279
+ };
280
+ group.runs += 1;
281
+ for (const hash of run.providerWireEvidence?.baseInstructionHashes ?? []) group.baseInstructionHashes.add(hash);
282
+ for (const hash of run.providerWireEvidence?.orderedToolSurfaceHashes ?? []) group.orderedToolSurfaceHashes.add(hash);
283
+ groups.set(key, group);
284
+ }
285
+ return [...groups.values()].map((group) => ({
286
+ scenarioId: group.scenarioId,
287
+ profile: group.profile,
288
+ lifecycle: group.lifecycle,
289
+ runs: group.runs,
290
+ baseInstructionHashCount: group.baseInstructionHashes.size,
291
+ orderedToolSurfaceHashCount: group.orderedToolSurfaceHashes.size,
292
+ passed: group.baseInstructionHashes.size === 1 && group.orderedToolSurfaceHashes.size === 1
293
+ })).sort((left, right) => left.scenarioId.localeCompare(right.scenarioId));
294
+ }
295
+
296
+ function diagnosticCheck(id, passed, details = {}, decisionRole = "blocking") {
297
+ return { id, passed: passed === true, decisionRole, ...details };
298
+ }
299
+
300
+ function pairRatioEvidence(pairRecords, valueFor) {
301
+ const records = pairRecords.map(({ pair, candidate, baseline }) => {
302
+ const values = valueFor({ candidate, baseline });
303
+ const baselineValue = values?.baseline;
304
+ const candidateValue = values?.candidate;
305
+ const comparable = Number.isFinite(baselineValue) && baselineValue > 0
306
+ && Number.isFinite(candidateValue) && candidateValue > 0
307
+ && (!Array.isArray(values?.issues) || values.issues.length === 0);
308
+ return {
309
+ pairId: pair.id,
310
+ scenarioId: pair.scenarioId,
311
+ repeat: pair.repeat,
312
+ comparable,
313
+ issues: comparable ? [] : values?.issues?.length ? values.issues : ["non-positive-or-unavailable-value"],
314
+ baseline: Number.isFinite(baselineValue) ? baselineValue : null,
315
+ candidate: Number.isFinite(candidateValue) ? candidateValue : null,
316
+ ratio: comparable ? candidateValue / baselineValue : null
317
+ };
318
+ });
319
+ const familyMap = new Map();
320
+ for (const record of records) {
321
+ const values = familyMap.get(record.scenarioId) ?? [];
322
+ values.push(record);
323
+ familyMap.set(record.scenarioId, values);
324
+ }
325
+ const families = [...familyMap.entries()].map(([scenarioId, values]) => {
326
+ const comparable = values.length > 0 && values.every((value) => value.comparable);
327
+ return {
328
+ scenarioId,
329
+ observedPairs: values.length,
330
+ comparable,
331
+ ratio: comparable ? geometricMean(values.map((value) => value.ratio)) : null,
332
+ issues: comparable ? [] : ["one-or-more-observed-pairs-incomparable"]
333
+ };
334
+ }).sort((left, right) => left.scenarioId.localeCompare(right.scenarioId));
335
+ return {
336
+ records,
337
+ families,
338
+ incomparablePairs: records.filter((record) => !record.comparable),
339
+ pairRegressions: records.filter((record) => Number.isFinite(record.ratio) && !atMostWithinFloatingPrecision(record.ratio, 1)),
340
+ familyRegressions: families.filter((family) => Number.isFinite(family.ratio) && !atMostWithinFloatingPrecision(family.ratio, 1))
341
+ };
342
+ }
343
+
344
+ function candidateOutcomeFailures(pairRecords, floor) {
345
+ return pairRecords.map(({ pair, candidate }) => {
346
+ const failures = [];
347
+ if (candidate?.resolved !== true) failures.push("unresolved-outcome");
348
+ if (candidate?.scope?.passed !== true) failures.push("scope-safety-evidence-failed");
349
+ if (candidate?.outputSafety?.passed !== true) failures.push("output-safety-evidence-failed");
350
+ if (candidate?.scenarioKind === "safety-refusal") {
351
+ if (candidate?.grade?.passed !== true) failures.push("safety-refusal-grade-failed");
352
+ } else {
353
+ if (candidate?.grade?.passed !== true) failures.push("quality-grade-failed");
354
+ if (candidate?.graderIntegrity?.passed !== true) failures.push("grader-integrity-failed");
355
+ if (candidate?.outputEvidence?.passed === false) failures.push("output-evidence-failed");
356
+ if (!Number.isFinite(candidate?.grade?.score) || candidate.grade.score <= floor) failures.push("quality-outcome-floor");
357
+ if (!Number.isFinite(candidate?.workflow?.score) || candidate.workflow.score <= floor) failures.push("workflow-outcome-floor");
358
+ if (!workflowContinuityEvidenceComplete(candidate?.workflow)) {
359
+ failures.push("workflow-evidence-incomplete-or-failed");
360
+ }
361
+ }
362
+ return {
363
+ pairId: pair.id,
364
+ failures,
365
+ resolved: candidate?.resolved === true,
366
+ gradeScore: Number.isFinite(candidate?.grade?.score) ? candidate.grade.score : null,
367
+ workflowScore: Number.isFinite(candidate?.workflow?.score) ? candidate.workflow.score : null
368
+ };
369
+ }).filter((item) => item.failures.length > 0);
370
+ }
371
+
372
+ /**
373
+ * Builds a provider-free, claim-ineligible decision aid for a paused benchmark.
374
+ * Future, entirely unstarted pairs are intentionally not blockers. A partially
375
+ * observed pair is a blocker because stage decisions must be made at pair
376
+ * boundaries.
377
+ */
378
+ export function buildBenchmarkStageDiagnostic({
379
+ runId,
380
+ reason,
381
+ runs,
382
+ fullOrder,
383
+ candidateSurface,
384
+ baselineSurface,
385
+ requestedModel,
386
+ requestedThinking,
387
+ suite,
388
+ manifest,
389
+ hostReadinessPolicy = null,
390
+ hostReadinessStageBoundaries = null,
391
+ generatedAt = new Date().toISOString()
392
+ }) {
393
+ const acceptedRuns = Array.isArray(runs) ? runs : [];
394
+ const expectedRuns = Array.isArray(fullOrder) ? fullOrder : [];
395
+ const pairs = expectedPairMap(expectedRuns);
396
+ const expectedRunKeys = new Set(expectedRuns.map(runKey));
397
+ const observedByRunKey = new Map();
398
+ const duplicateRuns = [];
399
+ const unexpectedRuns = [];
400
+ for (const run of acceptedRuns) {
401
+ const key = runKey(run);
402
+ if (!expectedRunKeys.has(key)) unexpectedRuns.push(key.replaceAll("\0", ":"));
403
+ if (observedByRunKey.has(key)) duplicateRuns.push(key.replaceAll("\0", ":"));
404
+ else observedByRunKey.set(key, run);
405
+ }
406
+
407
+ const completePairs = [];
408
+ const incompleteObservedPairs = [];
409
+ const unstartedPairs = [];
410
+ for (const pair of pairs.values()) {
411
+ const observed = [...pair.expectedSurfaces].filter((surface) => observedByRunKey.has(`${pair.scenarioId}\0${surface}\0${pair.repeat}`));
412
+ const missing = [...pair.expectedSurfaces].filter((surface) => !observed.includes(surface));
413
+ const summary = {
414
+ id: publicPairId(pair),
415
+ scenarioId: pair.scenarioId,
416
+ repeat: pair.repeat,
417
+ expectedSurfaces: [...pair.expectedSurfaces],
418
+ observedSurfaces: observed,
419
+ missingSurfaces: missing
420
+ };
421
+ if (observed.length === 0) unstartedPairs.push(summary);
422
+ else if (missing.length === 0) completePairs.push(summary);
423
+ else incompleteObservedPairs.push(summary);
424
+ }
425
+
426
+ const pairRecords = completePairs.map((pair) => ({
427
+ pair,
428
+ candidate: observedByRunKey.get(`${pair.scenarioId}\0${candidateSurface}\0${pair.repeat}`),
429
+ baseline: observedByRunKey.get(`${pair.scenarioId}\0${baselineSurface}\0${pair.repeat}`)
430
+ }));
431
+ const malformedCompletePairs = pairRecords.filter(({ candidate, baseline }) => !candidate || !baseline).map(({ pair }) => pair.id);
432
+ const baselineOnlyRegressions = pairRecords
433
+ .filter(({ candidate, baseline }) => baseline?.resolved === true && candidate?.resolved !== true)
434
+ .map(({ pair, candidate, baseline }) => ({
435
+ pairId: pair.id,
436
+ baselineResolved: baseline.resolved,
437
+ candidateResolved: candidate?.resolved === true,
438
+ candidateFailure: candidate?.failure ?? null
439
+ }));
440
+ const noBaselineOnlyRegressionPassed = completePairs.length > 0
441
+ && malformedCompletePairs.length === 0
442
+ && baselineOnlyRegressions.length === 0;
443
+ const pairedGradeComparabilityFailures = pairRecords.filter(({ candidate, baseline }) => (
444
+ !Number.isFinite(candidate?.grade?.score) || !Number.isFinite(baseline?.grade?.score)
445
+ )).map(({ pair }) => pair.id);
446
+ const pairedGradeRegressions = pairRecords.filter(({ candidate, baseline }) => (
447
+ Number.isFinite(candidate?.grade?.score)
448
+ && Number.isFinite(baseline?.grade?.score)
449
+ && !atMostWithinFloatingPrecision(baseline.grade.score, candidate.grade.score)
450
+ )).map(({ pair, candidate, baseline }) => ({
451
+ pairId: pair.id,
452
+ baselineGradeScore: baseline.grade.score,
453
+ candidateGradeScore: candidate.grade.score
454
+ }));
455
+ const observedGradeNonInferiorPassed = pairRecords.length > 0
456
+ && pairedGradeComparabilityFailures.length === 0
457
+ && pairedGradeRegressions.length === 0;
458
+ const outcomeFloor = suite?.releaseGate?.minimumOutcomeScoreExclusive;
459
+ const outcomeFloorConfigured = Number.isFinite(outcomeFloor);
460
+ const outcomeFailures = outcomeFloorConfigured ? candidateOutcomeFailures(pairRecords, outcomeFloor) : [];
461
+ const outcomeFloorPassed = outcomeFloorConfigured
462
+ && manifest?.stopAfterFailedPair === true
463
+ && pairRecords.length > 0
464
+ && outcomeFailures.length === 0;
465
+ const qualityPassed = noBaselineOnlyRegressionPassed && observedGradeNonInferiorPassed && outcomeFloorPassed;
466
+
467
+ const acceptedUsageFailures = acceptedRuns.map((run) => ({ runId: runKey(run).replaceAll("\0", ":"), issues: exactUsageIssues(run) }))
468
+ .filter((item) => item.issues.length > 0);
469
+ const acceptedUsagePassed = acceptedRuns.length > 0 && acceptedUsageFailures.length === 0;
470
+
471
+ const piRuns = acceptedRuns.filter((run) => run.surface === candidateSurface && candidateSurface === "piagent");
472
+ const piParityFailures = piRuns.map((run) => {
473
+ const issues = [];
474
+ if (run.usage?.model !== requestedModel) issues.push("accepted-model-mismatch");
475
+ if (run.usage?.thinkingLevel !== requestedThinking) issues.push("accepted-thinking-mismatch");
476
+ if (!benchmarkProviderWireEvidenceMatchesRequest(run.providerWireEvidence, requestedModel, requestedThinking)) {
477
+ issues.push("provider-wire-not-verified-or-request-bound");
478
+ }
479
+ return { runId: runKey(run).replaceAll("\0", ":"), issues };
480
+ }).filter((item) => item.issues.length > 0);
481
+ const pairedModelThinkingFailures = pairRecords.map(({ pair, candidate, baseline }) => ({
482
+ pairId: pair.id,
483
+ issues: [
484
+ candidate?.usage?.model !== baseline?.usage?.model ? "paired-model-mismatch" : null,
485
+ candidate?.usage?.thinkingLevel !== baseline?.usage?.thinkingLevel ? "paired-thinking-mismatch" : null
486
+ ].filter(Boolean)
487
+ })).filter((item) => item.issues.length > 0);
488
+ const wireGroups = providerWireGroups(piRuns);
489
+ const wireDriftGroups = wireGroups.filter((group) => !group.passed);
490
+ const providerParityPassed = typeof requestedModel === "string" && requestedModel.length > 0
491
+ && typeof requestedThinking === "string" && requestedThinking.length > 0
492
+ && piRuns.length > 0
493
+ && piParityFailures.length === 0
494
+ && pairedModelThinkingFailures.length === 0
495
+ && wireGroups.length > 0
496
+ && wireDriftGroups.length === 0;
497
+ const causalContextRequired = suite?.releaseGate?.requireCausalContextReceipt === true;
498
+ const causalContextSummary = summarizeBenchmarkCausalContextEvidence(piRuns, { required: causalContextRequired });
499
+ const causalContextAvailableRuns = causalContextSummary.currentAvailableRuns;
500
+ const causalContextPassed = !causalContextRequired
501
+ || causalContextSummary.currentCoverageStatus === "complete";
502
+
503
+ const freshEfficiency = pairRatioEvidence(pairRecords, ({ candidate, baseline }) => ({
504
+ baseline: baseline?.usage?.fresh,
505
+ candidate: candidate?.usage?.fresh
506
+ }));
507
+ const freshEfficiencyPassed = freshEfficiency.records.length > 0
508
+ && freshEfficiency.incomparablePairs.length === 0
509
+ && freshEfficiency.pairRegressions.length === 0
510
+ && freshEfficiency.familyRegressions.length === 0;
511
+
512
+ const pricingSnapshot = suite?.pricingSnapshot;
513
+ const pricingSnapshotErrors = benchmarkPricingSnapshotValidationErrors(pricingSnapshot);
514
+ const normalizedCostEvidence = pairRatioEvidence(pairRecords, ({ candidate, baseline }) => {
515
+ const normalizedBaseline = normalizeBenchmarkUsageCost(baseline?.usage, pricingSnapshot);
516
+ const normalizedCandidate = normalizeBenchmarkUsageCost(candidate?.usage, pricingSnapshot);
517
+ return {
518
+ baseline: normalizedBaseline.status === "measured" ? normalizedBaseline.amount : null,
519
+ candidate: normalizedCandidate.status === "measured" ? normalizedCandidate.amount : null,
520
+ issues: [
521
+ normalizedBaseline.status === "measured" ? null : `baseline:${normalizedBaseline.reason}`,
522
+ normalizedCandidate.status === "measured" ? null : `candidate:${normalizedCandidate.reason}`
523
+ ].filter(Boolean)
524
+ };
525
+ });
526
+ const normalizedCostPassed = pricingSnapshotErrors.length === 0
527
+ && normalizedCostEvidence.records.length > 0
528
+ && normalizedCostEvidence.incomparablePairs.length === 0
529
+ && normalizedCostEvidence.pairRegressions.length === 0
530
+ && normalizedCostEvidence.familyRegressions.length === 0;
531
+
532
+ const durationEfficiency = pairRatioEvidence(pairRecords, ({ candidate, baseline }) => ({
533
+ baseline: baseline?.durationSeconds,
534
+ candidate: candidate?.durationSeconds
535
+ }));
536
+ const durationEfficiencyPassed = durationEfficiency.records.length > 0
537
+ && durationEfficiency.incomparablePairs.length === 0
538
+ && durationEfficiency.pairRegressions.length === 0
539
+ && durationEfficiency.familyRegressions.length === 0;
540
+
541
+ const retryEvidenceFailures = acceptedRuns.map((run) => {
542
+ const issues = [];
543
+ if (!Number.isInteger(run.infrastructureRetries) || run.infrastructureRetries < 0) issues.push("invalid-infrastructure-retry-count");
544
+ if (!Array.isArray(run.infrastructureFailures)) issues.push("missing-infrastructure-failure-ledger");
545
+ else if (Number.isInteger(run.infrastructureRetries) && run.infrastructureFailures.length !== run.infrastructureRetries) {
546
+ issues.push("retry-ledger-count-mismatch");
547
+ }
548
+ return { runId: runKey(run).replaceAll("\0", ":"), issues };
549
+ }).filter((item) => item.issues.length > 0);
550
+ const infrastructureRetries = acceptedRuns.reduce((sum, run) => sum + (Number.isInteger(run.infrastructureRetries) ? run.infrastructureRetries : 0), 0);
551
+ const failedAttempts = acceptedRuns.reduce((sum, run) => sum + (Array.isArray(run.infrastructureFailures) ? run.infrastructureFailures.length : 0), 0);
552
+ const failedAttemptUnknownUsage = acceptedRuns.reduce((sum, run) => sum + (run.infrastructureFailures ?? [])
553
+ .filter((attempt) => attempt?.usageStatus === "unknown-after-provider-start").length, 0);
554
+ const manifestUnknownUsage = Number.isInteger(manifest?.unknownCostAttempts) && manifest.unknownCostAttempts >= 0
555
+ ? manifest.unknownCostAttempts
556
+ : manifest?.unknownCostAttempts === undefined ? 0 : 1;
557
+ const recoveredProviderAttempts = Array.isArray(manifest?.recoveredProviderAttempts)
558
+ ? manifest.recoveredProviderAttempts.length
559
+ : manifest?.recoveredProviderAttempts === undefined ? 0 : 1;
560
+ const tokenClaimsUnavailableReason = typeof manifest?.tokenClaimsUnavailableReason === "string"
561
+ ? manifest.tokenClaimsUnavailableReason
562
+ : manifest?.tokenClaimsUnavailableReason === undefined ? null : "malformed-token-claims-unavailable-reason";
563
+ const retryGatePassed = retryEvidenceFailures.length === 0
564
+ && infrastructureRetries === 0
565
+ && failedAttempts === 0
566
+ && recoveredProviderAttempts === 0;
567
+ const unknownUsageAttempts = failedAttemptUnknownUsage + manifestUnknownUsage;
568
+ const unknownUsagePassed = unknownUsageAttempts === 0 && tokenClaimsUnavailableReason === null;
569
+
570
+ const pairBoundary = incompleteObservedPairs.length === 0
571
+ && duplicateRuns.length === 0
572
+ && unexpectedRuns.length === 0;
573
+ const recognizedPause = typeof reason === "string"
574
+ && (reason.startsWith("max-sessions:") || reason.startsWith("max-runtime-minutes:"));
575
+ const pairContractPassed = pairs.size > 0
576
+ && [...pairs.values()].every((pair) => pair.expectedSurfaces.size === 2
577
+ && pair.expectedSurfaces.has(candidateSurface)
578
+ && pair.expectedSurfaces.has(baselineSurface));
579
+ const executionContractPassed = manifest?.stopAfterFailedPair === true
580
+ && manifest?.infrastructureRetries === 0;
581
+ const cleanReleaseSourceRequired = suite?.schemaVersion === 2
582
+ && suite?.releaseGate?.requireEfficiencyClaim === true
583
+ && suite?.releaseGate?.requireFullSuiteForClaim === true;
584
+ const cleanReleaseSourcePassed = !cleanReleaseSourceRequired || manifest?.sourceIdentity?.dirty === false;
585
+ const hostReadinessRequired = suite?.releaseGate?.requireHostReadinessForClaim === true;
586
+ const summarizedHostReadinessHistory = hostReadinessRequired
587
+ ? summarizeBenchmarkHostReadinessHistory({
588
+ policy: hostReadinessPolicy,
589
+ receipts: manifest?.hostReadinessReceipts,
590
+ completedRuns: acceptedRuns.length,
591
+ authorizedThroughRuns: manifest?.stageControl?.authorizedThroughRuns,
592
+ runId: manifest?.runId ?? runId,
593
+ configurationDigest: manifest?.configurationDigest,
594
+ stageBoundaries: hostReadinessStageBoundaries
595
+ })
596
+ : null;
597
+ const hostReadinessPolicyBindingValid = !hostReadinessRequired
598
+ || (benchmarkHostReadinessPolicyValidationErrors(hostReadinessPolicy).length === 0
599
+ && manifest?.hostReadinessPolicyDigest === benchmarkHostReadinessPolicyDigest(hostReadinessPolicy));
600
+ const hostReadinessHistory = summarizedHostReadinessHistory && !hostReadinessPolicyBindingValid
601
+ ? {
602
+ ...summarizedHostReadinessHistory,
603
+ valid: false,
604
+ ready: false,
605
+ errors: [...summarizedHostReadinessHistory.errors, "host-readiness-manifest-policy-digest-mismatch"]
606
+ }
607
+ : summarizedHostReadinessHistory;
608
+ const hostReadinessPassed = !hostReadinessRequired
609
+ || (hostReadinessHistory.valid === true && hostReadinessHistory.ready === true);
610
+ const checks = [
611
+ diagnosticCheck("recognized-spend-control-pause", recognizedPause, { reason }),
612
+ diagnosticCheck("paired-contract", pairContractPassed, { candidateSurface, baselineSurface }),
613
+ diagnosticCheck("spend-control-execution-contract", executionContractPassed, {
614
+ stopAfterFailedPair: manifest?.stopAfterFailedPair === true,
615
+ infrastructureRetries: Number.isInteger(manifest?.infrastructureRetries) ? manifest.infrastructureRetries : null
616
+ }),
617
+ diagnosticCheck("clean-release-source", cleanReleaseSourcePassed, {
618
+ required: cleanReleaseSourceRequired,
619
+ dirty: typeof manifest?.sourceIdentity?.dirty === "boolean" ? manifest.sourceIdentity.dirty : null
620
+ }),
621
+ diagnosticCheck("host-readiness-receipt-history", hostReadinessPassed, {
622
+ required: hostReadinessRequired,
623
+ validReceipts: hostReadinessHistory?.validReceiptCount ?? 0,
624
+ receipts: hostReadinessHistory?.receiptCount ?? 0,
625
+ coverage: hostReadinessHistory?.windowCoverage ?? null
626
+ }, hostReadinessRequired ? "blocking" : "observational"),
627
+ diagnosticCheck("pause-on-pair-boundary", pairBoundary, { incompleteObservedPairs: incompleteObservedPairs.length }),
628
+ diagnosticCheck("observed-complete-pair", completePairs.length > 0, { observedCompletePairs: completePairs.length }),
629
+ diagnosticCheck("no-baseline-pass-piagent-fail", noBaselineOnlyRegressionPassed, { regressions: baselineOnlyRegressions.length }),
630
+ diagnosticCheck("observed-paired-grade-noninferior", observedGradeNonInferiorPassed, {
631
+ incomparablePairs: pairedGradeComparabilityFailures.length,
632
+ regressions: pairedGradeRegressions.length
633
+ }),
634
+ diagnosticCheck("candidate-outcome-floor", outcomeFloorPassed, {
635
+ minimumOutcomeScoreExclusive: outcomeFloorConfigured ? outcomeFloor : null,
636
+ failures: outcomeFailures.length
637
+ }),
638
+ diagnosticCheck("accepted-usage-exact", acceptedUsagePassed, { failures: acceptedUsageFailures.length }),
639
+ diagnosticCheck("provider-wire-model-thinking-parity", providerParityPassed, { failures: piParityFailures.length + pairedModelThinkingFailures.length + wireDriftGroups.length }),
640
+ diagnosticCheck("piagent-causal-context-receipts", causalContextPassed, {
641
+ required: causalContextRequired,
642
+ availableRuns: causalContextAvailableRuns,
643
+ piagentRuns: piRuns.length,
644
+ unavailableRuns: piRuns.length - causalContextAvailableRuns
645
+ }),
646
+ diagnosticCheck("no-infrastructure-retry", retryGatePassed, { retries: infrastructureRetries }),
647
+ diagnosticCheck("no-unknown-attempt-usage", unknownUsagePassed, { unknownUsageAttempts }),
648
+ diagnosticCheck("no-observed-fresh-token-regression", freshEfficiencyPassed, {
649
+ incomparablePairs: freshEfficiency.incomparablePairs.length,
650
+ pairRegressions: freshEfficiency.pairRegressions.length,
651
+ familyRegressions: freshEfficiency.familyRegressions.length
652
+ }, "final-only"),
653
+ diagnosticCheck("normalized-cost-pricing-applicable-and-no-observed-regression", normalizedCostPassed, {
654
+ pricingSnapshotErrors: pricingSnapshotErrors.length,
655
+ incomparablePairs: normalizedCostEvidence.incomparablePairs.length,
656
+ pairRegressions: normalizedCostEvidence.pairRegressions.length,
657
+ familyRegressions: normalizedCostEvidence.familyRegressions.length
658
+ }, "observational"),
659
+ diagnosticCheck("no-observed-duration-regression", durationEfficiencyPassed, {
660
+ incomparablePairs: durationEfficiency.incomparablePairs.length,
661
+ pairRegressions: durationEfficiency.pairRegressions.length,
662
+ familyRegressions: durationEfficiency.familyRegressions.length
663
+ }, "observational")
664
+ ];
665
+ const blockingReasons = checks
666
+ .filter((check) => check.decisionRole === "blocking" && !check.passed)
667
+ .map((check) => check.id);
668
+
669
+ return {
670
+ schemaVersion: 1,
671
+ diagnosticOnly: true,
672
+ claimEligible: false,
673
+ runId,
674
+ generatedAt,
675
+ pause: { reason, recognizedSpendControlPause: recognizedPause, pairBoundary },
676
+ completedRuns: acceptedRuns.length,
677
+ expectedRuns: expectedRuns.length,
678
+ remainingRuns: Math.max(0, expectedRuns.length - acceptedRuns.length),
679
+ counts: {
680
+ completedSessions: acceptedRuns.length,
681
+ expectedSessions: expectedRuns.length,
682
+ expectedPairs: pairs.size,
683
+ observedCompletePairs: completePairs.length,
684
+ incompleteObservedPairs: incompleteObservedPairs.length,
685
+ unstartedPairs: unstartedPairs.length,
686
+ duplicateSessions: duplicateRuns.length,
687
+ unexpectedSessions: unexpectedRuns.length
688
+ },
689
+ pairs: {
690
+ completeObserved: completePairs,
691
+ incompleteObserved: incompleteObservedPairs,
692
+ unstarted: unstartedPairs,
693
+ duplicateRuns,
694
+ unexpectedRuns,
695
+ futureUnstartedPairsBlockStageAdvance: false
696
+ },
697
+ quality: {
698
+ rule: "no-baseline-pass-piagent-fail-and-candidate-outcomes-above-the-release-floor",
699
+ passed: qualityPassed,
700
+ noBaselineOnlyRegressionPassed,
701
+ observedGradeNonInferiorPassed,
702
+ observedCompletePairs: completePairs.length,
703
+ malformedCompletePairs,
704
+ baselineOnlyRegressions,
705
+ pairedGradeComparabilityFailures,
706
+ pairedGradeRegressions,
707
+ outcomeFloor: outcomeFloorConfigured ? {
708
+ minimumScoreExclusive: outcomeFloor,
709
+ stopAfterFailedPairEnabled: manifest?.stopAfterFailedPair === true,
710
+ passed: outcomeFloorPassed,
711
+ failures: outcomeFailures
712
+ } : {
713
+ minimumScoreExclusive: null,
714
+ stopAfterFailedPairEnabled: manifest?.stopAfterFailedPair === true,
715
+ passed: false,
716
+ failures: [{ failures: ["outcome-floor-not-configured"] }]
717
+ }
718
+ },
719
+ acceptedUsage: {
720
+ rule: "every-accepted-session-has-exact-provider-token-buckets",
721
+ passed: acceptedUsagePassed,
722
+ exactRuns: acceptedRuns.length - acceptedUsageFailures.length,
723
+ acceptedRuns: acceptedRuns.length,
724
+ failures: acceptedUsageFailures
725
+ },
726
+ providerParity: {
727
+ rule: "observed-pi-runs-match-requested-model-thinking-and-verified-provider-wire",
728
+ passed: providerParityPassed,
729
+ requestedModel: requestedModel ?? null,
730
+ requestedThinking: requestedThinking ?? null,
731
+ observedPiRuns: piRuns.length,
732
+ verifiedPiRuns: piRuns.length - piParityFailures.length,
733
+ piRunFailures: piParityFailures,
734
+ pairedModelThinkingFailures,
735
+ wireGroups,
736
+ wireDriftGroups
737
+ },
738
+ causalContextEvidence: {
739
+ rule: "every-observed-piagent-session-preserves-a-complete-privacy-safe-causal-context-receipt",
740
+ passed: causalContextPassed,
741
+ piagentRuns: piRuns.length,
742
+ ...causalContextSummary
743
+ },
744
+ infrastructure: {
745
+ retryGatePassed,
746
+ retryEvidenceFailures,
747
+ infrastructureRetries,
748
+ failedAttempts,
749
+ recoveredProviderAttempts,
750
+ unknownUsageGatePassed: unknownUsagePassed,
751
+ unknownUsageAttempts,
752
+ failedAttemptUnknownUsage,
753
+ manifestUnknownUsage,
754
+ tokenClaimsUnavailableReason
755
+ },
756
+ hostReadiness: hostReadinessHistory,
757
+ timingDiagnostics: summarizeBenchmarkTimingDiagnostics(acceptedRuns),
758
+ spendFutilityReview: {
759
+ rule: "observed-pair-and-observed-family-point-ratios-must-not-exceed-1; this-is-not-the-final-40-percent-claim-gate",
760
+ passed: freshEfficiencyPassed && normalizedCostPassed && durationEfficiencyPassed,
761
+ freshTokens: { passed: freshEfficiencyPassed, ...freshEfficiency },
762
+ normalizedApiEquivalentTextTokenCost: {
763
+ billedCost: false,
764
+ scope: "model-text-token-input-cache-output-only",
765
+ pricingSnapshotId: pricingSnapshotErrors.length === 0 ? pricingSnapshot.id : null,
766
+ pricingSnapshotErrors,
767
+ passed: normalizedCostPassed,
768
+ ...normalizedCostEvidence
769
+ },
770
+ duration: { passed: durationEfficiencyPassed, ...durationEfficiency }
771
+ },
772
+ checks,
773
+ blockingReasons,
774
+ stageAdvanceAllowed: blockingReasons.length === 0,
775
+ decisionContract: {
776
+ blocking: "quality-model-parity-task-continuity-and-exact-usage-only",
777
+ finalOnly: ["fresh-token-reduction"],
778
+ observational: ["normalized-api-equivalent-text-token-cost", "duration", "host-load"]
779
+ },
780
+ claimBoundary: "Provider-free partial-run diagnostic only. Intermediate token measurements cannot make a claim; cost, duration, and host load are observational and non-blocking."
781
+ };
782
+ }