@openwop/openwop-conformance 2.46.25 → 2.46.26

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 CHANGED
@@ -1,3 +1,9 @@
1
+ ## [2.46.26] — 2026-10-25 — RFC 0244 model-usage and cost legs
2
+
3
+ - **New leg `0244.efficiency-model-usage` in `v2-eval-trajectory-trials`**, on the existing trajectory and trials runs. Per-task `modelCallCount`, `inputTokens` and `outputTokens`, times the trial count, must sum to the agent's `provider.usage` inside its `agent.invocation.*` brackets (judge and delegate calls excluded); without brackets they must not exceed the run's usage.
4
+ - **New leg `0244.cost-every-trial`**, on the trials run: `totalCostUsd` must be at least the agent's priced usage over all trials. Judges in `lib/eval-efficiency-witness.ts`.
5
+ - **Host impact:** a run with no model usage, no brackets or unpriced usage records `inapplicable`; one that counts judge calls as the agent's, or prices one trial, fails.
6
+
1
7
  ## [2.46.25] — 2026-10-25 — RFC 0244 §C efficiency leg
2
8
 
3
9
  - **New leg `0244.efficiency-tool-calls` in `v2-eval-trajectory-trials`**, on the existing `conformance-eval-trajectory` run (and the `conformance-eval-trials` run when served), so no extra run. Each task's `efficiency.toolCallCount` must equal its script length, and on the one-trial run the counts must sum to the log's `agent.tool-called` events. Judge in `lib/eval-efficiency-witness.ts`.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "package": "@openwop/spec-artifacts",
3
- "version": "2.46.25",
4
- "stampSha256": "d50d0faa638afab3defdf1ab0771218528dfddbcf4867d112cb2c3cc68dfb120"
3
+ "version": "2.46.26",
4
+ "stampSha256": "e53058ead4546c46dc23498974219d081a05193fdb5dec16db93a221d023e0d9"
5
5
  }
package/fixtures.md CHANGED
@@ -1054,7 +1054,7 @@ Every task targets **the scripted agent `core.conformance.agents.scripted`**. It
1054
1054
  | Fixture | Facet | What the suite asserts |
1055
1055
  | --- | --- | --- |
1056
1056
  | `conformance-eval-trajectory` | `agents.evalSuite.trajectory` | each task's `trajectory` counts equal `lib/eval-trajectory.ts`'s grade of the script; an unmatched trajectory fails; a `kind: "trajectory"` task scores 1 or 0; the log carries one `agent.tool-called` per scripted call |
1057
- | `conformance-eval-trials` | `agents.evalSuite.trials` | `eval.started.trialCount: 3`; three `eval.scored` per task with `trialIndex` 0..2; the per-task `trials` block and `trialStats` equal the §B formulas. Without the facet: `400 validation_error` at `createRun` |
1057
+ | `conformance-eval-trials` | `agents.evalSuite.trials` | `eval.started.trialCount: 3`; three `eval.scored` per task with `trialIndex` 0..2; the per-task `trials` block and `trialStats` equal the §B formulas; `totalCostUsd`, when served with bracketed priced usage, is at least the agent's cost over all three trials. Without the facet: `400 validation_error` at `createRun` |
1058
1058
  | `conformance-eval-fixture-miss` | `agents.evalSuite.fixtureMatching` | `missed` reports `fixtureMissCount: 1`, `passed: false` and `score: 0` (summary and every `eval.scored`); `served` passes with no miss. That no live tool ran is shown by the counter fixtures below (RFC 0244 G2) |
1059
1059
  | `conformance-eval-trajectory-gate` | `agents.evalSuite.trajectory` | RFC 0246: both tasks keep `score` 1 and `aggregateScore` 1; `path-matched` carries `gatedScore` 1 and `path-wrong` `gatedScore` 0; `gatedAggregateScore` 0.5; suite `passed: false` although `aggregateScore` clears `passScore` 0.6 |
1060
1060
  | `conformance-eval-trajectory-gate-mean` | `agents.evalSuite.trajectory` + `agents.evalSuite.trials` | RFC 0246: two `eval.scored` with `score` 1 and `passed: false`; `trials.meanScore` 1, `gatedScore` 0, task `passed: false`; the summary carries `gatedAggregateScore` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/openwop-conformance",
3
- "version": "2.46.25",
3
+ "version": "2.46.26",
4
4
  "description": "Black-box conformance suite for OpenWOP hosts (v2 current; v1 scenarios retained for the frozen v1 tree).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -56,6 +56,6 @@
