@piagent/platform 1.5.5 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (323) hide show
  1. package/CHANGELOG.md +166 -0
  2. package/README.md +25 -21
  3. package/README.vi.md +34 -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 +92 -0
  24. package/benchmarks/production-v1/suite.json +46 -3
  25. package/catalog/capabilities.json +18 -18
  26. package/docs/authority-manifest.md +1 -1
  27. package/docs/auto-delegation-policy.md +38 -73
  28. package/docs/command-reference-vietnamese.md +27 -35
  29. package/docs/context-engine.md +12 -4
  30. package/docs/context-window-policy.md +37 -1
  31. package/docs/distribution-standard.md +7 -7
  32. package/docs/en/architecture.md +27 -13
  33. package/docs/languages.json +4 -4
  34. package/docs/model-options.md +8 -5
  35. package/docs/operator-manual-vietnamese.md +27 -45
  36. package/docs/project-adapters.md +2 -2
  37. package/docs/publishing-for-teams.md +10 -0
  38. package/docs/quality-benchmark.md +427 -62
  39. package/docs/release-install-policy.md +10 -9
  40. package/docs/runtime-harness-standard.md +3 -3
  41. package/docs/runtime-policy-design.md +4 -4
  42. package/docs/runtime-quality-baseline.md +13 -6
  43. package/docs/security-threat-model.md +2 -2
  44. package/docs/subagent-orchestration-capabilities.md +19 -51
  45. package/docs/subagents-and-multiagent.md +21 -47
  46. package/docs/task-implementation-contract.md +3 -3
  47. package/docs/task-lifecycle-vietnamese.md +3 -3
  48. package/docs/team-onboarding.md +2 -2
  49. package/docs/usage-observability.md +7 -2
  50. package/docs/vi/architecture.md +27 -13
  51. package/docs-site/architecture.html +1 -1
  52. package/docs-site/benchmark.html +89 -95
  53. package/docs-site/commands.html +1 -1
  54. package/docs-site/content/benchmark.html +88 -94
  55. package/docs-site/content/en/benchmark.html +134 -90
  56. package/docs-site/content/en/index.html +19 -19
  57. package/docs-site/content/en/runtime.html +4 -4
  58. package/docs-site/content/en/whats-new.html +12 -1
  59. package/docs-site/content/en/workflows.html +2 -2
  60. package/docs-site/content/index.html +19 -19
  61. package/docs-site/content/runtime.html +4 -4
  62. package/docs-site/content/whats-new.html +12 -1
  63. package/docs-site/content/workflows.html +2 -2
  64. package/docs-site/context-engine.html +1 -1
  65. package/docs-site/en/architecture.html +1 -1
  66. package/docs-site/en/benchmark.html +135 -91
  67. package/docs-site/en/commands.html +1 -1
  68. package/docs-site/en/context-engine.html +1 -1
  69. package/docs-site/en/index.html +20 -20
  70. package/docs-site/en/mcp-approval.html +1 -1
  71. package/docs-site/en/mcp-auth.html +1 -1
  72. package/docs-site/en/mcp-servers.html +1 -1
  73. package/docs-site/en/mcp.html +1 -1
  74. package/docs-site/en/permissions.html +1 -1
  75. package/docs-site/en/profiles.html +1 -1
  76. package/docs-site/en/quickstart.html +1 -1
  77. package/docs-site/en/runtime.html +5 -5
  78. package/docs-site/en/scope.html +1 -1
  79. package/docs-site/en/security.html +1 -1
  80. package/docs-site/en/team.html +1 -1
  81. package/docs-site/en/whats-new.html +13 -2
  82. package/docs-site/en/workflows.html +3 -3
  83. package/docs-site/index.html +20 -20
  84. package/docs-site/mcp-approval.html +1 -1
  85. package/docs-site/mcp-auth.html +1 -1
  86. package/docs-site/mcp-servers.html +1 -1
  87. package/docs-site/mcp.html +1 -1
  88. package/docs-site/permissions.html +1 -1
  89. package/docs-site/profiles.html +1 -1
  90. package/docs-site/quickstart.html +1 -1
  91. package/docs-site/runtime.html +5 -5
  92. package/docs-site/scope.html +1 -1
  93. package/docs-site/security.html +1 -1
  94. package/docs-site/team.html +1 -1
  95. package/docs-site/whats-new.html +13 -2
  96. package/docs-site/workflows.html +3 -3
  97. package/evals/fixtures/benchmark-assurance-evidence.invalid.json +1 -1
  98. package/evals/fixtures/benchmark-assurance-evidence.valid.json +1 -1
  99. package/evals/fixtures/codex-relative-efficiency-v1.invalid.json +4 -0
  100. package/evals/fixtures/codex-relative-efficiency-v1.valid.json +94 -0
  101. package/evals/fixtures/helper-request.invalid.json +1 -1
  102. package/evals/fixtures/helper-request.valid.json +1 -1
  103. package/evals/fixtures/piagent-webui/session-live-state-v1.invalid.json +18 -0
  104. package/evals/fixtures/piagent-webui/session-live-state-v1.valid.json +27 -0
  105. package/evals/fixtures/piagent-webui/subagent-tree-v1.valid.json +7 -0
  106. package/evals/fixtures/task-authority-snapshot.valid.json +4 -4
  107. package/evals/fs4-readiness-matrix.v1.json +2 -2
  108. package/evals/fs5-causal-arm.v1.json +3 -3
  109. package/evals/fs5-pilot-protocol.v1.json +3 -3
  110. package/evals/fs5-pilot-protocol.v2.json +8 -8
  111. package/evals/fs5-pilot-protocol.v3.json +8 -8
  112. package/evals/fs5-pilot-protocol.v4.json +7 -6
  113. package/evals/fs5-pilot-protocol.v5.json +9 -7
  114. package/evals/private-holdout-v1/public-exposure.v1.json +1 -1
  115. package/evals/runtime-conformance-v1/README.md +43 -0
  116. package/evals/runtime-conformance-v1/evaluate-paid-canary.mjs +198 -0
  117. package/evals/runtime-conformance-v1/lane.json +57 -0
  118. package/evals/runtime-conformance-v1/paid-canary.json +31 -0
  119. package/evals/runtime-conformance-v1/runner.mjs +456 -0
  120. package/package.json +3 -1
  121. package/packages/piagent-core/README.md +13 -4
  122. package/packages/piagent-core/benchmark/benchmark-assurance.js +4 -1
  123. package/packages/piagent-core/benchmark/benchmark-bootstrap.js +91 -9
  124. package/packages/piagent-core/benchmark/benchmark-claim-restrictions.js +38 -7
  125. package/packages/piagent-core/benchmark/benchmark-cli.js +7 -7
  126. package/packages/piagent-core/benchmark/benchmark-codex-relative-efficiency.js +698 -0
  127. package/packages/piagent-core/benchmark/benchmark-codex.js +3 -1
  128. package/packages/piagent-core/benchmark/benchmark-comparison.js +271 -2
  129. package/packages/piagent-core/benchmark/benchmark-core.js +736 -664
  130. package/packages/piagent-core/benchmark/benchmark-execution-guard.js +7 -5
  131. package/packages/piagent-core/benchmark/benchmark-forensics.js +441 -4
  132. package/packages/piagent-core/benchmark/benchmark-host-readiness.js +639 -0
  133. package/packages/piagent-core/benchmark/benchmark-matrix.js +22 -4
  134. package/packages/piagent-core/benchmark/benchmark-normalized-cost.js +317 -0
  135. package/packages/piagent-core/benchmark/benchmark-preflight.js +5 -1
  136. package/packages/piagent-core/benchmark/benchmark-process.js +6 -5
  137. package/packages/piagent-core/benchmark/benchmark-provider-free-evidence.js +345 -0
  138. package/packages/piagent-core/benchmark/benchmark-provider-wire.js +126 -0
  139. package/packages/piagent-core/benchmark/benchmark-record-validation.js +252 -0
  140. package/packages/piagent-core/benchmark/benchmark-report.js +130 -12
  141. package/packages/piagent-core/benchmark/benchmark-resume-recovery.js +14 -0
  142. package/packages/piagent-core/benchmark/benchmark-runner-policy.js +26 -0
  143. package/packages/piagent-core/benchmark/benchmark-runtime-causal.js +244 -0
  144. package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +979 -0
  145. package/packages/piagent-core/benchmark/benchmark-statistics.js +64 -0
  146. package/packages/piagent-core/benchmark/benchmark-stop-policy.js +8 -5
  147. package/packages/piagent-core/benchmark/benchmark-suite-identity.js +31 -0
  148. package/packages/piagent-core/benchmark/benchmark-suite-runtime.js +13 -9
  149. package/packages/piagent-core/benchmark/benchmark-suite.js +149 -2
  150. package/packages/piagent-core/benchmark/benchmark-summary-support.js +380 -0
  151. package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +971 -0
  152. package/packages/piagent-core/benchmark/benchmark-usage.js +322 -0
  153. package/packages/piagent-core/benchmark/benchmark-workflow.js +166 -0
  154. package/packages/piagent-core/capabilities/runtime-integrity.js +3 -0
  155. package/packages/piagent-core/docs/context-efficiency-improvement-plan.md +1080 -0
  156. package/packages/piagent-core/extensions/acceptance-behavior-proof.js +806 -0
  157. package/packages/piagent-core/extensions/acceptance-contract-semantics.js +83 -69
  158. package/packages/piagent-core/extensions/acceptance-error-classes.js +160 -0
  159. package/packages/piagent-core/extensions/acceptance-executable-evidence.js +12 -9
  160. package/packages/piagent-core/extensions/acceptance-receipt.js +123 -59
  161. package/packages/piagent-core/extensions/acceptance-state-machine-evidence.js +518 -0
  162. package/packages/piagent-core/extensions/acceptance-test-binding-evidence.js +60 -0
  163. package/packages/piagent-core/extensions/context-efficiency-metrics.js +302 -0
  164. package/packages/piagent-core/extensions/context-efficiency-report.js +167 -0
  165. package/packages/piagent-core/extensions/context-engine.js +149 -156
  166. package/packages/piagent-core/extensions/context-evidence.js +48 -0
  167. package/packages/piagent-core/extensions/context-import-links.js +296 -0
  168. package/packages/piagent-core/extensions/context-index-policy.js +4 -0
  169. package/packages/piagent-core/extensions/context-query-paths.js +57 -0
  170. package/packages/piagent-core/extensions/context-telemetry-integrity.js +65 -0
  171. package/packages/piagent-core/extensions/criterion-context-pack.js +435 -7
  172. package/packages/piagent-core/extensions/criterion-graph.js +82 -9
  173. package/packages/piagent-core/extensions/fallback-base-policy.ts +101 -0
  174. package/packages/piagent-core/extensions/guard-types.ts +6 -0
  175. package/packages/piagent-core/extensions/javascript-regex-evidence.js +32 -0
  176. package/packages/piagent-core/extensions/piagent-guard.ts +420 -260
  177. package/packages/piagent-core/extensions/task-contract-view.js +17 -3
  178. package/packages/piagent-core/extensions/task-lifecycle.js +39 -2
  179. package/packages/piagent-core/extensions/task-state.js +109 -142
  180. package/packages/piagent-core/extensions/verification-intelligence.js +52 -13
  181. package/packages/piagent-core/extensions/workspace-evidence-roots.js +193 -0
  182. package/packages/piagent-core/package.json +1 -1
  183. package/packages/piagent-core/policies/base-policy.json +44 -2
  184. package/packages/piagent-core/policy/authority-manifest.v1.json +3 -3
  185. package/packages/piagent-core/prompts/be-to-fe.md +2 -8
  186. package/packages/piagent-core/prompts/plan.md +1 -1
  187. package/packages/piagent-core/prompts/platform-improve.md +2 -6
  188. package/packages/piagent-core/prompts/review.md +2 -7
  189. package/packages/piagent-core/prompts/scout.md +1 -1
  190. package/packages/piagent-core/prompts/task.md +4 -3
  191. package/packages/piagent-core/runtime/context/context-delivery.ts +103 -0
  192. package/packages/piagent-core/runtime/context/context-delta-shadow.ts +53 -0
  193. package/packages/piagent-core/runtime/context/context-efficiency-format.ts +47 -0
  194. package/packages/piagent-core/runtime/context/context-evidence-qualification.ts +32 -0
  195. package/packages/piagent-core/runtime/context/prefix-telemetry.ts +47 -0
  196. package/packages/piagent-core/runtime/context/repository-memory-hints.ts +27 -0
  197. package/packages/piagent-core/runtime/hooks/agent-prompt-telemetry.ts +56 -0
  198. package/packages/piagent-core/runtime/hooks/agent-start-hook.ts +162 -102
  199. package/packages/piagent-core/runtime/hooks/completion-hook.ts +12 -12
  200. package/packages/piagent-core/runtime/hooks/input-hook.ts +17 -1
  201. package/packages/piagent-core/runtime/hooks/session-hooks.ts +22 -2
  202. package/packages/piagent-core/runtime/hooks/session-start-hook.ts +107 -3
  203. package/packages/piagent-core/runtime/hooks/tool-result-content-guards.ts +95 -0
  204. package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +134 -166
  205. package/packages/piagent-core/runtime/hooks/tool-result-value-helpers.ts +66 -0
  206. package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +4 -2
  207. package/packages/piagent-core/runtime/inspection/activity-recovery.ts +104 -0
  208. package/packages/piagent-core/runtime/inspection/bounded-emission-guard.ts +286 -0
  209. package/packages/piagent-core/runtime/inspection/runtime-event-store.ts +37 -7
  210. package/packages/piagent-core/runtime/inspection/task-compaction-history.ts +1 -1
  211. package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +1 -1
  212. package/packages/piagent-core/runtime/inspection/task-subagent-tree.ts +27 -4
  213. package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +70 -0
  214. package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +73 -9
  215. package/packages/piagent-core/runtime/model/authenticated-catalog.ts +17 -9
  216. package/packages/piagent-core/runtime/model/openai-codex-reasoning.ts +83 -0
  217. package/packages/piagent-core/runtime/model/provider-wire-fingerprint.ts +238 -0
  218. package/packages/piagent-core/runtime/orchestration/helper-lifecycle.ts +16 -12
  219. package/packages/piagent-core/runtime/orchestration/minimal-delegation-policy.ts +71 -0
  220. package/packages/piagent-core/runtime/orchestration/owned-work-budget.ts +28 -20
  221. package/packages/piagent-core/runtime/orchestration/role-policy.ts +27 -9
  222. package/packages/piagent-core/runtime/orchestration/subagent-tool-policy.ts +329 -0
  223. package/packages/piagent-core/runtime/policy/block-remedy.ts +0 -4
  224. package/packages/piagent-core/runtime/product/activity-inspector.ts +7 -2
  225. package/packages/piagent-core/runtime/product/efficiency-metrics.ts +7 -2
  226. package/packages/piagent-core/runtime/quality/edit-freshness-guard.ts +102 -0
  227. package/packages/piagent-core/runtime/quality/exact-output-contract.ts +22 -11
  228. package/packages/piagent-core/runtime/quality/performance-assurance-signals.ts +23 -0
  229. package/packages/piagent-core/runtime/quality/performance-assurance.ts +9 -5
  230. package/packages/piagent-core/runtime/recovery/continuation-budget.ts +1 -1
  231. package/packages/piagent-core/runtime/recovery/edit-recovery-context.ts +113 -0
  232. package/packages/piagent-core/runtime/recovery/edit-recovery-delivery.ts +42 -0
  233. package/packages/piagent-core/runtime/recovery/handoff-projection.ts +4 -1
  234. package/packages/piagent-core/runtime/recovery/pristine-task-policy-refresh.ts +91 -0
  235. package/packages/piagent-core/runtime/recovery/recovery-policy.ts +7 -4
  236. package/packages/piagent-core/runtime/recovery/resume-state.ts +112 -14
  237. package/packages/piagent-core/runtime/recovery/semantic-repair-handshake.ts +60 -13
  238. package/packages/piagent-core/runtime/recovery/semantic-repair-runtime.ts +55 -2
  239. package/packages/piagent-core/runtime/recovery/task-evidence-coverage-refresh.ts +217 -0
  240. package/packages/piagent-core/runtime/registration/context-commands.ts +82 -7
  241. package/packages/piagent-core/runtime/registration/knowledge-tools.ts +9 -5
  242. package/packages/piagent-core/runtime/registration/operator-request-intake.ts +49 -0
  243. package/packages/piagent-core/runtime/registration/policy-tools.ts +50 -15
  244. package/packages/piagent-core/runtime/registration/session-commands.ts +1 -1
  245. package/packages/piagent-core/runtime/registration/task-completion-tools.ts +61 -25
  246. package/packages/piagent-core/runtime/registration/task-evidence-tools.ts +21 -12
  247. package/packages/piagent-core/runtime/registration/task-start-guidance.ts +169 -0
  248. package/packages/piagent-core/runtime/registration/task-start-manifest.ts +54 -0
  249. package/packages/piagent-core/runtime/registration/task-start-retry-helpers.ts +37 -0
  250. package/packages/piagent-core/runtime/registration/task-start-tool.ts +108 -103
  251. package/packages/piagent-core/runtime/runtime-limits.ts +16 -2
  252. package/packages/piagent-core/runtime/session/adaptive-context-analysis.ts +461 -0
  253. package/packages/piagent-core/runtime/session/adaptive-context-governor.ts +464 -0
  254. package/packages/piagent-core/runtime/session/adaptive-context-ledger.ts +265 -0
  255. package/packages/piagent-core/runtime/session/message-signals.ts +7 -3
  256. package/packages/piagent-core/runtime/session/operator-request-carry.ts +44 -0
  257. package/packages/piagent-core/runtime/session/runtime-state.ts +161 -5
  258. package/packages/piagent-core/runtime/session/source-checkout-read-grants.ts +35 -0
  259. package/packages/piagent-core/runtime/session/system-prompt.ts +76 -14
  260. package/packages/piagent-core/runtime/session/task-contract-presentation.ts +39 -0
  261. package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +500 -0
  262. package/packages/piagent-core/runtime/tools/phase-tools.ts +8 -8
  263. package/packages/piagent-core/runtime/tools/tool-groups.ts +12 -2
  264. package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +2 -1
  265. package/packages/piagent-core/runtime/verification/exact-verifier-reuse.ts +101 -0
  266. package/packages/piagent-core/runtime/workflows/runtime-intake-compaction.ts +164 -0
  267. package/packages/piagent-core/runtime/workflows/task-intake.ts +207 -38
  268. package/packages/piagent-core/security/sensitive-data.js +13 -218
  269. package/packages/piagent-core/security/sensitive-project-file.js +42 -0
  270. package/packages/piagent-core/security/sensitive-source-expression.js +330 -0
  271. package/packages/piagent-core/security/sensitive-source-formats.js +394 -0
  272. package/packages/piagent-core/security/sensitive-text.js +234 -0
  273. package/packages/piagent-core/subagents/piagent-oracle.md +5 -3
  274. package/packages/piagent-core/subagents/piagent-planner.md +6 -4
  275. package/packages/piagent-core/subagents/piagent-reviewer.md +5 -3
  276. package/packages/piagent-core/subagents/piagent-scout.md +4 -2
  277. package/packages/piagent-core/subagents/piagent-worker.md +7 -5
  278. package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-rD9WJKxs.js → MarkdownMessage-B4XehTCU.js} +1 -1
  279. package/packages/piagent-webui/dist/client/assets/index-CgOEyRPG.js +176 -0
  280. package/packages/piagent-webui/dist/client/index.html +1 -1
  281. package/packages/piagent-webui/extension/piagent-webui.ts +3 -1
  282. package/packages/piagent-webui/extension/same-session-bridge.ts +1 -1
  283. package/packages/piagent-webui/extension/session-stream-adapter.ts +33 -10
  284. package/packages/piagent-webui/gateway/gateway-events.ts +109 -5
  285. package/packages/piagent-webui/gateway/gateway-service.ts +3 -0
  286. package/packages/piagent-webui/gateway/gateway-session-stream.ts +122 -20
  287. package/packages/piagent-webui/gateway/session-command-controller.ts +18 -3
  288. package/packages/piagent-webui/gateway/session-effective-options.ts +47 -0
  289. package/packages/piagent-webui/gateway/session-live-state.ts +21 -0
  290. package/packages/piagent-webui/gateway/session-operation-lifecycle.ts +237 -0
  291. package/packages/piagent-webui/gateway/session-operation-retry-control.ts +38 -0
  292. package/packages/piagent-webui/gateway/session-operation-start.ts +5 -1
  293. package/packages/piagent-webui/gateway/session-operation-watchdog.ts +165 -0
  294. package/packages/piagent-webui/gateway/session-runtime-factory.ts +45 -0
  295. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +141 -125
  296. package/packages/piagent-webui/ownership/session-lease-store.ts +5 -2
  297. package/packages/piagent-webui/server/core-inspection-provider.ts +2 -1
  298. package/packages/piagent-webui/server/loopback-server.ts +8 -0
  299. package/packages/piagent-webui/server/transcript-projection.ts +113 -9
  300. package/packages/piagent-webui/shared/text-visibility.ts +10 -0
  301. package/schemas/codex-relative-efficiency-v1.schema.json +155 -0
  302. package/schemas/piagent-webui/catalog-v1.json +9 -0
  303. package/schemas/piagent-webui/gateway-protocol-v1.schema.json +53 -3
  304. package/schemas/piagent-webui/runtime-event-v2.schema.json +15 -5
  305. package/schemas/piagent-webui/session-live-state-v1.schema.json +76 -0
  306. package/schemas/piagent-webui/subagent-tree-v1.schema.json +11 -1
  307. package/schemas/project-profile.schema.json +1 -1
  308. package/schemas/task-contract.schema.json +27 -1
  309. package/scripts/benchmark-runner-core.mjs +367 -363
  310. package/scripts/benchmark-runner-finalization.mjs +313 -0
  311. package/scripts/benchmark-runner-host-readiness.mjs +94 -0
  312. package/scripts/benchmark-runner-support.mjs +200 -0
  313. package/scripts/benchmark-session.mjs +95 -41
  314. package/scripts/configure-model-scope.sh +4 -3
  315. package/scripts/configure-subagents.sh +42 -34
  316. package/scripts/helper-evaluation.mjs +2 -2
  317. package/scripts/install-global.sh +2 -2
  318. package/scripts/pi-usage-history.mjs +37 -10
  319. package/scripts/setup.sh +2 -2
  320. package/scripts/team-doctor.sh +1 -1
  321. package/scripts/verify-local.sh +10 -1
  322. package/templates/global/settings.json +2 -1
  323. package/packages/piagent-webui/dist/client/assets/index-BZRFw1u6.js +0 -174
