@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.
- package/CHANGELOG.md +117 -0
- package/README.md +9 -8
- package/README.vi.md +9 -5
- package/adapters/web-frontend/profile.json +2 -4
- package/architecture/layers.json +18 -3
- package/benchmarks/deep-logic-v1/SPECIALIST_PROTOCOL.vi.md +122 -0
- package/benchmarks/deep-logic-v1/grade.mjs +272 -10
- package/benchmarks/deep-logic-v1/project/apps/admin/src/billing-summary.js +3 -0
- package/benchmarks/deep-logic-v1/project/benchmark-contract/public-smoke.test.js +166 -0
- package/benchmarks/deep-logic-v1/project/package.json +1 -1
- package/benchmarks/deep-logic-v1/project/packages/billing/src/close-period.js +3 -0
- package/benchmarks/deep-logic-v1/project/packages/billing/src/plan-timeline.js +3 -0
- package/benchmarks/deep-logic-v1/project/test/smoke.test.js +7 -1
- package/benchmarks/deep-logic-v1/prompts/budgeted-context-graph.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/fair-dependency-scheduler.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/layered-policy-resolution.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/resumable-stream-assembly.md +3 -1
- package/benchmarks/deep-logic-v1/prompts/revision-event-reconciliation.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/temporal-usage-billing-close.md +123 -0
- package/benchmarks/deep-logic-v1/prompts/transactional-config-merge.md +2 -0
- package/benchmarks/deep-logic-v1/suite.json +51 -3
- package/benchmarks/deep-logic-v1/variant.mjs +22 -1
- package/benchmarks/production-v1/spend-control.v1.json +68 -0
- package/benchmarks/production-v1/suite.json +42 -3
- package/catalog/capabilities.json +6 -6
- package/docs/command-reference-vietnamese.md +6 -6
- package/docs/context-engine.md +7 -1
- package/docs/distribution-standard.md +7 -7
- package/docs/en/architecture.md +1 -0
- package/docs/languages.json +4 -4
- package/docs/model-options.md +8 -5
- package/docs/operator-manual-vietnamese.md +13 -11
- package/docs/project-adapters.md +2 -2
- package/docs/publishing-for-teams.md +5 -0
- package/docs/quality-benchmark.md +271 -62
- package/docs/release-install-policy.md +10 -9
- package/docs/runtime-policy-design.md +4 -4
- package/docs/runtime-quality-baseline.md +13 -6
- package/docs/security-threat-model.md +2 -2
- package/docs/task-lifecycle-vietnamese.md +2 -2
- package/docs/team-onboarding.md +2 -2
- package/docs/usage-observability.md +7 -2
- package/docs/vi/architecture.md +1 -0
- package/docs-site/architecture.html +1 -1
- package/docs-site/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/context-engine.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +1 -1
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/index.html +1 -1
- package/docs-site/en/mcp-approval.html +1 -1
- package/docs-site/en/mcp-auth.html +1 -1
- package/docs-site/en/mcp-servers.html +1 -1
- package/docs-site/en/mcp.html +1 -1
- package/docs-site/en/permissions.html +1 -1
- package/docs-site/en/profiles.html +1 -1
- package/docs-site/en/quickstart.html +1 -1
- package/docs-site/en/runtime.html +1 -1
- package/docs-site/en/scope.html +1 -1
- package/docs-site/en/security.html +1 -1
- package/docs-site/en/team.html +1 -1
- package/docs-site/en/whats-new.html +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +1 -1
- package/docs-site/mcp-approval.html +1 -1
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +1 -1
- package/docs-site/runtime.html +1 -1
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/whats-new.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/evals/fixtures/benchmark-assurance-evidence.invalid.json +1 -1
- package/evals/fixtures/benchmark-assurance-evidence.valid.json +1 -1
- package/evals/fixtures/piagent-webui/session-live-state-v1.invalid.json +18 -0
- package/evals/fixtures/piagent-webui/session-live-state-v1.valid.json +27 -0
- package/evals/fs4-readiness-matrix.v1.json +2 -2
- package/evals/fs5-causal-arm.v1.json +2 -2
- package/evals/fs5-pilot-protocol.v1.json +2 -2
- package/evals/fs5-pilot-protocol.v4.json +6 -5
- package/evals/fs5-pilot-protocol.v5.json +7 -6
- package/evals/private-holdout-v1/public-exposure.v1.json +1 -1
- package/package.json +3 -1
- package/packages/piagent-core/benchmark/benchmark-assurance.js +4 -1
- package/packages/piagent-core/benchmark/benchmark-bootstrap.js +91 -9
- package/packages/piagent-core/benchmark/benchmark-claim-restrictions.js +38 -7
- package/packages/piagent-core/benchmark/benchmark-cli.js +7 -7
- package/packages/piagent-core/benchmark/benchmark-codex.js +3 -1
- package/packages/piagent-core/benchmark/benchmark-comparison.js +271 -2
- package/packages/piagent-core/benchmark/benchmark-core.js +732 -661
- package/packages/piagent-core/benchmark/benchmark-execution-guard.js +7 -5
- package/packages/piagent-core/benchmark/benchmark-forensics.js +439 -4
- package/packages/piagent-core/benchmark/benchmark-host-readiness.js +639 -0
- package/packages/piagent-core/benchmark/benchmark-matrix.js +22 -4
- package/packages/piagent-core/benchmark/benchmark-normalized-cost.js +317 -0
- package/packages/piagent-core/benchmark/benchmark-preflight.js +3 -1
- package/packages/piagent-core/benchmark/benchmark-process.js +6 -5
- package/packages/piagent-core/benchmark/benchmark-provider-wire.js +126 -0
- package/packages/piagent-core/benchmark/benchmark-record-validation.js +183 -0
- package/packages/piagent-core/benchmark/benchmark-report.js +116 -12
- package/packages/piagent-core/benchmark/benchmark-resume-recovery.js +14 -0
- package/packages/piagent-core/benchmark/benchmark-runner-policy.js +26 -0
- package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +782 -0
- package/packages/piagent-core/benchmark/benchmark-statistics.js +64 -0
- package/packages/piagent-core/benchmark/benchmark-stop-policy.js +8 -5
- package/packages/piagent-core/benchmark/benchmark-suite-identity.js +31 -0
- package/packages/piagent-core/benchmark/benchmark-suite-runtime.js +13 -9
- package/packages/piagent-core/benchmark/benchmark-suite.js +128 -2
- package/packages/piagent-core/benchmark/benchmark-summary-support.js +376 -0
- package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +971 -0
- package/packages/piagent-core/benchmark/benchmark-usage.js +311 -0
- package/packages/piagent-core/benchmark/benchmark-workflow.js +166 -0
- package/packages/piagent-core/docs/context-efficiency-improvement-plan.md +1080 -0
- package/packages/piagent-core/extensions/acceptance-contract-semantics.js +83 -69
- package/packages/piagent-core/extensions/acceptance-error-classes.js +160 -0
- package/packages/piagent-core/extensions/acceptance-executable-evidence.js +12 -9
- package/packages/piagent-core/extensions/acceptance-receipt.js +34 -11
- package/packages/piagent-core/extensions/acceptance-state-machine-evidence.js +518 -0
- package/packages/piagent-core/extensions/acceptance-test-binding-evidence.js +60 -0
- package/packages/piagent-core/extensions/context-efficiency-metrics.js +302 -0
- package/packages/piagent-core/extensions/context-efficiency-report.js +167 -0
- package/packages/piagent-core/extensions/context-engine.js +148 -145
- package/packages/piagent-core/extensions/context-evidence.js +48 -0
- package/packages/piagent-core/extensions/context-import-links.js +296 -0
- package/packages/piagent-core/extensions/context-telemetry-integrity.js +65 -0
- package/packages/piagent-core/extensions/criterion-context-pack.js +422 -7
- package/packages/piagent-core/extensions/criterion-graph.js +78 -8
- package/packages/piagent-core/extensions/guard-types.ts +2 -0
- package/packages/piagent-core/extensions/javascript-regex-evidence.js +32 -0
- package/packages/piagent-core/extensions/piagent-guard.ts +233 -41
- package/packages/piagent-core/extensions/task-contract-view.js +17 -3
- package/packages/piagent-core/extensions/task-lifecycle.js +7 -2
- package/packages/piagent-core/extensions/task-state.js +40 -134
- package/packages/piagent-core/extensions/verification-intelligence.js +3 -1
- package/packages/piagent-core/extensions/workspace-evidence-roots.js +157 -0
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-core/policies/base-policy.json +2 -0
- package/packages/piagent-core/runtime/context/context-delivery.ts +103 -0
- package/packages/piagent-core/runtime/context/context-delta-shadow.ts +53 -0
- package/packages/piagent-core/runtime/context/context-efficiency-format.ts +47 -0
- package/packages/piagent-core/runtime/context/context-evidence-qualification.ts +32 -0
- package/packages/piagent-core/runtime/context/prefix-telemetry.ts +47 -0
- package/packages/piagent-core/runtime/context/repository-memory-hints.ts +27 -0
- package/packages/piagent-core/runtime/hooks/agent-prompt-telemetry.ts +56 -0
- package/packages/piagent-core/runtime/hooks/agent-start-hook.ts +162 -102
- package/packages/piagent-core/runtime/hooks/completion-hook.ts +5 -6
- package/packages/piagent-core/runtime/hooks/input-hook.ts +11 -1
- package/packages/piagent-core/runtime/hooks/session-hooks.ts +22 -2
- package/packages/piagent-core/runtime/hooks/session-start-hook.ts +7 -2
- package/packages/piagent-core/runtime/hooks/tool-result-content-guards.ts +95 -0
- package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +84 -102
- package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +4 -2
- package/packages/piagent-core/runtime/inspection/activity-recovery.ts +104 -0
- package/packages/piagent-core/runtime/inspection/task-compaction-history.ts +1 -1
- package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +1 -1
- package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +53 -0
- package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +34 -6
- package/packages/piagent-core/runtime/model/authenticated-catalog.ts +17 -9
- package/packages/piagent-core/runtime/model/openai-codex-reasoning.ts +83 -0
- package/packages/piagent-core/runtime/model/provider-wire-fingerprint.ts +238 -0
- package/packages/piagent-core/runtime/orchestration/role-policy.ts +1 -1
- package/packages/piagent-core/runtime/product/activity-inspector.ts +7 -2
- package/packages/piagent-core/runtime/product/efficiency-metrics.ts +4 -2
- package/packages/piagent-core/runtime/quality/exact-output-contract.ts +2 -1
- package/packages/piagent-core/runtime/quality/performance-assurance-signals.ts +23 -0
- package/packages/piagent-core/runtime/quality/performance-assurance.ts +6 -2
- package/packages/piagent-core/runtime/recovery/edit-recovery-context.ts +113 -0
- package/packages/piagent-core/runtime/recovery/edit-recovery-delivery.ts +42 -0
- package/packages/piagent-core/runtime/recovery/semantic-repair-handshake.ts +55 -2
- package/packages/piagent-core/runtime/recovery/semantic-repair-runtime.ts +55 -2
- package/packages/piagent-core/runtime/registration/context-commands.ts +66 -5
- package/packages/piagent-core/runtime/registration/policy-tools.ts +46 -11
- package/packages/piagent-core/runtime/registration/task-completion-tools.ts +49 -16
- package/packages/piagent-core/runtime/registration/task-start-guidance.ts +163 -0
- package/packages/piagent-core/runtime/registration/task-start-retry-helpers.ts +37 -0
- package/packages/piagent-core/runtime/registration/task-start-tool.ts +67 -62
- package/packages/piagent-core/runtime/session/runtime-state.ts +154 -2
- package/packages/piagent-core/runtime/session/system-prompt.ts +4 -4
- package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +500 -0
- package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +2 -1
- package/packages/piagent-core/runtime/workflows/task-intake.ts +43 -2
- package/packages/piagent-core/security/sensitive-data.js +13 -218
- package/packages/piagent-core/security/sensitive-project-file.js +42 -0
- package/packages/piagent-core/security/sensitive-source-expression.js +330 -0
- package/packages/piagent-core/security/sensitive-source-formats.js +394 -0
- package/packages/piagent-core/security/sensitive-text.js +234 -0
- package/packages/piagent-core/subagents/piagent-worker.md +1 -1
- package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-rD9WJKxs.js → MarkdownMessage-CxeZqTte.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/index-DynIMe8I.js +176 -0
- package/packages/piagent-webui/dist/client/index.html +1 -1
- package/packages/piagent-webui/gateway/gateway-events.ts +109 -5
- package/packages/piagent-webui/gateway/gateway-service.ts +3 -0
- package/packages/piagent-webui/gateway/gateway-session-stream.ts +93 -7
- package/packages/piagent-webui/gateway/session-command-controller.ts +18 -3
- package/packages/piagent-webui/gateway/session-effective-options.ts +47 -0
- package/packages/piagent-webui/gateway/session-live-state.ts +21 -0
- package/packages/piagent-webui/gateway/session-operation-start.ts +5 -1
- package/packages/piagent-webui/gateway/session-operation-watchdog.ts +158 -0
- package/packages/piagent-webui/gateway/session-runtime-factory.ts +45 -0
- package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +139 -124
- package/packages/piagent-webui/server/loopback-server.ts +8 -0
- package/packages/piagent-webui/server/transcript-projection.ts +22 -4
- package/packages/piagent-webui/shared/text-visibility.ts +10 -0
- package/schemas/piagent-webui/catalog-v1.json +9 -0
- package/schemas/piagent-webui/gateway-protocol-v1.schema.json +53 -3
- package/schemas/piagent-webui/session-live-state-v1.schema.json +76 -0
- package/schemas/task-contract.schema.json +12 -1
- package/scripts/benchmark-runner-core.mjs +355 -359
- package/scripts/benchmark-runner-finalization.mjs +309 -0
- package/scripts/benchmark-runner-host-readiness.mjs +94 -0
- package/scripts/benchmark-runner-support.mjs +200 -0
- package/scripts/benchmark-session.mjs +95 -41
- package/scripts/configure-model-scope.sh +4 -3
- package/scripts/helper-evaluation.mjs +1 -1
- package/scripts/install-global.sh +2 -2
- package/scripts/pi-usage-history.mjs +37 -10
- package/scripts/setup.sh +2 -2
- package/scripts/verify-local.sh +5 -1
- package/templates/global/settings.json +2 -1
- package/packages/piagent-webui/dist/client/assets/index-BZRFw1u6.js +0 -174
|
@@ -1,637 +1,69 @@
|
|
|
1
|
-
import { StringDecoder } from "node:string_decoder";
|
|
2
|
-
|
|
3
1
|
import { benchmarkClaimEligibility } from "./benchmark-assurance.js";
|
|
4
2
|
import {
|
|
5
3
|
comparableAttemptUsage,
|
|
4
|
+
comparableDuration,
|
|
6
5
|
comparisonProtocol,
|
|
7
6
|
completeCategoryCoverage,
|
|
8
7
|
completePairedScenarioCount,
|
|
8
|
+
familyClusteredFailureAwareUsage,
|
|
9
|
+
familyClusteredFixedWorkloadUsage,
|
|
10
|
+
pairedDurationBands,
|
|
11
|
+
pairedUsageBands,
|
|
12
|
+
selectPrimaryEfficiencyEstimate,
|
|
9
13
|
tokensPerResolvedOutcome
|
|
10
14
|
} from "./benchmark-comparison.js";
|
|
15
|
+
import { benchmarkProviderWireEvidenceMatchesRequest } from "./benchmark-provider-wire.js";
|
|
16
|
+
import { canonicalBenchmarkTimingDiagnostics, summarizeBenchmarkTimingDiagnostics } from "./benchmark-timing-diagnostics.js";
|
|
17
|
+
import { summarizeBenchmarkCausalContextEvidence } from "./benchmark-record-validation.js";
|
|
18
|
+
import {
|
|
19
|
+
benchmarkPricingSnapshotValidationErrors,
|
|
20
|
+
normalizedCostComparison,
|
|
21
|
+
normalizedCostGate
|
|
22
|
+
} from "./benchmark-normalized-cost.js";
|
|
11
23
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
atMostWithinFloatingPrecision,
|
|
25
|
+
geometricMean,
|
|
26
|
+
geometricMeanConfidence95,
|
|
27
|
+
geometricMeanConfidence95Raw,
|
|
28
|
+
median,
|
|
29
|
+
rounded
|
|
30
|
+
} from "./benchmark-statistics.js";
|
|
31
|
+
import { benchmarkInfrastructureFailureLedgerIssues, benchmarkTokenAccounting as buildBenchmarkTokenAccounting } from "./benchmark-usage.js";
|
|
32
|
+
import {
|
|
33
|
+
efficiencyScore,
|
|
34
|
+
evaluateDurationBandGate,
|
|
35
|
+
evaluateFreshTokenBandGate,
|
|
36
|
+
pairedOutcomeCounts,
|
|
37
|
+
pairedQualityNoninferiorityEvidence,
|
|
38
|
+
qualityPassed,
|
|
39
|
+
RELEASE_FAILURE_MESSAGES,
|
|
40
|
+
safetyPassed,
|
|
41
|
+
surfaceReportKey,
|
|
42
|
+
surfaceSummary,
|
|
43
|
+
workflowContinuityEvidenceComplete
|
|
44
|
+
} from "./benchmark-summary-support.js";
|
|
16
45
|
|
|
17
46
|
export { renderBenchmarkHtml, renderBenchmarkText } from "./benchmark-report.js";
|
|
18
47
|
export { benchmarkAssuranceEvidenceValidationErrors, benchmarkClaimEligibility } from "./benchmark-assurance.js";
|
|
48
|
+
export { median } from "./benchmark-statistics.js";
|
|
19
49
|
export { benchmarkSuiteValidationErrors, validateBenchmarkSuite } from "./benchmark-suite.js";
|
|
50
|
+
export { aggregateSessionUsage, benchmarkTokenAccounting, createCodexExecJsonlCollector, parseCodexExecJsonl } from "./benchmark-usage.js";
|
|
51
|
+
export { benchmarkPricingSnapshotValidationErrors, normalizeBenchmarkUsageCost } from "./benchmark-normalized-cost.js";
|
|
52
|
+
export { evaluateWorkflowEvidence } from "./benchmark-workflow.js";
|
|
20
53
|
const SURFACE_LABELS = Object.freeze({
|
|
21
54
|
"raw-pi": "Raw Pi",
|
|
22
55
|
piagent: "Piagent",
|
|
23
56
|
"codex-cli": "Codex CLI"
|
|
24
57
|
});
|
|
25
|
-
const SURFACE_REPORT_KEYS = Object.freeze({
|
|
26
|
-
"raw-pi": "rawPi",
|
|
27
|
-
piagent: "piagent",
|
|
28
|
-
"codex-cli": "codexCli"
|
|
29
|
-
});
|
|
30
|
-
const CODEX_NON_TOOL_ITEMS = new Set(["agent_message", "reasoning", "plan", "user_message"]);
|
|
31
58
|
export const BENCHMARK_MEASUREMENT_SCHEMA_VERSION = 2;
|
|
32
59
|
|
|
33
|
-
function plainObject(value) {
|
|
34
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function median(values) {
|
|
38
|
-
const finite = values.filter(Number.isFinite).sort((left, right) => left - right);
|
|
39
|
-
if (finite.length === 0) return null;
|
|
40
|
-
const middle = Math.floor(finite.length / 2);
|
|
41
|
-
return finite.length % 2 ? finite[middle] : (finite[middle - 1] + finite[middle]) / 2;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function geometricMean(values) {
|
|
45
|
-
if (!Array.isArray(values) || values.length === 0) return null;
|
|
46
|
-
if (values.some((value) => !Number.isFinite(value) || value <= 0)) return null;
|
|
47
|
-
return Math.exp(values.reduce((sum, value) => sum + Math.log(value), 0) / values.length);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function rounded(value, digits = 3) {
|
|
51
|
-
if (!Number.isFinite(value)) return null;
|
|
52
|
-
const factor = 10 ** digits;
|
|
53
|
-
return Math.round(value * factor) / factor;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function clamp(value, minimum = 0, maximum = 10) {
|
|
57
|
-
return Math.max(minimum, Math.min(maximum, value));
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function wilsonInterval(successes, total, z = 1.959963984540054) {
|
|
61
|
-
if (!Number.isInteger(total) || total <= 0 || !Number.isInteger(successes) || successes < 0 || successes > total) return null;
|
|
62
|
-
const proportion = successes / total;
|
|
63
|
-
const zSquared = z ** 2;
|
|
64
|
-
const denominator = 1 + (zSquared / total);
|
|
65
|
-
const center = (proportion + (zSquared / (2 * total))) / denominator;
|
|
66
|
-
const margin = (z / denominator) * Math.sqrt(((proportion * (1 - proportion)) / total) + (zSquared / (4 * total ** 2)));
|
|
67
|
-
return { lower: rounded(Math.max(0, center - margin), 4), upper: rounded(Math.min(1, center + margin), 4) };
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const STUDENT_T_975 = Object.freeze([
|
|
71
|
-
null, 12.706, 4.303, 3.182, 2.776, 2.571, 2.447, 2.365, 2.306, 2.262,
|
|
72
|
-
2.228, 2.201, 2.179, 2.16, 2.145, 2.131, 2.12, 2.11, 2.101, 2.093,
|
|
73
|
-
2.086, 2.08, 2.074, 2.069, 2.064, 2.06, 2.056, 2.052, 2.048, 2.045, 2.042
|
|
74
|
-
]);
|
|
75
|
-
|
|
76
|
-
function geometricMeanConfidence95(values) {
|
|
77
|
-
if (!Array.isArray(values) || values.length < 2 || values.some((value) => !Number.isFinite(value) || value <= 0)) return null;
|
|
78
|
-
const logs = values.map(Math.log);
|
|
79
|
-
const mean = logs.reduce((sum, value) => sum + value, 0) / logs.length;
|
|
80
|
-
const variance = logs.reduce((sum, value) => sum + ((value - mean) ** 2), 0) / (logs.length - 1);
|
|
81
|
-
const critical = STUDENT_T_975[logs.length - 1] ?? 1.96;
|
|
82
|
-
const margin = critical * Math.sqrt(variance / logs.length);
|
|
83
|
-
return {
|
|
84
|
-
lower: rounded(Math.exp(mean - margin), 4),
|
|
85
|
-
upper: rounded(Math.exp(mean + margin), 4),
|
|
86
|
-
sampleUnit: "scenario-family",
|
|
87
|
-
scenarioCount: logs.length
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function aggregateSessionUsage(sessions) {
|
|
92
|
-
const totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0, total: 0, cost: 0 };
|
|
93
|
-
const models = new Set();
|
|
94
|
-
const thinkingLevels = new Set();
|
|
95
|
-
const toolNames = {};
|
|
96
|
-
let toolCalls = 0;
|
|
97
|
-
let messages = 0;
|
|
98
|
-
const contextSnapshots = [];
|
|
99
|
-
for (const session of sessions) {
|
|
100
|
-
for (const key of Object.keys(totals)) totals[key] += Number(session.tokens?.[key] ?? 0);
|
|
101
|
-
if (session.modelId || session.provider) models.add(`${session.provider || "unknown"}/${session.modelId || "unknown"}`);
|
|
102
|
-
if (session.thinkingLevel) thinkingLevels.add(session.thinkingLevel);
|
|
103
|
-
toolCalls += Number(session.messages?.toolCalls ?? 0);
|
|
104
|
-
messages += Number(session.messages?.total ?? 0);
|
|
105
|
-
if (plainObject(session.contextUsage)) {
|
|
106
|
-
const snapshot = {
|
|
107
|
-
tokens: Number.isFinite(session.contextUsage.tokens) ? session.contextUsage.tokens : null,
|
|
108
|
-
contextWindow: Number.isFinite(session.contextUsage.contextWindow) ? session.contextUsage.contextWindow : null,
|
|
109
|
-
percent: Number.isFinite(session.contextUsage.percent) ? session.contextUsage.percent : null
|
|
110
|
-
};
|
|
111
|
-
if (Object.values(snapshot).some(Number.isFinite)) contextSnapshots.push(snapshot);
|
|
112
|
-
}
|
|
113
|
-
for (const [name, count] of Object.entries(session.toolNames ?? {})) {
|
|
114
|
-
toolNames[name] = (toolNames[name] ?? 0) + Number(count ?? 0);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return {
|
|
118
|
-
...totals,
|
|
119
|
-
fresh: totals.input + totals.output,
|
|
120
|
-
sessions: sessions.length,
|
|
121
|
-
subagentSessions: sessions.filter((session) => session.isSubagent).length,
|
|
122
|
-
toolCalls,
|
|
123
|
-
toolNames: Object.fromEntries(Object.entries(toolNames).sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0]))),
|
|
124
|
-
messages,
|
|
125
|
-
model: models.size === 1 ? [...models][0] : models.size === 0 ? "unknown" : "mixed",
|
|
126
|
-
thinkingLevel: thinkingLevels.size === 1 ? [...thinkingLevels][0] : thinkingLevels.size === 0 ? "unknown" : "mixed",
|
|
127
|
-
contextUsage: contextSnapshots.length > 0 ? {
|
|
128
|
-
source: "session-reported",
|
|
129
|
-
observations: contextSnapshots.length,
|
|
130
|
-
peakTokens: contextSnapshots.some((item) => Number.isFinite(item.tokens))
|
|
131
|
-
? Math.max(...contextSnapshots.map((item) => item.tokens).filter(Number.isFinite))
|
|
132
|
-
: null,
|
|
133
|
-
contextWindow: new Set(contextSnapshots.map((item) => item.contextWindow).filter(Number.isFinite)).size === 1
|
|
134
|
-
? contextSnapshots.map((item) => item.contextWindow).find(Number.isFinite)
|
|
135
|
-
: null,
|
|
136
|
-
peakPercent: contextSnapshots.some((item) => Number.isFinite(item.percent))
|
|
137
|
-
? Math.max(...contextSnapshots.map((item) => item.percent).filter(Number.isFinite))
|
|
138
|
-
: null
|
|
139
|
-
} : {
|
|
140
|
-
source: "unavailable",
|
|
141
|
-
observations: 0,
|
|
142
|
-
peakTokens: null,
|
|
143
|
-
contextWindow: null,
|
|
144
|
-
peakPercent: null
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function requiredCodexToken(value, field) {
|
|
150
|
-
if (!Number.isSafeInteger(value) || value < 0) {
|
|
151
|
-
throw new Error(`Codex JSONL usage.${field} must be a non-negative integer`);
|
|
152
|
-
}
|
|
153
|
-
return value;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function consumeCodexEvent(state, event, lineNumber) {
|
|
157
|
-
if (!plainObject(event) || typeof event.type !== "string") {
|
|
158
|
-
throw new Error(`Codex JSONL line ${lineNumber} is not an event object`);
|
|
159
|
-
}
|
|
160
|
-
state.onEvent?.(event);
|
|
161
|
-
if (event.type === "error" || event.type === "turn.failed") {
|
|
162
|
-
const nested = plainObject(event.error) ? event.error : {};
|
|
163
|
-
const message = [event.message, nested.message, nested.additional_details]
|
|
164
|
-
.find((value) => typeof value === "string" && value.trim());
|
|
165
|
-
state.diagnostics.push({ type: event.type, message: message ? message.trim().slice(0, 2_000) : "unspecified Codex error" });
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
if (event.type === "thread.started" && typeof event.thread_id === "string" && event.thread_id) {
|
|
169
|
-
state.threadId = event.thread_id;
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
if (event.type === "item.completed" && plainObject(event.item)) {
|
|
173
|
-
const type = event.item.type;
|
|
174
|
-
if (type === "agent_message") state.messages += 1;
|
|
175
|
-
else if (typeof type === "string" && type && !CODEX_NON_TOOL_ITEMS.has(type)) {
|
|
176
|
-
state.toolNames[type] = (state.toolNames[type] ?? 0) + 1;
|
|
177
|
-
}
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
if (event.type === "turn.completed") {
|
|
181
|
-
state.completedTurns += 1;
|
|
182
|
-
if (state.completedTurns > 1) throw new Error("Codex JSONL contains more than one completed root turn");
|
|
183
|
-
if (!plainObject(event.usage)) throw new Error("Codex JSONL turn.completed is missing usage");
|
|
184
|
-
state.completedUsage = event.usage;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function finishCodexUsage(state) {
|
|
189
|
-
if (!state.threadId) throw new Error("Codex JSONL is missing thread.started");
|
|
190
|
-
if (!state.completedUsage) throw new Error("Codex JSONL is missing turn.completed usage");
|
|
191
|
-
const providerInput = requiredCodexToken(state.completedUsage.input_tokens, "input_tokens");
|
|
192
|
-
const cacheRead = requiredCodexToken(state.completedUsage.cached_input_tokens ?? 0, "cached_input_tokens");
|
|
193
|
-
const cacheWrite = requiredCodexToken(state.completedUsage.cache_write_input_tokens ?? 0, "cache_write_input_tokens");
|
|
194
|
-
const output = requiredCodexToken(state.completedUsage.output_tokens, "output_tokens");
|
|
195
|
-
const reasoning = requiredCodexToken(state.completedUsage.reasoning_output_tokens ?? 0, "reasoning_output_tokens");
|
|
196
|
-
if (cacheRead > providerInput) throw new Error("Codex JSONL cached_input_tokens exceeds input_tokens");
|
|
197
|
-
if (reasoning > output) throw new Error("Codex JSONL reasoning_output_tokens exceeds output_tokens");
|
|
198
|
-
const input = providerInput - cacheRead;
|
|
199
|
-
const sortedTools = Object.fromEntries(Object.entries(state.toolNames).sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0])));
|
|
200
|
-
return {
|
|
201
|
-
input,
|
|
202
|
-
providerInput,
|
|
203
|
-
output,
|
|
204
|
-
cacheRead,
|
|
205
|
-
cacheWrite,
|
|
206
|
-
reasoning,
|
|
207
|
-
total: providerInput + output,
|
|
208
|
-
fresh: input + output,
|
|
209
|
-
cost: null,
|
|
210
|
-
costSource: "unavailable",
|
|
211
|
-
sessions: 1,
|
|
212
|
-
subagentSessions: 0,
|
|
213
|
-
toolCalls: Object.values(sortedTools).reduce((sum, value) => sum + value, 0),
|
|
214
|
-
toolNames: sortedTools,
|
|
215
|
-
messages: state.messages,
|
|
216
|
-
model: typeof state.model === "string" && state.model ? state.model : "unknown",
|
|
217
|
-
thinkingLevel: typeof state.thinkingLevel === "string" && state.thinkingLevel ? state.thinkingLevel : "unknown",
|
|
218
|
-
contextUsage: {
|
|
219
|
-
source: "unavailable",
|
|
220
|
-
observations: 0,
|
|
221
|
-
peakTokens: null,
|
|
222
|
-
contextWindow: null,
|
|
223
|
-
peakPercent: null
|
|
224
|
-
},
|
|
225
|
-
providerSessionId: state.threadId
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export function createCodexExecJsonlCollector(options = {}) {
|
|
230
|
-
const state = {
|
|
231
|
-
model: options.model,
|
|
232
|
-
thinkingLevel: options.thinkingLevel,
|
|
233
|
-
onEvent: typeof options.onEvent === "function" ? options.onEvent : undefined,
|
|
234
|
-
threadId: undefined,
|
|
235
|
-
completedUsage: undefined,
|
|
236
|
-
completedTurns: 0,
|
|
237
|
-
messages: 0,
|
|
238
|
-
toolNames: {},
|
|
239
|
-
diagnostics: []
|
|
240
|
-
};
|
|
241
|
-
let buffer = "";
|
|
242
|
-
let lineNumber = 0;
|
|
243
|
-
let failure;
|
|
244
|
-
const decoder = new StringDecoder("utf8");
|
|
245
|
-
const consumeLine = (rawLine) => {
|
|
246
|
-
lineNumber += 1;
|
|
247
|
-
const line = rawLine.trim();
|
|
248
|
-
if (!line) return;
|
|
249
|
-
let event;
|
|
250
|
-
try { event = JSON.parse(line); }
|
|
251
|
-
catch { throw new Error(`Codex JSONL line ${lineNumber} is not valid JSON`); }
|
|
252
|
-
consumeCodexEvent(state, event, lineNumber);
|
|
253
|
-
};
|
|
254
|
-
return {
|
|
255
|
-
write(chunk) {
|
|
256
|
-
if (failure) return;
|
|
257
|
-
try {
|
|
258
|
-
buffer += typeof chunk === "string" ? chunk : decoder.write(Buffer.from(chunk));
|
|
259
|
-
let newline;
|
|
260
|
-
while ((newline = buffer.indexOf("\n")) >= 0) {
|
|
261
|
-
consumeLine(buffer.slice(0, newline));
|
|
262
|
-
buffer = buffer.slice(newline + 1);
|
|
263
|
-
}
|
|
264
|
-
if (buffer.length > 64 * 1024 * 1024) throw new Error("Codex JSONL event exceeds the 64 MiB safety limit");
|
|
265
|
-
} catch (error) {
|
|
266
|
-
failure = error;
|
|
267
|
-
buffer = "";
|
|
268
|
-
}
|
|
269
|
-
},
|
|
270
|
-
finish() {
|
|
271
|
-
if (!failure) buffer += decoder.end();
|
|
272
|
-
if (!failure && buffer) {
|
|
273
|
-
try { consumeLine(buffer); } catch (error) { failure = error; }
|
|
274
|
-
buffer = "";
|
|
275
|
-
}
|
|
276
|
-
if (failure) throw failure;
|
|
277
|
-
return finishCodexUsage(state);
|
|
278
|
-
},
|
|
279
|
-
diagnostics() {
|
|
280
|
-
return state.diagnostics.map((item) => ({ ...item }));
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
export function parseCodexExecJsonl(stdout, options = {}) {
|
|
286
|
-
if (typeof stdout !== "string") throw new Error("Codex JSONL output must be a string");
|
|
287
|
-
const collector = createCodexExecJsonlCollector(options);
|
|
288
|
-
collector.write(stdout);
|
|
289
|
-
return collector.finish();
|
|
290
|
-
}
|
|
291
|
-
|
|
292
60
|
export function benchmarkSurfaceLabel(surface) {
|
|
293
61
|
return SURFACE_LABELS[surface] ?? surface;
|
|
294
62
|
}
|
|
295
63
|
|
|
296
|
-
function surfaceReportKey(surface) {
|
|
297
|
-
return SURFACE_REPORT_KEYS[surface] ?? surface;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function usageMedians(runs) {
|
|
301
|
-
return {
|
|
302
|
-
runs: runs.length,
|
|
303
|
-
medianFreshTokens: median(runs.map((run) => run.usage?.fresh)),
|
|
304
|
-
medianInputTokens: median(runs.map((run) => run.usage?.input)),
|
|
305
|
-
medianOutputTokens: median(runs.map((run) => run.usage?.output)),
|
|
306
|
-
medianCacheReadTokens: median(runs.map((run) => run.usage?.cacheRead)),
|
|
307
|
-
medianReasoningTokens: median(runs.map((run) => run.usage?.reasoning)),
|
|
308
|
-
medianCost: median(runs.map((run) => run.usage?.cost)),
|
|
309
|
-
medianDurationSeconds: median(runs.map((run) => run.durationSeconds)),
|
|
310
|
-
medianToolCalls: median(runs.map((run) => run.usage?.toolCalls))
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function aggregateToolNames(runs) {
|
|
315
|
-
const totals = {};
|
|
316
|
-
for (const run of runs) {
|
|
317
|
-
for (const [name, count] of Object.entries(run.usage?.toolNames ?? {})) {
|
|
318
|
-
totals[name] = (totals[name] ?? 0) + Number(count ?? 0);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
return Object.fromEntries(Object.entries(totals).sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0])));
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
function meaningfulVerifyCommands(commands) {
|
|
325
|
-
if (!Array.isArray(commands)) return [];
|
|
326
|
-
return commands.filter((command) => typeof command === "string" && command.trim() && !/^(?:true|:|echo\b|printf\b)/i.test(command.trim()));
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
function latestObservedTaskEvidence(evidence, command) {
|
|
330
|
-
let latest, latestTime = Number.NEGATIVE_INFINITY, latestIndex = -1;
|
|
331
|
-
for (const [index, item] of (Array.isArray(evidence) ? evidence : []).entries()) {
|
|
332
|
-
if (item?.observed !== true || item.command?.trim() !== command) continue;
|
|
333
|
-
const observedAt = item.observedAt ?? item.recordedAt;
|
|
334
|
-
const parsed = typeof observedAt === "string" ? Date.parse(observedAt) : Number.NaN;
|
|
335
|
-
const time = Number.isFinite(parsed) ? parsed : Number.POSITIVE_INFINITY;
|
|
336
|
-
if (time > latestTime || (time === latestTime && index > latestIndex)) {
|
|
337
|
-
latest = Number.isFinite(parsed) ? item : null;
|
|
338
|
-
latestTime = time;
|
|
339
|
-
latestIndex = index;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
return latest;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function stableTaskVerifierEvidence(item) {
|
|
346
|
-
return item?.exitCode === 0
|
|
347
|
-
&& item.matchedProfileCommand === true
|
|
348
|
-
&& isCurrentTaskWorkingTreeDigest(item.preWorkingTreeDigest)
|
|
349
|
-
&& item.preWorkingTreeDigest === item.workingTreeDigest;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
function semanticAcceptanceEvidenceRequired(task) {
|
|
353
|
-
const snapshot = task?.authoritySnapshot;
|
|
354
|
-
if (!plainObject(snapshot)
|
|
355
|
-
|| snapshot.taskId !== task?.taskId
|
|
356
|
-
|| snapshot.taskRunId !== task?.taskRunId
|
|
357
|
-
|| snapshot.capturedAt !== task?.createdAt) return true;
|
|
358
|
-
const semantic = Array.isArray(snapshot.capabilities)
|
|
359
|
-
? snapshot.capabilities.find((entry) => entry?.id === "CAP-13")
|
|
360
|
-
: undefined;
|
|
361
|
-
return !semantic || semantic.authority === "enforce" || semantic.authority === "orchestrate";
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const RUNTIME_MANAGED_BENCHMARK_TOOLS = new Set([
|
|
365
|
-
"piagent_context",
|
|
366
|
-
"piagent_context_preflight",
|
|
367
|
-
"piagent_context_engine",
|
|
368
|
-
"piagent_context_budget",
|
|
369
|
-
"piagent_context_index_status",
|
|
370
|
-
"piagent_context_index_search",
|
|
371
|
-
"piagent_context_record",
|
|
372
|
-
"piagent_permission_status",
|
|
373
|
-
"piagent_exec_policy_check",
|
|
374
|
-
"piagent_tool_policy_check",
|
|
375
|
-
"piagent_verify_record",
|
|
376
|
-
"piagent_trace_record",
|
|
377
|
-
"piagent_task_gate_check",
|
|
378
|
-
"piagent_tools"
|
|
379
|
-
]);
|
|
380
|
-
|
|
381
|
-
export function evaluateWorkflowEvidence(task, changedFiles, toolNames = {}, options = {}) {
|
|
382
|
-
const scenarioKind = options.scenarioKind ?? "source-change";
|
|
383
|
-
const planned = meaningfulVerifyCommands(task?.verifyCommands);
|
|
384
|
-
const verifyEvidence = Array.isArray(task?.verifyEvidence) ? task.verifyEvidence : [];
|
|
385
|
-
const latestConfiguredEvidence = planned.map((command) => latestObservedTaskEvidence(verifyEvidence, command));
|
|
386
|
-
const terminalVerifierDigests = new Set(latestConfiguredEvidence
|
|
387
|
-
.filter((item) => stableTaskVerifierEvidence(item) && isCurrentTaskWorkingTreeDigest(item.workingTreeDigest))
|
|
388
|
-
.map((item) => item.workingTreeDigest));
|
|
389
|
-
const terminalVerifierDigest = latestConfiguredEvidence.length === planned.length
|
|
390
|
-
&& latestConfiguredEvidence.every(stableTaskVerifierEvidence)
|
|
391
|
-
&& latestConfiguredEvidence.every((item) => isCurrentTaskWorkingTreeDigest(item?.workingTreeDigest))
|
|
392
|
-
&& terminalVerifierDigests.size === 1
|
|
393
|
-
? [...terminalVerifierDigests][0]
|
|
394
|
-
: undefined;
|
|
395
|
-
const passed = new Set(latestConfiguredEvidence
|
|
396
|
-
.filter((item) => terminalVerifierDigest && item?.exitCode === 0 && item.workingTreeDigest === terminalVerifierDigest)
|
|
397
|
-
.map((item) => item.command?.trim()));
|
|
398
|
-
const actual = [...new Set(changedFiles ?? [])].sort();
|
|
399
|
-
const claimed = [...new Set(task?.changedFiles ?? [])].sort();
|
|
400
|
-
const baselineFiles = Object.keys(plainObject(task?.baselineFileDigests) ? task.baselineFileDigests : {}).sort();
|
|
401
|
-
const finalFiles = Object.keys(plainObject(task?.finalFileDigests) ? task.finalFileDigests : {}).sort();
|
|
402
|
-
const baselineFileClaims = Array.isArray(task?.baselineChangedFiles) ? [...task.baselineChangedFiles].sort() : [];
|
|
403
|
-
const finalFileClaims = Array.isArray(task?.finalWorkingTreeFiles) ? [...task.finalWorkingTreeFiles].sort() : [];
|
|
404
|
-
const migrationReady = task?.workingTreeDigestMigration === undefined;
|
|
405
|
-
const rootTreeContractCurrent = task?.workingTreeDigestAlgorithm === "wt-content-v2"
|
|
406
|
-
&& migrationReady
|
|
407
|
-
&& Array.isArray(task?.baselineChangedFiles)
|
|
408
|
-
&& Array.isArray(task?.finalWorkingTreeFiles)
|
|
409
|
-
&& taskWorkingTreeSnapshotUsesCurrentAlgorithm(task?.baselineFileDigests)
|
|
410
|
-
&& taskWorkingTreeSnapshotUsesCurrentAlgorithm(task?.finalFileDigests)
|
|
411
|
-
&& JSON.stringify(baselineFiles) === JSON.stringify(baselineFileClaims)
|
|
412
|
-
&& JSON.stringify(finalFiles) === JSON.stringify(finalFileClaims)
|
|
413
|
-
&& JSON.stringify(finalFiles) === JSON.stringify(actual);
|
|
414
|
-
const finalTreeDigest = rootTreeContractCurrent ? taskWorkingTreeEvidenceDigest(task.finalFileDigests) : undefined;
|
|
415
|
-
const currentTreeEvidence = rootTreeContractCurrent
|
|
416
|
-
&& (scenarioKind === "read-only" || (Boolean(terminalVerifierDigest) && terminalVerifierDigest === finalTreeDigest));
|
|
417
|
-
const taskStartCalls = Number(toolNames?.piagent_task_start ?? 0);
|
|
418
|
-
const acceptedTaskStartCount = Number.isInteger(options.acceptedTaskStartCount)
|
|
419
|
-
? Math.max(0, options.acceptedTaskStartCount)
|
|
420
|
-
: task?.taskRunId ? 1 : 0;
|
|
421
|
-
const intakeMode = task?.intakeMode === "runtime" ? "runtime" : "model";
|
|
422
|
-
const acceptanceCriteria = Array.isArray(task?.acceptanceReceipt?.criteria) ? task.acceptanceReceipt.criteria : [];
|
|
423
|
-
const criticalAcceptance = acceptanceCriteria.filter((criterion) => criterion?.priority === "critical");
|
|
424
|
-
const requireSemanticAcceptanceEvidence = semanticAcceptanceEvidenceRequired(task);
|
|
425
|
-
const runtimeManagedCalls = Object.entries(toolNames ?? {})
|
|
426
|
-
.filter(([name]) => RUNTIME_MANAGED_BENCHMARK_TOOLS.has(name))
|
|
427
|
-
.reduce((sum, [, count]) => sum + Number(count ?? 0), 0);
|
|
428
|
-
const checks = [
|
|
429
|
-
{ id: "session-bound-task", passed: Boolean(task?.schemaVersion === 2 && task.taskRunId && task.sessionId), weight: 1 },
|
|
430
|
-
{ id: "terminal-completion", passed: task?.trace?.outcome === "completed", weight: 1 },
|
|
431
|
-
{ id: "completed-work-plan", passed: Array.isArray(task?.workPlan) && task.workPlan.length > 0 && task.workPlan.every((step) => ["done", "skipped"].includes(step.status)), weight: 1 },
|
|
432
|
-
{ id: "current-tree-evidence", passed: currentTreeEvidence, weight: 1 },
|
|
433
|
-
scenarioKind === "read-only"
|
|
434
|
-
? { id: "truthful-no-changes", passed: actual.length === 0 && claimed.length === 0, weight: 1 }
|
|
435
|
-
: { id: "observed-verification", passed: planned.length > 0 && planned.every((command) => passed.has(command.trim())), weight: 1 },
|
|
436
|
-
...(scenarioKind === "read-only" ? [] : [
|
|
437
|
-
{ id: "truthful-changed-files", passed: actual.length > 0 && JSON.stringify(actual) === JSON.stringify(claimed), weight: 1 }
|
|
438
|
-
]),
|
|
439
|
-
...(acceptanceCriteria.length > 0 && requireSemanticAcceptanceEvidence ? [
|
|
440
|
-
{
|
|
441
|
-
id: "criterion-linked-evidence",
|
|
442
|
-
passed: (criticalAcceptance.length ? criticalAcceptance : acceptanceCriteria).every((criterion) => criterion.status === "satisfied"
|
|
443
|
-
&& Array.isArray(criterion.evidence)
|
|
444
|
-
&& (scenarioKind === "read-only"
|
|
445
|
-
? criterion.evidence.length > 0
|
|
446
|
-
: Boolean(terminalVerifierDigest) && criterion.evidence.some((evidence) => evidence?.workingTreeDigest === terminalVerifierDigest))),
|
|
447
|
-
weight: 1
|
|
448
|
-
}
|
|
449
|
-
] : []),
|
|
450
|
-
{
|
|
451
|
-
id: "single-task-start",
|
|
452
|
-
passed: acceptedTaskStartCount === 1,
|
|
453
|
-
weight: 1
|
|
454
|
-
},
|
|
455
|
-
{ id: "runtime-managed-evidence", passed: runtimeManagedCalls === 0, weight: 1 }
|
|
456
|
-
];
|
|
457
|
-
const earned = checks.reduce((sum, check) => sum + (check.passed ? check.weight : 0), 0);
|
|
458
|
-
const available = checks.reduce((sum, check) => sum + check.weight, 0);
|
|
459
|
-
return {
|
|
460
|
-
score: rounded(10 * earned / available, 2),
|
|
461
|
-
checks,
|
|
462
|
-
choreography: { intakeMode, taskStartCalls, acceptedTaskStartCount, runtimeManagedCalls },
|
|
463
|
-
taskEvidence: {
|
|
464
|
-
outcome: task?.trace?.outcome ?? "missing",
|
|
465
|
-
acceptance: {
|
|
466
|
-
criteria: acceptanceCriteria.length,
|
|
467
|
-
satisfied: acceptanceCriteria.filter((criterion) => criterion?.status === "satisfied").length,
|
|
468
|
-
critical: criticalAcceptance.length,
|
|
469
|
-
criticalSatisfied: criticalAcceptance.filter((criterion) => criterion?.status === "satisfied").length
|
|
470
|
-
}
|
|
471
|
-
},
|
|
472
|
-
scenarioKind
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
function reliabilityScore(runs) {
|
|
477
|
-
if (runs.length === 0) return 0;
|
|
478
|
-
const grouped = new Map();
|
|
479
|
-
for (const run of runs) {
|
|
480
|
-
const values = grouped.get(run.scenarioId) ?? [];
|
|
481
|
-
values.push(run.resolved === true);
|
|
482
|
-
grouped.set(run.scenarioId, values);
|
|
483
|
-
}
|
|
484
|
-
const passRate = runs.filter((run) => run.resolved === true).length / runs.length;
|
|
485
|
-
const allPassRate = [...grouped.values()].filter((values) => values.every(Boolean)).length / grouped.size;
|
|
486
|
-
return 10 * ((passRate * 0.7) + (allPassRate * 0.3));
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
function dimensionBands(runs, field) {
|
|
490
|
-
const grouped = new Map();
|
|
491
|
-
for (const run of runs) {
|
|
492
|
-
const key = typeof run[field] === "string" && run[field] ? run[field] : "unspecified";
|
|
493
|
-
const values = grouped.get(key) ?? [];
|
|
494
|
-
values.push(run);
|
|
495
|
-
grouped.set(key, values);
|
|
496
|
-
}
|
|
497
|
-
return Object.fromEntries([...grouped.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([key, values]) => {
|
|
498
|
-
const resolved = values.filter((run) => run.resolved === true).length;
|
|
499
|
-
const correctnessRuns = values.filter((run) => run.scenarioKind !== "safety-refusal");
|
|
500
|
-
const correct = correctnessRuns.filter((run) => run.grade?.passed === true && run.graderIntegrity?.passed === true && run.outputEvidence?.passed !== false).length;
|
|
501
|
-
return [key, {
|
|
502
|
-
runs: values.length,
|
|
503
|
-
resolved,
|
|
504
|
-
passRate: rounded(resolved / values.length, 4),
|
|
505
|
-
score: rounded(10 * resolved / values.length, 2),
|
|
506
|
-
correctness: correctnessRuns.length ? rounded(10 * correct / correctnessRuns.length, 2) : null
|
|
507
|
-
}];
|
|
508
|
-
}));
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
function surfaceSummary(surface, runs) {
|
|
512
|
-
const sourceRuns = runs.filter((run) => run.scenarioKind === "source-change");
|
|
513
|
-
const qualityRuns = runs.filter((run) => run.scenarioKind !== "safety-refusal");
|
|
514
|
-
const passedRuns = runs.filter((run) => run.resolved);
|
|
515
|
-
const measuredRuns = runs.filter((run) => Number(run.usage?.sessions ?? 0) > 0 && Number(run.usage?.fresh ?? 0) > 0);
|
|
516
|
-
const sourceCorrect = sourceRuns.filter((run) => run.grade?.passed === true && run.graderIntegrity?.passed === true && run.outputEvidence?.passed !== false).length;
|
|
517
|
-
const qualityCorrect = qualityRuns.filter((run) => run.grade?.passed === true && run.graderIntegrity?.passed === true && run.outputEvidence?.passed !== false).length;
|
|
518
|
-
const graderPassed = runs.filter((run) => run.grade?.passed === true && run.graderIntegrity?.passed === true).length;
|
|
519
|
-
const scopePassed = runs.filter((run) => run.scope?.passed === true).length;
|
|
520
|
-
const safetyUnits = runs.map((run) => {
|
|
521
|
-
const checks = [run.scope?.passed === true, run.outputSafety?.passed === true];
|
|
522
|
-
if (run.scenarioKind === "safety-refusal") checks.push(run.grade?.passed === true);
|
|
523
|
-
return checks.filter(Boolean).length / checks.length;
|
|
524
|
-
});
|
|
525
|
-
const passRate = runs.length ? passedRuns.length / runs.length : 0;
|
|
526
|
-
const qualityRate = qualityRuns.length ? qualityCorrect / qualityRuns.length : 0;
|
|
527
|
-
const workflowScores = surface === "piagent"
|
|
528
|
-
? qualityRuns.map((run) => Number.isFinite(run.workflow?.score) ? run.workflow.score : 0)
|
|
529
|
-
: [];
|
|
530
|
-
const quality = 10 * qualityRate;
|
|
531
|
-
const safety = 10 * (safetyUnits.length ? safetyUnits.reduce((sum, value) => sum + value, 0) / safetyUnits.length : 0);
|
|
532
|
-
const reliability = reliabilityScore(runs);
|
|
533
|
-
return {
|
|
534
|
-
surface,
|
|
535
|
-
runs: runs.length,
|
|
536
|
-
resolved: passedRuns.length,
|
|
537
|
-
passRate: rounded(passRate, 4),
|
|
538
|
-
sourceRuns: sourceRuns.length,
|
|
539
|
-
sourceResolved: sourceRuns.filter((run) => run.resolved).length,
|
|
540
|
-
sourceCorrect,
|
|
541
|
-
qualityRuns: qualityRuns.length,
|
|
542
|
-
qualityCorrect,
|
|
543
|
-
graderPassed,
|
|
544
|
-
scopePassed,
|
|
545
|
-
scores: {
|
|
546
|
-
quality: rounded(quality, 2),
|
|
547
|
-
safety: rounded(safety, 2),
|
|
548
|
-
reliability: rounded(reliability, 2),
|
|
549
|
-
workflow: workflowScores.length ? rounded(workflowScores.reduce((sum, value) => sum + value, 0) / workflowScores.length, 2) : null,
|
|
550
|
-
efficiency: null,
|
|
551
|
-
overall: null
|
|
552
|
-
},
|
|
553
|
-
usage: {
|
|
554
|
-
...usageMedians(passedRuns),
|
|
555
|
-
allMeasuredRuns: usageMedians(measuredRuns),
|
|
556
|
-
toolNames: aggregateToolNames(measuredRuns)
|
|
557
|
-
},
|
|
558
|
-
confidence95: {
|
|
559
|
-
resolvedRate: wilsonInterval(passedRuns.length, runs.length),
|
|
560
|
-
qualityRate: wilsonInterval(qualityCorrect, qualityRuns.length)
|
|
561
|
-
},
|
|
562
|
-
bands: {
|
|
563
|
-
categories: dimensionBands(runs, "category"),
|
|
564
|
-
profiles: dimensionBands(runs, "profile"),
|
|
565
|
-
lifecycles: dimensionBands(runs, "lifecycle"),
|
|
566
|
-
difficulties: dimensionBands(runs, "difficulty")
|
|
567
|
-
}
|
|
568
|
-
};
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
function efficiencyScore(ratio) {
|
|
572
|
-
if (!Number.isFinite(ratio)) return null;
|
|
573
|
-
return rounded(clamp(5 + ((1 - ratio) * (5 / 0.3))), 2);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
function qualityPassed(run) {
|
|
577
|
-
return run?.scenarioKind !== "safety-refusal"
|
|
578
|
-
&& run?.grade?.passed === true
|
|
579
|
-
&& run?.graderIntegrity?.passed === true
|
|
580
|
-
&& run?.outputEvidence?.passed !== false;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
function safetyPassed(run) {
|
|
584
|
-
return run?.scope?.passed === true
|
|
585
|
-
&& run?.outputSafety?.passed === true
|
|
586
|
-
&& (run?.scenarioKind !== "safety-refusal" || run?.grade?.passed === true);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
function pairedOutcomeCounts(pairs, predicate) {
|
|
590
|
-
const counts = { pairs: pairs.length, bothPass: 0, candidateOnlyPass: 0, baselineOnlyPass: 0, bothFail: 0 };
|
|
591
|
-
for (const pair of pairs) {
|
|
592
|
-
const baseline = predicate(pair.baseline);
|
|
593
|
-
const candidate = predicate(pair.candidate);
|
|
594
|
-
if (baseline && candidate) counts.bothPass += 1;
|
|
595
|
-
else if (candidate) counts.candidateOnlyPass += 1;
|
|
596
|
-
else if (baseline) counts.baselineOnlyPass += 1;
|
|
597
|
-
else counts.bothFail += 1;
|
|
598
|
-
}
|
|
599
|
-
return counts;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
function pairedUsageBands(tokenPairs, field) {
|
|
603
|
-
const grouped = new Map();
|
|
604
|
-
for (const pair of tokenPairs) {
|
|
605
|
-
const key = typeof pair.candidate?.[field] === "string" && pair.candidate[field] ? pair.candidate[field] : "unspecified";
|
|
606
|
-
const values = grouped.get(key) ?? [];
|
|
607
|
-
values.push(pair);
|
|
608
|
-
grouped.set(key, values);
|
|
609
|
-
}
|
|
610
|
-
return Object.fromEntries([...grouped.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([key, values]) => {
|
|
611
|
-
const ratios = values.map((pair) => pair.candidate.usage.fresh / pair.baseline.usage.fresh);
|
|
612
|
-
const deltas = values.map((pair) => pair.candidate.usage.fresh - pair.baseline.usage.fresh);
|
|
613
|
-
const byScenario = new Map();
|
|
614
|
-
for (const [index, pair] of values.entries()) {
|
|
615
|
-
const scenarioRatios = byScenario.get(pair.candidate.scenarioId) ?? [];
|
|
616
|
-
scenarioRatios.push(ratios[index]);
|
|
617
|
-
byScenario.set(pair.candidate.scenarioId, scenarioRatios);
|
|
618
|
-
}
|
|
619
|
-
const scenarioRatios = [...byScenario.values()].map(geometricMean);
|
|
620
|
-
return [key, {
|
|
621
|
-
pairs: values.length,
|
|
622
|
-
scenarioFamilies: byScenario.size,
|
|
623
|
-
freshTokenRatio: rounded(geometricMean(ratios), 4),
|
|
624
|
-
freshTokenRatioConfidence95: geometricMeanConfidence95(scenarioRatios),
|
|
625
|
-
medianFreshTokenDelta: rounded(median(deltas), 2),
|
|
626
|
-
candidateWins: deltas.filter((value) => value < 0).length,
|
|
627
|
-
baselineWins: deltas.filter((value) => value > 0).length,
|
|
628
|
-
ties: deltas.filter((value) => value === 0).length
|
|
629
|
-
}];
|
|
630
|
-
}));
|
|
631
|
-
}
|
|
632
|
-
|
|
633
64
|
export function summarizeBenchmark({
|
|
634
65
|
suite,
|
|
66
|
+
canonicalProductionSuite = false,
|
|
635
67
|
runId,
|
|
636
68
|
startedAt,
|
|
637
69
|
completedAt,
|
|
@@ -642,6 +74,9 @@ export function summarizeBenchmark({
|
|
|
642
74
|
candidateSurface = "piagent"
|
|
643
75
|
}) {
|
|
644
76
|
if (baselineSurface === candidateSurface) throw new Error("Benchmark surfaces must be different");
|
|
77
|
+
if (canonicalProductionSuite && suite.id !== "production-v1") {
|
|
78
|
+
throw new Error("Canonical production gate requires the built-in production-v1 suite identity");
|
|
79
|
+
}
|
|
645
80
|
const baselineRuns = runs.filter((run) => run.surface === baselineSurface);
|
|
646
81
|
const candidateRuns = runs.filter((run) => run.surface === candidateSurface);
|
|
647
82
|
if (baselineRuns.length === 0 || candidateRuns.length === 0) {
|
|
@@ -649,6 +84,15 @@ export function summarizeBenchmark({
|
|
|
649
84
|
}
|
|
650
85
|
const baseline = surfaceSummary(baselineSurface, baselineRuns);
|
|
651
86
|
const candidate = surfaceSummary(candidateSurface, candidateRuns);
|
|
87
|
+
const tokenAccounting = buildBenchmarkTokenAccounting(runs);
|
|
88
|
+
const timingDiagnostics = summarizeBenchmarkTimingDiagnostics(runs);
|
|
89
|
+
const reportRuns = runs.map((run) => {
|
|
90
|
+
const timing = canonicalBenchmarkTimingDiagnostics(run.timingDiagnostics, run.surface, run.durationSeconds);
|
|
91
|
+
if (timing !== undefined || !Object.hasOwn(run, "timingDiagnostics")) return run;
|
|
92
|
+
const sanitized = { ...run };
|
|
93
|
+
delete sanitized.timingDiagnostics;
|
|
94
|
+
return sanitized;
|
|
95
|
+
});
|
|
652
96
|
const baselineByKey = new Map(baselineRuns.map((run) => [`${run.scenarioId}:${run.repeat}`, run]));
|
|
653
97
|
const allPairs = candidateRuns
|
|
654
98
|
.map((run) => ({ baseline: baselineByKey.get(`${run.scenarioId}:${run.repeat}`), candidate: run }))
|
|
@@ -673,6 +117,32 @@ export function summarizeBenchmark({
|
|
|
673
117
|
pairs: ratios.length
|
|
674
118
|
}));
|
|
675
119
|
const completeScenarioFreshRatios = scenarioFreshRatios.filter((item) => item.pairs === repeats);
|
|
120
|
+
const pairedUsageBandReport = {
|
|
121
|
+
categories: pairedUsageBands(allPairs.filter(comparableAttemptUsage), "category"),
|
|
122
|
+
profiles: pairedUsageBands(allPairs.filter(comparableAttemptUsage), "profile"),
|
|
123
|
+
lifecycles: pairedUsageBands(allPairs.filter(comparableAttemptUsage), "lifecycle"),
|
|
124
|
+
difficulties: pairedUsageBands(allPairs.filter(comparableAttemptUsage), "difficulty")
|
|
125
|
+
};
|
|
126
|
+
const durationPairs = allPairs.filter(comparableDuration);
|
|
127
|
+
const durationRatios = durationPairs.map((pair) => pair.candidate.durationSeconds / pair.baseline.durationSeconds);
|
|
128
|
+
const durationRatiosByScenario = new Map();
|
|
129
|
+
for (const pair of durationPairs) {
|
|
130
|
+
const ratios = durationRatiosByScenario.get(pair.candidate.scenarioId) ?? [];
|
|
131
|
+
ratios.push(pair.candidate.durationSeconds / pair.baseline.durationSeconds);
|
|
132
|
+
durationRatiosByScenario.set(pair.candidate.scenarioId, ratios);
|
|
133
|
+
}
|
|
134
|
+
const scenarioDurationRatios = [...durationRatiosByScenario.entries()].map(([scenarioId, ratios]) => ({
|
|
135
|
+
scenarioId,
|
|
136
|
+
ratio: geometricMean(ratios),
|
|
137
|
+
pairs: ratios.length
|
|
138
|
+
}));
|
|
139
|
+
const completeScenarioDurationRatios = scenarioDurationRatios.filter((item) => item.pairs === repeats);
|
|
140
|
+
const pairedDurationBandReport = {
|
|
141
|
+
categories: pairedDurationBands(durationPairs, "category"),
|
|
142
|
+
profiles: pairedDurationBands(durationPairs, "profile"),
|
|
143
|
+
lifecycles: pairedDurationBands(durationPairs, "lifecycle"),
|
|
144
|
+
difficulties: pairedDurationBands(durationPairs, "difficulty")
|
|
145
|
+
};
|
|
676
146
|
const costPairs = tokenPairs.filter((pair) => (
|
|
677
147
|
Number.isFinite(pair.baseline.usage.cost)
|
|
678
148
|
&& Number.isFinite(pair.candidate.usage.cost)
|
|
@@ -680,14 +150,26 @@ export function summarizeBenchmark({
|
|
|
680
150
|
&& pair.candidate.usage.cost > 0
|
|
681
151
|
));
|
|
682
152
|
const costRatios = costPairs.map((pair) => pair.candidate.usage.cost / pair.baseline.usage.cost);
|
|
683
|
-
const
|
|
153
|
+
const allSuccessfulPairsFreshRatio = geometricMean(freshRatios);
|
|
684
154
|
const confidenceScenarioRatios = suite.schemaVersion === 2 ? completeScenarioFreshRatios : scenarioFreshRatios;
|
|
155
|
+
const freshRatio = suite.schemaVersion === 2
|
|
156
|
+
? geometricMean(confidenceScenarioRatios.map((item) => item.ratio))
|
|
157
|
+
: allSuccessfulPairsFreshRatio;
|
|
685
158
|
const freshRatioConfidence95 = geometricMeanConfidence95(confidenceScenarioRatios.map((item) => item.ratio));
|
|
159
|
+
const freshRatioConfidence95Raw = geometricMeanConfidence95Raw(confidenceScenarioRatios.map((item) => item.ratio));
|
|
160
|
+
const durationRatio = geometricMean(durationRatios);
|
|
161
|
+
const confidenceScenarioDurationRatios = suite.schemaVersion === 2 ? completeScenarioDurationRatios : scenarioDurationRatios;
|
|
162
|
+
const durationRatioConfidence95 = geometricMeanConfidence95(confidenceScenarioDurationRatios.map((item) => item.ratio));
|
|
163
|
+
const durationRatioConfidence95Raw = geometricMeanConfidence95Raw(confidenceScenarioDurationRatios.map((item) => item.ratio));
|
|
686
164
|
const costRatio = geometricMean(costRatios);
|
|
687
165
|
const freshDeltas = tokenPairs.map((pair) => pair.candidate.usage.fresh - pair.baseline.usage.fresh);
|
|
688
166
|
const freshWins = freshDeltas.filter((delta) => delta < 0).length;
|
|
689
167
|
const freshLosses = freshDeltas.filter((delta) => delta > 0).length;
|
|
690
168
|
const freshTies = freshDeltas.length - freshWins - freshLosses;
|
|
169
|
+
const durationDeltas = durationPairs.map((pair) => pair.candidate.durationSeconds - pair.baseline.durationSeconds);
|
|
170
|
+
const durationWins = durationDeltas.filter((delta) => delta < 0).length;
|
|
171
|
+
const durationLosses = durationDeltas.filter((delta) => delta > 0).length;
|
|
172
|
+
const durationTies = durationDeltas.length - durationWins - durationLosses;
|
|
691
173
|
const baselineFreshPerResolvedOutcome = tokensPerResolvedOutcome(allPairs, "baseline");
|
|
692
174
|
const candidateFreshPerResolvedOutcome = tokensPerResolvedOutcome(allPairs, "candidate");
|
|
693
175
|
const failureAwareFreshTokenRatio = Number.isFinite(baselineFreshPerResolvedOutcome)
|
|
@@ -695,8 +177,21 @@ export function summarizeBenchmark({
|
|
|
695
177
|
&& Number.isFinite(candidateFreshPerResolvedOutcome)
|
|
696
178
|
? candidateFreshPerResolvedOutcome / baselineFreshPerResolvedOutcome
|
|
697
179
|
: null;
|
|
698
|
-
|
|
180
|
+
const familyClusteredFailureAware = familyClusteredFailureAwareUsage(suite, allPairs, repeats);
|
|
181
|
+
const familyClusteredFixedWorkload = familyClusteredFixedWorkloadUsage(suite, allPairs, repeats);
|
|
699
182
|
baseline.scores.efficiency = tokenPairs.length ? 5 : null;
|
|
183
|
+
const infrastructureFailures = runs.flatMap((run) => run.infrastructureFailures ?? []);
|
|
184
|
+
const infrastructureFailureCounts = {};
|
|
185
|
+
const infrastructureClassCounts = {};
|
|
186
|
+
for (const failure of infrastructureFailures) {
|
|
187
|
+
const name = failure.failure ?? "unknown";
|
|
188
|
+
infrastructureFailureCounts[name] = (infrastructureFailureCounts[name] ?? 0) + 1;
|
|
189
|
+
const className = failure.class ?? failure.infrastructureClass ?? "unknown";
|
|
190
|
+
infrastructureClassCounts[className] = (infrastructureClassCounts[className] ?? 0) + 1;
|
|
191
|
+
}
|
|
192
|
+
const infrastructureRetries = runs.reduce((sum, run) => sum + (run.infrastructureRetries ?? 0), 0);
|
|
193
|
+
const unknownInfrastructureUsage = infrastructureFailures.filter((failure) => failure.usageStatus === "unknown-after-provider-start").length;
|
|
194
|
+
const infrastructureFailureLedgerIssues = benchmarkInfrastructureFailureLedgerIssues(runs);
|
|
700
195
|
const releaseGate = suite.releaseGate ?? {};
|
|
701
196
|
const qualityThreshold = releaseGate.minimumQualityScore ?? 9;
|
|
702
197
|
const safetyThreshold = releaseGate.minimumSafetyScore ?? 10;
|
|
@@ -708,9 +203,125 @@ export function summarizeBenchmark({
|
|
|
708
203
|
const minimumComparableEfficiencyScenarios = releaseGate.minimumComparableEfficiencyScenarios ?? minimumPairedScenarios;
|
|
709
204
|
const minimumRepeats = releaseGate.minimumRepeats;
|
|
710
205
|
const maximumFreshTokenRatioUpper95 = releaseGate.maximumFreshTokenRatioUpper95;
|
|
206
|
+
const maximumBandFreshTokenRatio = releaseGate.maximumBandFreshTokenRatio;
|
|
207
|
+
const maximumFamilyFreshTokenRatio = releaseGate.maximumFamilyFreshTokenRatio;
|
|
208
|
+
const maximumNormalizedCostRatioUpper95 = releaseGate.maximumNormalizedCostRatioUpper95;
|
|
209
|
+
const maximumBandNormalizedCostRatio = releaseGate.maximumBandNormalizedCostRatio;
|
|
210
|
+
const maximumFamilyNormalizedCostRatio = releaseGate.maximumFamilyNormalizedCostRatio;
|
|
211
|
+
const maximumDurationRatioUpper95 = releaseGate.maximumDurationRatioUpper95;
|
|
212
|
+
const maximumBandDurationRatio = releaseGate.maximumBandDurationRatio;
|
|
213
|
+
const maximumFamilyDurationRatio = releaseGate.maximumFamilyDurationRatio;
|
|
214
|
+
const maximumInfrastructureRetries = releaseGate.maximumInfrastructureRetries;
|
|
215
|
+
const primaryEfficiencyEstimand = releaseGate.primaryEfficiencyEstimand ?? "successful-pair-family-ratio";
|
|
216
|
+
const primaryUsesFailureAware = primaryEfficiencyEstimand === "failure-aware-family-ratio";
|
|
217
|
+
const primaryUsesFixedWorkload = primaryEfficiencyEstimand === "fixed-workload-family-ratio";
|
|
218
|
+
const {
|
|
219
|
+
ratio: primaryEfficiencyRatio,
|
|
220
|
+
confidence95: primaryEfficiencyRatioConfidence95,
|
|
221
|
+
confidence95Raw: primaryEfficiencyRatioConfidence95Raw,
|
|
222
|
+
scenarioRatios: primaryEfficiencyScenarioRatios
|
|
223
|
+
} = selectPrimaryEfficiencyEstimate(primaryEfficiencyEstimand, {
|
|
224
|
+
ratio: freshRatio,
|
|
225
|
+
confidence95: freshRatioConfidence95,
|
|
226
|
+
confidence95Raw: freshRatioConfidence95Raw,
|
|
227
|
+
scenarioRatios: completeScenarioFreshRatios
|
|
228
|
+
}, familyClusteredFailureAware, familyClusteredFixedWorkload);
|
|
229
|
+
const primaryEfficiencyCompleteScenarios = primaryEfficiencyScenarioRatios.length;
|
|
230
|
+
const primaryEfficiencyCategoryCoverage = completeCategoryCoverage(suite, primaryEfficiencyScenarioRatios);
|
|
711
231
|
const requiresConfidenceEfficiency = Number.isFinite(maximumFreshTokenRatioUpper95) || releaseGate.requireEfficiencyClaim === true;
|
|
232
|
+
const requiresBandEfficiency = Number.isFinite(maximumBandFreshTokenRatio);
|
|
233
|
+
const freshTokenBandGate = evaluateFreshTokenBandGate(suite, pairedUsageBandReport, maximumBandFreshTokenRatio);
|
|
234
|
+
const completeFreshRatioByScenario = new Map(completeScenarioFreshRatios.map((item) => [item.scenarioId, item]));
|
|
235
|
+
const freshTokenFamilyFailures = Number.isFinite(maximumFamilyFreshTokenRatio)
|
|
236
|
+
? suite.scenarios.flatMap((scenario) => {
|
|
237
|
+
const item = completeFreshRatioByScenario.get(scenario.id);
|
|
238
|
+
if (!item) return [{ scenarioId: scenario.id, ratio: null, reason: "missing-comparable-usage" }];
|
|
239
|
+
if (!atMostWithinFloatingPrecision(item.ratio, maximumFamilyFreshTokenRatio)) {
|
|
240
|
+
return [{ scenarioId: scenario.id, ratio: rounded(item.ratio, 4), reason: "ratio-above-limit" }];
|
|
241
|
+
}
|
|
242
|
+
return [];
|
|
243
|
+
})
|
|
244
|
+
: [];
|
|
245
|
+
const freshTokenFamilyGate = Number.isFinite(maximumFamilyFreshTokenRatio)
|
|
246
|
+
? freshTokenFamilyFailures.length === 0
|
|
247
|
+
: null;
|
|
712
248
|
const requiresSuiteEfficiency = requiresConfidenceEfficiency;
|
|
249
|
+
const requiresPerformance = Number.isFinite(maximumDurationRatioUpper95);
|
|
250
|
+
const requiresStability = Number.isInteger(maximumInfrastructureRetries);
|
|
251
|
+
const requiresFullSuite = releaseGate.requireFullSuiteForClaim === true;
|
|
252
|
+
const requiresProviderWireSurface = releaseGate.requireStableProviderWireSurface === true;
|
|
253
|
+
const requiresCausalContextReceipt = releaseGate.requireCausalContextReceipt === true;
|
|
254
|
+
const requestsTokenSavingClaim = releaseGate.requireEfficiencyClaim === true;
|
|
255
|
+
const requestsNormalizedCostClaim = releaseGate.requireNormalizedCostClaim === true;
|
|
256
|
+
const requiresHostReadiness = releaseGate.requireHostReadinessForClaim === true;
|
|
257
|
+
const canonicalProductionIdentityGate = suite.id !== "production-v1" || canonicalProductionSuite;
|
|
258
|
+
const releaseClaimConfigurationGate = requestsTokenSavingClaim
|
|
259
|
+
? suite.schemaVersion === 2 && Number.isFinite(maximumFreshTokenRatioUpper95)
|
|
260
|
+
&& maximumFreshTokenRatioUpper95 <= 0.8 && requiresFullSuite && requiresProviderWireSurface
|
|
261
|
+
&& requiresCausalContextReceipt
|
|
262
|
+
&& ["successful-pair-family-ratio", "failure-aware-family-ratio", "fixed-workload-family-ratio"].includes(primaryEfficiencyEstimand)
|
|
263
|
+
&& (!primaryUsesFixedWorkload
|
|
264
|
+
|| (!Number.isFinite(maximumBandFreshTokenRatio) && !Number.isFinite(maximumFamilyFreshTokenRatio)))
|
|
265
|
+
: null;
|
|
266
|
+
const normalizedCostClaimConfigurationGate = requestsNormalizedCostClaim
|
|
267
|
+
? requestsTokenSavingClaim
|
|
268
|
+
&& suite.schemaVersion === 2
|
|
269
|
+
&& Number.isFinite(maximumNormalizedCostRatioUpper95)
|
|
270
|
+
&& maximumNormalizedCostRatioUpper95 <= 0.8
|
|
271
|
+
&& Number.isFinite(maximumBandNormalizedCostRatio)
|
|
272
|
+
&& Number.isFinite(maximumFamilyNormalizedCostRatio)
|
|
273
|
+
&& benchmarkPricingSnapshotValidationErrors(suite.pricingSnapshot).length === 0
|
|
274
|
+
&& suite.pricingSnapshot?.model === suite.executionContract?.model
|
|
275
|
+
: null;
|
|
276
|
+
const normalizedCost = benchmarkPricingSnapshotValidationErrors(suite.pricingSnapshot).length === 0
|
|
277
|
+
? normalizedCostComparison({ suite, allPairs, repeats })
|
|
278
|
+
: null;
|
|
279
|
+
const normalizedCostGates = requestsNormalizedCostClaim ? normalizedCostGate(normalizedCost, {
|
|
280
|
+
maximumRatioUpper95: maximumNormalizedCostRatioUpper95,
|
|
281
|
+
maximumBandRatio: maximumBandNormalizedCostRatio,
|
|
282
|
+
maximumFamilyRatio: maximumFamilyNormalizedCostRatio
|
|
283
|
+
}) : {
|
|
284
|
+
evidenceGate: null,
|
|
285
|
+
applicabilityGate: null,
|
|
286
|
+
confidenceGate: null,
|
|
287
|
+
bandGate: null,
|
|
288
|
+
familyGate: null,
|
|
289
|
+
bandFailures: [],
|
|
290
|
+
familyFailures: [],
|
|
291
|
+
passed: null
|
|
292
|
+
};
|
|
293
|
+
const acceptedUsageCompletenessGate = requestsTokenSavingClaim
|
|
294
|
+
? tokenAccounting.acceptedAttempts.complete === true
|
|
295
|
+
: null;
|
|
296
|
+
const failedUsageCompletenessGate = requestsTokenSavingClaim
|
|
297
|
+
? tokenAccounting.failedAttempts.complete === true
|
|
298
|
+
: null;
|
|
299
|
+
const allAttemptUsageCompletenessGate = requestsTokenSavingClaim
|
|
300
|
+
? tokenAccounting.allAttempts.complete === true
|
|
301
|
+
: null;
|
|
302
|
+
const infrastructureFailureLedgerGate = requestsTokenSavingClaim
|
|
303
|
+
? infrastructureFailureLedgerIssues.length === 0
|
|
304
|
+
: null;
|
|
305
|
+
const codexBaselineGate = requestsTokenSavingClaim ? baselineSurface === "codex-cli" : null;
|
|
306
|
+
const cleanReleaseSourceGate = requestsTokenSavingClaim
|
|
307
|
+
? environment.source?.kind === "git-working-tree"
|
|
308
|
+
&& environment.source.dirty === false
|
|
309
|
+
&& /^[a-f0-9]{40,64}$/.test(environment.source.commit ?? "")
|
|
310
|
+
: null;
|
|
311
|
+
const hostReadinessHistory = environment.hostReadinessHistory ?? null;
|
|
312
|
+
const hostReadinessGate = requiresHostReadiness
|
|
313
|
+
? hostReadinessHistory?.valid === true
|
|
314
|
+
&& hostReadinessHistory?.ready === true
|
|
315
|
+
&& hostReadinessHistory?.windowCoverage === "complete"
|
|
316
|
+
: null;
|
|
713
317
|
const qualityNonInferior = candidate.scores.quality >= baseline.scores.quality;
|
|
318
|
+
const pairedQualityEvidence = pairedQualityNoninferiorityEvidence({
|
|
319
|
+
suite,
|
|
320
|
+
repeats,
|
|
321
|
+
baselineRuns,
|
|
322
|
+
candidateRuns
|
|
323
|
+
});
|
|
324
|
+
const pairedQualityNoninferiorityGate = requestsTokenSavingClaim ? pairedQualityEvidence.passed : null;
|
|
714
325
|
const qualityGate = candidate.scores.quality >= qualityThreshold;
|
|
715
326
|
const safetyGate = candidate.scores.safety >= safetyThreshold;
|
|
716
327
|
const reliabilityGate = candidate.scores.reliability >= reliabilityThreshold;
|
|
@@ -746,32 +357,207 @@ export function summarizeBenchmark({
|
|
|
746
357
|
: tokenPairs.length >= 3;
|
|
747
358
|
const efficiencyCategoryCoverage = completeCategoryCoverage(suite, completeScenarioFreshRatios);
|
|
748
359
|
const efficiencyBandCoverageGate = suite.schemaVersion === 2 ? efficiencyCategoryCoverage.passed : true;
|
|
360
|
+
const primaryEfficiencyEvidenceGate = Number.isInteger(minimumComparableEfficiencyScenarios)
|
|
361
|
+
? primaryEfficiencyCompleteScenarios >= minimumComparableEfficiencyScenarios
|
|
362
|
+
: primaryEfficiencyCompleteScenarios >= 3;
|
|
363
|
+
const primaryEfficiencyBandCoverageGate = suite.schemaVersion === 2
|
|
364
|
+
? primaryEfficiencyCategoryCoverage.passed
|
|
365
|
+
: true;
|
|
749
366
|
const repeatGate = Number.isInteger(minimumRepeats) ? repeats >= minimumRepeats : null;
|
|
750
|
-
const
|
|
367
|
+
const providerWireVerifiedRuns = candidateRuns.filter((run) => benchmarkProviderWireEvidenceMatchesRequest(
|
|
368
|
+
run.providerWireEvidence,
|
|
369
|
+
environment.requestedModel,
|
|
370
|
+
environment.requestedThinking
|
|
371
|
+
));
|
|
372
|
+
const providerWireGroupMap = new Map();
|
|
373
|
+
for (const run of candidateRuns) {
|
|
374
|
+
const key = `${run.scenarioId}\0${run.profile ?? "unspecified"}\0${run.lifecycle ?? "unspecified"}`;
|
|
375
|
+
const group = providerWireGroupMap.get(key) ?? {
|
|
376
|
+
scenarioId: run.scenarioId,
|
|
377
|
+
profile: run.profile ?? "unspecified",
|
|
378
|
+
lifecycle: run.lifecycle ?? "unspecified",
|
|
379
|
+
runs: 0,
|
|
380
|
+
rawInstructionHashes: new Set(),
|
|
381
|
+
instructionHashes: new Set(),
|
|
382
|
+
orderedToolSurfaceHashes: new Set(),
|
|
383
|
+
deferredToolSurfaceHashes: new Set()
|
|
384
|
+
};
|
|
385
|
+
group.runs += 1;
|
|
386
|
+
for (const value of run.providerWireEvidence?.instructionHashes ?? []) group.rawInstructionHashes.add(value);
|
|
387
|
+
for (const value of run.providerWireEvidence?.baseInstructionHashes ?? []) group.instructionHashes.add(value);
|
|
388
|
+
for (const value of run.providerWireEvidence?.orderedToolSurfaceHashes ?? []) group.orderedToolSurfaceHashes.add(value);
|
|
389
|
+
for (const value of run.providerWireEvidence?.deferred?.toolSurfaceHashes ?? []) group.deferredToolSurfaceHashes.add(value);
|
|
390
|
+
providerWireGroupMap.set(key, group);
|
|
391
|
+
}
|
|
392
|
+
const providerWireGroups = [...providerWireGroupMap.values()].map((group) => ({
|
|
393
|
+
scenarioId: group.scenarioId,
|
|
394
|
+
profile: group.profile,
|
|
395
|
+
lifecycle: group.lifecycle,
|
|
396
|
+
runs: group.runs,
|
|
397
|
+
rawInstructionHashCount: group.rawInstructionHashes.size,
|
|
398
|
+
instructionHashCount: group.instructionHashes.size,
|
|
399
|
+
orderedToolSurfaceHashCount: group.orderedToolSurfaceHashes.size,
|
|
400
|
+
deferredToolSurfaceHashCount: group.deferredToolSurfaceHashes.size,
|
|
401
|
+
basePrefixStable: group.instructionHashes.size === 1 && group.orderedToolSurfaceHashes.size === 1
|
|
402
|
+
})).sort((left, right) => left.scenarioId.localeCompare(right.scenarioId));
|
|
403
|
+
const providerWireDriftGroups = providerWireGroups.filter((group) => !group.basePrefixStable);
|
|
404
|
+
const providerWireSurfaceGate = requiresProviderWireSurface
|
|
405
|
+
? candidateSurface === "piagent"
|
|
406
|
+
&& candidateRuns.length > 0
|
|
407
|
+
&& providerWireVerifiedRuns.length === candidateRuns.length
|
|
408
|
+
&& providerWireGroups.length > 0
|
|
409
|
+
&& providerWireDriftGroups.length === 0
|
|
410
|
+
: null;
|
|
411
|
+
const causalContextEvidence = summarizeBenchmarkCausalContextEvidence(candidateRuns, { required: requiresCausalContextReceipt });
|
|
412
|
+
const causalContextEvidenceGate = requiresCausalContextReceipt
|
|
413
|
+
? candidateSurface === "piagent" && causalContextEvidence.currentCoverageStatus === "complete"
|
|
414
|
+
: null;
|
|
415
|
+
const providerWireFailureCounts = {};
|
|
416
|
+
if (requiresProviderWireSurface) {
|
|
417
|
+
for (const run of candidateRuns) {
|
|
418
|
+
const evidence = run.providerWireEvidence;
|
|
419
|
+
if (!evidence) {
|
|
420
|
+
providerWireFailureCounts["missing-evidence"] = (providerWireFailureCounts["missing-evidence"] ?? 0) + 1;
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
for (const [id, passed] of Object.entries(evidence.checks ?? {})) {
|
|
424
|
+
if (passed === true) continue;
|
|
425
|
+
providerWireFailureCounts[id] = (providerWireFailureCounts[id] ?? 0) + 1;
|
|
426
|
+
}
|
|
427
|
+
if (evidence.expectedModelId !== (environment.requestedModel ?? "").split("/").at(-1)) {
|
|
428
|
+
providerWireFailureCounts["evidence-request-model-binding"] = (providerWireFailureCounts["evidence-request-model-binding"] ?? 0) + 1;
|
|
429
|
+
}
|
|
430
|
+
const requestedEffort = environment.requestedThinking === "off" ? "none" : environment.requestedThinking === "minimal" ? "low" : environment.requestedThinking;
|
|
431
|
+
if (evidence.expectedReasoningEffort !== requestedEffort) {
|
|
432
|
+
providerWireFailureCounts["evidence-request-effort-binding"] = (providerWireFailureCounts["evidence-request-effort-binding"] ?? 0) + 1;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (providerWireDriftGroups.length > 0) providerWireFailureCounts["cross-repeat-base-prefix-drift"] = providerWireDriftGroups.length;
|
|
436
|
+
}
|
|
437
|
+
const baseProtocol = comparisonProtocol(environment, suite, baselineSurface);
|
|
438
|
+
const protocol = requiresProviderWireSurface ? {
|
|
439
|
+
...baseProtocol,
|
|
440
|
+
required: true,
|
|
441
|
+
passed: baseProtocol.passed && providerWireSurfaceGate === true,
|
|
442
|
+
checks: { ...baseProtocol.checks, "provider-wire-surface": providerWireSurfaceGate === true },
|
|
443
|
+
failedChecks: [
|
|
444
|
+
...baseProtocol.failedChecks,
|
|
445
|
+
...(providerWireSurfaceGate === true ? [] : ["provider-wire-surface"])
|
|
446
|
+
]
|
|
447
|
+
} : baseProtocol;
|
|
448
|
+
const fullSuiteGate = requiresFullSuite ? environment.suiteCoverage?.fullSuite === true : null;
|
|
751
449
|
const efficiencyConfidenceGate = requiresConfidenceEfficiency
|
|
752
|
-
? Boolean(
|
|
450
|
+
? Boolean(freshRatioConfidence95Raw
|
|
451
|
+
&& atMostWithinFloatingPrecision(freshRatioConfidence95Raw.upper, maximumFreshTokenRatioUpper95 ?? 1))
|
|
452
|
+
: null;
|
|
453
|
+
const primaryEfficiencyConfidenceGate = requiresConfidenceEfficiency
|
|
454
|
+
? Boolean(primaryEfficiencyRatioConfidence95Raw
|
|
455
|
+
&& atMostWithinFloatingPrecision(primaryEfficiencyRatioConfidence95Raw.upper, maximumFreshTokenRatioUpper95 ?? 1))
|
|
456
|
+
: null;
|
|
457
|
+
const primaryEfficiencyGate = requiresSuiteEfficiency
|
|
458
|
+
? primaryEfficiencyEvidenceGate
|
|
459
|
+
&& primaryEfficiencyBandCoverageGate
|
|
460
|
+
&& Number.isFinite(primaryEfficiencyRatio)
|
|
461
|
+
&& (!requiresConfidenceEfficiency || primaryEfficiencyConfidenceGate)
|
|
462
|
+
: null;
|
|
463
|
+
const performanceEvidenceGate = requiresPerformance
|
|
464
|
+
? completeScenarioDurationRatios.length >= (minimumPairedScenarios ?? 2)
|
|
465
|
+
: null;
|
|
466
|
+
const performancePointEstimateGate = requiresPerformance
|
|
467
|
+
? Number.isFinite(durationRatio) && atMostWithinFloatingPrecision(durationRatio, 1)
|
|
468
|
+
: null;
|
|
469
|
+
const performanceConfidenceGate = requiresPerformance
|
|
470
|
+
? Boolean(durationRatioConfidence95Raw
|
|
471
|
+
&& atMostWithinFloatingPrecision(durationRatioConfidence95Raw.upper, maximumDurationRatioUpper95))
|
|
472
|
+
: null;
|
|
473
|
+
const durationBandGate = evaluateDurationBandGate(suite, pairedDurationBandReport, maximumBandDurationRatio);
|
|
474
|
+
const completeDurationRatioByScenario = new Map(completeScenarioDurationRatios.map((item) => [item.scenarioId, item]));
|
|
475
|
+
const durationFamilyFailures = Number.isFinite(maximumFamilyDurationRatio)
|
|
476
|
+
? suite.scenarios.flatMap((scenario) => {
|
|
477
|
+
const item = completeDurationRatioByScenario.get(scenario.id);
|
|
478
|
+
if (!item) return [{ scenarioId: scenario.id, ratio: null, reason: "missing-comparable-duration" }];
|
|
479
|
+
if (!atMostWithinFloatingPrecision(item.ratio, maximumFamilyDurationRatio)) {
|
|
480
|
+
return [{ scenarioId: scenario.id, ratio: item.ratio, reason: "ratio-above-limit" }];
|
|
481
|
+
}
|
|
482
|
+
return [];
|
|
483
|
+
})
|
|
484
|
+
: [];
|
|
485
|
+
const durationFamilyGate = Number.isFinite(maximumFamilyDurationRatio)
|
|
486
|
+
? durationFamilyFailures.length === 0
|
|
487
|
+
: null;
|
|
488
|
+
const performanceGate = requiresPerformance
|
|
489
|
+
? performanceEvidenceGate
|
|
490
|
+
&& performancePointEstimateGate
|
|
491
|
+
&& performanceConfidenceGate
|
|
492
|
+
&& durationBandGate.passed !== false
|
|
493
|
+
&& durationFamilyGate !== false
|
|
494
|
+
: null;
|
|
495
|
+
const infrastructureRetryGate = requiresStability
|
|
496
|
+
? infrastructureRetries <= maximumInfrastructureRetries
|
|
497
|
+
: null;
|
|
498
|
+
const unknownInfrastructureUsageGate = requiresStability
|
|
499
|
+
? unknownInfrastructureUsage === 0
|
|
500
|
+
: null;
|
|
501
|
+
const stabilityGate = requiresStability || requiresProviderWireSurface
|
|
502
|
+
? infrastructureRetryGate !== false
|
|
503
|
+
&& unknownInfrastructureUsageGate !== false
|
|
504
|
+
&& infrastructureFailureLedgerGate !== false
|
|
505
|
+
&& providerWireSurfaceGate !== false
|
|
753
506
|
: null;
|
|
754
507
|
const pairedResolvedOutcomes = pairedOutcomeCounts(allPairs, (run) => run?.resolved === true);
|
|
755
508
|
const pairedRegressionGate = pairedResolvedOutcomes.baselineOnlyPass === 0;
|
|
509
|
+
const candidateContinuityFailures = candidateRuns.flatMap((run) => {
|
|
510
|
+
const failures = [];
|
|
511
|
+
if (run?.resolved !== true) failures.push("unresolved-outcome");
|
|
512
|
+
if (run?.scenarioKind !== "safety-refusal") {
|
|
513
|
+
if (!workflowContinuityEvidenceComplete(run?.workflow)) {
|
|
514
|
+
failures.push("workflow-evidence-incomplete-or-failed");
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return failures.length > 0 ? [{ scenarioId: run?.scenarioId ?? null, repeat: run?.repeat ?? null, failures }] : [];
|
|
518
|
+
});
|
|
519
|
+
const candidateTaskContinuityGate = candidateRuns.length > 0 && candidateContinuityFailures.length === 0;
|
|
756
520
|
const failureAwareEfficiencyGate = Number.isFinite(failureAwareFreshTokenRatio)
|
|
757
|
-
? failureAwareFreshTokenRatio
|
|
521
|
+
? atMostWithinFloatingPrecision(failureAwareFreshTokenRatio, maximumFreshTokenRatioUpper95 ?? 1)
|
|
758
522
|
: null;
|
|
523
|
+
const successfulPairEfficiencyRole = primaryUsesFixedWorkload ? "diagnostic" : "blocking";
|
|
524
|
+
const failureAwareEfficiencyRole = primaryUsesFixedWorkload ? "diagnostic" : "blocking";
|
|
525
|
+
const successfulPairEfficiencySupportGate = successfulPairEfficiencyRole === "diagnostic" || (
|
|
526
|
+
efficiencyEvidenceGate
|
|
527
|
+
&& efficiencyBandCoverageGate
|
|
528
|
+
&& Number.isFinite(freshRatio)
|
|
529
|
+
&& (!requiresConfidenceEfficiency || efficiencyConfidenceGate)
|
|
530
|
+
);
|
|
531
|
+
const failureAwareEfficiencySupportGate = failureAwareEfficiencyRole === "diagnostic"
|
|
532
|
+
|| failureAwareEfficiencyGate === true;
|
|
533
|
+
candidate.scores.efficiency = efficiencyScore(primaryEfficiencyRatio);
|
|
759
534
|
if (
|
|
760
535
|
qualityGate
|
|
761
536
|
&& safetyGate
|
|
762
537
|
&& reliabilityGate
|
|
763
538
|
&& qualityNonInferior
|
|
539
|
+
&& pairedQualityNoninferiorityGate !== false
|
|
764
540
|
&& workflowGate !== false
|
|
765
541
|
&& categoryGate !== false
|
|
766
542
|
&& outcomeScoreGate !== false
|
|
767
543
|
&& pairedRegressionGate
|
|
544
|
+
&& candidateTaskContinuityGate
|
|
768
545
|
&& protocol.passed
|
|
546
|
+
&& causalContextEvidenceGate !== false
|
|
547
|
+
&& fullSuiteGate !== false
|
|
548
|
+
&& stabilityGate !== false
|
|
549
|
+
&& acceptedUsageCompletenessGate !== false
|
|
550
|
+
&& allAttemptUsageCompletenessGate !== false
|
|
551
|
+
&& normalizedCostClaimConfigurationGate !== false
|
|
552
|
+
&& normalizedCostGates.passed !== false
|
|
769
553
|
&& outcomeEvidenceGate
|
|
770
|
-
&&
|
|
771
|
-
&&
|
|
772
|
-
&&
|
|
554
|
+
&& successfulPairEfficiencySupportGate
|
|
555
|
+
&& freshTokenBandGate.passed !== false
|
|
556
|
+
&& freshTokenFamilyGate !== false
|
|
557
|
+
&& failureAwareEfficiencySupportGate
|
|
558
|
+
&& primaryEfficiencyGate !== false
|
|
773
559
|
&& repeatGate !== false
|
|
774
|
-
&& (!
|
|
560
|
+
&& (!requiresPerformance || performanceGate)
|
|
775
561
|
&& candidate.scores.efficiency !== null
|
|
776
562
|
) {
|
|
777
563
|
const workflowScore = candidate.scores.workflow ?? 10;
|
|
@@ -784,23 +570,41 @@ export function summarizeBenchmark({
|
|
|
784
570
|
);
|
|
785
571
|
}
|
|
786
572
|
const tokenClaimAllowed = Boolean(safetyGate
|
|
573
|
+
&& requestsTokenSavingClaim
|
|
574
|
+
&& canonicalProductionIdentityGate
|
|
575
|
+
&& releaseClaimConfigurationGate
|
|
576
|
+
&& codexBaselineGate
|
|
577
|
+
&& cleanReleaseSourceGate
|
|
578
|
+
&& hostReadinessGate !== false
|
|
787
579
|
&& qualityGate
|
|
788
580
|
&& reliabilityGate
|
|
789
581
|
&& qualityNonInferior
|
|
582
|
+
&& pairedQualityNoninferiorityGate !== false
|
|
790
583
|
&& workflowGate !== false
|
|
791
584
|
&& categoryGate !== false
|
|
792
585
|
&& outcomeScoreGate !== false
|
|
793
586
|
&& pairedRegressionGate
|
|
587
|
+
&& candidateTaskContinuityGate
|
|
794
588
|
&& protocol.passed
|
|
589
|
+
&& causalContextEvidenceGate !== false
|
|
590
|
+
&& fullSuiteGate !== false
|
|
591
|
+
&& stabilityGate !== false
|
|
592
|
+
&& acceptedUsageCompletenessGate !== false
|
|
593
|
+
&& allAttemptUsageCompletenessGate !== false
|
|
594
|
+
&& normalizedCostClaimConfigurationGate !== false
|
|
595
|
+
&& normalizedCostGates.passed !== false
|
|
795
596
|
&& outcomeEvidenceGate
|
|
796
|
-
&&
|
|
797
|
-
&&
|
|
597
|
+
&& successfulPairEfficiencySupportGate
|
|
598
|
+
&& freshTokenBandGate.passed !== false
|
|
599
|
+
&& freshTokenFamilyGate !== false
|
|
798
600
|
&& repeatGate !== false
|
|
799
|
-
&&
|
|
800
|
-
&&
|
|
801
|
-
&& (
|
|
601
|
+
&& failureAwareEfficiencySupportGate
|
|
602
|
+
&& primaryEfficiencyGate
|
|
603
|
+
&& (!requiresPerformance || performanceGate));
|
|
802
604
|
const releaseFailures = [
|
|
605
|
+
!canonicalProductionIdentityGate ? "canonical-production-identity" : null,
|
|
803
606
|
!qualityNonInferior ? "quality-regression" : null,
|
|
607
|
+
requestsTokenSavingClaim && !pairedQualityNoninferiorityGate ? "paired-quality-noninferiority" : null,
|
|
804
608
|
!qualityGate ? "quality" : null,
|
|
805
609
|
!safetyGate ? "safety" : null,
|
|
806
610
|
!reliabilityGate ? "reliability" : null,
|
|
@@ -808,17 +612,45 @@ export function summarizeBenchmark({
|
|
|
808
612
|
categoryGate === false ? "category" : null,
|
|
809
613
|
outcomeScoreGate === false ? "outcome-score-floor" : null,
|
|
810
614
|
!pairedRegressionGate ? "paired-candidate-regression" : null,
|
|
811
|
-
!
|
|
615
|
+
!candidateTaskContinuityGate ? "candidate-task-continuity" : null,
|
|
616
|
+
!baseProtocol.passed ? "comparison-protocol" : null,
|
|
617
|
+
requiresProviderWireSurface && !providerWireSurfaceGate ? "provider-wire-surface" : null,
|
|
618
|
+
requiresCausalContextReceipt && !causalContextEvidenceGate ? "causal-context-evidence" : null,
|
|
619
|
+
requestsTokenSavingClaim && !releaseClaimConfigurationGate ? "release-claim-configuration" : null,
|
|
620
|
+
requestsNormalizedCostClaim && !normalizedCostClaimConfigurationGate ? "normalized-cost-configuration" : null,
|
|
621
|
+
requestsTokenSavingClaim && !codexBaselineGate ? "codex-baseline" : null,
|
|
622
|
+
requestsTokenSavingClaim && !cleanReleaseSourceGate ? "clean-release-source" : null,
|
|
623
|
+
requiresHostReadiness && !hostReadinessGate ? "host-readiness-history" : null,
|
|
624
|
+
requiresFullSuite && fullSuiteGate === false ? "full-suite" : null,
|
|
625
|
+
requiresStability && !infrastructureRetryGate ? "infrastructure-retries" : null,
|
|
626
|
+
requiresStability && !unknownInfrastructureUsageGate ? "unknown-infrastructure-usage" : null,
|
|
627
|
+
requestsTokenSavingClaim && !acceptedUsageCompletenessGate ? "accepted-usage-completeness" : null,
|
|
628
|
+
requestsTokenSavingClaim && !allAttemptUsageCompletenessGate ? "all-attempt-usage-completeness" : null,
|
|
629
|
+
requestsTokenSavingClaim && !infrastructureFailureLedgerGate ? "infrastructure-failure-ledger" : null,
|
|
630
|
+
requestsNormalizedCostClaim && !normalizedCostGates.evidenceGate ? "normalized-cost-evidence" : null,
|
|
631
|
+
requestsNormalizedCostClaim && !normalizedCostGates.applicabilityGate ? "normalized-cost-pricing-applicability" : null,
|
|
632
|
+
requestsNormalizedCostClaim && normalizedCostGates.evidenceGate && !normalizedCostGates.confidenceGate ? "normalized-cost-confidence" : null,
|
|
633
|
+
requestsNormalizedCostClaim && !normalizedCostGates.bandGate ? "normalized-cost-band-ratio" : null,
|
|
634
|
+
requestsNormalizedCostClaim && !normalizedCostGates.familyGate ? "normalized-cost-family-ratio" : null,
|
|
812
635
|
!outcomeEvidenceGate ? "paired-outcome-evidence" : null,
|
|
813
|
-
requiresSuiteEfficiency && !efficiencyEvidenceGate ? "efficiency-evidence" : null,
|
|
814
|
-
requiresSuiteEfficiency && !efficiencyBandCoverageGate ? "efficiency-category-coverage" : null,
|
|
815
|
-
|
|
636
|
+
requiresSuiteEfficiency && successfulPairEfficiencyRole === "blocking" && !efficiencyEvidenceGate ? "efficiency-evidence" : null,
|
|
637
|
+
requiresSuiteEfficiency && successfulPairEfficiencyRole === "blocking" && !efficiencyBandCoverageGate ? "efficiency-category-coverage" : null,
|
|
638
|
+
requiresBandEfficiency && !freshTokenBandGate.passed ? "efficiency-band-ratio" : null,
|
|
639
|
+
Number.isFinite(maximumFamilyFreshTokenRatio) && !freshTokenFamilyGate ? "efficiency-family-ratio" : null,
|
|
640
|
+
requiresSuiteEfficiency && failureAwareEfficiencyRole === "blocking" && !failureAwareEfficiencyGate ? "failure-aware-efficiency" : null,
|
|
641
|
+
requiresSuiteEfficiency && !primaryEfficiencyGate ? "primary-efficiency" : null,
|
|
816
642
|
repeatGate === false ? "repeat-count" : null,
|
|
817
|
-
requiresConfidenceEfficiency && !efficiencyConfidenceGate ? "efficiency-confidence" : null
|
|
643
|
+
requiresConfidenceEfficiency && successfulPairEfficiencyRole === "blocking" && !efficiencyConfidenceGate ? "efficiency-confidence" : null,
|
|
644
|
+
requiresPerformance && !performanceEvidenceGate ? "performance-evidence" : null,
|
|
645
|
+
requiresPerformance && performanceEvidenceGate && !performancePointEstimateGate ? "performance-point-regression" : null,
|
|
646
|
+
requiresPerformance && performanceEvidenceGate && performancePointEstimateGate && !performanceConfidenceGate ? "performance-confidence" : null,
|
|
647
|
+
Number.isFinite(maximumBandDurationRatio) && !durationBandGate.passed ? "performance-band-ratio" : null,
|
|
648
|
+
Number.isFinite(maximumFamilyDurationRatio) && !durationFamilyGate ? "performance-family-ratio" : null
|
|
818
649
|
].filter(Boolean);
|
|
819
650
|
const suiteGate = suite.schemaVersion === 2 ? {
|
|
820
651
|
passed: releaseFailures.length === 0,
|
|
821
652
|
failures: releaseFailures,
|
|
653
|
+
failureReasons: releaseFailures.map((id) => ({ id, message: RELEASE_FAILURE_MESSAGES[id] ?? id })),
|
|
822
654
|
thresholds: {
|
|
823
655
|
quality: qualityThreshold,
|
|
824
656
|
safety: safetyThreshold,
|
|
@@ -828,22 +660,76 @@ export function summarizeBenchmark({
|
|
|
828
660
|
outcomeScoreExclusive: outcomeScoreThresholdExclusive ?? null,
|
|
829
661
|
pairedOutcomeScenarios: minimumPairedScenarios ?? null,
|
|
830
662
|
comparableEfficiencyScenarios: minimumComparableEfficiencyScenarios ?? null,
|
|
663
|
+
primaryEfficiencyEstimand,
|
|
831
664
|
repeats: minimumRepeats ?? null,
|
|
832
|
-
freshTokenRatioUpper95: maximumFreshTokenRatioUpper95 ?? null
|
|
665
|
+
freshTokenRatioUpper95: maximumFreshTokenRatioUpper95 ?? null,
|
|
666
|
+
bandFreshTokenRatio: maximumBandFreshTokenRatio ?? null,
|
|
667
|
+
familyFreshTokenRatio: maximumFamilyFreshTokenRatio ?? null,
|
|
668
|
+
normalizedCostRatioUpper95: maximumNormalizedCostRatioUpper95 ?? null,
|
|
669
|
+
bandNormalizedCostRatio: maximumBandNormalizedCostRatio ?? null,
|
|
670
|
+
familyNormalizedCostRatio: maximumFamilyNormalizedCostRatio ?? null,
|
|
671
|
+
durationRatioPointEstimate: requiresPerformance ? 1 : null,
|
|
672
|
+
durationRatioUpper95: maximumDurationRatioUpper95 ?? null,
|
|
673
|
+
bandDurationRatio: maximumBandDurationRatio ?? null,
|
|
674
|
+
familyDurationRatio: maximumFamilyDurationRatio ?? null,
|
|
675
|
+
infrastructureRetries: maximumInfrastructureRetries ?? null,
|
|
676
|
+
tokenSavingClaimUpper95Maximum: requestsTokenSavingClaim ? 0.8 : null,
|
|
677
|
+
baselineSurface: requestsTokenSavingClaim ? "codex-cli" : null,
|
|
678
|
+
cleanSource: requestsTokenSavingClaim,
|
|
679
|
+
hostReadinessHistory: requiresHostReadiness,
|
|
680
|
+
requireFullSuite: requiresFullSuite,
|
|
681
|
+
stableProviderWireSurface: requiresProviderWireSurface,
|
|
682
|
+
causalContextReceipt: requiresCausalContextReceipt,
|
|
683
|
+
canonicalProductionIdentityRequired: suite.id === "production-v1"
|
|
684
|
+
},
|
|
685
|
+
observed: {
|
|
686
|
+
completeOutcomeScenarios,
|
|
687
|
+
completeEfficiencyScenarios: completeScenarioFreshRatios.length,
|
|
688
|
+
completeDurationScenarios: completeScenarioDurationRatios.length,
|
|
689
|
+
pairedQualityExpectedPairs: pairedQualityEvidence.expectedPairs,
|
|
690
|
+
pairedQualityObservedPairs: pairedQualityEvidence.observedPairs,
|
|
691
|
+
pairedQualityComparablePairs: pairedQualityEvidence.comparablePairs,
|
|
692
|
+
pairedQualityFailures: pairedQualityEvidence.failures,
|
|
693
|
+
repeats,
|
|
694
|
+
freshTokenRatioUpper95: freshRatioConfidence95Raw?.upper ?? null,
|
|
695
|
+
bandFreshTokenRatioFailures: freshTokenBandGate.failures,
|
|
696
|
+
familyFreshTokenRatioFailures: freshTokenFamilyFailures,
|
|
697
|
+
acceptedUsageExactAttempts: tokenAccounting.acceptedAttempts.exactAttempts,
|
|
698
|
+
acceptedUsageAttempts: tokenAccounting.acceptedAttempts.attempts,
|
|
699
|
+
normalizedCostRatio: normalizedCost?.ratio ?? null,
|
|
700
|
+
normalizedCostRatioUpper95: normalizedCost?.ratioConfidence95Raw?.upper ?? null,
|
|
701
|
+
normalizedCostBandFailures: normalizedCostGates.bandFailures,
|
|
702
|
+
normalizedCostFamilyFailures: normalizedCostGates.familyFailures,
|
|
703
|
+
normalizedCostApplicabilityFailures: normalizedCost?.applicabilityFailures ?? [],
|
|
704
|
+
primaryEfficiencyCompleteScenarios,
|
|
705
|
+
primaryEfficiencyRatio: rounded(primaryEfficiencyRatio, 4),
|
|
706
|
+
primaryEfficiencyRatioUpper95: primaryEfficiencyRatioConfidence95Raw?.upper ?? null,
|
|
707
|
+
durationRatio: rounded(durationRatio, 4),
|
|
708
|
+
durationRatioUpper95: durationRatioConfidence95Raw?.upper ?? null,
|
|
709
|
+
durationBandFailures: durationBandGate.failures,
|
|
710
|
+
durationFamilyFailures,
|
|
711
|
+
infrastructureRetries,
|
|
712
|
+
unknownInfrastructureUsage,
|
|
713
|
+
baselineSurface,
|
|
714
|
+
sourceKind: environment.source?.kind ?? null,
|
|
715
|
+
sourceCommit: environment.source?.commit ?? null,
|
|
716
|
+
sourceDirty: environment.source?.dirty ?? null,
|
|
717
|
+
hostReadinessValidReceipts: hostReadinessHistory?.validReceiptCount ?? null,
|
|
718
|
+
hostReadinessReceipts: hostReadinessHistory?.receiptCount ?? null,
|
|
719
|
+
hostReadinessCoverage: hostReadinessHistory?.windowCoverage ?? null,
|
|
720
|
+
fullSuite: environment.suiteCoverage?.fullSuite ?? null,
|
|
721
|
+
canonicalProductionIdentity: canonicalProductionSuite,
|
|
722
|
+
providerWireVerifiedRuns: providerWireVerifiedRuns.length,
|
|
723
|
+
providerWireRuns: candidateRuns.length,
|
|
724
|
+
providerWireGroups: providerWireGroups.length,
|
|
725
|
+
providerWireDriftGroups: providerWireDriftGroups.length,
|
|
726
|
+
causalContextAvailableRuns: causalContextEvidence.currentAvailableRuns,
|
|
727
|
+
causalContextRuns: causalContextEvidence.runs,
|
|
728
|
+
causalContextRequiredSchemaVersion: causalContextEvidence.requiredSchemaVersion
|
|
833
729
|
}
|
|
834
730
|
} : null;
|
|
835
731
|
const baselineKey = surfaceReportKey(baselineSurface);
|
|
836
732
|
const candidateKey = surfaceReportKey(candidateSurface);
|
|
837
|
-
const infrastructureFailures = runs.flatMap((run) => run.infrastructureFailures ?? []);
|
|
838
|
-
const infrastructureFailureCounts = {};
|
|
839
|
-
const infrastructureClassCounts = {};
|
|
840
|
-
for (const failure of infrastructureFailures) {
|
|
841
|
-
const name = failure.failure ?? "unknown";
|
|
842
|
-
infrastructureFailureCounts[name] = (infrastructureFailureCounts[name] ?? 0) + 1;
|
|
843
|
-
const className = failure.class ?? failure.infrastructureClass ?? "unknown";
|
|
844
|
-
infrastructureClassCounts[className] = (infrastructureClassCounts[className] ?? 0) + 1;
|
|
845
|
-
}
|
|
846
|
-
const infrastructureRetries = runs.reduce((sum, run) => sum + (run.infrastructureRetries ?? 0), 0);
|
|
847
733
|
const claimEligibility = benchmarkClaimEligibility({
|
|
848
734
|
suite,
|
|
849
735
|
environment,
|
|
@@ -868,32 +754,49 @@ export function summarizeBenchmark({
|
|
|
868
754
|
failureCounts: infrastructureFailureCounts,
|
|
869
755
|
classCounts: infrastructureClassCounts
|
|
870
756
|
},
|
|
757
|
+
tokenAccounting,
|
|
758
|
+
timingDiagnostics,
|
|
871
759
|
surfaces: { [baselineKey]: baseline, [candidateKey]: candidate },
|
|
872
760
|
comparison: {
|
|
873
761
|
baselineSurface,
|
|
874
762
|
candidateSurface,
|
|
875
763
|
purpose: claimEligibility.comparisonPurpose,
|
|
876
764
|
usageEstimator: "paired-geometric-mean-ratio",
|
|
765
|
+
durationEstimator: "paired-geometric-mean-ratio-clustered-by-scenario-family",
|
|
877
766
|
failureAwareUsageEstimator: "total-comparable-attempt-fresh-tokens-per-resolved-outcome",
|
|
767
|
+
failureAwareFamilyUsageEstimator: "geometric-mean-of-family-total-comparable-attempt-fresh-tokens-per-resolved-outcome-ratios",
|
|
768
|
+
fixedWorkloadUsageEstimator: "geometric-mean-of-family-total-exact-scheduled-workload-ratios",
|
|
769
|
+
fixedWorkloadEstimatorVersion: 1,
|
|
878
770
|
pairedOutcomeScenarios: completeOutcomeScenarios,
|
|
879
771
|
pairedSuccessfulRuns: pairs.length,
|
|
880
772
|
pairedUsageRuns: tokenPairs.length,
|
|
881
773
|
pairedUsageScenarios: scenarioFreshRatios.length,
|
|
882
774
|
pairedCompleteScenarios: completeScenarioFreshRatios.length,
|
|
775
|
+
pairedDurationRuns: durationPairs.length,
|
|
776
|
+
pairedDurationScenarios: scenarioDurationRatios.length,
|
|
777
|
+
pairedCompleteDurationScenarios: completeScenarioDurationRatios.length,
|
|
778
|
+
pairedDurationBands: pairedDurationBandReport,
|
|
883
779
|
pairedCostRuns: costPairs.length,
|
|
780
|
+
normalizedCost,
|
|
781
|
+
normalizedCostClaimConfigurationGate,
|
|
782
|
+
normalizedCostEvidenceGate: normalizedCostGates.evidenceGate,
|
|
783
|
+
normalizedCostPricingApplicabilityGate: normalizedCostGates.applicabilityGate,
|
|
784
|
+
normalizedCostConfidenceGate: normalizedCostGates.confidenceGate,
|
|
785
|
+
normalizedCostBandGate: normalizedCostGates.bandGate,
|
|
786
|
+
normalizedCostBandFailures: normalizedCostGates.bandFailures,
|
|
787
|
+
normalizedCostFamilyGate: normalizedCostGates.familyGate,
|
|
788
|
+
normalizedCostFamilyFailures: normalizedCostGates.familyFailures,
|
|
789
|
+
normalizedCostGate: normalizedCostGates.passed,
|
|
884
790
|
pairedOutcomes: {
|
|
885
791
|
resolved: pairedResolvedOutcomes,
|
|
886
792
|
quality: pairedOutcomeCounts(allPairs.filter((pair) => pair.candidate.scenarioKind !== "safety-refusal"), qualityPassed),
|
|
887
793
|
safety: pairedOutcomeCounts(allPairs, safetyPassed)
|
|
888
794
|
},
|
|
889
|
-
pairedUsageBands:
|
|
890
|
-
categories: pairedUsageBands(tokenPairs, "category"),
|
|
891
|
-
profiles: pairedUsageBands(tokenPairs, "profile"),
|
|
892
|
-
lifecycles: pairedUsageBands(tokenPairs, "lifecycle"),
|
|
893
|
-
difficulties: pairedUsageBands(tokenPairs, "difficulty")
|
|
894
|
-
},
|
|
795
|
+
pairedUsageBands: pairedUsageBandReport,
|
|
895
796
|
pairedFreshTokenWins: { [candidateKey]: freshWins, [baselineKey]: freshLosses, ties: freshTies },
|
|
896
797
|
medianPairedFreshTokenDelta: rounded(median(freshDeltas), 2),
|
|
798
|
+
pairedDurationWins: { [candidateKey]: durationWins, [baselineKey]: durationLosses, ties: durationTies },
|
|
799
|
+
medianPairedDurationDeltaSeconds: rounded(median(durationDeltas), 2),
|
|
897
800
|
medianFreshTokens: { [baselineKey]: baselineFresh, [candidateKey]: candidateFresh },
|
|
898
801
|
medianCost: { [baselineKey]: baselineCost, [candidateKey]: candidateCost },
|
|
899
802
|
freshTokensPerResolvedOutcome: {
|
|
@@ -901,12 +804,69 @@ export function summarizeBenchmark({
|
|
|
901
804
|
[candidateKey]: rounded(candidateFreshPerResolvedOutcome, 2)
|
|
902
805
|
},
|
|
903
806
|
failureAwareFreshTokenRatio: rounded(failureAwareFreshTokenRatio, 4),
|
|
807
|
+
failureAwareFamilyFreshTokenRatio: rounded(familyClusteredFailureAware.ratio, 4),
|
|
808
|
+
failureAwareFamilyFreshTokenRatioConfidence95: familyClusteredFailureAware.confidence95,
|
|
809
|
+
failureAwareFamilyFreshTokenRatioConfidence95Raw: familyClusteredFailureAware.confidence95Raw,
|
|
810
|
+
failureAwareFamilyCoverage: {
|
|
811
|
+
complete: familyClusteredFailureAware.complete,
|
|
812
|
+
expectedScenarioFamilies: familyClusteredFailureAware.expectedScenarioFamilies,
|
|
813
|
+
usableScenarioFamilies: familyClusteredFailureAware.usableScenarioFamilies,
|
|
814
|
+
sampleUnit: familyClusteredFailureAware.sampleUnit,
|
|
815
|
+
scenarioIds: familyClusteredFailureAware.scenarioIds
|
|
816
|
+
},
|
|
817
|
+
failureAwareFamilyRatios: familyClusteredFailureAware.families,
|
|
818
|
+
fixedWorkloadFamilyFreshTokenRatio: rounded(familyClusteredFixedWorkload.ratio, 4),
|
|
819
|
+
fixedWorkloadFamilyFreshTokenRatioRaw: familyClusteredFixedWorkload.ratio,
|
|
820
|
+
fixedWorkloadFamilyFreshTokenRatioConfidence95: familyClusteredFixedWorkload.confidence95,
|
|
821
|
+
fixedWorkloadFamilyFreshTokenRatioConfidence95Raw: familyClusteredFixedWorkload.confidence95Raw,
|
|
822
|
+
fixedWorkloadAggregateFreshTokenRatio: rounded(familyClusteredFixedWorkload.aggregateFreshTokenRatio, 4),
|
|
823
|
+
fixedWorkloadFamilyCoverage: {
|
|
824
|
+
complete: familyClusteredFixedWorkload.complete,
|
|
825
|
+
expectedScenarioFamilies: familyClusteredFixedWorkload.expectedScenarioFamilies,
|
|
826
|
+
usableScenarioFamilies: familyClusteredFixedWorkload.usableScenarioFamilies,
|
|
827
|
+
expectedAttemptsPerFamily: familyClusteredFixedWorkload.expectedAttemptsPerFamily,
|
|
828
|
+
sampleUnit: familyClusteredFixedWorkload.sampleUnit,
|
|
829
|
+
outcomeConditioning: familyClusteredFixedWorkload.outcomeConditioning,
|
|
830
|
+
aggregation: familyClusteredFixedWorkload.aggregation,
|
|
831
|
+
attemptPolicy: familyClusteredFixedWorkload.attemptPolicy,
|
|
832
|
+
scenarioIds: familyClusteredFixedWorkload.scenarioIds
|
|
833
|
+
},
|
|
834
|
+
fixedWorkloadFamilyRatios: familyClusteredFixedWorkload.families,
|
|
835
|
+
allSuccessfulPairsFreshTokenRatio: rounded(allSuccessfulPairsFreshRatio, 4),
|
|
904
836
|
freshTokenRatio: rounded(freshRatio, 4),
|
|
837
|
+
freshTokenRatioRaw: freshRatio,
|
|
905
838
|
freshTokenRatioConfidence95: freshRatioConfidence95,
|
|
839
|
+
freshTokenRatioConfidence95Raw: freshRatioConfidence95Raw,
|
|
840
|
+
freshTokenRatioSample: {
|
|
841
|
+
sampleUnit: "scenario-family",
|
|
842
|
+
scenarioCount: confidenceScenarioRatios.length,
|
|
843
|
+
scenarioIds: confidenceScenarioRatios.map((item) => item.scenarioId)
|
|
844
|
+
},
|
|
845
|
+
primaryEfficiencyEstimand,
|
|
846
|
+
primaryEfficiencyRatio: rounded(primaryEfficiencyRatio, 4),
|
|
847
|
+
primaryEfficiencyRatioRaw: primaryEfficiencyRatio,
|
|
848
|
+
primaryEfficiencyRatioConfidence95,
|
|
849
|
+
primaryEfficiencyRatioConfidence95Raw,
|
|
850
|
+
primaryEfficiencySample: {
|
|
851
|
+
sampleUnit: "scenario-family",
|
|
852
|
+
scenarioCount: primaryEfficiencyCompleteScenarios,
|
|
853
|
+
scenarioIds: primaryEfficiencyScenarioRatios.map((item) => item.scenarioId),
|
|
854
|
+
outcomeConditioning: primaryUsesFixedWorkload ? "none" : "resolved-outcome-conditioned"
|
|
855
|
+
},
|
|
856
|
+
primaryEfficiencyDeltaPercent: Number.isFinite(primaryEfficiencyRatio)
|
|
857
|
+
? rounded((primaryEfficiencyRatio - 1) * 100, 2)
|
|
858
|
+
: null,
|
|
906
859
|
freshTokenDeltaPercent: Number.isFinite(freshRatio) ? rounded((freshRatio - 1) * 100, 2) : null,
|
|
860
|
+
durationRatio: rounded(durationRatio, 4),
|
|
861
|
+
durationRatioRaw: durationRatio,
|
|
862
|
+
durationRatioConfidence95,
|
|
863
|
+
durationRatioConfidence95Raw,
|
|
864
|
+
durationDeltaPercent: Number.isFinite(durationRatio) ? rounded((durationRatio - 1) * 100, 2) : null,
|
|
907
865
|
costRatio: rounded(costRatio, 4),
|
|
908
866
|
costDeltaPercent: Number.isFinite(costRatio) ? rounded((costRatio - 1) * 100, 2) : null,
|
|
909
867
|
qualityNonInferior,
|
|
868
|
+
pairedQualityNoninferiorityGate,
|
|
869
|
+
pairedQualityEvidence,
|
|
910
870
|
qualityGate,
|
|
911
871
|
safetyGate,
|
|
912
872
|
reliabilityGate,
|
|
@@ -916,16 +876,65 @@ export function summarizeBenchmark({
|
|
|
916
876
|
outcomeScoreGate,
|
|
917
877
|
outcomeScoreFailures,
|
|
918
878
|
pairedRegressionGate,
|
|
879
|
+
candidateTaskContinuityGate,
|
|
880
|
+
candidateContinuityFailures,
|
|
919
881
|
comparisonProtocolGate: protocol,
|
|
882
|
+
providerWireSurfaceGate,
|
|
883
|
+
causalContextEvidenceGate,
|
|
884
|
+
causalContextEvidence,
|
|
885
|
+
providerWireEvidence: {
|
|
886
|
+
required: requiresProviderWireSurface,
|
|
887
|
+
runs: candidateRuns.length,
|
|
888
|
+
verifiedRuns: providerWireVerifiedRuns.length,
|
|
889
|
+
groups: providerWireGroups,
|
|
890
|
+
driftGroups: providerWireDriftGroups,
|
|
891
|
+
failureCounts: providerWireFailureCounts,
|
|
892
|
+
deferredChangesAreBaseDrift: false
|
|
893
|
+
},
|
|
894
|
+
releaseClaimConfigurationGate,
|
|
895
|
+
canonicalProductionIdentityGate,
|
|
896
|
+
codexBaselineGate,
|
|
897
|
+
cleanReleaseSourceGate,
|
|
898
|
+
hostReadinessGate,
|
|
899
|
+
fullSuiteGate,
|
|
920
900
|
outcomeEvidenceGate,
|
|
921
901
|
efficiencyEvidenceGate,
|
|
902
|
+
successfulPairEfficiencyRole,
|
|
903
|
+
successfulPairEfficiencySupportGate,
|
|
922
904
|
efficiencyBandCoverageGate,
|
|
923
905
|
efficiencyCategoryCoverage,
|
|
906
|
+
freshTokenBandGate: freshTokenBandGate.passed,
|
|
907
|
+
freshTokenBandFailures: freshTokenBandGate.failures,
|
|
908
|
+
freshTokenFamilyGate,
|
|
909
|
+
freshTokenFamilyFailures,
|
|
924
910
|
failureAwareEfficiencyGate,
|
|
911
|
+
failureAwareEfficiencyRole,
|
|
912
|
+
failureAwareEfficiencySupportGate,
|
|
913
|
+
primaryEfficiencyEvidenceGate,
|
|
914
|
+
primaryEfficiencyBandCoverageGate,
|
|
915
|
+
primaryEfficiencyCategoryCoverage,
|
|
916
|
+
primaryEfficiencyConfidenceGate,
|
|
917
|
+
primaryEfficiencyGate,
|
|
925
918
|
repeatGate,
|
|
926
919
|
efficiencyConfidenceGate,
|
|
920
|
+
performanceEvidenceGate,
|
|
921
|
+
performancePointEstimateGate,
|
|
922
|
+
performanceConfidenceGate,
|
|
923
|
+
durationBandGate: durationBandGate.passed,
|
|
924
|
+
durationBandFailures: durationBandGate.failures,
|
|
925
|
+
durationFamilyGate,
|
|
926
|
+
durationFamilyFailures,
|
|
927
|
+
performanceGate,
|
|
928
|
+
infrastructureRetryGate,
|
|
929
|
+
unknownInfrastructureUsageGate,
|
|
930
|
+
acceptedUsageCompletenessGate,
|
|
931
|
+
failedUsageCompletenessGate,
|
|
932
|
+
allAttemptUsageCompletenessGate,
|
|
933
|
+
infrastructureFailureLedgerGate,
|
|
934
|
+
infrastructureFailureLedgerIssues,
|
|
935
|
+
stabilityGate,
|
|
927
936
|
suiteGate,
|
|
928
|
-
productionGate:
|
|
937
|
+
productionGate: canonicalProductionSuite ? suiteGate : null,
|
|
929
938
|
tokenClaimAllowed,
|
|
930
939
|
claimEligibility
|
|
931
940
|
},
|
|
@@ -934,29 +943,91 @@ export function summarizeBenchmark({
|
|
|
934
943
|
? "safety-gate-failed"
|
|
935
944
|
: !qualityNonInferior
|
|
936
945
|
? "quality-regression"
|
|
946
|
+
: pairedQualityNoninferiorityGate === false
|
|
947
|
+
? "paired-quality-noninferiority-gate-failed"
|
|
937
948
|
: !qualityGate
|
|
938
949
|
? "quality-gate-failed"
|
|
939
950
|
: !reliabilityGate
|
|
940
951
|
? "reliability-gate-failed"
|
|
941
|
-
: !
|
|
952
|
+
: !baseProtocol.passed
|
|
942
953
|
? "comparison-protocol-gate-failed"
|
|
943
954
|
: workflowGate === false
|
|
944
955
|
? "workflow-gate-failed"
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
:
|
|
958
|
-
|
|
956
|
+
: categoryGate === false
|
|
957
|
+
? "category-gate-failed"
|
|
958
|
+
: outcomeScoreGate === false
|
|
959
|
+
? "outcome-score-floor-gate-failed"
|
|
960
|
+
: !pairedRegressionGate
|
|
961
|
+
? "paired-candidate-regression"
|
|
962
|
+
: !candidateTaskContinuityGate
|
|
963
|
+
? "candidate-task-continuity-gate-failed"
|
|
964
|
+
: !canonicalProductionIdentityGate
|
|
965
|
+
? "canonical-production-identity-gate-failed"
|
|
966
|
+
: requestsTokenSavingClaim && releaseClaimConfigurationGate === false
|
|
967
|
+
? "release-claim-configuration-gate-failed"
|
|
968
|
+
: requestsTokenSavingClaim && codexBaselineGate === false
|
|
969
|
+
? "codex-baseline-gate-failed"
|
|
970
|
+
: requestsTokenSavingClaim && cleanReleaseSourceGate === false
|
|
971
|
+
? "clean-release-source-gate-failed"
|
|
972
|
+
: requiresHostReadiness && hostReadinessGate === false
|
|
973
|
+
? "host-readiness-history-gate-failed"
|
|
974
|
+
: requiresProviderWireSurface && providerWireSurfaceGate === false
|
|
975
|
+
? "provider-wire-surface-gate-failed"
|
|
976
|
+
: requiresCausalContextReceipt && causalContextEvidenceGate === false
|
|
977
|
+
? "causal-context-evidence-gate-failed"
|
|
978
|
+
: fullSuiteGate === false
|
|
979
|
+
? "full-suite-gate-failed"
|
|
980
|
+
: requiresStability && infrastructureRetryGate === false
|
|
981
|
+
? "stability-infrastructure-retry-gate-failed"
|
|
982
|
+
: requiresStability && unknownInfrastructureUsageGate === false
|
|
983
|
+
? "stability-unknown-usage-gate-failed"
|
|
984
|
+
: requestsTokenSavingClaim && infrastructureFailureLedgerGate === false
|
|
985
|
+
? "stability-failure-ledger-gate-failed"
|
|
986
|
+
: requestsTokenSavingClaim && acceptedUsageCompletenessGate === false
|
|
987
|
+
? "accepted-usage-completeness-gate-failed"
|
|
988
|
+
: requestsTokenSavingClaim && allAttemptUsageCompletenessGate === false
|
|
989
|
+
? "all-attempt-usage-completeness-gate-failed"
|
|
990
|
+
: requestsNormalizedCostClaim && normalizedCostClaimConfigurationGate === false
|
|
991
|
+
? "normalized-cost-configuration-gate-failed"
|
|
992
|
+
: requestsNormalizedCostClaim && normalizedCostGates.applicabilityGate === false
|
|
993
|
+
? "normalized-cost-pricing-applicability-gate-failed"
|
|
994
|
+
: requestsNormalizedCostClaim && normalizedCostGates.evidenceGate === false
|
|
995
|
+
? "normalized-cost-evidence-gate-failed"
|
|
996
|
+
: requestsNormalizedCostClaim && normalizedCostGates.confidenceGate === false
|
|
997
|
+
? "normalized-cost-confidence-gate-failed"
|
|
998
|
+
: requestsNormalizedCostClaim && normalizedCostGates.bandGate === false
|
|
999
|
+
? "normalized-cost-band-ratio-gate-failed"
|
|
1000
|
+
: requestsNormalizedCostClaim && normalizedCostGates.familyGate === false
|
|
1001
|
+
? "normalized-cost-family-ratio-gate-failed"
|
|
1002
|
+
: !outcomeEvidenceGate
|
|
1003
|
+
? "paired-outcome-evidence-gate-failed"
|
|
1004
|
+
: repeatGate === false
|
|
1005
|
+
? "repeat-gate-failed"
|
|
1006
|
+
: primaryUsesFixedWorkload && primaryEfficiencyGate === false
|
|
1007
|
+
? "primary-efficiency-gate-failed"
|
|
1008
|
+
: requiresPerformance && performanceEvidenceGate === false
|
|
1009
|
+
? "performance-evidence-gate-failed"
|
|
1010
|
+
: requiresPerformance && performancePointEstimateGate === false
|
|
1011
|
+
? "performance-point-regression"
|
|
1012
|
+
: requiresPerformance && performanceConfidenceGate === false
|
|
1013
|
+
? "performance-confidence-gate-failed"
|
|
1014
|
+
: durationBandGate.passed === false
|
|
1015
|
+
? "performance-band-ratio-gate-failed"
|
|
1016
|
+
: durationFamilyGate === false
|
|
1017
|
+
? "performance-family-ratio-gate-failed"
|
|
1018
|
+
: requiresBandEfficiency && freshTokenBandGate.passed === false
|
|
1019
|
+
? "efficiency-band-ratio-gate-failed"
|
|
1020
|
+
: freshTokenFamilyGate === false
|
|
1021
|
+
? "efficiency-family-ratio-gate-failed"
|
|
1022
|
+
: requiresConfidenceEfficiency
|
|
1023
|
+
&& successfulPairEfficiencyRole === "blocking"
|
|
1024
|
+
&& efficiencyConfidenceGate === false
|
|
1025
|
+
? "efficiency-confidence-gate-failed"
|
|
1026
|
+
: tokenClaimAllowed
|
|
1027
|
+
? `${candidateSurface}-more-efficient`
|
|
1028
|
+
: "observational-efficiency-only",
|
|
1029
|
+
note: `Raw metrics and hidden verifier results are authoritative. Fixed-workload efficiency includes every predeclared paired attempt, including exact provider-started failed-attempt usage, without conditioning token measurement on task outcome; quality and continuity remain independent hard gates. Successful-pair efficiency uses matched ${benchmarkSurfaceLabel(candidateSurface)}/${benchmarkSurfaceLabel(baselineSurface)} resolved-outcome ratios; failure-aware effort divides every comparable attempt by resolved outcomes. Normalized cost is API-equivalent text-token input/cache/output cost from the versioned suite pricing snapshot and exact token buckets, never OAuth/provider-billed or tool-specific total cost. Duration compares all matched runs with compatible model and effort evidence. Provider-wire evidence verifies the requested model and effort plus stable base instructions/tools within each scenario/profile/lifecycle across repeats; deferred tool-search batches are reported separately. Confidence intervals cluster repeats by scenario family. Claim scope is ${claimEligibility.achievedTier}; generated value variants are not treated as independent task families.`
|
|
959
1030
|
},
|
|
960
|
-
runs
|
|
1031
|
+
runs: reportRuns
|
|
961
1032
|
};
|
|
962
1033
|
}
|