@openwop/openwop-conformance 2.45.15 → 2.45.17
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 +33 -0
- package/README.md +2 -2
- package/dist/spec-artifacts.lock.json +2 -2
- package/package.json +2 -2
- package/requirements.json +1335 -14
- package/scenario-majors.json +104 -2
- package/schemas/CORPUS-STAMP.json +13 -13
- package/src/lib/artifact-schema-url-witness.ts +83 -0
- package/src/lib/dispatch-witness.ts +212 -0
- package/src/lib/family-advert-witness.ts +204 -5
- package/src/lib/fixture-run-observer.ts +97 -0
- package/src/lib/prompt-library-witness.ts +11 -2
- package/src/lib/provider-usage-witness.ts +63 -0
- package/src/lib/run-graph-double.ts +144 -0
- package/src/lib/subworkflow-witness.ts +192 -0
- package/src/scenarios/v2-agent-runtime-advertisement.test.ts +51 -0
- package/src/scenarios/v2-ai-envelope-advertisement.test.ts +43 -0
- package/src/scenarios/v2-artifact-created-static.test.ts +92 -0
- package/src/scenarios/v2-artifact-type-schema-url.test.ts +44 -0
- package/src/scenarios/v2-artifact-types-advertisement.test.ts +64 -0
- package/src/scenarios/v2-authorization-advertisement.test.ts +66 -0
- package/src/scenarios/v2-channel-presence-advertisement.test.ts +41 -0
- package/src/scenarios/v2-conversation-turn-model-provenance-advertisement.test.ts +41 -0
- package/src/scenarios/v2-conversation-turn-model-provenance.test.ts +110 -0
- package/src/scenarios/v2-credentials-advertisement.test.ts +66 -0
- package/src/scenarios/v2-data-residency-admission.test.ts +98 -0
- package/src/scenarios/v2-data-residency-advertisement.test.ts +52 -0
- package/src/scenarios/v2-dead-letter-advertisement.test.ts +54 -0
- package/src/scenarios/v2-discovery-etag.test.ts +86 -0
- package/src/scenarios/v2-dispatch-input-mapping.test.ts +70 -0
- package/src/scenarios/v2-dispatch-loop.test.ts +80 -0
- package/src/scenarios/v2-envelope-contracts-advertisement.test.ts +40 -0
- package/src/scenarios/v2-export-bundle-static.test.ts +108 -0
- package/src/scenarios/v2-multi-party-conversation-advertisement.test.ts +52 -0
- package/src/scenarios/v2-node-pack-runtimes-advertisement.test.ts +52 -0
- package/src/scenarios/v2-nondeterminism-policy-advertisement.test.ts +41 -0
- package/src/scenarios/v2-portability-advertisement.test.ts +63 -0
- package/src/scenarios/v2-prompt-library-advertisement.test.ts +40 -0
- package/src/scenarios/v2-prompt-list-and-fetch.test.ts +4 -2
- package/src/scenarios/v2-provider-usage-advertisement.test.ts +61 -0
- package/src/scenarios/v2-provider-usage-emission.test.ts +50 -0
- package/src/scenarios/v2-provider-usage-payload-static.test.ts +92 -0
- package/src/scenarios/v2-purpose-propagation-advertisement.test.ts +52 -0
- package/src/scenarios/v2-run-snapshot-etag.test.ts +35 -22
- package/src/scenarios/v2-scheduling-advertisement.test.ts +55 -0
- package/src/scenarios/v2-self-hosted-runner-advertisement.test.ts +52 -0
- package/src/scenarios/v2-self-hosted-runner-frames-static.test.ts +121 -0
- package/src/scenarios/v2-sub-workflow-advertisement.test.ts +53 -0
- package/src/scenarios/v2-subworkflow-input-mapping.test.ts +74 -0
- package/src/scenarios/v2-subworkflow-linkage.test.ts +76 -0
- package/src/scenarios/v2-ui-plugins-advertisement.test.ts +85 -0
package/scenario-majors.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "GENERATED by conformance/scripts/generate-scenario-majors.mjs (RFC 0168 §D.3). Do not edit; add a file to BOTH_MAJORS in the generator to target both majors.",
|
|
3
3
|
"counts": {
|
|
4
|
-
"files":
|
|
4
|
+
"files": 649,
|
|
5
5
|
"v1": 455,
|
|
6
|
-
"v2":
|
|
6
|
+
"v2": 209
|
|
7
7
|
},
|
|
8
8
|
"majors": {
|
|
9
9
|
"a2a-1-0-agent-card.test.ts": [
|
|
@@ -1299,6 +1299,12 @@
|
|
|
1299
1299
|
"v2-agent-org-chart-served-shape.test.ts": [
|
|
1300
1300
|
2
|
|
1301
1301
|
],
|
|
1302
|
+
"v2-agent-runtime-advertisement.test.ts": [
|
|
1303
|
+
2
|
|
1304
|
+
],
|
|
1305
|
+
"v2-ai-envelope-advertisement.test.ts": [
|
|
1306
|
+
2
|
|
1307
|
+
],
|
|
1302
1308
|
"v2-ai-envelope-shape-static.test.ts": [
|
|
1303
1309
|
2
|
|
1304
1310
|
],
|
|
@@ -1314,12 +1320,24 @@
|
|
|
1314
1320
|
"v2-artifact-a2a-shape.test.ts": [
|
|
1315
1321
|
2
|
|
1316
1322
|
],
|
|
1323
|
+
"v2-artifact-created-static.test.ts": [
|
|
1324
|
+
2
|
|
1325
|
+
],
|
|
1326
|
+
"v2-artifact-type-schema-url.test.ts": [
|
|
1327
|
+
2
|
|
1328
|
+
],
|
|
1329
|
+
"v2-artifact-types-advertisement.test.ts": [
|
|
1330
|
+
2
|
|
1331
|
+
],
|
|
1317
1332
|
"v2-assurance-downgrade-audited.test.ts": [
|
|
1318
1333
|
2
|
|
1319
1334
|
],
|
|
1320
1335
|
"v2-auth-challenge.test.ts": [
|
|
1321
1336
|
2
|
|
1322
1337
|
],
|
|
1338
|
+
"v2-authorization-advertisement.test.ts": [
|
|
1339
|
+
2
|
|
1340
|
+
],
|
|
1323
1341
|
"v2-bound-id-kinds.test.ts": [
|
|
1324
1342
|
2
|
|
1325
1343
|
],
|
|
@@ -1350,6 +1368,9 @@
|
|
|
1350
1368
|
"v2-chain-pin-exact.test.ts": [
|
|
1351
1369
|
2
|
|
1352
1370
|
],
|
|
1371
|
+
"v2-channel-presence-advertisement.test.ts": [
|
|
1372
|
+
2
|
|
1373
|
+
],
|
|
1353
1374
|
"v2-client-version-header.test.ts": [
|
|
1354
1375
|
2
|
|
1355
1376
|
],
|
|
@@ -1365,6 +1386,12 @@
|
|
|
1365
1386
|
"v2-content-locale-keys.test.ts": [
|
|
1366
1387
|
2
|
|
1367
1388
|
],
|
|
1389
|
+
"v2-conversation-turn-model-provenance-advertisement.test.ts": [
|
|
1390
|
+
2
|
|
1391
|
+
],
|
|
1392
|
+
"v2-conversation-turn-model-provenance.test.ts": [
|
|
1393
|
+
2
|
|
1394
|
+
],
|
|
1368
1395
|
"v2-conversation-turn-parts.test.ts": [
|
|
1369
1396
|
2
|
|
1370
1397
|
],
|
|
@@ -1377,6 +1404,27 @@
|
|
|
1377
1404
|
"v2-credential-interrupt.test.ts": [
|
|
1378
1405
|
2
|
|
1379
1406
|
],
|
|
1407
|
+
"v2-credentials-advertisement.test.ts": [
|
|
1408
|
+
2
|
|
1409
|
+
],
|
|
1410
|
+
"v2-data-residency-admission.test.ts": [
|
|
1411
|
+
2
|
|
1412
|
+
],
|
|
1413
|
+
"v2-data-residency-advertisement.test.ts": [
|
|
1414
|
+
2
|
|
1415
|
+
],
|
|
1416
|
+
"v2-dead-letter-advertisement.test.ts": [
|
|
1417
|
+
2
|
|
1418
|
+
],
|
|
1419
|
+
"v2-discovery-etag.test.ts": [
|
|
1420
|
+
2
|
|
1421
|
+
],
|
|
1422
|
+
"v2-dispatch-input-mapping.test.ts": [
|
|
1423
|
+
2
|
|
1424
|
+
],
|
|
1425
|
+
"v2-dispatch-loop.test.ts": [
|
|
1426
|
+
2
|
|
1427
|
+
],
|
|
1380
1428
|
"v2-dual-stack-negotiation.test.ts": [
|
|
1381
1429
|
2
|
|
1382
1430
|
],
|
|
@@ -1395,6 +1443,9 @@
|
|
|
1395
1443
|
"v2-enum-growth-rule.test.ts": [
|
|
1396
1444
|
2
|
|
1397
1445
|
],
|
|
1446
|
+
"v2-envelope-contracts-advertisement.test.ts": [
|
|
1447
|
+
2
|
|
1448
|
+
],
|
|
1398
1449
|
"v2-envelope-reasoning-shape.test.ts": [
|
|
1399
1450
|
2
|
|
1400
1451
|
],
|
|
@@ -1425,6 +1476,9 @@
|
|
|
1425
1476
|
"v2-event-type-closed.test.ts": [
|
|
1426
1477
|
2
|
|
1427
1478
|
],
|
|
1479
|
+
"v2-export-bundle-static.test.ts": [
|
|
1480
|
+
2
|
|
1481
|
+
],
|
|
1428
1482
|
"v2-ext-family-claims.test.ts": [
|
|
1429
1483
|
2
|
|
1430
1484
|
],
|
|
@@ -1521,6 +1575,9 @@
|
|
|
1521
1575
|
"v2-mrtr-rounds-ceiling.test.ts": [
|
|
1522
1576
|
2
|
|
1523
1577
|
],
|
|
1578
|
+
"v2-multi-party-conversation-advertisement.test.ts": [
|
|
1579
|
+
2
|
|
1580
|
+
],
|
|
1524
1581
|
"v2-negotiation-authenticated.test.ts": [
|
|
1525
1582
|
2
|
|
1526
1583
|
],
|
|
@@ -1530,6 +1587,12 @@
|
|
|
1530
1587
|
"v2-no-transport-advertisement.test.ts": [
|
|
1531
1588
|
2
|
|
1532
1589
|
],
|
|
1590
|
+
"v2-node-pack-runtimes-advertisement.test.ts": [
|
|
1591
|
+
2
|
|
1592
|
+
],
|
|
1593
|
+
"v2-nondeterminism-policy-advertisement.test.ts": [
|
|
1594
|
+
2
|
|
1595
|
+
],
|
|
1533
1596
|
"v2-oauth-client-pkce-state-iss.test.ts": [
|
|
1534
1597
|
2
|
|
1535
1598
|
],
|
|
@@ -1563,6 +1626,9 @@
|
|
|
1563
1626
|
"v2-poll-cursor-v2.test.ts": [
|
|
1564
1627
|
2
|
|
1565
1628
|
],
|
|
1629
|
+
"v2-portability-advertisement.test.ts": [
|
|
1630
|
+
2
|
|
1631
|
+
],
|
|
1566
1632
|
"v2-preferred-version-default.test.ts": [
|
|
1567
1633
|
2
|
|
1568
1634
|
],
|
|
@@ -1578,6 +1644,9 @@
|
|
|
1578
1644
|
"v2-prompt-end-to-end-events.test.ts": [
|
|
1579
1645
|
2
|
|
1580
1646
|
],
|
|
1647
|
+
"v2-prompt-library-advertisement.test.ts": [
|
|
1648
|
+
2
|
|
1649
|
+
],
|
|
1581
1650
|
"v2-prompt-list-and-fetch.test.ts": [
|
|
1582
1651
|
2
|
|
1583
1652
|
],
|
|
@@ -1602,6 +1671,18 @@
|
|
|
1602
1671
|
"v2-provider-conflict.test.ts": [
|
|
1603
1672
|
2
|
|
1604
1673
|
],
|
|
1674
|
+
"v2-provider-usage-advertisement.test.ts": [
|
|
1675
|
+
2
|
|
1676
|
+
],
|
|
1677
|
+
"v2-provider-usage-emission.test.ts": [
|
|
1678
|
+
2
|
|
1679
|
+
],
|
|
1680
|
+
"v2-provider-usage-payload-static.test.ts": [
|
|
1681
|
+
2
|
|
1682
|
+
],
|
|
1683
|
+
"v2-purpose-propagation-advertisement.test.ts": [
|
|
1684
|
+
2
|
|
1685
|
+
],
|
|
1605
1686
|
"v2-queue-cross-tenant-isolation.test.ts": [
|
|
1606
1687
|
2
|
|
1607
1688
|
],
|
|
@@ -1662,12 +1743,21 @@
|
|
|
1662
1743
|
"v2-safefetch-ssrf-refused.test.ts": [
|
|
1663
1744
|
2
|
|
1664
1745
|
],
|
|
1746
|
+
"v2-scheduling-advertisement.test.ts": [
|
|
1747
|
+
2
|
|
1748
|
+
],
|
|
1665
1749
|
"v2-secret-canary-absent.test.ts": [
|
|
1666
1750
|
2
|
|
1667
1751
|
],
|
|
1668
1752
|
"v2-secrets-run-witness.test.ts": [
|
|
1669
1753
|
2
|
|
1670
1754
|
],
|
|
1755
|
+
"v2-self-hosted-runner-advertisement.test.ts": [
|
|
1756
|
+
2
|
|
1757
|
+
],
|
|
1758
|
+
"v2-self-hosted-runner-frames-static.test.ts": [
|
|
1759
|
+
2
|
|
1760
|
+
],
|
|
1671
1761
|
"v2-sse-last-event-id-cursor.test.ts": [
|
|
1672
1762
|
2
|
|
1673
1763
|
],
|
|
@@ -1683,9 +1773,18 @@
|
|
|
1683
1773
|
"v2-stream-sse-projection.test.ts": [
|
|
1684
1774
|
2
|
|
1685
1775
|
],
|
|
1776
|
+
"v2-sub-workflow-advertisement.test.ts": [
|
|
1777
|
+
2
|
|
1778
|
+
],
|
|
1686
1779
|
"v2-subject-link-record.test.ts": [
|
|
1687
1780
|
2
|
|
1688
1781
|
],
|
|
1782
|
+
"v2-subworkflow-input-mapping.test.ts": [
|
|
1783
|
+
2
|
|
1784
|
+
],
|
|
1785
|
+
"v2-subworkflow-linkage.test.ts": [
|
|
1786
|
+
2
|
|
1787
|
+
],
|
|
1689
1788
|
"v2-table-schema-enforcement.test.ts": [
|
|
1690
1789
|
2
|
|
1691
1790
|
],
|
|
@@ -1704,6 +1803,9 @@
|
|
|
1704
1803
|
"v2-trigger-dead-letter-read.test.ts": [
|
|
1705
1804
|
2
|
|
1706
1805
|
],
|
|
1806
|
+
"v2-ui-plugins-advertisement.test.ts": [
|
|
1807
|
+
2
|
|
1808
|
+
],
|
|
1707
1809
|
"v2-unadvertised-operation-not-found.test.ts": [
|
|
1708
1810
|
2
|
|
1709
1811
|
],
|
|
@@ -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.45.
|
|
5
|
-
"corpusTag": "v2.45.
|
|
4
|
+
"version": "2.45.17",
|
|
5
|
+
"corpusTag": "v2.45.17",
|
|
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": "
|
|
13
|
-
"api/v2/asyncapi.yaml": "
|
|
14
|
-
"api/v2/openapi.yaml": "
|
|
12
|
+
"api/seams-v2.yaml": "d963b75d8b3b689a67e276f29024d7d2b58a4b4a79c11b9f2c112b30c5173156",
|
|
13
|
+
"api/v2/asyncapi.yaml": "a1d8826c7a8c6bc64361a1db69b607025988fc7fb64a2cb52cca0a79f9ace7c5",
|
|
14
|
+
"api/v2/openapi.yaml": "d9c1a78a13a32c653d148126c7dd086bd25e1394cac2f4a35db6290ffdc7fa3b",
|
|
15
15
|
"api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
|
|
16
16
|
"schemas/README.md": "bd1c00fae7b6fda506a75aff841bbdc438d4ce092642a72041203bee999b88de",
|
|
17
17
|
"schemas/a2a-task-state.schema.json": "75d5049dea8bd873ff0e7546f1c60c8d36c219bec7084264360be54a8be30ae1",
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"schemas/v2/audit-verify-result.schema.json": "14af8e9283510f0a40e48a2059c929ee44e0fc9fa3cc66a95bfbe90b17c48297",
|
|
119
119
|
"schemas/v2/budget-policy.schema.json": "1de68095db0beb5c7a4be629de26e79f62ebbe748a88d46f36e768edfd1f0d68",
|
|
120
120
|
"schemas/v2/capabilities.schema.json": "c7a01b2f569139f99ba5e1a5329a42556fbd82bc743f8fd96963304395fc9ef0",
|
|
121
|
-
"schemas/v2/certification-bundle.schema.json": "
|
|
121
|
+
"schemas/v2/certification-bundle.schema.json": "012c0176fbe05425507a8096412344388c0e2e1884c5fe1bc189ef1af0532997",
|
|
122
122
|
"schemas/v2/channel-presence-payload.schema.json": "4eeb224910e6f7eee3ab5e7c3899559c25c83a26d0022e0ad195c4672611977a",
|
|
123
123
|
"schemas/v2/channel-written-payload.schema.json": "ccecff3c71a3275ad8db035ac0e04db25e6f8d23cf091ddbcd5a60d1be1cbb6b",
|
|
124
124
|
"schemas/v2/chat-card-pack-manifest.schema.json": "92a57db2fd4b2463f14ef155fef8e3f18afc78960b646459dcf32efc79ff6bf5",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"schemas/v2/configurable.schema.json": "33a6884047e2490f723733bf8b74d3b9164e00374cfea6dc3eac5a70dc368861",
|
|
129
129
|
"schemas/v2/connection-pack-manifest.schema.json": "8d019de6bd0c5b14ea3b227580734ec792521493b396a850f7f9217aa7a6a547",
|
|
130
130
|
"schemas/v2/connection-provider-registry.schema.json": "5b404da328a95c45808929e233ee766ebd635cf0df6f5d15d4c19354dfd7e75d",
|
|
131
|
-
"schemas/v2/conversation-event.schema.json": "
|
|
131
|
+
"schemas/v2/conversation-event.schema.json": "51dce69b33e3eb1913b9b2a0fcc0bee3dcf86761faf0c56dd004f4c580c95d39",
|
|
132
132
|
"schemas/v2/conversation-turn.schema.json": "75bb6a4a03072a958feb5b34e2a1f40471e9e3996a81fa430b65717f0773c9a4",
|
|
133
133
|
"schemas/v2/credential-provenance.schema.json": "f86b09e94b1c524dec7d1c6353965665ae8891e9517faef6e742d639c5578c99",
|
|
134
134
|
"schemas/v2/credential-reference.schema.json": "ea699ce30f58fb2c32d4279158b3f730f70be7b2dc8c3037693a76e66eb3e001",
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
"schemas/v2/memory-entry.schema.json": "290576ae84f4fef4cdf975932b87963283b11c50ea3d2654b32cd96aa6537c3d",
|
|
161
161
|
"schemas/v2/memory-list-options.schema.json": "f66703bccb68efb28391c273abb66aa117ee5b5ce475c477846ed700c336afcd",
|
|
162
162
|
"schemas/v2/node-pack-manifest.schema.json": "6e25106c647d58ff6b11c198a83de7f1f988e47c8e3bf9f28ac5f84eef900f5d",
|
|
163
|
-
"schemas/v2/orchestrator-decision.schema.json": "
|
|
163
|
+
"schemas/v2/orchestrator-decision.schema.json": "4d4b4c5fe73c22a1f42242b403650206ad58fd981f8fd45795894cebe3a514ae",
|
|
164
164
|
"schemas/v2/org-chart-responsibility-view.schema.json": "8a2565e4cdc6737a3946a70799f93642808b92f9c8d56dcdff3a0782053b89a1",
|
|
165
165
|
"schemas/v2/pack-lockfile.schema.json": "2685417702c105146b780cd99154296a46578fbb10d81c8c713348ee26fea898",
|
|
166
166
|
"schemas/v2/part.schema.json": "08b75eaec9a0b4a8cedca7bab732dd906b52b0749eaa444ec1ac015aa43519a5",
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
"schemas/v2/residency.schema.json": "3fd23c9732beb140504e81560fc426eb6764d547e56da5fb92c5a5c7bf04db3a",
|
|
174
174
|
"schemas/v2/run-ancestry-response.schema.json": "334c17f2062dea62726ca1d07b8be3f169cdc422af843c1def5fb317039814c9",
|
|
175
175
|
"schemas/v2/run-diff-response.schema.json": "8bdb2045c274580038bd74781f7d062f5049839797c164a89de4ed89edc53a74",
|
|
176
|
-
"schemas/v2/run-event-payloads.schema.json": "
|
|
176
|
+
"schemas/v2/run-event-payloads.schema.json": "942d6f65a765f6b574922a54d1e531ab66bc8d5c673a006ec68f8d75f3f0aec9",
|
|
177
177
|
"schemas/v2/run-event.schema.json": "2f0d7416bd376c56affe97b6b2b49981532e8e9ff45c0a162cf806c78b3e7fb7",
|
|
178
178
|
"schemas/v2/run-list-response.schema.json": "c2dbc34768dcf64528914a213aa3cb55952e8e3e90a64b04a9423b2a19749d38",
|
|
179
179
|
"schemas/v2/run-options.schema.json": "f0e9f494d80086c2ed2cf9fe87df54e5b4e66601699c4a1089f4edbc7ba58867",
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
"schemas/workspace-file.schema.json": "464de85c2a068243084ee9c1d969bc7cd5d8f7948574e58450d6493c38a0e1e4",
|
|
208
208
|
"spec/v1/alias-detectors.json": "0b2f28808ffe0b9d98a187775038c3406bb70919747a788a6e4f866e293ae6d3",
|
|
209
209
|
"spec/v1/capability-declaration-classes.json": "e7729aed5c4b4e1dd02abab0530f14cc95f5d4070fe51fb139e7f5cccefa00c6",
|
|
210
|
-
"spec/v1/core-standard-manifest.json": "
|
|
210
|
+
"spec/v1/core-standard-manifest.json": "2ad9ad7d0d478da17f8b9829997c4fc9b905162e3c2b0c6e4828f50470f7f4e0",
|
|
211
211
|
"spec/v1/deprecations.json": "a3293072ea951857395d05f0437264e88965f1e9019ff61c55bacfa9c1aaa17c",
|
|
212
212
|
"spec/v1/deprecations.schema.json": "3e393c405d2a41b467d8c5e3c468549078df1ce6a6d2588fc488097b95d9b55b",
|
|
213
213
|
"spec/v1/end-of-support.json": "35f0bf3b70fe78b16e2a2fd81a153fc27e703f6c16376c6fe7cdf1f4f2c4e6d4",
|
|
@@ -309,9 +309,9 @@
|
|
|
309
309
|
"spec/v2/path-manifest.json": "b84c7561f50c7df0cb61b202bd6595acad3ee7edca7a45f711949bea3c69bd27",
|
|
310
310
|
"spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
|
|
311
311
|
"spec/v2/profiles.json": "180beb9ef2d161766fa23b2987e7e829851e3d316273147cf6a4a3f324befd6b",
|
|
312
|
-
"spec/v2/release.json": "
|
|
312
|
+
"spec/v2/release.json": "5b6e531003a3c47ed176f1f4fa1777b3b597cb386f31b1bfe4ac962df16ae4a3",
|
|
313
313
|
"spec/v2/retention-floors.json": "eaf3722d95c79947af1d4269ef85117e126518c588cfcf1a2b21b97269f51624",
|
|
314
|
-
"spec/v2/surface-baseline.json": "
|
|
314
|
+
"spec/v2/surface-baseline.json": "273566823eac3465b9f692c9cb795eca669e753bd0e733575b4722d176e115ce"
|
|
315
315
|
},
|
|
316
|
-
"corpusCommit": "
|
|
316
|
+
"corpusCommit": "725db8ec383cc3d61068846def2d5b90771b8933"
|
|
317
317
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The artifact canonical schema-URL witness (`artifact-type-packs.md`
|
|
3
|
+
* §Schema distribution), unaided.
|
|
4
|
+
*
|
|
5
|
+
* "Its canonical URL and `$id` is
|
|
6
|
+
* `{HostBase}/schemas/artifacts/{artifactTypeId}.schema.json`, served as
|
|
7
|
+
* `application/schema+json`. A host advertising `artifactTypes` SHOULD serve
|
|
8
|
+
* each installed type's schema there, and MUST for a host-registered type whose
|
|
9
|
+
* `schemaVersion` it advertises."
|
|
10
|
+
*
|
|
11
|
+
* The MUST set is read from discovery alone: every `artifactTypes.types[id]`
|
|
12
|
+
* with `registrationSource: "host"` and an integer `schemaVersion`
|
|
13
|
+
* (`capabilities.schema.json`: the facet "discloses which §Schema distribution
|
|
14
|
+
* regime applies"). For each, `GET {HostBase}/schemas/artifacts/{id}.schema.json`:
|
|
15
|
+
* served answers `200`;
|
|
16
|
+
* media with `Content-Type: application/schema+json`;
|
|
17
|
+
* schema a JSON object whose `$id` is an absolute URL ending
|
|
18
|
+
* `/schemas/artifacts/{id}.schema.json`.
|
|
19
|
+
* `{HostBase}` is the base the suite drives the host at (the v2 text does not
|
|
20
|
+
* define it further), so the `$id`'s origin is not compared: a host fronted by
|
|
21
|
+
* a public origin legitimately mints its `$id` there.
|
|
22
|
+
*
|
|
23
|
+
* {@link driveSchemaUrls} observes and asserts nothing; {@link judgeSchemaUrl}
|
|
24
|
+
* is pure, proven in `artifact-schema-url-witness.test.ts`.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { driver } from './driver.js';
|
|
28
|
+
import type { MajorProfile } from './major-profile.js';
|
|
29
|
+
import { finding, isRecord, skip, type Finding, type Skip } from './fixture-run-observer.js';
|
|
30
|
+
|
|
31
|
+
const DOC = 'artifact-type-packs.md §Schema distribution';
|
|
32
|
+
|
|
33
|
+
export interface SchemaUrlObservation {
|
|
34
|
+
readonly artifactTypeId: string;
|
|
35
|
+
readonly path: string;
|
|
36
|
+
readonly status: number;
|
|
37
|
+
readonly contentType: string | null;
|
|
38
|
+
readonly json: unknown;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The host-registered types whose `schemaVersion` the host advertises, sorted. */
|
|
42
|
+
export function hostRegisteredTypes(profile: MajorProfile, doc: unknown): string[] | Skip {
|
|
43
|
+
const fam = profile.family(doc, 'artifactTypes');
|
|
44
|
+
if (fam === null) return skip('inapplicable', 'the host does not advertise artifactTypes');
|
|
45
|
+
const types = isRecord(fam['types']) ? fam['types'] : {};
|
|
46
|
+
const ids = Object.entries(types)
|
|
47
|
+
.filter(([, t]) => isRecord(t) && t['registrationSource'] === 'host' && Number.isInteger(t['schemaVersion']))
|
|
48
|
+
.map(([id]) => id)
|
|
49
|
+
.sort();
|
|
50
|
+
if (ids.length === 0) return skip('inapplicable', 'the host advertises no artifactTypes.types entry with registrationSource "host" and a schemaVersion — serving the canonical URL is only a SHOULD for the rest');
|
|
51
|
+
return ids;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const schemaPath = (artifactTypeId: string): string => `/schemas/artifacts/${encodeURIComponent(artifactTypeId)}.schema.json`;
|
|
55
|
+
|
|
56
|
+
/** Fetch each MUST-served schema. Asserts nothing. */
|
|
57
|
+
export async function driveSchemaUrls(profile: MajorProfile, doc: unknown): Promise<Skip | SchemaUrlObservation[]> {
|
|
58
|
+
const ids = hostRegisteredTypes(profile, doc);
|
|
59
|
+
if (!Array.isArray(ids)) return ids;
|
|
60
|
+
const out: SchemaUrlObservation[] = [];
|
|
61
|
+
for (const artifactTypeId of ids) {
|
|
62
|
+
const path = schemaPath(artifactTypeId);
|
|
63
|
+
const r = await driver.get(path, { headers: { Accept: 'application/schema+json, application/json' } });
|
|
64
|
+
out.push({ artifactTypeId, path, status: r.status, contentType: r.headers.get('content-type'), json: r.json });
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** One type's served schema. Pure. */
|
|
70
|
+
export function judgeSchemaUrl(o: SchemaUrlObservation): Finding[] {
|
|
71
|
+
const media = (o.contentType ?? '').split(';')[0]!.trim().toLowerCase();
|
|
72
|
+
const id = isRecord(o.json) ? o.json['$id'] : undefined;
|
|
73
|
+
let idOk = false;
|
|
74
|
+
if (typeof id === 'string') {
|
|
75
|
+
try { idOk = /^https?:$/.test(new URL(id).protocol) && id.endsWith(`/schemas/artifacts/${o.artifactTypeId}.schema.json`); } catch { idOk = false; }
|
|
76
|
+
}
|
|
77
|
+
return [
|
|
78
|
+
finding(o.status === 200, DOC, `the host MUST serve host-registered ${o.artifactTypeId}'s schema at ${o.path} (got ${o.status})`),
|
|
79
|
+
finding(media === 'application/schema+json', DOC, `${o.path} MUST be served as application/schema+json (got ${JSON.stringify(o.contentType)})`),
|
|
80
|
+
finding(isRecord(o.json), DOC, `${o.path} MUST be a JSON Schema object`),
|
|
81
|
+
finding(idOk, DOC, `the schema's $id MUST be its canonical URL, {HostBase}/schemas/artifacts/${o.artifactTypeId}.schema.json (got ${JSON.stringify(id)})`),
|
|
82
|
+
];
|
|
83
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `core.dispatch` witnesses, fixture ports through `POST /runs` and
|
|
3
|
+
* `events/poll`. No seam.
|
|
4
|
+
*
|
|
5
|
+
* Input mapping (`spec/v2/facets/agents.schema.json` `dispatchMapping`;
|
|
6
|
+
* `schemas/v2/dispatch-config.schema.json` `inputMapping`), on
|
|
7
|
+
* `conformance-dispatch-input-mapping[-no-default]` →
|
|
8
|
+
* `conformance-dispatch-input-mapping-child`. A host advertising
|
|
9
|
+
* `agents.dispatchMapping: true` honors `inputMapping`, "building child inputs
|
|
10
|
+
* from parent variables before dispatch": the child receives
|
|
11
|
+
* `inputs[childKey] = parentVariables[parentKey]`.
|
|
12
|
+
* projection the child's `inputs.childGreeting` is the parent's
|
|
13
|
+
* `parentName` ("Alice");
|
|
14
|
+
* unset an unset `parentName` projects to undefined — the child's
|
|
15
|
+
* `inputs.childGreeting` is absent, never `null` or a placeholder.
|
|
16
|
+
*
|
|
17
|
+
* Supervisor loop (`execution.md` §`multiAgent`, level 1 and level 5), on
|
|
18
|
+
* `conformance-dispatch-loop`:
|
|
19
|
+
* terminates the run completes; each turn records a decision as
|
|
20
|
+
* `runOrchestrator.decided` (`orchestrator.decided` at major 2),
|
|
21
|
+
* and the last is `terminate` — `terminate` completes the run,
|
|
22
|
+
* so no decision follows it;
|
|
23
|
+
* decisions every decision payload is well-formed (the decision checked
|
|
24
|
+
* branch by branch — see {@link decisionBranchValidator}), and
|
|
25
|
+
* its `agentId` is the same for the run's lifetime;
|
|
26
|
+
* iteration at `executionModel.version >= 5`, every decision carries
|
|
27
|
+
* `iteration`, 1-based, incremented by exactly 1 per turn.
|
|
28
|
+
*
|
|
29
|
+
* The drivers observe and assert nothing; the judges are pure, proven in
|
|
30
|
+
* `dispatch-witness.test.ts`.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { isFixtureAdvertised } from './fixtures.js';
|
|
34
|
+
import type { MajorProfile } from './major-profile.js';
|
|
35
|
+
import {
|
|
36
|
+
completionsOf, finding, isRecord, observed, observeRun, readRun, runCompleted, skip,
|
|
37
|
+
type Ev, type Finding, type ObservedRun, type ObserveOpts, type Outcome, type RunRead, type Skip, type Validate,
|
|
38
|
+
} from './fixture-run-observer.js';
|
|
39
|
+
|
|
40
|
+
export const DISPATCH_PARENT_FIXTURE = 'conformance-dispatch-input-mapping';
|
|
41
|
+
export const DISPATCH_NO_DEFAULT_FIXTURE = 'conformance-dispatch-input-mapping-no-default';
|
|
42
|
+
export const DISPATCH_CHILD_FIXTURE = 'conformance-dispatch-input-mapping-child';
|
|
43
|
+
export const DISPATCH_NODE = 'dispatch';
|
|
44
|
+
export const LOOP_FIXTURE = 'conformance-dispatch-loop';
|
|
45
|
+
|
|
46
|
+
const DOC_MAP = 'agents.schema.json dispatchMapping; dispatch-config.schema.json inputMapping';
|
|
47
|
+
const DOC_LOOP = 'execution.md §multiAgent';
|
|
48
|
+
|
|
49
|
+
export interface DispatchObservation {
|
|
50
|
+
readonly parent: ObservedRun;
|
|
51
|
+
/** How the child was found: the parent's `node.dispatched`, or the dispatch node's `node.completed` outputs. */
|
|
52
|
+
readonly childRunId: string | undefined;
|
|
53
|
+
readonly child: RunRead | undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** `agents.dispatchMapping: true`, the parent fixture and the child fixture. */
|
|
57
|
+
export function dispatchMappingGate(profile: MajorProfile, doc: unknown, fixture: string): Skip | null {
|
|
58
|
+
const agents = profile.family(doc, 'agents');
|
|
59
|
+
if (agents === null) return skip('inapplicable', 'the host does not advertise agents');
|
|
60
|
+
if (agents['dispatchMapping'] !== true) return skip('inapplicable', 'the host does not advertise agents.dispatchMapping: true, so inputMapping does not bind it (it must refuse the field at registration instead)');
|
|
61
|
+
for (const id of [fixture, DISPATCH_CHILD_FIXTURE]) if (!isFixtureAdvertised(id)) return skip('inapplicable', `fixture ${id} is not advertised — the fixture is the opt-in`);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Find the dispatched child: `node.dispatched` naming the child workflow, else the dispatch node's outputs. */
|
|
66
|
+
export function locateChild(profile: MajorProfile, events: readonly Ev[], childWorkflowId: string): string | undefined {
|
|
67
|
+
const dispatchedType = profile.eventType('node.dispatched') ?? 'node.dispatched';
|
|
68
|
+
const d = events.find((e) => e.type === dispatchedType && e.payload['childWorkflowId'] === childWorkflowId && typeof e.payload['childRunId'] === 'string');
|
|
69
|
+
if (d !== undefined) return d.payload['childRunId'] as string;
|
|
70
|
+
for (const c of completionsOf(events, DISPATCH_NODE)) {
|
|
71
|
+
const out = c.payload['outputs'];
|
|
72
|
+
if (isRecord(out) && typeof out['childRunId'] === 'string' && out['childRunId'].length > 0) return out['childRunId'];
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Run a dispatch input-mapping fixture and follow it to the child. Asserts nothing. */
|
|
78
|
+
export async function driveDispatchMapping(profile: MajorProfile, doc: unknown, fixture: string, opts: ObserveOpts = {}): Promise<Skip | DispatchObservation> {
|
|
79
|
+
const g = dispatchMappingGate(profile, doc, fixture);
|
|
80
|
+
if (g) return g;
|
|
81
|
+
const parent = await observeRun(profile, fixture, opts);
|
|
82
|
+
const childRunId = locateChild(profile, parent.events, DISPATCH_CHILD_FIXTURE);
|
|
83
|
+
return { parent, childRunId, child: childRunId === undefined ? undefined : await readRun(profile, childRunId) };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function childInputs(o: DispatchObservation): Skip | { inputs: Record<string, unknown>; reached: Finding[] } {
|
|
87
|
+
if (o.parent.createStatus !== 201 && o.parent.createStatus !== 202) return { inputs: {}, reached: runCompleted(o.parent) };
|
|
88
|
+
if (o.childRunId === undefined) return skip('inapplicable', `no v2 rule requires a host to expose the dispatched child, and this one does not: the parent log names no ${DISPATCH_CHILD_FIXTURE} run (no node.dispatched, no dispatch-node outputs.childRunId), so its inputs cannot be read`);
|
|
89
|
+
const c = o.child;
|
|
90
|
+
return {
|
|
91
|
+
inputs: c !== undefined && isRecord(c.snapshot['inputs']) ? c.snapshot['inputs'] : {},
|
|
92
|
+
reached: [
|
|
93
|
+
...runCompleted(o.parent),
|
|
94
|
+
finding(c?.status === 200, 'runs.md getRun', `the dispatched child run MUST be readable (GET answered ${String(c?.status)})`),
|
|
95
|
+
finding(c?.snapshot['status'] === 'completed', `fixtures.md ${DISPATCH_CHILD_FIXTURE}`, `the child run MUST end completed (got ${JSON.stringify(c?.snapshot['status'])})`),
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Leg: the child's inputs carry the parent's projected variable. Pure. */
|
|
101
|
+
export function judgeProjection(o: DispatchObservation): Outcome {
|
|
102
|
+
const c = childInputs(o);
|
|
103
|
+
if ('kind' in c) return c;
|
|
104
|
+
return observed([
|
|
105
|
+
...c.reached,
|
|
106
|
+
finding(c.inputs['childGreeting'] === 'Alice', DOC_MAP, `the child MUST receive inputs.childGreeting = parentVariables.parentName ("Alice"; got ${JSON.stringify(c.inputs['childGreeting'])})`),
|
|
107
|
+
]);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Leg: an unset parent variable projects to undefined — absent, never null. Pure. */
|
|
111
|
+
export function judgeUnsetProjection(o: DispatchObservation): Outcome {
|
|
112
|
+
const c = childInputs(o);
|
|
113
|
+
if ('kind' in c) return c;
|
|
114
|
+
return observed([
|
|
115
|
+
...c.reached,
|
|
116
|
+
finding(c.inputs['childGreeting'] !== null, `${DOC_MAP} (mirrors execution.md §subWorkflow inputMapping: never null)`, 'an unset parent variable MUST NOT project as null'),
|
|
117
|
+
finding(!('childGreeting' in c.inputs), DOC_MAP, `inputs[childKey] = parentVariables[parentKey] is undefined for an unset parent variable: inputs.childGreeting MUST be absent (got ${JSON.stringify(c.inputs['childGreeting'])})`),
|
|
118
|
+
]);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface LoopObservation { readonly run: ObservedRun; readonly decidedType: string; readonly version: number }
|
|
122
|
+
|
|
123
|
+
/** `multiAgent.executionModel.version >= 1`, the fixture, and this major's event name. */
|
|
124
|
+
export function loopGate(profile: MajorProfile, doc: unknown): Skip | { decidedType: string; version: number } {
|
|
125
|
+
const ma = profile.family(doc, 'multiAgent');
|
|
126
|
+
const em = isRecord(ma?.['executionModel']) ? ma['executionModel'] : undefined;
|
|
127
|
+
const version = em?.['version'];
|
|
128
|
+
if (typeof version !== 'number' || version < 1) return skip('inapplicable', 'the host does not advertise multiAgent.executionModel (version >= 1), so the supervisor loop does not bind it');
|
|
129
|
+
if (!isFixtureAdvertised(LOOP_FIXTURE)) return skip('inapplicable', `fixture ${LOOP_FIXTURE} is not advertised — the fixture is the opt-in`);
|
|
130
|
+
const decidedType = profile.eventType('runOrchestrator.decided');
|
|
131
|
+
if (decidedType === undefined) return skip('blocked', 'the event codemap is not on disk in this layout — the suite will not guess an event name');
|
|
132
|
+
return { decidedType, version };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Run the loop fixture. Asserts nothing. */
|
|
136
|
+
export async function driveLoop(profile: MajorProfile, doc: unknown, opts: ObserveOpts = {}): Promise<Skip | LoopObservation> {
|
|
137
|
+
const g = loopGate(profile, doc);
|
|
138
|
+
if ('kind' in g) return g;
|
|
139
|
+
return { run: await observeRun(profile, LOOP_FIXTURE, opts), ...g };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const decisions = (o: LoopObservation): Ev[] => o.run.events.filter((e) => e.type === o.decidedType);
|
|
143
|
+
const kindOf = (e: Ev): unknown => (isRecord(e.payload['decision']) ? e.payload['decision']['kind'] : undefined);
|
|
144
|
+
|
|
145
|
+
/** Leg: decisions are recorded, the last is `terminate`, and it completes the run. Pure. */
|
|
146
|
+
export function judgeLoopTerminates(o: LoopObservation): Outcome {
|
|
147
|
+
const ds = decisions(o);
|
|
148
|
+
const firstTerminate = ds.findIndex((e) => kindOf(e) === 'terminate');
|
|
149
|
+
return observed([
|
|
150
|
+
...runCompleted(o.run),
|
|
151
|
+
finding(ds.length > 0, `${DOC_LOOP} (level 1)`, `each turn MUST record its decision as ${o.decidedType} (got none)`),
|
|
152
|
+
finding(ds.length > 0 && kindOf(ds[ds.length - 1]!) === 'terminate', `${DOC_LOOP} (level 1: terminate completes the run)`, `the completed loop's last decision MUST be terminate (got ${JSON.stringify(ds.map(kindOf))})`),
|
|
153
|
+
finding(firstTerminate === -1 || firstTerminate === ds.length - 1, `${DOC_LOOP} (level 1: terminate completes the run)`, `no decision may follow a terminate (got ${JSON.stringify(ds.map(kindOf))})`),
|
|
154
|
+
]);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* A validator for one `OrchestratorDecision`, by its `oneOf` branches.
|
|
159
|
+
*
|
|
160
|
+
* `schemas/v2/orchestrator-decision.schema.json` closes its ROOT with
|
|
161
|
+
* `additionalProperties: false` and declares no root `properties`, so the
|
|
162
|
+
* schema as a whole rejects every decision, `kind` included (the v1 root is
|
|
163
|
+
* open). Validating against it would convict every host. Until the corpus
|
|
164
|
+
* fixes it, a decision is valid when exactly one branch accepts it.
|
|
165
|
+
*/
|
|
166
|
+
export function decisionBranchValidator(branch: (index: number) => Validate, branches = 3): Validate {
|
|
167
|
+
const vs = Array.from({ length: branches }, (_, i) => branch(i));
|
|
168
|
+
return (doc) => {
|
|
169
|
+
const results = vs.map((v) => v(doc));
|
|
170
|
+
const ok = results.filter((r) => r.ok).length === 1;
|
|
171
|
+
return { ok, errors: ok ? '' : results.map((r, i) => `branch ${i}: ${r.errors || 'accepted'}`).join(' | ') };
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const PAYLOAD_KEYS = new Set(['agentId', 'decision', 'iteration', 'causationHostId']);
|
|
176
|
+
const AGENT_ID = /^[A-Za-z0-9._~:-]{1,128}$/;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Leg: every decision payload is well-formed (the `runOrchestratorDecided`
|
|
180
|
+
* def's closed key set and `agentId`; the decision by its branches), and the
|
|
181
|
+
* deciding agent never changes. Pure.
|
|
182
|
+
*/
|
|
183
|
+
export function judgeDecisions(o: LoopObservation, validateDecision: Validate): Outcome {
|
|
184
|
+
const ds = decisions(o);
|
|
185
|
+
if (ds.length === 0) return skip('inapplicable', `the loop recorded no ${o.decidedType}, so there is nothing to judge here — the terminates leg convicts that`);
|
|
186
|
+
const agents = new Set(ds.map((e) => e.payload['agentId']));
|
|
187
|
+
const DEF = 'schemas run-event-payloads runOrchestratorDecided';
|
|
188
|
+
return observed([
|
|
189
|
+
...ds.flatMap((e) => {
|
|
190
|
+
const extra = Object.keys(e.payload).filter((k) => !PAYLOAD_KEYS.has(k));
|
|
191
|
+
const agentId = e.payload['agentId'];
|
|
192
|
+
const v = validateDecision(e.payload['decision']);
|
|
193
|
+
return [
|
|
194
|
+
finding(extra.length === 0, DEF, `a ${o.decidedType} payload carries only agentId, decision, iteration, causationHostId (seq ${e.sequence}; extra ${JSON.stringify(extra)})`),
|
|
195
|
+
finding(typeof agentId === 'string' && AGENT_ID.test(agentId), `${DEF}.agentId`, `every ${o.decidedType} MUST carry agentId (seq ${e.sequence}; got ${JSON.stringify(agentId)})`),
|
|
196
|
+
finding(v.ok, 'schemas orchestrator-decision', `every decision MUST be one OrchestratorDecision (seq ${e.sequence}): ${v.errors}`),
|
|
197
|
+
];
|
|
198
|
+
}),
|
|
199
|
+
finding(agents.size === 1, `${DEF}.agentId`, `orchestrator identity is set at the first decision and does not change (got ${JSON.stringify([...agents])})`),
|
|
200
|
+
]);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Leg: at version >= 5, `iteration` is 1-based and +1 per turn. Pure. */
|
|
204
|
+
export function judgeIteration(o: LoopObservation): Outcome {
|
|
205
|
+
if (o.version < 5) return skip('inapplicable', `the host advertises multiAgent.executionModel.version ${o.version}; iteration binds from level 5`);
|
|
206
|
+
const ds = decisions(o);
|
|
207
|
+
if (ds.length === 0) return skip('inapplicable', `the loop recorded no ${o.decidedType}, so there is nothing to judge here — the terminates leg convicts that`);
|
|
208
|
+
const its = ds.map((e) => e.payload['iteration']);
|
|
209
|
+
return observed([
|
|
210
|
+
finding(its.every((n, i) => n === i + 1), `${DOC_LOOP} (level 5)`, `every ${o.decidedType} MUST carry iteration, 1-based and incremented by exactly 1 per turn (got ${JSON.stringify(its)})`),
|
|
211
|
+
]);
|
|
212
|
+
}
|