@openwop/openwop-conformance 2.0.0-rc.13 → 2.0.0-rc.14

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "package": "@openwop/spec-artifacts",
3
- "version": "2.0.0-rc.13",
4
- "stampSha256": "70588d48596c9141975f89d3116b8fdc93d61d5faf5a93a7be6b9100d4e7311c"
3
+ "version": "2.0.0-rc.14",
4
+ "stampSha256": "d79a223d634538161fa12071ac4ba8ef581b7fa776181aa630ffd7ff28aadeb5"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/openwop-conformance",
3
- "version": "2.0.0-rc.13",
3
+ "version": "2.0.0-rc.14",
4
4
  "description": "Production-ready black-box conformance suite for OpenWOP v1.0 compliant servers.",
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.0.0-rc.13"
59
+ "@openwop/spec-artifacts": "2.0.0-rc.14"
60
60
  }
61
61
  }
package/requirements.json CHANGED
@@ -3,8 +3,8 @@
3
3
  "generatedFrom": "src/scenarios/*.test.ts",
4
4
  "counts": {
5
5
  "files": 544,
6
- "tests": 2119,
7
- "withStableId": 2119,
6
+ "tests": 2118,
7
+ "withStableId": 2118,
8
8
  "interpolatedTitles": 0,
9
9
  "explicitIds": 2057
10
10
  },
@@ -25741,24 +25741,10 @@
25741
25741
  }
25742
25742
  ]
25743
25743
  },