56
56
  "@openwop/spec-artifacts": "file:../spec-artifacts"
57
57
  },
58
58
  "peerDependencies": {
59
- "@openwop/spec-artifacts": "2.46.25"
59
+ "@openwop/spec-artifacts": "2.46.26"
60
60
  }
61
61
  }
package/requirements.json CHANGED
@@ -3,10 +3,10 @@
3
3
  "generatedFrom": "src/scenarios/*.test.ts",
4
4
  "counts": {
5
5
  "files": 749,
6
- "tests": 2844,
7
- "withStableId": 2844,
6
+ "tests": 2846,
7
+ "withStableId": 2846,
8
8
  "interpolatedTitles": 0,
9
- "explicitIds": 2717
9
+ "explicitIds": 2719
10
10
  },
11
11
  "records": [
12
12
  {
@@ -31092,7 +31092,7 @@
31092
31092
  {
31093
31093
  "id": "openwop.it.v2-eval-trajectory-trials.the-rfc-0244-suite-summary-and-event-fields-validate-and-the-negatives-are-refus",
31094
31094
  "file": "v2-eval-trajectory-trials.test.ts",
31095
- "line": 185,
31095
+ "line": 196,
31096
31096
  "title": "the RFC 0244 suite, summary and event fields validate and the negatives are refused",
31097
31097
  "explicitId": "openwop.requirement.0244.wire-shape",
31098
31098
  "citations": [
@@ -31131,7 +31131,7 @@
31131
31131
  {
31132
31132
  "id": "openwop.it.v2-eval-trajectory-trials.the-rfc-0244-additions-are-content-free-eval-summary-no-content-leak",
31133
31133
  "file": "v2-eval-trajectory-trials.test.ts",
31134
- "line": 208,
31134
+ "line": 219,
31135
31135
  "title": "the RFC 0244 additions are content-free (eval-summary-no-content-leak)",
31136
31136
  "explicitId": "openwop.requirement.0244.content-free",
31137
31137
  "citations": [
@@ -31148,7 +31148,7 @@
31148
31148
  {
31149
31149
  "id": "openwop.it.v2-eval-trajectory-trials.the-eval-suite-fixtures-validate-against-the-v2-suite-schema",
31150
31150
  "file": "v2-eval-trajectory-trials.test.ts",
31151
- "line": 215,
31151
+ "line": 226,
31152
31152
  "title": "the eval-suite fixtures validate against the v2 suite schema",
31153
31153
  "explicitId": "openwop.requirement.0244.fixtures-valid",
31154
31154
  "citations": [
@@ -31162,7 +31162,7 @@
31162
31162
  {
31163
31163
  "id": "openwop.it.v2-eval-trajectory-trials.the-rfc-0246-gating-fields-validate-and-stay-in-0-1",
31164
31164
  "file": "v2-eval-trajectory-trials.test.ts",
31165
- "line": 222,
31165
+ "line": 233,
31166
31166
  "title": "the RFC 0246 gating fields validate and stay in 0–1",
31167
31167
  "explicitId": "openwop.requirement.0246.gated-fields-shape",
31168
31168
  "citations": [
@@ -31184,7 +31184,7 @@
31184
31184
  {
31185
31185
  "id": "openwop.it.v2-eval-trajectory-trials.a-fixture-entry-may-be-marked-iserror-and-only-as-a-boolean-rfc-0245-a",
31186
31186
  "file": "v2-eval-trajectory-trials.test.ts",
31187
- "line": 230,
31187
+ "line": 241,
31188
31188
  "title": "a fixture entry may be marked isError, and only as a boolean (RFC 0245 §A)",
31189
31189
  "explicitId": "openwop.requirement.0245.fixture-error-shape",
31190
31190
  "citations": [
@@ -31206,7 +31206,7 @@
31206
31206
  {
31207
31207
  "id": "openwop.it.v2-eval-trajectory-trials.a-trajectory-suite-is-graded-per-the-reference-grader",
31208
31208
  "file": "v2-eval-trajectory-trials.test.ts",
31209
- "line": 240,
31209
+ "line": 251,
31210
31210
  "title": "a trajectory suite is graded per the reference grader",
31211
31211
  "explicitId": "openwop.requirement.0244.trajectory-graded",
31212
31212
  "citations": [
@@ -31240,7 +31240,7 @@
31240
31240
  {
31241
31241
  "id": "openwop.it.v2-eval-trajectory-trials.an-eval-run-brackets-its-scores-with-one-eval-started-and-one-eval-completed-rfc",
31242
31242
  "file": "v2-eval-trajectory-trials.test.ts",
31243
- "line": 274,
31243
+ "line": 285,
31244
31244
  "title": "an eval run brackets its scores with one eval.started and one eval.completed (RFC 0081 §C)",
31245
31245
  "explicitId": "openwop.requirement.0081.eval-envelope",
31246
31246
  "citations": [
@@ -31254,7 +31254,7 @@
31254
31254
  {
31255
31255
  "id": "openwop.it.v2-eval-trajectory-trials.the-served-evalsummary-validates-and-its-counts-match-its-rows-rfc-0081-c",
31256
31256
  "file": "v2-eval-trajectory-trials.test.ts",
31257
- "line": 282,
31257
+ "line": 293,
31258
31258
  "title": "the served EvalSummary validates and its counts match its rows (RFC 0081 §C)",
31259
31259
  "explicitId": "openwop.requirement.0081.summary-served",
31260
31260
  "citations": [
@@ -31268,7 +31268,7 @@
31268
31268
  {
31269
31269
  "id": "openwop.it.v2-eval-trajectory-trials.repeated-trials-emit-one-eval-scored-per-task-per-trial",
31270
31270
  "file": "v2-eval-trajectory-trials.test.ts",
31271
- "line": 303,
31271
+ "line": 314,
31272
31272
  "title": "repeated trials emit one eval.scored per task per trial",
31273
31273
  "explicitId": "openwop.requirement.0244.trials-per-task",
31274
31274
  "citations": [
@@ -31286,7 +31286,7 @@
31286
31286
  {
31287
31287
  "id": "openwop.it.v2-eval-trajectory-trials.the-per-task-trials-block-and-trialstats-follow-the-b-formulas",
31288
31288
  "file": "v2-eval-trajectory-trials.test.ts",
31289
- "line": 314,
31289
+ "line": 325,
31290
31290
  "title": "the per-task trials block and trialStats follow the §B formulas",
31291
31291
  "explicitId": "openwop.requirement.0244.trial-stats-formula",
31292
31292
  "citations": [
@@ -31325,7 +31325,7 @@
31325
31325
  {
31326
31326
  "id": "openwop.it.v2-eval-trajectory-trials.efficiency-toolcallcount-counts-the-scripted-agent-tool-called-events-c",
31327
31327
  "file": "v2-eval-trajectory-trials.test.ts",
31328
- "line": 337,
31328
+ "line": 348,
31329
31329
  "title": "efficiency.toolCallCount counts the scripted agent.tool-called events (§C)",
31330
31330
  "explicitId": "openwop.requirement.0244.efficiency-tool-calls",
31331
31331
  "citations": [
@@ -31337,9 +31337,37 @@
31337
31337
  ]
31338
31338
  },
31339
31339
  {
31340
- "id": "openwop.it.v2-eval-trajectory-trials.a-miss-under-onmiss-live-reaches-the-live-counter-and-is-counted-d",
31340
+ "id": "openwop.it.v2-eval-trajectory-trials.efficiency-model-and-token-counts-match-the-agent-s-provider-usage-c",
31341
+ "file": "v2-eval-trajectory-trials.test.ts",
31342
+ "line": 360,
31343
+ "title": "efficiency model and token counts match the agent's provider.usage (§C)",
31344
+ "explicitId": "openwop.requirement.0244.efficiency-model-usage",
31345
+ "citations": [
31346
+ {
31347
+ "section": "eval-summary.schema.json efficiency (RFC 0244 §C)",
31348
+ "requirement": null,
31349
+ "interpolated": true
31350
+ }
31351
+ ]
31352
+ },
31353
+ {
31354
+ "id": "openwop.it.v2-eval-trajectory-trials.totalcostusd-counts-every-trial-b",
31341
31355
  "file": "v2-eval-trajectory-trials.test.ts",
31342
31356
  "line": 371,
31357
+ "title": "totalCostUsd counts every trial (§B)",
31358
+ "explicitId": "openwop.requirement.0244.cost-every-trial",
31359
+ "citations": [
31360
+ {
31361
+ "section": "agent-eval-suite.schema.json thresholds.maxCostUsd, eval-summary.schema.json totalCostUsd (RFC 0244 §B)",
31362
+ "requirement": null,
31363
+ "interpolated": true
31364
+ }
31365
+ ]
31366
+ },
31367
+ {
31368
+ "id": "openwop.it.v2-eval-trajectory-trials.a-miss-under-onmiss-live-reaches-the-live-counter-and-is-counted-d",
31369
+ "file": "v2-eval-trajectory-trials.test.ts",
31370
+ "line": 401,
31343
31371
  "title": "a miss under onMiss \"live\" reaches the live counter and is counted (§D)",
31344
31372
  "explicitId": "openwop.requirement.0244.live-miss-counted",
31345
31373
  "citations": [
@@ -31353,7 +31381,7 @@
31353
31381
  {
31354
31382
  "id": "openwop.it.v2-eval-trajectory-trials.repeated-calls-are-served-the-first-unconsumed-fixture-entry-once-each-d",
31355
31383
  "file": "v2-eval-trajectory-trials.test.ts",
31356
- "line": 379,
31384
+ "line": 409,
31357
31385
  "title": "repeated calls are served the first unconsumed fixture entry, once each (§D)",
31358
31386
  "explicitId": "openwop.requirement.0244.first-unconsumed",
31359
31387
  "citations": [
@@ -31367,7 +31395,7 @@
31367
31395
  {
31368
31396
  "id": "openwop.it.v2-eval-trajectory-trials.a-miss-under-onmiss-fail-never-reaches-the-live-counter-d",
31369
31397
  "file": "v2-eval-trajectory-trials.test.ts",
31370
- "line": 387,
31398
+ "line": 417,
31371
31399
  "title": "a miss under onMiss \"fail\" never reaches the live counter (§D)",
31372
31400
  "explicitId": "openwop.requirement.0244.miss-no-live-call",
31373
31401
  "citations": [
@@ -31381,7 +31409,7 @@
31381
31409
  {
31382
31410
  "id": "openwop.it.v2-eval-trajectory-trials.a-fixture-miss-under-onmiss-fail-fails-the-trial-and-is-counted",
31383
31411
  "file": "v2-eval-trajectory-trials.test.ts",
31384
- "line": 395,
31412
+ "line": 425,
31385
31413
  "title": "a fixture miss under onMiss \"fail\" fails the trial and is counted",
31386
31414
  "explicitId": "openwop.requirement.0244.fixture-miss-fails",
31387
31415
  "citations": [
@@ -31418,7 +31446,7 @@
31418
31446
  {
31419
31447
  "id": "openwop.it.v2-eval-trajectory-trials.a-suite-using-an-unadvertised-rfc-0244-feature-is-refused-at-createrun",
31420
31448
  "file": "v2-eval-trajectory-trials.test.ts",
31421
- "line": 415,
31449
+ "line": 445,
31422
31450
  "title": "a suite using an unadvertised RFC 0244 feature is refused at createRun",
31423
31451
  "explicitId": "openwop.requirement.0244.unadvertised-feature-refused",
31424
31452
  "citations": [
@@ -31436,7 +31464,7 @@
31436
31464
  {
31437
31465
  "id": "openwop.it.v2-eval-trajectory-trials.under-passrule-mean-a-task-whose-trials-failed-their-trajectory-does-not-pass-rf",
31438
31466
  "file": "v2-eval-trajectory-trials.test.ts",
31439
- "line": 431,
31467
+ "line": 461,
31440
31468
  "title": "under passRule \"mean\" a task whose trials failed their trajectory does not pass (RFC 0246)",
31441
31469
  "explicitId": "openwop.requirement.0246.mean-gated",
31442
31470
  "citations": [
@@ -31450,7 +31478,7 @@
31450
31478
  {
31451
31479
  "id": "openwop.it.v2-eval-trajectory-trials.a-suite-whose-tasks-failed-their-trajectory-does-not-pass-on-the-output-scores-r",
31452
31480
  "file": "v2-eval-trajectory-trials.test.ts",
31453
- "line": 444,
31481
+ "line": 474,
31454
31482
  "title": "a suite whose tasks failed their trajectory does not pass on the output scores (RFC 0246)",
31455
31483
  "explicitId": "openwop.requirement.0246.suite-gated",
31456
31484
  "citations": [
@@ -31464,7 +31492,7 @@
31464
31492
  {
31465
31493
  "id": "openwop.it.v2-eval-trajectory-trials.a-fixture-entry-marked-iserror-is-replayed-as-a-tool-error-not-a-success-rfc-024",
31466
31494
  "file": "v2-eval-trajectory-trials.test.ts",
31467
- "line": 455,
31495
+ "line": 485,
31468
31496
  "title": "a fixture entry marked isError is replayed as a tool error, not a success (RFC 0245)",
31469
31497
  "explicitId": "openwop.requirement.0245.fixture-error-replayed",
31470
31498
  "citations": [
@@ -31478,7 +31506,7 @@
31478
31506
  {
31479
31507
  "id": "openwop.it.v2-eval-trajectory-trials.a-suite-using-iserror-is-refused-at-createrun-without-fixtureerrors-rfc-0245-c",
31480
31508
  "file": "v2-eval-trajectory-trials.test.ts",
31481
- "line": 469,
31509
+ "line": 499,
31482
31510
  "title": "a suite using isError is refused at createRun without fixtureErrors (RFC 0245 §C)",
31483
31511
  "explicitId": "openwop.requirement.0245.unadvertised-refused",
31484
31512
  "citations": [
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "_comment": "Provenance of @openwop/spec-artifacts (RFC 0168 §D.2). files: SHA-256 per file; the conformance suite compares the installed peer against dist/spec-artifacts.lock.json at start.",
3
3
  "package": "@openwop/spec-artifacts",
4
- "version": "2.46.25",
5
- "corpusTag": "v2.46.25",
4
+ "version": "2.46.26",
5
+ "corpusTag": "v2.46.26",
6
6
  "files": {
7
7
  "api/.redocly.lint-ignore.yaml": "bf5a8350b88a72fa43f59605ed8d903ed24b6cfccda5e45509c9f6ed9ee4e712",
8
8
  "api/asyncapi.yaml": "d5ecb9ee6114582be3b1f662c84bfac9ae96dae7bacb853e461168f70a8e1c7d",
9
9
  "api/grpc/openwop.proto": "c3e72bb17cba514ee98feb6434e6c9b6ea6795bfd086489ec69fd882dd1ad977",
10
10
  "api/openapi.yaml": "ac6de5303872664b78ff419c035915593e01599e02835e777a0123de1baeb398",
11
11
  "api/redocly.yaml": "b0604c89b2ca6d5076ec25725c539dad44a741a811fe524439ee6daef8baa09f",
12
- "api/seams-v2.yaml": "8fd581fc6b17706f32f6793d5cf00fd6de9c1d4791645d37efe90df2d430d9d5",
13
- "api/v2/asyncapi.yaml": "f1a40cc22ed7c3c7069e49ff50da59b893f8cac43474fed8f48b4dbed4bdf5a2",
14
- "api/v2/openapi.yaml": "8287abaade3983fc4546cb2a7c7d5e4e50595377b4fdf53ca65738d7284ce1a4",
12
+ "api/seams-v2.yaml": "fc5aaff321913531e04b13522de92a9a8fa3f61be836696e9ab83fbc563caa87",
13
+ "api/v2/asyncapi.yaml": "0ea85f3cb0af276cd7ed82e14810c1093917f0d1daa80bc0226b78e127c4e17d",
14
+ "api/v2/openapi.yaml": "7c7cd37cc0cabcd37285502594977f6ddc5a59f30938d7aede36f69e05322244",
15
15
  "api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
16
16
  "schemas/README.md": "276fc1d51eb08e14e9127b9fd27761d7046ee33c12000f3a64a801322db8bf58",
17
17
  "schemas/a2a-task-state.schema.json": "75d5049dea8bd873ff0e7546f1c60c8d36c219bec7084264360be54a8be30ae1",
@@ -212,7 +212,7 @@
212
212
  "schemas/workspace-file.schema.json": "464de85c2a068243084ee9c1d969bc7cd5d8f7948574e58450d6493c38a0e1e4",
213
213
  "spec/v1/alias-detectors.json": "22444c22bb88c568339ef512553f9fc38146e22b566d11ab8608f655d688d19c",
214
214
  "spec/v1/capability-declaration-classes.json": "e7729aed5c4b4e1dd02abab0530f14cc95f5d4070fe51fb139e7f5cccefa00c6",
215
- "spec/v1/core-standard-manifest.json": "c3705885e787498f604ffd256c4d6e26afcc929a79a548b7ecd46bf87e9e8a0f",
215
+ "spec/v1/core-standard-manifest.json": "580b853bb37383d5acea488fba6747193d1db4e6e63025255433dababf008d60",
216
216
  "spec/v1/deprecations.json": "e723bc11d7272c71789ad1303bb7f21809a8a024abf57594f9d5c35dc199ece9",
217
217
  "spec/v1/deprecations.schema.json": "3e393c405d2a41b467d8c5e3c468549078df1ce6a6d2588fc488097b95d9b55b",
218
218
  "spec/v1/end-of-support.json": "35f0bf3b70fe78b16e2a2fd81a153fc27e703f6c16376c6fe7cdf1f4f2c4e6d4",
@@ -318,9 +318,9 @@
318
318
  "spec/v2/path-manifest.json": "20f598f56df460ad3ed50aba3d6bc2933ea16a3c96ce125da1c5dd6989d4155c",
319
319
  "spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
320
320
  "spec/v2/profiles.json": "b382b261c7844798575f7c1b37c934f0da19846016a2337d883d4f5ef6e05479",
321
- "spec/v2/release.json": "0d42cf69cb062a05c6b7d7d09dea7bbc44e918ffb056112303459883ddd032f0",
321
+ "spec/v2/release.json": "e2a9a7d13015eb3ca85bdbcd6ec422b6e91780fb9019b0e75e2855b826728b1d",
322
322
  "spec/v2/retention-floors.json": "eaf3722d95c79947af1d4269ef85117e126518c588cfcf1a2b21b97269f51624",
323
- "spec/v2/surface-baseline.json": "585d61f9dae285fdb9e302568fefc2d91faaa166bd6a8c20e3bac1a82940f8af"
323
+ "spec/v2/surface-baseline.json": "4a1e5ab2349349eeeb9fa173e392627d49c2bee77ac8a42897aeacf2c3a4d784"
324
324
  },
325
- "corpusCommit": "77aeb0cacb91551dab835cf0e985be8423e06542"
325
+ "corpusCommit": "e5e8306a4f9c8c41394cfbe63fb58a08a74fe5b9"
326
326
  }
@@ -56,3 +56,84 @@ export function judgeToolCallCount(summary: Rec, tasks: readonly ScriptedTask[],
56
56
  }
57
57
  return { applicable: true, findings };
58
58
  }
59
+
60
+ /**
61
+ * The `provider.usage` payloads of the agent under test, in log order.
62
+ * `provider.usage` carries no `agentId`, so attribution is positional: a usage
63
+ * event counts while an `agent.invocation.started` of `agentId` is open and no
64
+ * other agent's invocation (a judge, a delegate) is open inside it. Brackets
65
+ * are emitted only by an `agents.liveRuntime` host; `bracketed: false` means
66
+ * the log has none, and the usage list is then every `provider.usage` of the run.
67
+ */
68
+ export function agentUsage(events: readonly { readonly type: string; readonly payload: Rec }[], agentId: string): { bracketed: boolean; usage: Rec[] } {
69
+ const open = new Map<string, boolean>();
70
+ let mine = 0;
71
+ let other = 0;
72
+ let bracketed = false;
73
+ const inside: Rec[] = [];
74
+ const all: Rec[] = [];
75
+ for (const e of events) {
76
+ const id = e.payload['invocationId'];
77
+ if (e.type === 'agent.invocation.started' && typeof id === 'string') {
78
+ bracketed = true;
79
+ const isMine = e.payload['agentId'] === agentId;
80
+ open.set(id, isMine);
81
+ if (isMine) mine += 1; else other += 1;
82
+ } else if (e.type === 'agent.invocation.completed' && typeof id === 'string' && open.has(id)) {
83
+ if (open.get(id)) mine -= 1; else other -= 1;
84
+ open.delete(id);
85
+ } else if (e.type === 'provider.usage') {
86
+ all.push(e.payload);
87
+ if (mine > 0 && other === 0) inside.push(e.payload);
88
+ }
89
+ }
90
+ return bracketed ? { bracketed, usage: inside } : { bracketed, usage: all };
91
+ }
92
+
93
+ const FIELDS = [['modelCallCount', () => 1], ['inputTokens', (u: Rec) => u['inputTokens']], ['outputTokens', (u: Rec) => u['outputTokens']]] as const;
94
+ const close = (a: number, b: number): boolean => Math.abs(a - b) <= 1e-9 * Math.max(1, Math.abs(b));
95
+
96
+ /**
97
+ * §C `modelCallCount`, `inputTokens` and `outputTokens`. Each is a mean over
98
+ * `trials` identical trials, so the per-task values times `trials` sum to the
99
+ * agent's usage in the log. With brackets the sums MUST be equal; without them
100
+ * the run's usage also holds any host-internal call, so the sums MUST NOT
101
+ * exceed it. A field is judged only when every task reports it. A run with no
102
+ * usage and zero counts witnesses nothing (`applicable: false`).
103
+ */
104
+ export function judgeModelUsage(summary: Rec, taskIds: readonly string[], log: { bracketed: boolean; usage: readonly Rec[] }, trials: number): EfficiencyVerdict {
105
+ const entries = (Array.isArray(summary['tasks']) ? (summary['tasks'] as unknown[]) : []).filter(isRec);
106
+ const effs = taskIds.map((id) => entries.find((e) => e['taskId'] === id)?.['efficiency']);
107
+ const findings: EfficiencyFinding[] = [];
108
+ let witnessed = false;
109
+ for (const [field, of] of FIELDS) {
110
+ const vals = effs.map((x) => (isRec(x) ? x[field] : undefined));
111
+ if (!vals.every((v) => typeof v === 'number')) continue;
112
+ const reported = (vals as number[]).reduce((a, b) => a + b, 0) * trials;
113
+ const inLog = log.usage.reduce((a, u) => a + (typeof of(u) === 'number' ? (of(u) as number) : 0), 0);
114
+ if (reported === 0 && inLog === 0) continue;
115
+ witnessed = true;
116
+ findings.push(log.bracketed
117
+ ? { ok: close(reported, inLog), message: `the per-task efficiency.${field} values times ${trials} trial(s) MUST sum to the ${inLog} the agent's provider.usage events inside its invocation brackets carry (got ${reported})` }
118
+ : { ok: reported <= inLog + 1e-9 * Math.max(1, inLog), message: `the per-task efficiency.${field} values times ${trials} trial(s) MUST NOT exceed the ${inLog} the run's provider.usage events carry (got ${reported})` });
119
+ }
120
+ return witnessed ? { applicable: true, findings } : { applicable: false, findings: [] };
121
+ }
122
+
123
+ /**
124
+ * §B "cost counts every trial": on a multi-trial run the summary's
125
+ * `totalCostUsd` holds the `costEstimateUsd` of the agent's usage in every
126
+ * trial, so a host that priced only one trial reads short. Only that floor is
127
+ * judged: whether a judge's or the host's own calls are priced in is not
128
+ * pinned, so a higher total is not a failure. Judged only
129
+ * with brackets (otherwise the agent's usage cannot be told from the host's
130
+ * own) and only when every attributed usage event carries a cost.
131
+ */
132
+ export function judgeCostEveryTrial(summary: Rec, log: { bracketed: boolean; usage: readonly Rec[] }): EfficiencyVerdict {
133
+ const total = summary['totalCostUsd'];
134
+ if (typeof total !== 'number' || !log.bracketed || log.usage.length === 0) return { applicable: false, findings: [] };
135
+ const costs = log.usage.map((u) => u['costEstimateUsd']);
136
+ if (!costs.every((c) => typeof c === 'number')) return { applicable: false, findings: [] };
137
+ const sum = (costs as number[]).reduce((a, b) => a + b, 0);
138
+ return { applicable: true, findings: [{ ok: total >= sum || close(total, sum), message: `totalCostUsd MUST count every trial: it MUST be at least the ${sum} costEstimateUsd of the agent's ${log.usage.length} provider.usage events across all trials (got ${total})` }] };
139
+ }
@@ -38,6 +38,15 @@
38
38
  * optional, so a host that reports none records `inapplicable`. Judge in
39
39
  * `lib/eval-efficiency-witness.ts`. The never-gated rule is not judged:
40
40
  * no fixture makes efficiency the only difference between two verdicts.
41
+ * 6c. §C model usage and §B cost (2.46.26), on the same runs. The per-task
42
+ * `modelCallCount`, `inputTokens` and `outputTokens`, times the trial
43
+ * count, sum to the agent's `provider.usage` inside its
44
+ * `agent.invocation.*` brackets (judge and delegate calls excluded), or do
45
+ * not exceed the run's usage when the host emits no brackets
46
+ * (`0244.efficiency-model-usage`). On the trials run, `totalCostUsd` is
47
+ * at least the agent's priced usage over all three trials
48
+ * (`0244.cost-every-trial`). The scripted agent need not call a model, so
49
+ * a run with no usage, no brackets or no prices records `inapplicable`.
41
50
  * 6b. §D through the counter tool `conformance.eval:counter` (2.46.25, G2),
42
51
  * gated on `fixtureMatching` and both counter fixtures in discovery.
43
52
  * Three sequential runs: `conformance-eval-counter-live` (A), then
@@ -100,7 +109,7 @@ import { judgeEvalEnvelope, judgeSummaryServed } from '../lib/eval-envelope-witn
100
109
  import { gradeTrajectory, passAtK, passHatK, scoreStderr, withinTolerance, type TrajectorySpec } from '../lib/eval-trajectory.js';
101
110
  import { judgeMeanGated, judgeSuiteGated } from '../lib/eval-gate-witness.js';
102
111
  import { judgeFixtureErrorReplayed } from '../lib/eval-fixture-error-witness.js';
103
- import { judgeToolCallCount } from '../lib/eval-efficiency-witness.js';
112
+ import { agentUsage, judgeCostEveryTrial, judgeModelUsage, judgeToolCallCount } from '../lib/eval-efficiency-witness.js';
104
113
  import { counterCalls, judgeFirstUnconsumed, judgeLiveMiss, judgeMissNoLiveCall, type CounterCall } from '../lib/eval-counter-witness.js';
105
114
 
106
115
  const PROFILE = majorProfile(2);
@@ -117,6 +126,8 @@ const ID_TRIAL_STATS = 'openwop.requirement.0244.trial-stats-formula';
117
126
  const ID_MISS = 'openwop.requirement.0244.fixture-miss-fails';
118
127
  const ID_REFUSED = 'openwop.requirement.0244.unadvertised-feature-refused';
119
128
  const ID_EFFICIENCY = 'openwop.requirement.0244.efficiency-tool-calls';
129
+ const ID_MODEL_USAGE = 'openwop.requirement.0244.efficiency-model-usage';
130
+ const ID_COST_TRIALS = 'openwop.requirement.0244.cost-every-trial';
120
131
  const ID_LIVE_MISS = 'openwop.requirement.0244.live-miss-counted';
121
132
  const ID_FIRST_UNCONSUMED = 'openwop.requirement.0244.first-unconsumed';
122
133
  const ID_NO_LIVE_CALL = 'openwop.requirement.0244.miss-no-live-call';
@@ -346,6 +357,25 @@ describe('v2 RFC 0244 — host behaviour', () => {
346
357
  for (const v of verdicts) for (const x of v.findings) expect(x.ok, req(ID_EFFICIENCY, 'eval-summary.schema.json efficiency (RFC 0244 §C)', x.message)).toBe(true);
347
358
  });
348
359
 
360
+ it('efficiency model and token counts match the agent\'s provider.usage (§C)', async () => {
361
+ const r = await trajectoryRun();
362
+ if ('skip' in r) return softSkip(...r.skip);
363
+ const ids = (s: Suite) => s.tasks.map((t) => t.taskId);
364
+ const verdicts = [judgeModelUsage(r.o.summary, ids(fixture('conformance-eval-trajectory')), agentUsage(r.o.events, AGENT), 1)];
365
+ const t = await trialsRun();
366
+ if (!('skip' in t)) verdicts.push(judgeModelUsage(t.o.summary, ids(t.suite), agentUsage(t.o.events, AGENT), t.n));
367
+ if (!verdicts.some((v) => v.applicable)) return softSkip('inapplicable', 'no run carries both a reported model count and provider.usage to check it against (the scripted agent need not call a model; RFC 0244 §C fields are optional)');
368
+ for (const v of verdicts) for (const x of v.findings) expect(x.ok, req(ID_MODEL_USAGE, 'eval-summary.schema.json efficiency (RFC 0244 §C)', x.message)).toBe(true);
369
+ });
370
+
371
+ it('totalCostUsd counts every trial (§B)', async () => {
372
+ const t = await trialsRun();
373
+ if ('skip' in t) return softSkip(...t.skip);
374
+ const v = judgeCostEveryTrial(t.o.summary, agentUsage(t.o.events, AGENT));
375
+ if (!v.applicable) return softSkip('inapplicable', 'the trials run carries no totalCostUsd, no agent.invocation.* brackets, or an unpriced provider.usage, so the per-trial cost is not observable');
376
+ for (const x of v.findings) expect(x.ok, req(ID_COST_TRIALS, 'agent-eval-suite.schema.json thresholds.maxCostUsd, eval-summary.schema.json totalCostUsd (RFC 0244 §B)', x.message)).toBe(true);
377
+ });
378
+
349
379
  type CounterRuns = { skip: [Parameters<typeof softSkip>[0], string] } | { a: CounterCall[]; b: CounterCall[]; c: CounterCall[]; aMisses: unknown };
350
380
  let counterSeq: Promise<CounterRuns> | undefined;
351
381
  /** A → B → C, strictly in order, once per worker: the three counter legs read the same runs. */