@openwop/openwop-conformance 2.0.6 → 2.0.7
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 +59 -0
- package/dist/spec-artifacts.lock.json +2 -2
- package/package.json +2 -2
- package/schemas/CORPUS-STAMP.json +11 -11
- package/src/lib/era2-seed.ts +16 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# `@openwop/openwop-conformance` Changelog
|
|
2
2
|
|
|
3
|
+
## [2.0.7] — 2026-09-06 — three claims of coverage that were not coverage
|
|
4
|
+
|
|
5
|
+
No host behaviour changes. One gate changes disposition, and the two prose
|
|
6
|
+
corrections remove claims the corpus was making about its own evidence.
|
|
7
|
+
|
|
8
|
+
**`vendorControlGate` answers `blocked`, not `inapplicable`, when
|
|
9
|
+
`spec/v2/declaration.json` cannot be resolved.** 2.0.6 — the release that fixed
|
|
10
|
+
this scenario — got the disposition wrong on the branch it had just repaired.
|
|
11
|
+
`inapplicable` asserts *the requirement does not bind this host*, which is a
|
|
12
|
+
statement about the host made on the strength of a fact about the suite, and a
|
|
13
|
+
false one: the rule binds exactly as before and the suite merely failed to read
|
|
14
|
+
its own corpus. It is also the quiet answer. `inapplicable` certifies;
|
|
15
|
+
`blocked` is bundle-wide fatal (RFC 0168 §E.1). The disposition that was wrong
|
|
16
|
+
was the one that made no sound.
|
|
17
|
+
|
|
18
|
+
As of 2.0.6 that branch is unreachable — the registry resolves in every layout
|
|
19
|
+
and the publish workflow asserts it. That is the argument *for* making it
|
|
20
|
+
fatal. An unreachable branch answering `inapplicable` is a trapdoor back to the
|
|
21
|
+
D1 resolution defect, which was invisible precisely because it degraded a live
|
|
22
|
+
witness into a quiet skip.
|
|
23
|
+
|
|
24
|
+
**The general rule is now written down** (`spec/v2/core/conformance.md`
|
|
25
|
+
§"Whose fact is the reason?"): a soft-skip reason MUST name a fact about the
|
|
26
|
+
host under test, and where the predicate is instead a fact about the suite —
|
|
27
|
+
its layout, its corpus, a fixture it cannot resolve — the row MUST record
|
|
28
|
+
`blocked`. Gate ordering follows (host facts before suite facts) but is not the
|
|
29
|
+
guarantee; ordering only decides which *true* reason is reported. The guarantee
|
|
30
|
+
is that a suite-side gate can never be silent, because it is never
|
|
31
|
+
`inapplicable`.
|
|
32
|
+
|
|
33
|
+
Credit where it is due: this came from a host operator who predicted a third
|
|
34
|
+
failure mode I had not considered — a row already `inapplicable` for a true host
|
|
35
|
+
reason, re-gated onto a suite-side precondition, stays `inapplicable`. `skip →
|
|
36
|
+
skip`, no count moves, no gate reddens, and the row silently stops describing
|
|
37
|
+
the host it names. Measured against the tree, their case does not bite this
|
|
38
|
+
scenario (the seams gate returns first, at `:96`, above the precondition at
|
|
39
|
+
`:97`), but the rule they proposed was right and the ordering only held by
|
|
40
|
+
construction — nothing written down stopped the next scenario from getting it
|
|
41
|
+
wrong.
|
|
42
|
+
|
|
43
|
+
`era2-unmapped-gates.test.ts` gains a row asserting that **no** reachable
|
|
44
|
+
verdict in either gate is `inapplicable`, so a future suite-side gate that
|
|
45
|
+
soft-skips quietly reddens a test instead of a bundle. Sabotage-verified:
|
|
46
|
+
restoring 2.0.6's disposition reddens exactly those two rows and no others.
|
|
47
|
+
|
|
48
|
+
### Corpus prose
|
|
49
|
+
|
|
50
|
+
- **`persistence.md` §"The seat"** claimed `v2-v1-events-translated` reading
|
|
51
|
+
through poll, SSE and a fork meant "a wrapper-only adapter is caught". It does
|
|
52
|
+
not. Three wrappers pass those three legs exactly as one correctly seated
|
|
53
|
+
adapter does, and the rule binds *every* reader, including ones the suite has
|
|
54
|
+
no name for. The seat is a **claims-check** discharged by ADR disclosure and
|
|
55
|
+
audit; the scenario catches a reader that was *missed*, not an adapter that
|
|
56
|
+
was *misplaced*. The clause also cited a scenario by the wrong name and
|
|
57
|
+
pointed at `conformance.md`, which said nothing about any of it. Both MUSTs
|
|
58
|
+
are unchanged — only the false coverage claim is gone.
|
|
59
|
+
- **RFC 0180** supplies the vendor-org registration procedure the registry
|
|
60
|
+
never had, and `persistence.md` §"The codemap is data" now points at it.
|
|
61
|
+
|
|
3
62
|
## [2.0.6] — 2026-09-06 — the release that made a rule uncheckable
|
|
4
63
|
|
|
5
64
|
**If you pinned 2.0.5, `v2-unmapped-type-refused` did not run against your
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openwop/openwop-conformance",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.7",
|
|
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.
|
|
59
|
+
"@openwop/spec-artifacts": "2.0.7"
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -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.0.
|
|
5
|
-
"corpusTag": "v2.0.
|
|
4
|
+
"version": "2.0.7",
|
|
5
|
+
"corpusTag": "v2.0.7",
|
|
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": "39081c59fb696159806b0f2f9a42e7e9ff830d622fcf2ad4159b21357580a955",
|
|
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": "0d18b9414567efb5662f0a8bc06725d0e038aab14f327db7a1b8ebe3b9f4cbb9",
|
|
13
|
+
"api/v2/asyncapi.yaml": "25196e36b92b0dab97904b1f3461826d2066e579963c26c7e6168d2e5688bdfe",
|
|
14
|
+
"api/v2/openapi.yaml": "e48e5669918ddda197a17508eca24ea42e834a62b309091c87d063cb52b1b2cb",
|
|
15
15
|
"api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
|
|
16
16
|
"schemas/README.md": "0c0b737ffcf8f30e7d2809cec8a498232de710f41443212922ad8337cdde0b51",
|
|
17
17
|
"schemas/a2a-task-state.schema.json": "c9365918f993f943b4b619d42551eb066a1ed33a08d895d51b395432a5b1f1bc",
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
"schemas/workspace-file.schema.json": "464de85c2a068243084ee9c1d969bc7cd5d8f7948574e58450d6493c38a0e1e4",
|
|
200
200
|
"spec/v1/alias-detectors.json": "fee4594ef49953953ffcd0b3813300067d16b3e65ebff2aac722034ac9b3f545",
|
|
201
201
|
"spec/v1/capability-declaration-classes.json": "e7729aed5c4b4e1dd02abab0530f14cc95f5d4070fe51fb139e7f5cccefa00c6",
|
|
202
|
-
"spec/v1/core-standard-manifest.json": "
|
|
202
|
+
"spec/v1/core-standard-manifest.json": "0484560c0bb72e5da9fa393b0723961e1cb7837eaf90c035ff37b7e7fdad6476",
|
|
203
203
|
"spec/v1/deprecations.json": "1d5acb69a9b8ccb57275a95605f74aef1d920685f8407c9d382a46b59dc803bb",
|
|
204
204
|
"spec/v1/deprecations.schema.json": "18c87e78bedc210431f795ae44c5b5d202f2f3317850d5cf86867d4f1fa1cdfb",
|
|
205
205
|
"spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
|
|
@@ -213,7 +213,7 @@
|
|
|
213
213
|
"spec/v1/spec-gaps.json": "6cc9962c6b969f632e07a78b52a4f61447ff579e2990cbae989866f584a86042",
|
|
214
214
|
"spec/v2/README.md": "f56bd8d58be4ac04543c9f7b2fe92b294738d6121a4f21cbd1ce751e72b94c83",
|
|
215
215
|
"spec/v2/core/capabilities.md": "0f222434bbe58c881362a626ab9db6bce0ae2e54cb858e3d71b662dd1fc13150",
|
|
216
|
-
"spec/v2/core/conformance.md": "
|
|
216
|
+
"spec/v2/core/conformance.md": "6dda58339117819b77710cd53d25f34cc9e602a35a7958d1afc4e3d4b6b7de23",
|
|
217
217
|
"spec/v2/core/connection-packs.md": "34e519dbe5b091c9758729787d398b35b1dc41f1e01ebd028e7e6b838ce2f6ee",
|
|
218
218
|
"spec/v2/core/errors.md": "671895de1b7c987a1dfd53fe0a814159efadae0ffd4c8c06bf1749d345270580",
|
|
219
219
|
"spec/v2/core/events.md": "7b9207079cede7ec335126b98bcb95d655ae3b7322b18febd1b4df51750b0a33",
|
|
@@ -225,14 +225,14 @@
|
|
|
225
225
|
"spec/v2/core/interrupt.md": "4bd345bccdb8e2762ca95833cc67086158640c27ffa5ef84915a4ab3de348440",
|
|
226
226
|
"spec/v2/core/overview.md": "8ece6667535d24ed4013a046cb11e1a649f70e39625fc55e09ceb2c02505ed9c",
|
|
227
227
|
"spec/v2/core/packs.md": "90f32947816b4ec2b045b063ad2914126c73353883514a270ad200205dc8e51b",
|
|
228
|
-
"spec/v2/core/persistence.md": "
|
|
228
|
+
"spec/v2/core/persistence.md": "e9830ae228bcbc33f03d81a5f2b51e031466feb84387971dd3459bf5e1687701",
|
|
229
229
|
"spec/v2/core/replay.md": "19b2fcbda4693895d39b99593f498b76376d77472a813bba6c22fca02e106332",
|
|
230
230
|
"spec/v2/core/runs.md": "f5f24df6da76b1d6e2cf655af3bbe3340195c36ec8d9ce0ca6e357385b1a8771",
|
|
231
231
|
"spec/v2/core/security-defaults.md": "53a1bc549aaa356a4fcb56cdb1c4f5880d3fb65d5d49dd570a413bb29aff82e5",
|
|
232
232
|
"spec/v2/core/versioning.md": "2eb4e8e5a1208a026a3d497d1e0fb76a4f7cb97e514d6f41f45dd66b89405abb",
|
|
233
233
|
"spec/v2/core/webhooks.md": "1d2719335f8fb46cd31dbb836b44ea7d78ed54f98ea181927502814603c5b935",
|
|
234
234
|
"spec/v2/core/workflow-chain-packs.md": "99ad4aeeeeb05521720dc2ae18ae63e6d604361780ed1b76778ca6d44da70eed",
|
|
235
|
-
"spec/v2/declaration.json": "
|
|
235
|
+
"spec/v2/declaration.json": "bd8a1dcee899a4478ac96b52da6ee07e1cb5fce4465939ac32e19e52f4d5c6b2",
|
|
236
236
|
"spec/v2/declaration.schema.json": "eac5f8080bd572f147bd57d0c4ac8ad73b14536d9236222490ae29a33b21e184",
|
|
237
237
|
"spec/v2/errors.json": "f179414a92f30b5dadf26e9e57699649a67324bd7186d5287647d17605d137d3",
|
|
238
238
|
"spec/v2/event-codemap.json": "37869a03cdfd8758b57e6f350641a6ebbd383231cebda51f5473ad85f94ab74c",
|
|
@@ -268,8 +268,8 @@
|
|
|
268
268
|
"spec/v2/path-manifest.json": "034152e09b1458c66810d4050e20a273b2b9b8fe2d92b66e8b819477de58a1be",
|
|
269
269
|
"spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
|
|
270
270
|
"spec/v2/profiles.json": "0636f19fceae625390003a347e70ef4797d84766b5c24ce8a02cea52aadebca4",
|
|
271
|
-
"spec/v2/release.json": "
|
|
271
|
+
"spec/v2/release.json": "2937de1d170c218e4d336088035c2a4fe6b7e951b6c6bd8bd375f0580ae07a53",
|
|
272
272
|
"spec/v2/retention-floors.json": "eaf3722d95c79947af1d4269ef85117e126518c588cfcf1a2b21b97269f51624"
|
|
273
273
|
},
|
|
274
|
-
"corpusCommit": "
|
|
274
|
+
"corpusCommit": "8f8818dd663240bdd1ea074a25fd9354d0fde2c3"
|
|
275
275
|
}
|
package/src/lib/era2-seed.ts
CHANGED
|
@@ -253,11 +253,24 @@ export function unmappedRefusalGate(registered: ReadonlySet<string> | undefined,
|
|
|
253
253
|
* not name MUST be read under its own name unchanged.
|
|
254
254
|
*
|
|
255
255
|
* This leg genuinely needs the registry to resolve — it asserts that an org IS
|
|
256
|
-
* registered, and an absent registry cannot establish that.
|
|
257
|
-
*
|
|
256
|
+
* registered, and an absent registry cannot establish that.
|
|
257
|
+
*
|
|
258
|
+
* AN UNRESOLVABLE REGISTRY IS `blocked`, NOT `inapplicable` (conformance.md
|
|
259
|
+
* §Whose fact is the reason?). Suite 2.0.6 said `inapplicable`, which asserts
|
|
260
|
+
* the requirement does not bind this host — a statement about the HOST made on
|
|
261
|
+
* the strength of a fact about the SUITE, and a false one: the rule binds
|
|
262
|
+
* exactly as before and the suite merely failed to read its own corpus.
|
|
263
|
+
* `inapplicable` also certifies, while `blocked` is bundle-wide fatal
|
|
264
|
+
* (RFC 0168 §E.1), so the wrong disposition is the silent one.
|
|
265
|
+
*
|
|
266
|
+
* As of 2.0.6 this branch is unreachable — the registry resolves in every
|
|
267
|
+
* layout and the publish workflow asserts it. That is the argument FOR making
|
|
268
|
+
* it fatal, not against: an unreachable branch answering `inapplicable` is a
|
|
269
|
+
* trapdoor back to the D1 resolution defect, which was invisible precisely
|
|
270
|
+
* because it degraded a live witness into a quiet skip.
|
|
258
271
|
*/
|
|
259
272
|
export function vendorControlGate(registered: ReadonlySet<string> | undefined, map: ReadonlyMap<string, string>, type: string): Gate {
|
|
260
|
-
if (registered === undefined) return { ok: false, kind: '
|
|
273
|
+
if (registered === undefined) return { ok: false, kind: 'blocked', reason: 'spec/v2/declaration.json is not resolvable in this layout — the control leg asserts that a REGISTERED org passes through, and guessing which orgs are registered would make the suite the registry. This is a fact about the SUITE, so it is blocked and not inapplicable (conformance.md §Whose fact is the reason?)' };
|
|
261
274
|
if (!registered.has(orgOf(type))) return { ok: false, kind: 'blocked', reason: `the control leg needs org '${orgOf(type)}' registered in spec/v2/declaration.json extensions (registered: ${[...registered].join(', ') || 'none'}) — without a registered org the positive half of the vendor rule cannot be driven at all` };
|
|
262
275
|
if (map.has(type)) return { ok: false, kind: 'blocked', reason: `${type} now has a codemap row (→ ${String(map.get(type))}) — the control leg requires a type the codemap does not name` };
|
|
263
276
|
return { ok: true };
|