25744
- {
25745
- "id": "openwop.it.v2-advertised-fixtures-exist.every-advertised-fixture-id-is-one-the-corpus-defines",
25746
- "file": "v2-advertised-fixtures-exist.test.ts",
25747
- "line": 60,
25748
- "title": "every advertised fixture id is one the corpus defines",
25749
- "explicitId": null,
25750
- "citations": [
25751
- {
25752
- "section": null,
25753
- "requirement": null,
25754
- "interpolated": true
25755
- }
25756
- ]
25757
- },
25758
25744
  {
25759
25745
  "id": "openwop.it.v2-advertised-fixtures-exist.a-sampled-advertised-fixture-is-actually-creatable-not-just-listed",
25760
25746
  "file": "v2-advertised-fixtures-exist.test.ts",
25761
- "line": 80,
25747
+ "line": 62,
25762
25748
  "title": "a sampled advertised fixture is actually creatable, not just listed",
25763
25749
  "explicitId": null,
25764
25750
  "citations": [
@@ -26561,7 +26547,7 @@
26561
26547
  {
26562
26548
  "id": "openwop.it.v2-era-2-append-vocabulary.the-run-keeps-the-era-it-was-created-with-an-append-does-not-promote-it-to-era-3",
26563
26549
  "file": "v2-era-2-append-vocabulary.test.ts",
26564
- "line": 119,
26550
+ "line": 128,
26565
26551
  "title": "the run keeps the era it was created with; an append does not promote it to era 3",
26566
26552
  "explicitId": null,
26567
26553
  "citations": [
@@ -1,7 +1,7 @@
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.0.0-rc.13",
4
+ "version": "2.0.0-rc.14",
5
5
  "corpusTag": null,
6
6
  "files": {
7
7
  "api/.redocly.lint-ignore.yaml": "bf5a8350b88a72fa43f59605ed8d903ed24b6cfccda5e45509c9f6ed9ee4e712",
@@ -9,9 +9,9 @@
9
9
  "api/grpc/openwop.proto": "c3e72bb17cba514ee98feb6434e6c9b6ea6795bfd086489ec69fd882dd1ad977",
10
10
  "api/openapi.yaml": "39081c59fb696159806b0f2f9a42e7e9ff830d622fcf2ad4159b21357580a955",
11
11
  "api/redocly.yaml": "b0604c89b2ca6d5076ec25725c539dad44a741a811fe524439ee6daef8baa09f",
12
- "api/seams-v2.yaml": "fd9b0ac5fad1dbcde81c072480ab1b2054dfac801620f4b0a56cce293dd55ecf",
13
- "api/v2/asyncapi.yaml": "17c9e96919f050e77a290025ae77f69420a835790e8a434fadea242445f6bdca",
14
- "api/v2/openapi.yaml": "d187a8e648c4db4981dd8b73abbc7b10346febaa30124c7413de7d4f78f56b04",
12
+ "api/seams-v2.yaml": "5c9741ace7a24e7cb9475cec28585b6888809181fe19beffe1d1866a2882531e",
13
+ "api/v2/asyncapi.yaml": "de67cb65409e07291264d3059647a9b558c5b72186c1b6d49b0e1e292c1b048c",
14
+ "api/v2/openapi.yaml": "76c003262b413b7226948c7fddb8a5457fafed95f332213660ecbaf6b15a3bbf",
15
15
  "api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
16
16
  "schemas/README.md": "0c0b737ffcf8f30e7d2809cec8a498232de710f41443212922ad8337cdde0b51",
17
17
  "schemas/a2a-task-state.schema.json": "c9365918f993f943b4b619d42551eb066a1ed33a08d895d51b395432a5b1f1bc",
@@ -198,7 +198,7 @@
198
198
  "schemas/workspace-file.schema.json": "464de85c2a068243084ee9c1d969bc7cd5d8f7948574e58450d6493c38a0e1e4",
199
199
  "spec/v1/alias-detectors.json": "fee4594ef49953953ffcd0b3813300067d16b3e65ebff2aac722034ac9b3f545",
200
200
  "spec/v1/capability-declaration-classes.json": "e7729aed5c4b4e1dd02abab0530f14cc95f5d4070fe51fb139e7f5cccefa00c6",
201
- "spec/v1/core-standard-manifest.json": "10b5c192827884300f77b1bd481fdb70e8fccf0b636c2e37d0a3834497ce508a",
201
+ "spec/v1/core-standard-manifest.json": "2e4f6c617a7166181c67851b9d7c336bb06f2b9a5e805dae5d3315f06102db00",
202
202
  "spec/v1/deprecations.json": "520d79927a8ed43ccf62c207a7cf6cf7b19b16e00bbbbdf0410667e939c19d85",
203
203
  "spec/v1/deprecations.schema.json": "4cdbbb8eb9c0092913a5704c943880f0c8581bcf0f640a7df5a84105d53c8aee",
204
204
  "spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
@@ -228,7 +228,7 @@
228
228
  "spec/v2/path-manifest.json": "034152e09b1458c66810d4050e20a273b2b9b8fe2d92b66e8b819477de58a1be",
229
229
  "spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
230
230
  "spec/v2/profiles.json": "1f0ee40491131cf561ef19a0394c47ba476b4567514fe16befb6cada4a10a5a4",
231
- "spec/v2/release.json": "c5a7d6f086e6d9bce497e2c21fe5a1f11d96533f30b5596f3332ad1a77898a9b"
231
+ "spec/v2/release.json": "71cf76db2a446b9d8363c3211dd4d46b7dc1e2ed8199c101c3bbd09b7579a915"
232
232
  },
233
- "corpusCommit": "ef6f06aafc7265609229411a104d00546fe25074"
233
+ "corpusCommit": "b52f0c2d11e77e728463f1d397e57bf640ece6e4"
234
234
  }
@@ -3,40 +3,42 @@
3
3
  * the host must be able to honour (suite 2.0.0, target major 2; unaided).
4
4
  *
5
5
  * `fixtures[]` in discovery gates scenarios: `isFixtureAdvertised(id)` decides
6
- * whether a scenario runs at all. Nothing checked that an advertised id names a
7
- * fixture the corpus actually defines, or that the host can serve it. A host
8
- * whose advertised list and seeded set drift apart therefore fails somewhere
9
- * else entirely the scenario gated on the missing fixture attempts, fails on
10
- * a run that cannot be created, and the failure is attributed to that
11
- * scenario's requirement rather than to the advertisement that was wrong.
6
+ * whether a scenario runs at all. So a host whose advertised list and seeded set
7
+ * drift apart fails somewhere else entirely the scenario gated on the missing
8
+ * fixture attempts, fails on a run that cannot be created, and the failure is
9
+ * attributed to that scenario's requirement rather than to the advertisement
10
+ * that was wrong. That misattribution is what this scenario exists to catch.
12
11
  *
13
- * No host is currently known to exhibit this. A tier-2 host was thought to
14
- * (46 seeded against 47 advertised) and then verified and retracted it the
15
- * count had been eyeballed from an array literal rather than measured, and the
16
- * two sets are in fact identical. The scenario is kept because the failure mode
17
- * is a property of the gating mechanism, not of that host: `fixtures[]` decides
18
- * whether a scenario runs, so a wrong advertisement is charged to whatever runs
19
- * next. Leg 1 is also the stronger check an id the corpus catalog does not
20
- * define is wrong however well a host's own two lists agree with each other.
12
+ * **This scenario shipped with a second leg that was wrong, and the correction
13
+ * matters more than the check.** That leg asserted the advertised ids are a
14
+ * SUBSET of `conformance/fixtures/` "the vocabulary is closed, so an id the
15
+ * corpus does not define is a typo or an invention". The vocabulary is not
16
+ * closed. Host-supplied fixtures are the normal case: dozens of ids the
17
+ * scenarios gate on are deliberately not shipped, and `v2-approver-enforced`
18
+ * says so in its own docstring it needs an approval fixture whose
19
+ * `approversList` names a principal the suite is not, and records `blocked`
20
+ * naming it precisely because "no such fixture ships in `conformance/fixtures/`".
21
21
  *
22
- * Two legs, both cheap:
23
- * 1. the advertised ids are a subset of the corpus fixture catalog the
24
- * vocabulary is closed, so an id the corpus does not define is a typo or
25
- * an invention, not a capability;
26
- * 2. a bounded sample of advertised fixtures is actually creatable, so the
27
- * list is a claim about reachable state rather than a wish.
22
+ * So the leg failed a host for doing exactly what the corpus asks. It was found
23
+ * by running the suite against the reference host, which advertised two
24
+ * host-supplied fixtures and was marked non-conformant for it. Set membership
25
+ * cannot distinguish a typo from a legitimate host fixture, and a check that
26
+ * cannot tell those apart is not a check — it is a coin flip that happens to
27
+ * land on "fail" for correct hosts.
28
+ *
29
+ * What survives is the leg that was always sound: an advertised fixture MUST be
30
+ * creatable. That holds whoever defines it, and it is the one that catches the
31
+ * drift the misattribution comes from.
28
32
  *
29
33
  * @see spec/v2/core/conformance.md
30
- * @see conformance/fixtures.md
34
+ * @see conformance/src/scenarios/v2-approver-enforced.test.ts (a host-supplied fixture, by design)
31
35
  */
32
36
 
33
37
  import { describe, it, expect } from 'vitest';
34
- import { existsSync, readdirSync } from 'node:fs';
35
38
  import { driver, type OpenWOPResponse } from '../lib/driver.js';
36
39
  import { v2Discovery } from '../lib/v2.js';
37
40
  import { softSkip } from '../lib/soft-skip.js';
38
41
  import { req } from '../lib/requirement-ids.js';
39
- import { FIXTURES_DIR } from '../lib/paths.js';
40
42
 
41
43
  const ID = 'openwop.requirement.0168.advertised-fixtures-exist';
42
44
  const DOC = 'spec/v2/core/conformance.md §Fixtures';
@@ -57,26 +59,6 @@ function advertisedIds(doc: Record<string, unknown>): string[] {
57
59
  }
58
60
 
59
61
  describe('v2-advertised-fixtures-exist (conformance.md §Fixtures)', () => {
60
- it('every advertised fixture id is one the corpus defines', async () => {
61
- const doc = await v2Discovery().catch(() => null);
62
- if (!doc) return softSkip('blocked', 'v2 discovery unreachable');
63
- const ids = advertisedIds(doc);
64
- if (ids.length === 0) return softSkip('inapplicable', 'the host advertises no fixtures[] — there is no claim to falsify');
65
- if (FIXTURES_DIR === null || !existsSync(FIXTURES_DIR)) {
66
- return softSkip('blocked', 'the fixture catalog is absent from this layout, so an advertised id cannot be checked against it');
67
- }
68
- const catalog = new Set(
69
- readdirSync(FIXTURES_DIR)
70
- .filter((f) => f.endsWith('.json'))
71
- .map((f) => f.replace(/\.json$/, '')),
72
- );
73
- const unknown = ids.filter((id) => !catalog.has(id));
74
- expect(
75
- unknown,
76
- req(ID, DOC, `every id in fixtures[] MUST name a fixture the corpus defines — the vocabulary is closed, so an id the catalog does not carry is a typo or an invention rather than a capability (${unknown.length} unknown of ${ids.length}: ${unknown.slice(0, 5).join(', ')})`),
77
- ).toEqual([]);
78
- });
79
-
80
62
  it('a sampled advertised fixture is actually creatable, not just listed', async () => {
81
63
  const doc = await v2Discovery().catch(() => null);
82
64
  if (!doc) return softSkip('blocked', 'v2 discovery unreachable');
@@ -61,6 +61,15 @@ describe('v2-era-2-append-vocabulary (RFC 0176 §A — the writer rule)', () =>
61
61
  return softSkip('blocked', `GET /runs/${runId}/events/poll answered ${before?.status ?? 'no response'} on the seeded era-2 run — the log cannot be read back`);
62
62
  }
63
63
  const seedCount = eventsOf(before).length;
64
+ // The seam returning ok is a WRAPPER claim; the readable log is the artifact.
65
+ // A seam that reports success and seeds nothing leaves no era-2 log to append
66
+ // to, so there is nothing here to witness the writer rule with — that is
67
+ // `blocked`, not a writer-rule failure. Asserting against an empty log would
68
+ // charge this requirement for a seam defect, which is the misattribution the
69
+ // suite exists to avoid.
70
+ if (seedCount === 0) {
71
+ return softSkip('blocked', `seedEra2Log reported success but the log reads back empty (0 events) — the seam's return value is not evidence that a log exists, and without a seeded era-2 log the writer rule is unwitnessed here`);
72
+ }
64
73
 
65
74
  // One canonical mutation so the HOST's own writer appends. Cancel is the
66
75
  // universally available terminal transition; a host that refuses it on a