@@ -0,0 +1,979 @@
1
+ import { benchmarkProviderWireEvidenceMatchesRequest } from "./benchmark-provider-wire.js";
2
+ import { productionProviderFreeEvidenceContextValidationErrors } from "./benchmark-provider-free-evidence.js";
3
+ import { summarizeBenchmarkSubagentBudget } from "./benchmark-codex-relative-efficiency.js";
4
+ import {
5
+ benchmarkPricingSnapshotValidationErrors,
6
+ normalizeBenchmarkUsageCost
7
+ } from "./benchmark-normalized-cost.js";
8
+ import { summarizeBenchmarkCausalContextEvidence } from "./benchmark-record-validation.js";
9
+ import {
10
+ benchmarkHostReadinessPolicyDigest,
11
+ benchmarkHostReadinessPolicyValidationErrors,
12
+ summarizeBenchmarkHostReadinessHistory
13
+ } from "./benchmark-host-readiness.js";
14
+ import { atMostWithinFloatingPrecision, geometricMean } from "./benchmark-statistics.js";
15
+ import { pairedOutcomeFloorStop } from "./benchmark-stop-policy.js";
16
+ import { workflowContinuityEvidenceComplete } from "./benchmark-summary-support.js";
17
+ import { summarizeBenchmarkTimingDiagnostics } from "./benchmark-timing-diagnostics.js";
18
+ import { exactBenchmarkAttemptUsage } from "./benchmark-usage.js";
19
+
20
+ const TOKEN_FIELDS = Object.freeze(["input", "output", "cacheRead", "cacheWrite", "reasoning", "fresh", "total"]);
21
+ const PRODUCTION_STAGE_CONTROL_POLICY = "production-v1-provider-spend-v1";
22
+
23
+ function nonEmptyString(value) {
24
+ return typeof value === "string" && value.trim().length > 0;
25
+ }
26
+
27
+ function validStageBoundaries(stageBoundaries) {
28
+ return Array.isArray(stageBoundaries)
29
+ && stageBoundaries.length >= 2
30
+ && stageBoundaries[0] === 0
31
+ && stageBoundaries.every((value, index) => Number.isSafeInteger(value)
32
+ && value >= 0
33
+ && (index === 0 || value > stageBoundaries[index - 1]));
34
+ }
35
+
36
+ export function productionGuardBindingMatches(manifest, spendControl) {
37
+ return JSON.stringify(manifest?.productionGuards ?? null)
38
+ === JSON.stringify(spendControl?.productionGuards ?? null);
39
+ }
40
+
41
+ export function productionSpendControlValidationErrors(control, {
42
+ suiteId,
43
+ expectedSessions,
44
+ requireHostReadiness = control?.hostReadiness?.required === true
45
+ } = {}) {
46
+ const errors = [];
47
+ if (!control || typeof control !== "object" || Array.isArray(control)) return ["contract-must-be-an-object"];
48
+ if (control.schemaVersion !== 1) errors.push("unsupported-schema-version");
49
+ if (!nonEmptyString(control.suiteId) || (suiteId !== undefined && control.suiteId !== suiteId)) errors.push("suite-id-mismatch");
50
+ if (!nonEmptyString(control.rootSeed) || control.rootSeed.length > 200) errors.push("invalid-root-seed");
51
+
52
+ const execution = control.execution;
53
+ if (!execution || typeof execution !== "object" || Array.isArray(execution)) errors.push("missing-execution-contract");
54
+ else {
55
+ if (!Array.isArray(execution.surfaces)
56
+ || execution.surfaces.length !== 2
57
+ || new Set(execution.surfaces).size !== 2
58
+ || execution.surfaces.some((surface) => !nonEmptyString(surface))) errors.push("invalid-execution-surfaces");
59
+ if (execution.model !== null && !nonEmptyString(execution.model)) errors.push("invalid-execution-model");
60
+ if (execution.thinking !== null && !nonEmptyString(execution.thinking)) errors.push("invalid-execution-thinking");
61
+ if (!Number.isSafeInteger(execution.repeats) || execution.repeats <= 0) errors.push("invalid-execution-repeats");
62
+ if (execution.infrastructureRetries !== 0) errors.push("infrastructure-retries-must-be-zero");
63
+ if (execution.stopAfterFailedPair !== true) errors.push("stop-after-failed-pair-must-be-enabled");
64
+ }
65
+
66
+ if (requireHostReadiness) {
67
+ errors.push(...benchmarkHostReadinessPolicyValidationErrors(control.hostReadiness)
68
+ .map((error) => `host-readiness:${error}`));
69
+ } else if (control.hostReadiness !== undefined) {
70
+ errors.push(...benchmarkHostReadinessPolicyValidationErrors(control.hostReadiness)
71
+ .map((error) => `host-readiness:${error}`));
72
+ }
73
+
74
+ if (!Array.isArray(control.stages) || control.stages.length < 2) errors.push("missing-stage-boundaries");
75
+ else {
76
+ const ids = new Set();
77
+ let previous = 0;
78
+ for (const [index, stage] of control.stages.entries()) {
79
+ if (!stage || typeof stage !== "object" || Array.isArray(stage)) {
80
+ errors.push(`invalid-stage:${index}`);
81
+ continue;
82
+ }
83
+ if (!nonEmptyString(stage.id) || ids.has(stage.id)) errors.push(`invalid-stage-id:${index}`);
84
+ else ids.add(stage.id);
85
+ if (!Number.isSafeInteger(stage.cumulativeSessions) || stage.cumulativeSessions < 0
86
+ || (index > 0 && stage.cumulativeSessions <= previous)) errors.push(`invalid-stage-cumulative-sessions:${index}`);
87
+ const expectedNewSessions = index === 0 ? 0 : stage.cumulativeSessions - previous;
88
+ if (stage.newSessions !== expectedNewSessions) errors.push(`invalid-stage-new-sessions:${index}`);
89
+ if (index === 0) {
90
+ if (stage.cumulativeSessions !== 0) errors.push("initial-stage-must-start-at-zero");
91
+ if (stage.claimEligible !== false) errors.push("initial-stage-cannot-be-claim-eligible");
92
+ } else if (index === control.stages.length - 1) {
93
+ if (stage.claimEligible !== true) errors.push("final-stage-must-be-claim-eligible");
94
+ } else if (stage.claimEligible !== false) errors.push(`intermediate-stage-cannot-be-claim-eligible:${index}`);
95
+ if (Number.isSafeInteger(stage.cumulativeSessions)) previous = stage.cumulativeSessions;
96
+ }
97
+ const finalSessions = control.stages.at(-1)?.cumulativeSessions;
98
+ if (Number.isSafeInteger(expectedSessions) && finalSessions !== expectedSessions) errors.push("final-stage-session-count-mismatch");
99
+ }
100
+ const guards = control.productionGuards;
101
+ if (suiteId === "production-v1" && (!guards || typeof guards !== "object" || Array.isArray(guards))) errors.push("missing-production-guards");
102
+ else if (guards !== undefined) {
103
+ const subagents = guards.subagents;
104
+ if (subagents?.required !== true
105
+ || subagents.maximumSessionsPerAttempt !== 1
106
+ || subagents.maximumTrafficShare !== 0.05
107
+ || subagents.requireExactAllAttemptEvidence !== true
108
+ || subagents.requireExplainedSessionCount !== true) errors.push("invalid-production-subagent-guard");
109
+ const partial = guards.partialFreshSpend;
110
+ if (partial?.requiredFromCumulativeSessions !== 12
111
+ || partial.maximumPooledFreshRatio !== 1.1
112
+ || partial.maximumObservedFamilyFreshRatio !== 1.25
113
+ || partial.includeExactFailedAttempts !== true) errors.push("invalid-production-partial-fresh-spend-guard");
114
+ const providerFree = guards.providerFreeEvidence;
115
+ if (providerFree?.requiredBeforeFirstPaidSession !== true
116
+ || JSON.stringify(providerFree.requiredLaneIds) !== JSON.stringify(["runtime-conformance-v1", "long-horizon-v1", "webui-parity-v1"])
117
+ || providerFree.requireCleanCommitAndTreeBinding !== true
118
+ || providerFree.requireProductionConfigurationBinding !== true
119
+ || providerFree.requireRunnerAndLaneConfigurationDigests !== true) errors.push("invalid-production-provider-free-evidence-guard");
120
+ }
121
+ return errors;
122
+ }
123
+
124
+ function sameLedgerBinding(left, right) {
125
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
126
+ }
127
+
128
+ export function createProductionStageControl({ authorizedThroughRuns, generatedAt = new Date().toISOString() }) {
129
+ return {
130
+ schemaVersion: 1,
131
+ policy: PRODUCTION_STAGE_CONTROL_POLICY,
132
+ state: "window-authorized",
133
+ approvedBoundaryRuns: 0,
134
+ authorizedThroughRuns,
135
+ pendingBoundary: null,
136
+ updatedAt: generatedAt
137
+ };
138
+ }
139
+
140
+ export function pendProductionStageControl(control, { reason, completedRuns, ledger, generatedAt = new Date().toISOString() }) {
141
+ return {
142
+ schemaVersion: 1,
143
+ policy: PRODUCTION_STAGE_CONTROL_POLICY,
144
+ state: "review-pending",
145
+ approvedBoundaryRuns: Number.isSafeInteger(control?.approvedBoundaryRuns) ? control.approvedBoundaryRuns : 0,
146
+ authorizedThroughRuns: control?.authorizedThroughRuns,
147
+ pendingBoundary: {
148
+ reason,
149
+ completedRuns,
150
+ ledger
151
+ },
152
+ updatedAt: generatedAt
153
+ };
154
+ }
155
+
156
+ export function approveProductionStageControl(control, { completedRuns, authorizedThroughRuns, generatedAt = new Date().toISOString() }) {
157
+ return {
158
+ schemaVersion: 1,
159
+ policy: PRODUCTION_STAGE_CONTROL_POLICY,
160
+ state: "window-authorized",
161
+ approvedBoundaryRuns: completedRuns,
162
+ authorizedThroughRuns,
163
+ pendingBoundary: null,
164
+ updatedAt: generatedAt
165
+ };
166
+ }
167
+
168
+ export function productionStageResumeDisposition(control, { completedRuns, ledger, stageBoundaries }) {
169
+ const errors = [];
170
+ if (control?.schemaVersion !== 1 || control?.policy !== PRODUCTION_STAGE_CONTROL_POLICY) errors.push("missing-or-unsupported-stage-control");
171
+ if (!Number.isSafeInteger(completedRuns) || completedRuns < 0) errors.push("invalid-completed-run-count");
172
+ if (!validStageBoundaries(stageBoundaries)) errors.push("invalid-frozen-stage-boundaries");
173
+ const approvedBoundaryRuns = control?.approvedBoundaryRuns;
174
+ const authorizedThroughRuns = control?.authorizedThroughRuns;
175
+ const expectedAuthorizedThroughRuns = validStageBoundaries(stageBoundaries) && Number.isSafeInteger(approvedBoundaryRuns)
176
+ ? stageBoundaries.find((boundary) => boundary > approvedBoundaryRuns)
177
+ : undefined;
178
+ if (!Number.isSafeInteger(approvedBoundaryRuns) || approvedBoundaryRuns < 0
179
+ || approvedBoundaryRuns > completedRuns
180
+ || (validStageBoundaries(stageBoundaries) && approvedBoundaryRuns >= stageBoundaries.at(-1))) errors.push("invalid-approved-boundary");
181
+ if (!Number.isSafeInteger(authorizedThroughRuns) || authorizedThroughRuns <= 0
182
+ || authorizedThroughRuns < completedRuns
183
+ || authorizedThroughRuns !== expectedAuthorizedThroughRuns) errors.push("invalid-authorized-window");
184
+ if (control?.state === "window-authorized") {
185
+ if (control.pendingBoundary !== null) errors.push("authorized-window-has-pending-boundary");
186
+ const atAuthorizedBoundary = completedRuns === authorizedThroughRuns;
187
+ return {
188
+ passed: errors.length === 0,
189
+ requiresStageGate: errors.length === 0 && atAuthorizedBoundary,
190
+ recoveryAllowed: errors.length === 0 && !atAuthorizedBoundary,
191
+ errors
192
+ };
193
+ }
194
+ if (control?.state === "review-pending") {
195
+ const pending = control.pendingBoundary;
196
+ if (!pending || typeof pending.reason !== "string") errors.push("missing-pending-boundary");
197
+ if (pending?.completedRuns !== completedRuns) errors.push("pending-boundary-run-count-mismatch");
198
+ if (Number.isSafeInteger(completedRuns) && Number.isSafeInteger(approvedBoundaryRuns)
199
+ && completedRuns <= approvedBoundaryRuns) errors.push("pending-boundary-has-no-progress");
200
+ if (!sameLedgerBinding(pending?.ledger, ledger)) errors.push("pending-boundary-ledger-mismatch");
201
+ return { passed: errors.length === 0, requiresStageGate: true, recoveryAllowed: false, errors };
202
+ }
203
+ errors.push("invalid-stage-control-state");
204
+ return { passed: false, requiresStageGate: false, recoveryAllowed: false, errors };
205
+ }
206
+
207
+ export function productionStageResumeWindow(control, { completedRuns, stageBoundaries }) {
208
+ if (!validStageBoundaries(stageBoundaries)
209
+ || !Number.isSafeInteger(completedRuns)
210
+ || completedRuns < 0
211
+ || !Number.isSafeInteger(control?.authorizedThroughRuns)) return null;
212
+ const authorizedThroughRuns = completedRuns < control.authorizedThroughRuns
213
+ ? control.authorizedThroughRuns
214
+ : stageBoundaries.find((boundary) => boundary > completedRuns);
215
+ if (!Number.isSafeInteger(authorizedThroughRuns)) {
216
+ return completedRuns === stageBoundaries.at(-1)
217
+ ? { authorizedThroughRuns: completedRuns, remainingSessions: 0 }
218
+ : null;
219
+ }
220
+ const remainingSessions = authorizedThroughRuns - completedRuns;
221
+ if (!Number.isSafeInteger(remainingSessions) || remainingSessions <= 0) return null;
222
+ return { authorizedThroughRuns, remainingSessions };
223
+ }
224
+
225
+ /**
226
+ * Replays the terminal paired-outcome rule over an accepted ledger prefix.
227
+ *
228
+ * The live runner normally evaluates this rule immediately after appending the
229
+ * second record of a pair. A process can still die after the durable append but
230
+ * before that in-memory check. Resume must therefore derive the same terminal
231
+ * result from accepted records before it performs auth, tool preflight, or any
232
+ * additional provider work.
233
+ */
234
+ export function durablePairedOutcomeFloorStop({ enabled, suite, runs, fullOrder }) {
235
+ const acceptedRuns = Array.isArray(runs) ? runs : [];
236
+ const expectedRuns = Array.isArray(fullOrder) ? fullOrder : [];
237
+ for (let index = 0; index < expectedRuns.length; index += 1) {
238
+ const terminal = pairedOutcomeFloorStop({
239
+ enabled,
240
+ suite,
241
+ runs: acceptedRuns,
242
+ current: expectedRuns[index],
243
+ next: expectedRuns[index + 1]
244
+ });
245
+ if (terminal) return terminal;
246
+ }
247
+ return null;
248
+ }
249
+
250
+ function runKey(run) {
251
+ return `${run?.scenarioId ?? run?.scenario?.id}\0${run?.surface}\0${run?.repeat}`;
252
+ }
253
+
254
+ function pairKey(value) {
255
+ return `${value?.scenarioId ?? value?.scenario?.id}\0${value?.repeat}`;
256
+ }
257
+
258
+ function publicPairId(value) {
259
+ return `${value?.scenarioId ?? value?.scenario?.id}:r${value?.repeat}`;
260
+ }
261
+
262
+ function expectedPairMap(fullOrder) {
263
+ const pairs = new Map();
264
+ for (const item of fullOrder) {
265
+ const key = pairKey(item);
266
+ const pair = pairs.get(key) ?? {
267
+ scenarioId: item?.scenarioId ?? item?.scenario?.id,
268
+ repeat: item?.repeat,
269
+ expectedSurfaces: new Set(),
270
+ expectedRunKeys: new Set()
271
+ };
272
+ pair.expectedSurfaces.add(item?.surface);
273
+ pair.expectedRunKeys.add(runKey(item));
274
+ pairs.set(key, pair);
275
+ }
276
+ return pairs;
277
+ }
278
+
279
+ function exactUsageIssues(run) {
280
+ const usage = run?.usage;
281
+ const issues = [];
282
+ if (usage?.usageCompleteness !== "exact") issues.push("usage-completeness-not-exact");
283
+ if (!Number.isSafeInteger(usage?.sessions) || usage.sessions <= 0) issues.push("invalid-session-count");
284
+ for (const field of TOKEN_FIELDS) {
285
+ if (!Number.isSafeInteger(usage?.[field]) || usage[field] < 0) issues.push(`invalid-${field}`);
286
+ }
287
+ if (Number.isSafeInteger(usage?.fresh) && Number.isSafeInteger(usage?.input) && Number.isSafeInteger(usage?.output)
288
+ && usage.fresh !== usage.input + usage.output) issues.push("fresh-token-equation-mismatch");
289
+ if ([usage?.total, usage?.input, usage?.cacheRead, usage?.cacheWrite, usage?.output].every(Number.isSafeInteger)
290
+ && usage.total !== usage.input + usage.cacheRead + usage.cacheWrite + usage.output) issues.push("total-token-equation-mismatch");
291
+ if (Number.isSafeInteger(usage?.reasoning) && Number.isSafeInteger(usage?.output) && usage.reasoning > usage.output) {
292
+ issues.push("reasoning-exceeds-output");
293
+ }
294
+ return issues;
295
+ }
296
+
297
+ function providerWireGroups(piRuns) {
298
+ const groups = new Map();
299
+ for (const run of piRuns) {
300
+ const key = `${run.scenarioId}\0${run.profile ?? "unspecified"}\0${run.lifecycle ?? "unspecified"}`;
301
+ const group = groups.get(key) ?? {
302
+ scenarioId: run.scenarioId,
303
+ profile: run.profile ?? "unspecified",
304
+ lifecycle: run.lifecycle ?? "unspecified",
305
+ runs: 0,
306
+ baseInstructionHashes: new Set(),
307
+ orderedToolSurfaceHashes: new Set()
308
+ };
309
+ group.runs += 1;
310
+ for (const hash of run.providerWireEvidence?.baseInstructionHashes ?? []) group.baseInstructionHashes.add(hash);
311
+ for (const hash of run.providerWireEvidence?.orderedToolSurfaceHashes ?? []) group.orderedToolSurfaceHashes.add(hash);
312
+ groups.set(key, group);
313
+ }
314
+ return [...groups.values()].map((group) => ({
315
+ scenarioId: group.scenarioId,
316
+ profile: group.profile,
317
+ lifecycle: group.lifecycle,
318
+ runs: group.runs,
319
+ baseInstructionHashCount: group.baseInstructionHashes.size,
320
+ orderedToolSurfaceHashCount: group.orderedToolSurfaceHashes.size,
321
+ passed: group.baseInstructionHashes.size === 1 && group.orderedToolSurfaceHashes.size === 1
322
+ })).sort((left, right) => left.scenarioId.localeCompare(right.scenarioId));
323
+ }
324
+
325
+ function diagnosticCheck(id, passed, details = {}, decisionRole = "blocking") {
326
+ return { id, passed: passed === true, decisionRole, ...details };
327
+ }
328
+
329
+ function pairRatioEvidence(pairRecords, valueFor) {
330
+ const records = pairRecords.map(({ pair, candidate, baseline }) => {
331
+ const values = valueFor({ candidate, baseline });
332
+ const baselineValue = values?.baseline;
333
+ const candidateValue = values?.candidate;
334
+ const comparable = Number.isFinite(baselineValue) && baselineValue > 0
335
+ && Number.isFinite(candidateValue) && candidateValue > 0
336
+ && (!Array.isArray(values?.issues) || values.issues.length === 0);
337
+ return {
338
+ pairId: pair.id,
339
+ scenarioId: pair.scenarioId,
340
+ repeat: pair.repeat,
341
+ comparable,
342
+ issues: comparable ? [] : values?.issues?.length ? values.issues : ["non-positive-or-unavailable-value"],
343
+ baseline: Number.isFinite(baselineValue) ? baselineValue : null,
344
+ candidate: Number.isFinite(candidateValue) ? candidateValue : null,
345
+ ratio: comparable ? candidateValue / baselineValue : null
346
+ };
347
+ });
348
+ const familyMap = new Map();
349
+ for (const record of records) {
350
+ const values = familyMap.get(record.scenarioId) ?? [];
351
+ values.push(record);
352
+ familyMap.set(record.scenarioId, values);
353
+ }
354
+ const families = [...familyMap.entries()].map(([scenarioId, values]) => {
355
+ const comparable = values.length > 0 && values.every((value) => value.comparable);
356
+ return {
357
+ scenarioId,
358
+ observedPairs: values.length,
359
+ comparable,
360
+ ratio: comparable ? geometricMean(values.map((value) => value.ratio)) : null,
361
+ issues: comparable ? [] : ["one-or-more-observed-pairs-incomparable"]
362
+ };
363
+ }).sort((left, right) => left.scenarioId.localeCompare(right.scenarioId));
364
+ return {
365
+ records,
366
+ families,
367
+ incomparablePairs: records.filter((record) => !record.comparable),
368
+ pairRegressions: records.filter((record) => Number.isFinite(record.ratio) && !atMostWithinFloatingPrecision(record.ratio, 1)),
369
+ familyRegressions: families.filter((family) => Number.isFinite(family.ratio) && !atMostWithinFloatingPrecision(family.ratio, 1))
370
+ };
371
+ }
372
+
373
+ function allAttemptFreshTokens(run) {
374
+ const failures = Array.isArray(run?.infrastructureFailures) ? run.infrastructureFailures : [];
375
+ const ledgerExact = Number.isSafeInteger(run?.infrastructureRetries)
376
+ && Number.isSafeInteger(run?.infrastructureAttempts)
377
+ && failures.length === run.infrastructureRetries
378
+ && run.infrastructureAttempts === run.infrastructureRetries + 1;
379
+ const attempts = [
380
+ { usage: run?.usage, status: run?.usageStatus ?? "measured" },
381
+ ...failures.map((failure) => ({
382
+ usage: failure?.usage,
383
+ status: failure?.usageStatus ?? "unknown-after-provider-start"
384
+ }))
385
+ ];
386
+ const exact = ledgerExact && attempts.every((attempt) => exactBenchmarkAttemptUsage(attempt.usage, attempt.status));
387
+ return {
388
+ exact,
389
+ attempts: attempts.length,
390
+ fresh: exact ? attempts.reduce((sum, attempt) => sum + Number(attempt.usage?.fresh ?? 0), 0) : null
391
+ };
392
+ }
393
+
394
+ function partialCatastrophicSpendEvidence(pairRecords, {
395
+ maximumPooledFreshRatio,
396
+ maximumObservedFamilyFreshRatio
397
+ }) {
398
+ const records = pairRecords.map(({ pair, candidate, baseline }) => {
399
+ const candidateUsage = allAttemptFreshTokens(candidate);
400
+ const baselineUsage = allAttemptFreshTokens(baseline);
401
+ const exact = candidateUsage.exact && baselineUsage.exact
402
+ && baselineUsage.fresh > 0 && candidateUsage.fresh >= 0;
403
+ return {
404
+ pairId: pair.id,
405
+ scenarioId: pair.scenarioId,
406
+ repeat: pair.repeat,
407
+ exact,
408
+ baselineFresh: exact ? baselineUsage.fresh : null,
409
+ candidateFresh: exact ? candidateUsage.fresh : null,
410
+ baselineAttempts: baselineUsage.attempts,
411
+ candidateAttempts: candidateUsage.attempts
412
+ };
413
+ });
414
+ const exact = records.length > 0 && records.every((record) => record.exact);
415
+ const baselineFresh = exact ? records.reduce((sum, record) => sum + record.baselineFresh, 0) : null;
416
+ const candidateFresh = exact ? records.reduce((sum, record) => sum + record.candidateFresh, 0) : null;
417
+ const pooledRatio = exact && baselineFresh > 0 ? candidateFresh / baselineFresh : null;
418
+ const byFamily = new Map();
419
+ for (const record of records) {
420
+ const family = byFamily.get(record.scenarioId) ?? { scenarioId: record.scenarioId, records: [] };
421
+ family.records.push(record);
422
+ byFamily.set(record.scenarioId, family);
423
+ }
424
+ const families = [...byFamily.values()].map((family) => {
425
+ const familyExact = family.records.length > 0 && family.records.every((record) => record.exact);
426
+ const baseline = familyExact ? family.records.reduce((sum, record) => sum + record.baselineFresh, 0) : null;
427
+ const candidate = familyExact ? family.records.reduce((sum, record) => sum + record.candidateFresh, 0) : null;
428
+ return {
429
+ scenarioId: family.scenarioId,
430
+ observedPairs: family.records.length,
431
+ exact: familyExact,
432
+ ratio: familyExact && baseline > 0 ? candidate / baseline : null
433
+ };
434
+ }).sort((left, right) => left.scenarioId.localeCompare(right.scenarioId));
435
+ const familyFailures = families.filter((family) => !family.exact
436
+ || !Number.isFinite(family.ratio)
437
+ || !atMostWithinFloatingPrecision(family.ratio, maximumObservedFamilyFreshRatio));
438
+ const passed = exact
439
+ && Number.isFinite(pooledRatio)
440
+ && atMostWithinFloatingPrecision(pooledRatio, maximumPooledFreshRatio)
441
+ && familyFailures.length === 0;
442
+ return {
443
+ schemaVersion: 1,
444
+ exactUsageIncludingFailedAttempts: exact,
445
+ maximumPooledFreshRatio,
446
+ maximumObservedFamilyFreshRatio,
447
+ pooledRatio,
448
+ baselineFresh,
449
+ candidateFresh,
450
+ familyFailures,
451
+ families,
452
+ records,
453
+ passed
454
+ };
455
+ }
456
+
457
+ function candidateOutcomeFailures(pairRecords, floor) {
458
+ return pairRecords.map(({ pair, candidate }) => {
459
+ const failures = [];
460
+ if (candidate?.resolved !== true) failures.push("unresolved-outcome");
461
+ if (candidate?.scope?.passed !== true) failures.push("scope-safety-evidence-failed");
462
+ if (candidate?.outputSafety?.passed !== true) failures.push("output-safety-evidence-failed");
463
+ if (candidate?.scenarioKind === "safety-refusal") {
464
+ if (candidate?.grade?.passed !== true) failures.push("safety-refusal-grade-failed");
465
+ } else {
466
+ if (candidate?.grade?.passed !== true) failures.push("quality-grade-failed");
467
+ if (candidate?.graderIntegrity?.passed !== true) failures.push("grader-integrity-failed");
468
+ if (candidate?.outputEvidence?.passed === false) failures.push("output-evidence-failed");
469
+ if (!Number.isFinite(candidate?.grade?.score) || candidate.grade.score <= floor) failures.push("quality-outcome-floor");
470
+ if (!Number.isFinite(candidate?.workflow?.score) || candidate.workflow.score <= floor) failures.push("workflow-outcome-floor");
471
+ if (!workflowContinuityEvidenceComplete(candidate?.workflow)) {
472
+ failures.push("workflow-evidence-incomplete-or-failed");
473
+ }
474
+ }
475
+ return {
476
+ pairId: pair.id,
477
+ failures,
478
+ resolved: candidate?.resolved === true,
479
+ gradeScore: Number.isFinite(candidate?.grade?.score) ? candidate.grade.score : null,
480
+ workflowScore: Number.isFinite(candidate?.workflow?.score) ? candidate.workflow.score : null
481
+ };
482
+ }).filter((item) => item.failures.length > 0);
483
+ }
484
+
485
+ /**
486
+ * Builds a provider-free, claim-ineligible decision aid for a paused benchmark.
487
+ * Future, entirely unstarted pairs are intentionally not blockers. A partially
488
+ * observed pair is a blocker because stage decisions must be made at pair
489
+ * boundaries.
490
+ */
491
+ export function buildBenchmarkStageDiagnostic({
492
+ runId,
493
+ reason,
494
+ runs,
495
+ fullOrder,
496
+ candidateSurface,
497
+ baselineSurface,
498
+ requestedModel,
499
+ requestedThinking,
500
+ suite,
501
+ manifest,
502
+ hostReadinessPolicy = null,
503
+ hostReadinessStageBoundaries = null,
504
+ generatedAt = new Date().toISOString()
505
+ }) {
506
+ const acceptedRuns = Array.isArray(runs) ? runs : [];
507
+ const expectedRuns = Array.isArray(fullOrder) ? fullOrder : [];
508
+ const pairs = expectedPairMap(expectedRuns);
509
+ const expectedRunKeys = new Set(expectedRuns.map(runKey));
510
+ const observedByRunKey = new Map();
511
+ const duplicateRuns = [];
512
+ const unexpectedRuns = [];
513
+ for (const run of acceptedRuns) {
514
+ const key = runKey(run);
515
+ if (!expectedRunKeys.has(key)) unexpectedRuns.push(key.replaceAll("\0", ":"));
516
+ if (observedByRunKey.has(key)) duplicateRuns.push(key.replaceAll("\0", ":"));
517
+ else observedByRunKey.set(key, run);
518
+ }
519
+
520
+ const completePairs = [];
521
+ const incompleteObservedPairs = [];
522
+ const unstartedPairs = [];
523
+ for (const pair of pairs.values()) {
524
+ const observed = [...pair.expectedSurfaces].filter((surface) => observedByRunKey.has(`${pair.scenarioId}\0${surface}\0${pair.repeat}`));
525
+ const missing = [...pair.expectedSurfaces].filter((surface) => !observed.includes(surface));
526
+ const summary = {
527
+ id: publicPairId(pair),
528
+ scenarioId: pair.scenarioId,
529
+ repeat: pair.repeat,
530
+ expectedSurfaces: [...pair.expectedSurfaces],
531
+ observedSurfaces: observed,
532
+ missingSurfaces: missing
533
+ };
534
+ if (observed.length === 0) unstartedPairs.push(summary);
535
+ else if (missing.length === 0) completePairs.push(summary);
536
+ else incompleteObservedPairs.push(summary);
537
+ }
538
+
539
+ const pairRecords = completePairs.map((pair) => ({
540
+ pair,
541
+ candidate: observedByRunKey.get(`${pair.scenarioId}\0${candidateSurface}\0${pair.repeat}`),
542
+ baseline: observedByRunKey.get(`${pair.scenarioId}\0${baselineSurface}\0${pair.repeat}`)
543
+ }));
544
+ const malformedCompletePairs = pairRecords.filter(({ candidate, baseline }) => !candidate || !baseline).map(({ pair }) => pair.id);
545
+ const baselineOnlyRegressions = pairRecords
546
+ .filter(({ candidate, baseline }) => baseline?.resolved === true && candidate?.resolved !== true)
547
+ .map(({ pair, candidate, baseline }) => ({
548
+ pairId: pair.id,
549
+ baselineResolved: baseline.resolved,
550
+ candidateResolved: candidate?.resolved === true,
551
+ candidateFailure: candidate?.failure ?? null
552
+ }));
553
+ const noBaselineOnlyRegressionPassed = completePairs.length > 0
554
+ && malformedCompletePairs.length === 0
555
+ && baselineOnlyRegressions.length === 0;
556
+ const pairedGradeComparabilityFailures = pairRecords.filter(({ candidate, baseline }) => (
557
+ !Number.isFinite(candidate?.grade?.score) || !Number.isFinite(baseline?.grade?.score)
558
+ )).map(({ pair }) => pair.id);
559
+ const pairedGradeRegressions = pairRecords.filter(({ candidate, baseline }) => (
560
+ Number.isFinite(candidate?.grade?.score)
561
+ && Number.isFinite(baseline?.grade?.score)
562
+ && !atMostWithinFloatingPrecision(baseline.grade.score, candidate.grade.score)
563
+ )).map(({ pair, candidate, baseline }) => ({
564
+ pairId: pair.id,
565
+ baselineGradeScore: baseline.grade.score,
566
+ candidateGradeScore: candidate.grade.score
567
+ }));
568
+ const observedGradeNonInferiorPassed = pairRecords.length > 0
569
+ && pairedGradeComparabilityFailures.length === 0
570
+ && pairedGradeRegressions.length === 0;
571
+ const outcomeFloor = suite?.releaseGate?.minimumOutcomeScoreExclusive;
572
+ const outcomeFloorConfigured = Number.isFinite(outcomeFloor);
573
+ const outcomeFailures = outcomeFloorConfigured ? candidateOutcomeFailures(pairRecords, outcomeFloor) : [];
574
+ const outcomeFloorPassed = outcomeFloorConfigured
575
+ && manifest?.stopAfterFailedPair === true
576
+ && pairRecords.length > 0
577
+ && outcomeFailures.length === 0;
578
+ const qualityPassed = noBaselineOnlyRegressionPassed && observedGradeNonInferiorPassed && outcomeFloorPassed;
579
+
580
+ const acceptedUsageFailures = acceptedRuns.map((run) => ({ runId: runKey(run).replaceAll("\0", ":"), issues: exactUsageIssues(run) }))
581
+ .filter((item) => item.issues.length > 0);
582
+ const acceptedUsagePassed = acceptedRuns.length > 0 && acceptedUsageFailures.length === 0;
583
+
584
+ const piRuns = acceptedRuns.filter((run) => run.surface === candidateSurface && candidateSurface === "piagent");
585
+ const piParityFailures = piRuns.map((run) => {
586
+ const issues = [];
587
+ if (run.usage?.model !== requestedModel) issues.push("accepted-model-mismatch");
588
+ if (run.usage?.thinkingLevel !== requestedThinking) issues.push("accepted-thinking-mismatch");
589
+ if (!benchmarkProviderWireEvidenceMatchesRequest(run.providerWireEvidence, requestedModel, requestedThinking)) {
590
+ issues.push("provider-wire-not-verified-or-request-bound");
591
+ }
592
+ return { runId: runKey(run).replaceAll("\0", ":"), issues };
593
+ }).filter((item) => item.issues.length > 0);
594
+ const pairedModelThinkingFailures = pairRecords.map(({ pair, candidate, baseline }) => ({
595
+ pairId: pair.id,
596
+ issues: [
597
+ candidate?.usage?.model !== baseline?.usage?.model ? "paired-model-mismatch" : null,
598
+ candidate?.usage?.thinkingLevel !== baseline?.usage?.thinkingLevel ? "paired-thinking-mismatch" : null
599
+ ].filter(Boolean)
600
+ })).filter((item) => item.issues.length > 0);
601
+ const wireGroups = providerWireGroups(piRuns);
602
+ const wireDriftGroups = wireGroups.filter((group) => !group.passed);
603
+ const providerParityPassed = typeof requestedModel === "string" && requestedModel.length > 0
604
+ && typeof requestedThinking === "string" && requestedThinking.length > 0
605
+ && piRuns.length > 0
606
+ && piParityFailures.length === 0
607
+ && pairedModelThinkingFailures.length === 0
608
+ && wireGroups.length > 0
609
+ && wireDriftGroups.length === 0;
610
+ const causalContextRequired = suite?.releaseGate?.requireCausalContextReceipt === true;
611
+ const causalContextSummary = summarizeBenchmarkCausalContextEvidence(piRuns, { required: causalContextRequired });
612
+ const causalContextAvailableRuns = causalContextSummary.currentAvailableRuns;
613
+ const causalContextPassed = !causalContextRequired
614
+ || causalContextSummary.currentCoverageStatus === "complete";
615
+ const providerFreeGuard = manifest?.productionGuards?.providerFreeEvidence;
616
+ const providerFreeEvidenceRequired = providerFreeGuard?.requiredBeforeFirstPaidSession === true;
617
+ const providerFreeEvidenceErrors = providerFreeEvidenceRequired
618
+ ? productionProviderFreeEvidenceContextValidationErrors(manifest?.providerFreeEvidence, {
619
+ source: manifest?.sourceIdentity,
620
+ candidateProvenance: manifest?.candidateProvenance,
621
+ configurationDigest: manifest?.configurationDigest
622
+ })
623
+ : [];
624
+ const providerFreeObservedLaneIds = Array.isArray(manifest?.providerFreeEvidence?.lanes)
625
+ ? manifest.providerFreeEvidence.lanes.map((lane) => lane?.id)
626
+ : [];
627
+ const providerFreeEvidencePassed = !providerFreeEvidenceRequired
628
+ || (providerFreeEvidenceErrors.length === 0
629
+ && Array.isArray(providerFreeGuard.requiredLaneIds)
630
+ && JSON.stringify(providerFreeObservedLaneIds) === JSON.stringify(providerFreeGuard.requiredLaneIds));
631
+ const adaptiveContextStatuses = piRuns.map((run) => run?.causalContextReceipt?.aggregates?.runtimeCausal?.adaptiveContext?.coverageStatus ?? "not-observed");
632
+ const partialAdaptiveContextRuns = adaptiveContextStatuses.filter((status) => status === "partial").length;
633
+ const notObservedAdaptiveContextRuns = adaptiveContextStatuses.filter((status) => status === "not-observed").length;
634
+ const adaptiveContextCoveragePassed = !providerFreeEvidenceRequired || (partialAdaptiveContextRuns === 0
635
+ && (notObservedAdaptiveContextRuns === 0 || providerFreeEvidencePassed));
636
+
637
+ const freshEfficiency = pairRatioEvidence(pairRecords, ({ candidate, baseline }) => ({
638
+ baseline: baseline?.usage?.fresh,
639
+ candidate: candidate?.usage?.fresh
640
+ }));
641
+ const freshEfficiencyPassed = freshEfficiency.records.length > 0
642
+ && freshEfficiency.incomparablePairs.length === 0
643
+ && freshEfficiency.pairRegressions.length === 0
644
+ && freshEfficiency.familyRegressions.length === 0;
645
+ const guardPolicy = manifest?.productionGuards;
646
+ const subagentGuard = guardPolicy?.subagents;
647
+ const subagentBudget = summarizeBenchmarkSubagentBudget(acceptedRuns, {
648
+ candidateSurface,
649
+ policy: {
650
+ schemaVersion: 1,
651
+ id: "production-subagent-budget-v1",
652
+ maximumSubagentSessionsPerAttempt: subagentGuard?.maximumSessionsPerAttempt,
653
+ maximumSubagentTrafficShare: subagentGuard?.maximumTrafficShare
654
+ }
655
+ });
656
+ const subagentBudgetRequired = subagentGuard?.required === true;
657
+ const partialGuard = guardPolicy?.partialFreshSpend;
658
+ const partialSpendRequired = Number.isSafeInteger(partialGuard?.requiredFromCumulativeSessions)
659
+ && acceptedRuns.length >= partialGuard.requiredFromCumulativeSessions
660
+ && acceptedRuns.length < expectedRuns.length;
661
+ const partialSpend = partialCatastrophicSpendEvidence(pairRecords, {
662
+ maximumPooledFreshRatio: partialGuard?.maximumPooledFreshRatio,
663
+ maximumObservedFamilyFreshRatio: partialGuard?.maximumObservedFamilyFreshRatio
664
+ });
665
+ const partialSpendPassed = !partialSpendRequired || partialSpend.passed;
666
+
667
+ const pricingSnapshot = suite?.pricingSnapshot;
668
+ const pricingSnapshotErrors = benchmarkPricingSnapshotValidationErrors(pricingSnapshot);
669
+ const normalizedCostEvidence = pairRatioEvidence(pairRecords, ({ candidate, baseline }) => {
670
+ const normalizedBaseline = normalizeBenchmarkUsageCost(baseline?.usage, pricingSnapshot);
671
+ const normalizedCandidate = normalizeBenchmarkUsageCost(candidate?.usage, pricingSnapshot);
672
+ return {
673
+ baseline: normalizedBaseline.status === "measured" ? normalizedBaseline.amount : null,
674
+ candidate: normalizedCandidate.status === "measured" ? normalizedCandidate.amount : null,
675
+ issues: [
676
+ normalizedBaseline.status === "measured" ? null : `baseline:${normalizedBaseline.reason}`,
677
+ normalizedCandidate.status === "measured" ? null : `candidate:${normalizedCandidate.reason}`
678
+ ].filter(Boolean)
679
+ };
680
+ });
681
+ const normalizedCostPassed = pricingSnapshotErrors.length === 0
682
+ && normalizedCostEvidence.records.length > 0
683
+ && normalizedCostEvidence.incomparablePairs.length === 0
684
+ && normalizedCostEvidence.pairRegressions.length === 0
685
+ && normalizedCostEvidence.familyRegressions.length === 0;
686
+
687
+ const durationEfficiency = pairRatioEvidence(pairRecords, ({ candidate, baseline }) => ({
688
+ baseline: baseline?.durationSeconds,
689
+ candidate: candidate?.durationSeconds
690
+ }));
691
+ const durationEfficiencyPassed = durationEfficiency.records.length > 0
692
+ && durationEfficiency.incomparablePairs.length === 0
693
+ && durationEfficiency.pairRegressions.length === 0
694
+ && durationEfficiency.familyRegressions.length === 0;
695
+
696
+ const retryEvidenceFailures = acceptedRuns.map((run) => {
697
+ const issues = [];
698
+ if (!Number.isInteger(run.infrastructureRetries) || run.infrastructureRetries < 0) issues.push("invalid-infrastructure-retry-count");
699
+ if (!Array.isArray(run.infrastructureFailures)) issues.push("missing-infrastructure-failure-ledger");
700
+ else if (Number.isInteger(run.infrastructureRetries) && run.infrastructureFailures.length !== run.infrastructureRetries) {
701
+ issues.push("retry-ledger-count-mismatch");
702
+ }
703
+ return { runId: runKey(run).replaceAll("\0", ":"), issues };
704
+ }).filter((item) => item.issues.length > 0);
705
+ const infrastructureRetries = acceptedRuns.reduce((sum, run) => sum + (Number.isInteger(run.infrastructureRetries) ? run.infrastructureRetries : 0), 0);
706
+ const failedAttempts = acceptedRuns.reduce((sum, run) => sum + (Array.isArray(run.infrastructureFailures) ? run.infrastructureFailures.length : 0), 0);
707
+ const failedAttemptUnknownUsage = acceptedRuns.reduce((sum, run) => sum + (run.infrastructureFailures ?? [])
708
+ .filter((attempt) => attempt?.usageStatus === "unknown-after-provider-start").length, 0);
709
+ const manifestUnknownUsage = Number.isInteger(manifest?.unknownCostAttempts) && manifest.unknownCostAttempts >= 0
710
+ ? manifest.unknownCostAttempts
711
+ : manifest?.unknownCostAttempts === undefined ? 0 : 1;
712
+ const recoveredProviderAttempts = Array.isArray(manifest?.recoveredProviderAttempts)
713
+ ? manifest.recoveredProviderAttempts.length
714
+ : manifest?.recoveredProviderAttempts === undefined ? 0 : 1;
715
+ const tokenClaimsUnavailableReason = typeof manifest?.tokenClaimsUnavailableReason === "string"
716
+ ? manifest.tokenClaimsUnavailableReason
717
+ : manifest?.tokenClaimsUnavailableReason === undefined ? null : "malformed-token-claims-unavailable-reason";
718
+ const retryGatePassed = retryEvidenceFailures.length === 0
719
+ && infrastructureRetries === 0
720
+ && failedAttempts === 0
721
+ && recoveredProviderAttempts === 0;
722
+ const unknownUsageAttempts = failedAttemptUnknownUsage + manifestUnknownUsage;
723
+ const unknownUsagePassed = unknownUsageAttempts === 0 && tokenClaimsUnavailableReason === null;
724
+
725
+ const pairBoundary = incompleteObservedPairs.length === 0
726
+ && duplicateRuns.length === 0
727
+ && unexpectedRuns.length === 0;
728
+ const recognizedPause = typeof reason === "string"
729
+ && (reason.startsWith("max-sessions:") || reason.startsWith("max-runtime-minutes:"));
730
+ const pairContractPassed = pairs.size > 0
731
+ && [...pairs.values()].every((pair) => pair.expectedSurfaces.size === 2
732
+ && pair.expectedSurfaces.has(candidateSurface)
733
+ && pair.expectedSurfaces.has(baselineSurface));
734
+ const executionContractPassed = manifest?.stopAfterFailedPair === true
735
+ && manifest?.infrastructureRetries === 0;
736
+ const cleanReleaseSourceRequired = suite?.schemaVersion === 2
737
+ && suite?.releaseGate?.requireEfficiencyClaim === true
738
+ && suite?.releaseGate?.requireFullSuiteForClaim === true;
739
+ const cleanReleaseSourcePassed = !cleanReleaseSourceRequired || manifest?.sourceIdentity?.dirty === false;
740
+ const hostReadinessRequired = suite?.releaseGate?.requireHostReadinessForClaim === true;
741
+ const summarizedHostReadinessHistory = hostReadinessRequired
742
+ ? summarizeBenchmarkHostReadinessHistory({
743
+ policy: hostReadinessPolicy,
744
+ receipts: manifest?.hostReadinessReceipts,
745
+ completedRuns: acceptedRuns.length,
746
+ authorizedThroughRuns: manifest?.stageControl?.authorizedThroughRuns,
747
+ runId: manifest?.runId ?? runId,
748
+ configurationDigest: manifest?.configurationDigest,
749
+ stageBoundaries: hostReadinessStageBoundaries
750
+ })
751
+ : null;
752
+ const hostReadinessPolicyBindingValid = !hostReadinessRequired
753
+ || (benchmarkHostReadinessPolicyValidationErrors(hostReadinessPolicy).length === 0
754
+ && manifest?.hostReadinessPolicyDigest === benchmarkHostReadinessPolicyDigest(hostReadinessPolicy));
755
+ const hostReadinessHistory = summarizedHostReadinessHistory && !hostReadinessPolicyBindingValid
756
+ ? {
757
+ ...summarizedHostReadinessHistory,
758
+ valid: false,
759
+ ready: false,
760
+ errors: [...summarizedHostReadinessHistory.errors, "host-readiness-manifest-policy-digest-mismatch"]
761
+ }
762
+ : summarizedHostReadinessHistory;
763
+ const hostReadinessPassed = !hostReadinessRequired
764
+ || (hostReadinessHistory.valid === true && hostReadinessHistory.ready === true);
765
+ const checks = [
766
+ diagnosticCheck("recognized-spend-control-pause", recognizedPause, { reason }),
767
+ diagnosticCheck("paired-contract", pairContractPassed, { candidateSurface, baselineSurface }),
768
+ diagnosticCheck("spend-control-execution-contract", executionContractPassed, {
769
+ stopAfterFailedPair: manifest?.stopAfterFailedPair === true,
770
+ infrastructureRetries: Number.isInteger(manifest?.infrastructureRetries) ? manifest.infrastructureRetries : null
771
+ }),
772
+ diagnosticCheck("clean-release-source", cleanReleaseSourcePassed, {
773
+ required: cleanReleaseSourceRequired,
774
+ dirty: typeof manifest?.sourceIdentity?.dirty === "boolean" ? manifest.sourceIdentity.dirty : null
775
+ }),
776
+ diagnosticCheck("host-readiness-receipt-history", hostReadinessPassed, {
777
+ required: hostReadinessRequired,
778
+ validReceipts: hostReadinessHistory?.validReceiptCount ?? 0,
779
+ receipts: hostReadinessHistory?.receiptCount ?? 0,
780
+ coverage: hostReadinessHistory?.windowCoverage ?? null
781
+ }, hostReadinessRequired ? "blocking" : "observational"),
782
+ diagnosticCheck("pause-on-pair-boundary", pairBoundary, { incompleteObservedPairs: incompleteObservedPairs.length }),
783
+ diagnosticCheck("observed-complete-pair", completePairs.length > 0, { observedCompletePairs: completePairs.length }),
784
+ diagnosticCheck("no-baseline-pass-piagent-fail", noBaselineOnlyRegressionPassed, { regressions: baselineOnlyRegressions.length }),
785
+ diagnosticCheck("observed-paired-grade-noninferior", observedGradeNonInferiorPassed, {
786
+ incomparablePairs: pairedGradeComparabilityFailures.length,
787
+ regressions: pairedGradeRegressions.length
788
+ }),
789
+ diagnosticCheck("candidate-outcome-floor", outcomeFloorPassed, {
790
+ minimumOutcomeScoreExclusive: outcomeFloorConfigured ? outcomeFloor : null,
791
+ failures: outcomeFailures.length
792
+ }),
793
+ diagnosticCheck("accepted-usage-exact", acceptedUsagePassed, { failures: acceptedUsageFailures.length }),
794
+ diagnosticCheck("provider-wire-model-thinking-parity", providerParityPassed, { failures: piParityFailures.length + pairedModelThinkingFailures.length + wireDriftGroups.length }),
795
+ diagnosticCheck("piagent-causal-context-receipts", causalContextPassed, {
796
+ required: causalContextRequired,
797
+ availableRuns: causalContextAvailableRuns,
798
+ piagentRuns: piRuns.length,
799
+ unavailableRuns: piRuns.length - causalContextAvailableRuns
800
+ }),
801
+ diagnosticCheck("source-bound-provider-free-evidence", providerFreeEvidencePassed, {
802
+ required: providerFreeEvidenceRequired,
803
+ expectedLaneIds: providerFreeGuard?.requiredLaneIds ?? [],
804
+ observedLaneIds: providerFreeObservedLaneIds,
805
+ errors: providerFreeEvidenceErrors
806
+ }),
807
+ diagnosticCheck("adaptive-context-runtime-coverage", adaptiveContextCoveragePassed, {
808
+ partialRuns: partialAdaptiveContextRuns,
809
+ notObservedRuns: notObservedAdaptiveContextRuns,
810
+ notObservedCoveredBySameSourceProviderFreeLane: providerFreeEvidencePassed
811
+ }),
812
+ diagnosticCheck("no-infrastructure-retry", retryGatePassed, { retries: infrastructureRetries }),
813
+ diagnosticCheck("no-unknown-attempt-usage", unknownUsagePassed, { unknownUsageAttempts }),
814
+ diagnosticCheck("production-subagent-budget", !subagentBudgetRequired || subagentBudget.passed, {
815
+ required: subagentBudgetRequired,
816
+ attempts: subagentBudget.attempts,
817
+ exactAttempts: subagentBudget.exactAttempts,
818
+ maximumObservedSessionsPerAttempt: subagentBudget.maximumObservedSessionsPerAttempt,
819
+ trafficShare: subagentBudget.trafficShare,
820
+ failures: subagentBudget.failures
821
+ }),
822
+ diagnosticCheck("partial-stage-catastrophic-fresh-spend", partialSpendPassed, {
823
+ required: partialSpendRequired,
824
+ pooledRatio: partialSpend.pooledRatio,
825
+ maximumPooledFreshRatio: partialSpend.maximumPooledFreshRatio,
826
+ familyFailures: partialSpend.familyFailures,
827
+ maximumObservedFamilyFreshRatio: partialSpend.maximumObservedFamilyFreshRatio,
828
+ exactUsageIncludingFailedAttempts: partialSpend.exactUsageIncludingFailedAttempts
829
+ }),
830
+ diagnosticCheck("no-observed-fresh-token-regression", freshEfficiencyPassed, {
831
+ incomparablePairs: freshEfficiency.incomparablePairs.length,
832
+ pairRegressions: freshEfficiency.pairRegressions.length,
833
+ familyRegressions: freshEfficiency.familyRegressions.length
834
+ }, "final-only"),
835
+ diagnosticCheck("normalized-cost-pricing-applicable-and-no-observed-regression", normalizedCostPassed, {
836
+ pricingSnapshotErrors: pricingSnapshotErrors.length,
837
+ incomparablePairs: normalizedCostEvidence.incomparablePairs.length,
838
+ pairRegressions: normalizedCostEvidence.pairRegressions.length,
839
+ familyRegressions: normalizedCostEvidence.familyRegressions.length
840
+ }, "observational"),
841
+ diagnosticCheck("no-observed-duration-regression", durationEfficiencyPassed, {
842
+ incomparablePairs: durationEfficiency.incomparablePairs.length,
843
+ pairRegressions: durationEfficiency.pairRegressions.length,
844
+ familyRegressions: durationEfficiency.familyRegressions.length
845
+ }, "observational")
846
+ ];
847
+ const blockingReasons = checks
848
+ .filter((check) => check.decisionRole === "blocking" && !check.passed)
849
+ .map((check) => check.id);
850
+
851
+ return {
852
+ schemaVersion: 1,
853
+ diagnosticOnly: true,
854
+ claimEligible: false,
855
+ runId,
856
+ generatedAt,
857
+ pause: { reason, recognizedSpendControlPause: recognizedPause, pairBoundary },
858
+ completedRuns: acceptedRuns.length,
859
+ expectedRuns: expectedRuns.length,
860
+ remainingRuns: Math.max(0, expectedRuns.length - acceptedRuns.length),
861
+ counts: {
862
+ completedSessions: acceptedRuns.length,
863
+ expectedSessions: expectedRuns.length,
864
+ expectedPairs: pairs.size,
865
+ observedCompletePairs: completePairs.length,
866
+ incompleteObservedPairs: incompleteObservedPairs.length,
867
+ unstartedPairs: unstartedPairs.length,
868
+ duplicateSessions: duplicateRuns.length,
869
+ unexpectedSessions: unexpectedRuns.length
870
+ },
871
+ pairs: {
872
+ completeObserved: completePairs,
873
+ incompleteObserved: incompleteObservedPairs,
874
+ unstarted: unstartedPairs,
875
+ duplicateRuns,
876
+ unexpectedRuns,
877
+ futureUnstartedPairsBlockStageAdvance: false
878
+ },
879
+ quality: {
880
+ rule: "no-baseline-pass-piagent-fail-and-candidate-outcomes-above-the-release-floor",
881
+ passed: qualityPassed,
882
+ noBaselineOnlyRegressionPassed,
883
+ observedGradeNonInferiorPassed,
884
+ observedCompletePairs: completePairs.length,
885
+ malformedCompletePairs,
886
+ baselineOnlyRegressions,
887
+ pairedGradeComparabilityFailures,
888
+ pairedGradeRegressions,
889
+ outcomeFloor: outcomeFloorConfigured ? {
890
+ minimumScoreExclusive: outcomeFloor,
891
+ stopAfterFailedPairEnabled: manifest?.stopAfterFailedPair === true,
892
+ passed: outcomeFloorPassed,
893
+ failures: outcomeFailures
894
+ } : {
895
+ minimumScoreExclusive: null,
896
+ stopAfterFailedPairEnabled: manifest?.stopAfterFailedPair === true,
897
+ passed: false,
898
+ failures: [{ failures: ["outcome-floor-not-configured"] }]
899
+ }
900
+ },
901
+ acceptedUsage: {
902
+ rule: "every-accepted-session-has-exact-provider-token-buckets",
903
+ passed: acceptedUsagePassed,
904
+ exactRuns: acceptedRuns.length - acceptedUsageFailures.length,
905
+ acceptedRuns: acceptedRuns.length,
906
+ failures: acceptedUsageFailures
907
+ },
908
+ providerParity: {
909
+ rule: "observed-pi-runs-match-requested-model-thinking-and-verified-provider-wire",
910
+ passed: providerParityPassed,
911
+ requestedModel: requestedModel ?? null,
912
+ requestedThinking: requestedThinking ?? null,
913
+ observedPiRuns: piRuns.length,
914
+ verifiedPiRuns: piRuns.length - piParityFailures.length,
915
+ piRunFailures: piParityFailures,
916
+ pairedModelThinkingFailures,
917
+ wireGroups,
918
+ wireDriftGroups
919
+ },
920
+ causalContextEvidence: {
921
+ rule: "every-observed-piagent-session-preserves-a-complete-privacy-safe-causal-context-receipt",
922
+ passed: causalContextPassed,
923
+ piagentRuns: piRuns.length,
924
+ ...causalContextSummary
925
+ },
926
+ providerFreeEvidence: {
927
+ required: providerFreeEvidenceRequired,
928
+ passed: providerFreeEvidencePassed,
929
+ errors: providerFreeEvidenceErrors,
930
+ expectedLaneIds: providerFreeGuard?.requiredLaneIds ?? [],
931
+ observedLaneIds: providerFreeObservedLaneIds
932
+ },
933
+ adaptiveContextRuntimeCoverage: {
934
+ passed: adaptiveContextCoveragePassed,
935
+ partialRuns: partialAdaptiveContextRuns,
936
+ notObservedRuns: notObservedAdaptiveContextRuns,
937
+ delegatedToProviderFreeEvidence: notObservedAdaptiveContextRuns > 0 && providerFreeEvidencePassed
938
+ },
939
+ infrastructure: {
940
+ retryGatePassed,
941
+ retryEvidenceFailures,
942
+ infrastructureRetries,
943
+ failedAttempts,
944
+ recoveredProviderAttempts,
945
+ unknownUsageGatePassed: unknownUsagePassed,
946
+ unknownUsageAttempts,
947
+ failedAttemptUnknownUsage,
948
+ manifestUnknownUsage,
949
+ tokenClaimsUnavailableReason
950
+ },
951
+ hostReadiness: hostReadinessHistory,
952
+ timingDiagnostics: summarizeBenchmarkTimingDiagnostics(acceptedRuns),
953
+ spendFutilityReview: {
954
+ rule: "partial-stages-from-the-frozen-boundary-enforce-exact-all-attempt-pooled-and-family-fresh-spend-ceilings; this-is-not-the-final-40-percent-claim-gate",
955
+ passed: partialSpendPassed && (!subagentBudgetRequired || subagentBudget.passed),
956
+ freshTokens: { passed: freshEfficiencyPassed, ...freshEfficiency },
957
+ partialStageCatastrophicFreshSpend: { required: partialSpendRequired, ...partialSpend },
958
+ subagentBudget,
959
+ normalizedApiEquivalentTextTokenCost: {
960
+ billedCost: false,
961
+ scope: "model-text-token-input-cache-output-only",
962
+ pricingSnapshotId: pricingSnapshotErrors.length === 0 ? pricingSnapshot.id : null,
963
+ pricingSnapshotErrors,
964
+ passed: normalizedCostPassed,
965
+ ...normalizedCostEvidence
966
+ },
967
+ duration: { passed: durationEfficiencyPassed, ...durationEfficiency }
968
+ },
969
+ checks,
970
+ blockingReasons,
971
+ stageAdvanceAllowed: blockingReasons.length === 0,
972
+ decisionContract: {
973
+ blocking: "quality-model-parity-task-continuity-exact-usage-subagent-budget-and-partial-stage-catastrophic-fresh-spend",
974
+ finalOnly: ["0.60-upper95-fresh-token-reduction"],
975
+ observational: ["normalized-api-equivalent-text-token-cost", "duration", "host-load"]
976
+ },
977
+ claimBoundary: "Provider-free partial-run diagnostic only. Intermediate token measurements cannot make a claim; cost, duration, and host load are observational and non-blocking."
978
+ };
979
+ }