@openwop/openwop-conformance 2.0.4 → 2.0.5

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,5 +1,59 @@
1
1
  # `@openwop/openwop-conformance` Changelog
2
2
 
3
+ ## [2.0.5] — 2026-09-06 — four rules with no way to be checked
4
+
5
+ Four instruments that could not, even in principle, return the answer they
6
+ appeared to give. Three of them were green.
7
+
8
+ **The vendor rule's registry did not exist.** `events.md` §Rules and
9
+ `persistence.md` §The codemap is data both require a vendor event type's first
10
+ segment to be an org registered under `extensions` in
11
+ `spec/v2/declaration.json`. There was no `extensions` key. Three near misses
12
+ kept it plausible — `extensionsKeyPattern` is a key SHAPE, `reservedOrgs` lists
13
+ FORBIDDEN orgs, and `metadata[]` carries a row keyed `extensions` that is the
14
+ host's own extension map in the discovery payload. The registry now exists and
15
+ holds `example`, reserved by the protocol and never assignable to a vendor.
16
+
17
+ **`v2-unmapped-type-refused` drove only the refusal half**, so a host that
18
+ refuses EVERY unmapped type — including a registered vendor type it MUST pass
19
+ through — went green while violating the rule. New leg
20
+ `openwop.requirement.0176.vendor-type-passthrough`: same log shape, one segment
21
+ changed. Its preconditions were a note inside a seeded payload, prose in a place
22
+ no runner reads; they are checked now, and the file blocks with the reason.
23
+
24
+ **"Byte-equivalent" was witnessed by comparing two of ten fields.**
25
+ `v2-run-fork-prefix` compared `${sequence}:${type}`, so a fork could inherit a
26
+ prefix whose payloads differed in every field and pass. It now compares `type`,
27
+ `nodeId` and `payload`, excluding `eventId`/`runId`/`timestamp`/`causationId` —
28
+ using **`runs.md` §Diff and ancestry's** exclusion set rather than one invented
29
+ for the leg. `schemaVersion`, `engineVersion` and the §37 snapshot claim are
30
+ recorded as named residue, unasserted, with the reason. Floor membership
31
+ unchanged: still RULED OUT.
32
+
33
+ **A v3 bundle's `certified: true` was uncheckable by its recipient.** v2 bundles
34
+ carried `discovery.document` and the verifier re-derived every claimed profile
35
+ from it (RFC 0148 §B(1)); v3 dropped the field and the check with it. Optional
36
+ `discovery.document` returns: the digest is re-derived first (the signature
37
+ covers `sha256`, not the document, so a swap would otherwise verify), then every
38
+ certified profile is re-derived, and absence is surfaced as
39
+ `derivabilityChecked: false` rather than swallowed. Sabotage-proved.
40
+
41
+ **A requirement's id depended on whether it passed.** The registry generator
42
+ read `req()`'s first argument only as a string literal, so `const ID = …`
43
+ recorded `explicitId: null` and the row fell back to a title-derived slug —
44
+ `v2-run-fork-prefix` is in the evidence tree under two ids, the explicit one
45
+ where the assertion ran and the slug where the leg was `inapplicable`. A
46
+ verifier asking whether a bundle carries a requirement got a well-formed NO from
47
+ a host that had merely not held the profile. 2058 explicit ids became 2106.
48
+
49
+ **`memory-attribution-replay-stable` is `majors: [1, 2]`** (was `[1]`). Its rule
50
+ is `replay.md` §Determinism caveat 5 in both majors, word for word. What held it
51
+ back was a gate returning early **unrecorded** and three hard-coded `/v1/` paths
52
+ that are not seams. Both are properties of the instrument. First row of the
53
+ 445-file backfill.
54
+
55
+ **A rule you cannot check is not a weaker rule; it is a rule that is not there.**
56
+
3
57
  ## [2.0.4] — 2026-09-06 — a fixture that punished a host for obeying the rule the scenario checks
4
58
 
5
59
  `v2-provider-conflict` drove `connection-pack-github`. On a host shipping a built-in `github`, RFC 0177 §D.1 requires refusing the later registration — so the fixture never installed and the qualified-form leg recorded **`blocked`** permanently, on a host whose only fault was obeying the rule under test. A production host carried that row across a dozen cuts; any blocked row denies certification (RFC 0168 §E.1).
package/dist/cli.js CHANGED
@@ -653,7 +653,11 @@ async function runCertify(args, baseUrl, apiKey) {
653
653
  generatedAt: new Date().toISOString(),
654
654
  suite: { name: '@openwop/openwop-conformance', version, targetMajor: target.major, specArtifactsVersion: lock?.version ?? 'repo-layout', ...(lock ? { stampSha256: lock.stampSha256 } : {}) },
655
655
  host: { name: host.name, version: host.version, ...(host.vendor ? { vendor: host.vendor } : {}), build, signingKeyId: keyId, ...(relaxations && relaxations.length ? { relaxations } : {}) },
656
- discovery: { url: discoveryUrl, sha256, protocolVersions, preferredVersion },
656
+ // `document` is what makes `claimedProfiles[].certified` checkable by
657
+ // someone other than this process (RFC 0148 §B(1)); v2 carried it and v3
658
+ // dropped it. `sha256` is a digest of `canonicalJSON(document)`, so the
659
+ // two are consistent by construction and the verifier re-derives it.
660
+ discovery: { url: discoveryUrl, sha256, protocolVersions, preferredVersion, document },
657
661
  claimedProfiles: claimed3,
658
662
  results: { totals: totals3, requirements: rows3 },
659
663
  witnessSha256: witnessDigest(rows3),
@@ -18,6 +18,7 @@
18
18
  * in cli.ts) and pure: it never reads the environment.
19
19
  */
20
20
  import { createHash, createPrivateKey, createPublicKey, sign as edSign, verify as edVerify } from 'node:crypto';
21
+ import { profileDerivable } from './profiles.js';
21
22
  export const SIGNATURE_OVER = ['witnessSha256', 'host.build', 'suite.version', 'discovery.sha256'];
22
23
  /** Deterministic JSON: keys sorted at every level, no whitespace. */
23
24
  export function canonicalJSON(value) {
@@ -125,6 +126,33 @@ export function verifyBundleV3(bundle, opts = {}) {
125
126
  }
126
127
  if (expected.blocked > 0 && certifiedProfiles.length > 0)
127
128
  rejections.push({ kind: 'blocked-certified', detail: `${expected.blocked} blocked row(s): a bundle with blocked > 0 does not certify (RFC 0168 §E.1)` });
129
+ // Derivability, restored. RFC 0148 §B(1): a profile certifies only if it is
130
+ // DERIVABLE from what the host advertised. `verifyBundleV2` checked exactly
131
+ // that against `discovery.document`; v3 stopped carrying the document and the
132
+ // check went with it, leaving `certified: true` a claim only its emitter
133
+ // could evaluate. When the document is present the check runs again — and it
134
+ // runs on the SAME bytes the signature covers, because `discovery.sha256` is
135
+ // a digest of `canonicalJSON(document)` and is re-derived here first. A
136
+ // document that does not hash to the signed digest is a substituted
137
+ // document, and rejecting it is the whole point of checking.
138
+ const document = bundle.discovery?.document;
139
+ let derivabilityChecked = false;
140
+ if (document !== undefined) {
141
+ const digest = createHash('sha256').update(canonicalJSON(document)).digest('hex');
142
+ if (digest !== bundle.discovery?.sha256) {
143
+ rejections.push({ kind: 'discovery-digest', detail: `discovery.document hashes to ${digest.slice(0, 12)} but discovery.sha256 is ${String(bundle.discovery?.sha256).slice(0, 12)} — the captured document is not the one the signature attests to` });
144
+ }
145
+ else {
146
+ derivabilityChecked = true;
147
+ for (const p of bundle.claimedProfiles ?? []) {
148
+ if (!p.certified)
149
+ continue;
150
+ if (!profileDerivable(document, p.id)) {
151
+ rejections.push({ kind: 'profile-not-derivable', profile: p.id, detail: `${p.id} is marked certified, but the captured discovery document does not derive it (RFC 0148 §B(1)) — evidence cannot certify a profile the host does not advertise` });
152
+ }
153
+ }
154
+ }
155
+ }
128
156
  // RFC 0168 §E.2: the verifier REFUSES, it does not warn — but a refusal is
129
157
  // scoped to what it names. A rejection carrying a `profile` removes that
130
158
  // profile only (a relaxation on one obligation does not poison an unrelated
@@ -138,5 +166,6 @@ export function verifyBundleV3(bundle, opts = {}) {
138
166
  signatureVerified,
139
167
  verifierSignatureVerified,
140
168
  certifiedProfiles: bundleWide.length > 0 ? [] : certifiedProfiles.filter((p) => !scoped.has(p)),
169
+ derivabilityChecked,
141
170
  };
142
171
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "package": "@openwop/spec-artifacts",
3
- "version": "2.0.4",
4
- "stampSha256": "8abb52df9340e47ac5d16d15fb0abe88cc3bd6857e2cb8be269079d6d7ca1530"
3
+ "version": "2.0.5",
4
+ "stampSha256": "0046fddf0cc553f5da0fa9ee108a4c45af6b35fe3c1456e62436127c591dc405"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/openwop-conformance",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
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.4"
59
+ "@openwop/spec-artifacts": "2.0.5"
60
60
  }
61
61
  }
@@ -1,7 +1,172 @@
1
1
  {
2
- "$comment": "old id → new id. Add a row when a test title is reworded so bundles citing the old id still resolve.",
2
+ "$comment": "old id → new id. Add a row when a test title is reworded so bundles citing the old id still resolve. Suite 2.0.5 added 165 rows for a SECOND cause: the registry generator now resolves module-level const bindings, so a leg that soft-skips is labelled by its explicit requirement id instead of the title-derived slug it used to fall back to. The label moved without any title changing, and the generator --check cannot see it (it compares the record id, which did not move) — 11 rows across the three committed host bundles cited slugs the 2.0.5 suite no longer mints.",
3
3
  "aliases": {
4
4
  "openwop.it.v2-run-cancel.cancelling-a-terminal-run-answers-409-run-terminal-or-200-idempotently-the-prose": "openwop.it.v2-run-cancel.cancelling-a-terminal-run-is-refused-409-run-terminal",
5
- "openwop.it.pause-resume.pause-on-an-already-paused-run-is-a-no-op-200-202-idempotent": "openwop.it.pause-resume.pause-on-an-already-paused-run-returns-409-with-details-runstatus-paused-unless"
5
+ "openwop.it.pause-resume.pause-on-an-already-paused-run-is-a-no-op-200-202-idempotent": "openwop.it.pause-resume.pause-on-an-already-paused-run-returns-409-with-details-runstatus-paused-unless",
6
+ "openwop.it.era-key-stamped-v1.a-run-the-host-just-created-carries-eventlogschemaversion": "openwop.requirement.version-negotiation.era-key-stamped",
7
+ "openwop.it.era-key-stamped-v1.a-freshly-created-run-is-not-classified-legacy-by-the-host-s-own-rule": "openwop.requirement.version-negotiation.era-key-not-legacy",
8
+ "openwop.it.era-key-stamped-v1.a-run-the-host-just-created-carries-engineversion-the-legacy-escape-cannot-reach": "openwop.requirement.version-negotiation.engine-version-stamped",
9
+ "openwop.it.v2-advertised-fixtures-exist.a-sampled-advertised-fixture-is-actually-creatable-not-just-listed": "openwop.requirement.0168.advertised-fixtures-exist",
10
+ "openwop.it.v2-advertised-path-space-served.a-host-advertising-major-2-reaches-the-surfaces-it-already-serves-under-v1": "openwop.requirement.0172.advertised-path-space-served",
11
+ "openwop.it.v2-approver-enforced.a-resolver-outside-approverslist-is-refused-at-resolve-time": "openwop.requirement.0173.approver-enforced",
12
+ "openwop.it.v2-assurance-downgrade-audited.an-identity-below-the-lane-floor-is-refused-with-sender-constraint-missing": "openwop.requirement.0170.assurance-downgrade-audited.refused",
13
+ "openwop.it.v2-assurance-downgrade-audited.a-resolved-identity-records-the-assurance-actually-used-never-a-downgraded-beare": "openwop.requirement.0170.assurance-downgrade-audited.audited",
14
+ "openwop.it.v2-bundle-v3-signed.a-signed-v3-bundle-validates-against-the-closed-root-schema-an-extra-root-key-is": "openwop.requirement.0168.bundle-v3-signed.schema-closed-root",
15
+ "openwop.it.v2-bundle-v3-signed.the-attestation-verifies-under-the-host-key-and-a-flipped-witnesssha256-is-refus": "openwop.requirement.0168.bundle-v3-signed.witness-digest",
16
+ "openwop.it.v2-bundle-v3-signed.an-independent-claim-self-signed-under-the-host-key-is-refused-a-distinct-verifi": "openwop.requirement.0168.bundle-v3-signed.independent-self-signed",
17
+ "openwop.it.v2-capabilities-root-closed.the-host-document-validates-against-capabilities-schema-json": "openwop.requirement.0169.capabilities-root-closed.valid",
18
+ "openwop.it.v2-capabilities-root-closed.an-unknown-root-key-fails-validation": "openwop.requirement.0169.capabilities-root-closed.unknown-root-key",
19
+ "openwop.it.v2-capabilities-root-closed.a-dotted-mirror-key-fails-validation": "openwop.requirement.0169.capabilities-root-closed.dotted-key",
20
+ "openwop.it.v2-capabilities-root-closed.the-v1-capabilities-wrapper-fails-validation": "openwop.requirement.0169.capabilities-root-closed.wrapper",
21
+ "openwop.it.v2-capabilities-root-closed.a-root-profiles-fails-validation": "openwop.requirement.0169.capabilities-root-closed.profiles",
22
+ "openwop.it.v2-capability-record-shape.every-family-record-carries-status-since-and-witness-from-the-wire-legal-sets": "openwop.requirement.0169.capability-record-shape.required-fields",
23
+ "openwop.it.v2-capability-record-shape.until-is-present-iff-the-record-is-experimental-or-deprecated": "openwop.requirement.0169.capability-record-shape.until-iff-not-stable",
24
+ "openwop.it.v2-capability-record-shape.no-advertised-record-carries-an-until-already-in-the-past": "openwop.requirement.0169.capability-record-shape.until-not-past",
25
+ "openwop.it.v2-chain-pin-exact.a-chain-reference-carrying-a-range-core-ai-callprompt-1-is-refused-at-register": "openwop.requirement.0177.chain-pin-exact.range-refused",
26
+ "openwop.it.v2-chain-pin-exact.a-chain-reference-pinning-an-exact-version-core-ai-callprompt-1-0-0-registers": "openwop.requirement.0177.chain-pin-exact.exact-accepted",
27
+ "openwop.it.v2-coherence-not-in-bundle.every-corpus-ledger-id-has-a-scenario-in-src-coherence-and-none-in-src-scenarios": "openwop.requirement.0168.coherence-not-in-bundle.disjoint-by-construction",
28
+ "openwop.it.v2-coherence-not-in-bundle.the-bundle-schema-rejects-a-v3-bundle-carrying-a-corpus-coherence-id-and-accepts": "openwop.requirement.0168.coherence-not-in-bundle.schema-forbids-coherence-ids",
29
+ "openwop.it.v2-compensation-read-projection.get-runs-runid-compensation-on-a-fresh-run-validates-with-status-none": "openwop.requirement.0173.compensation-read-projection",
30
+ "openwop.it.v2-compensation-read-projection.an-unknown-run-projects-404-not-found-through-the-canonical-envelope": "openwop.requirement.0173.compensation-read-projection.not-found",
31
+ "openwop.it.v2-configurable-closed.the-standalone-schema-rejects-a-dotted-key-and-an-unknown-root-key-and-accepts-t": "openwop.requirement.0171.configurable-closed.schema",
32
+ "openwop.it.v2-configurable-closed.post-runs-rejects-a-dotted-key-with-400-validation-error": "openwop.requirement.0171.configurable-closed.dotted-key",
33
+ "openwop.it.v2-configurable-closed.post-runs-rejects-an-unknown-root-key-with-400-validation-error": "openwop.requirement.0171.configurable-closed.unknown-key",
34
+ "openwop.it.v2-created-run-readable.a-run-created-at-this-base-is-readable-and-pollable-at-this-base-by-the-id-it-re": "openwop.requirement.0172.created-run-readable",
35
+ "openwop.it.v2-dual-stack-negotiation.a-run-created-through-v1-runs-with-no-header-is-readable-through-runs-under-open": "openwop.requirement.0172.dual-stack-negotiation.cross-major-read",
36
+ "openwop.it.v2-dual-stack-negotiation.an-unlisted-major-is-406-protocol-version-unsupported-with-details-protocolversi": "openwop.requirement.0172.dual-stack-negotiation.unlisted-major",
37
+ "openwop.it.v2-dual-stack-negotiation.openwop-version-2-0-on-a-v1-path-is-400-protocol-version-mismatch": "openwop.requirement.0172.dual-stack-negotiation.v1-path-mismatch",
38
+ "openwop.it.v2-dual-stack-negotiation.every-response-reports-the-contract-that-produced-it": "openwop.requirement.0172.dual-stack-negotiation.response-header",
39
+ "openwop.it.v2-effect-identity-business-key.get-runs-runid-effects-validates-and-every-row-is-keyed-on-business-identity-or": "openwop.requirement.0173.effect-identity-business-key",
40
+ "openwop.it.v2-effect-identity-business-key.the-same-provider-key-is-presented-across-two-transport-retries": "openwop.requirement.0173.effect-identity-business-key.retry",
41
+ "openwop.it.v2-effect-seam-manifest.get-host-effect-seams-validates-and-every-row-is-guarded": "openwop.requirement.0173.effect-seam-manifest",
42
+ "openwop.it.v2-effect-seam-manifest.the-replay-facet-names-the-manifest-address-as-the-constant-host-effect-seams": "openwop.requirement.0173.effect-seam-manifest.facet",
43
+ "openwop.it.v2-effect-seam-no-refire.driving-one-seam-of-each-kind-observes-no-re-fire-on-replay": "openwop.requirement.0173.effect-seam-no-refire",
44
+ "openwop.it.v2-enum-growth-rule.the-envelope-accepts-a-registered-but-unknown-to-this-suite-vendor-member": "openwop.requirement.0171.enum-growth-rule.unknown-member-accepted",
45
+ "openwop.it.v2-enum-growth-rule.the-reserved-prefix-and-a-malformed-member-are-rejected": "openwop.requirement.0171.enum-growth-rule.reserved-rejected",
46
+ "openwop.it.v2-era-2-append-vocabulary.a-host-append-to-an-open-era-2-run-keeps-the-log-in-v1-vocabulary-so-the-whole-l": "openwop.requirement.0176.era-2-append-vocabulary",
47
+ "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": "openwop.requirement.0176.era-2-append-vocabulary",
48
+ "openwop.it.v2-era-key.a-run-created-now-carries-eventlogschemaversion-3-on-its-snapshot": "openwop.requirement.0176.era-key",
49
+ "openwop.it.v2-era-key.discovery-advertises-the-value-the-host-writes-for-new-runs-and-nothing-else": "openwop.requirement.0176.era-key.discovery",
50
+ "openwop.it.v2-era-stamp-universal.discovery-advertises-an-era-the-host-actually-writes-and-a-new-run-carries-it": "openwop.requirement.0176.era-stamp-universal",
51
+ "openwop.it.v2-era-stamp-universal.a-v2-era-host-stamps-3-so-its-new-runs-are-never-read-as-the-v1-era": "openwop.requirement.0176.era-stamp-universal",
52
+ "openwop.it.v2-error-registry.an-error-response-is-the-closed-envelope-with-a-registered-code-at-its-registere": "openwop.requirement.0171.error-registry.envelope",
53
+ "openwop.it.v2-error-registry.retry-timing-is-never-spelled-inside-details": "openwop.requirement.0171.error-registry.no-retry-details",
54
+ "openwop.it.v2-error-registry.a-429-rate-limited-response-carries-retry-after": "openwop.requirement.0171.error-registry.retry-after",
55
+ "openwop.it.v2-event-type-closed.every-emitted-type-is-a-registered-protocol-type-or-a-vendor-type-under-an-adver": "openwop.requirement.0171.event-type-closed.type",
56
+ "openwop.it.v2-event-type-closed.every-emitted-event-validates-as-a-runeventdoc": "openwop.requirement.0171.event-type-closed.envelope",
57
+ "openwop.it.v2-fork-a-v1-run.the-fork-of-an-era-2-run-is-accepted-and-its-prefix-is-byte-equivalent-to-the-tr": "openwop.requirement.0176.fork-a-v1-run.prefix",
58
+ "openwop.it.v2-fork-a-v1-run.run-started-on-the-fork-carries-the-legacy-subject-where-the-parent-had-none": "openwop.requirement.0176.fork-a-v1-run.legacy-subject",
59
+ "openwop.it.v2-form-when-reuses-edge-conditions.a-field-when-is-the-edge-condition-grammar-type-left-right-and-no-other-expressi": "openwop.requirement.0177.form-when-reuses-edge-conditions",
60
+ "openwop.it.v2-header-scheme.no-removed-header-family-appears-on-any-response": "openwop.requirement.0171.header-scheme.no-legacy-headers",
61
+ "openwop.it.v2-header-scheme.openwop-version-names-the-contract-on-every-response": "openwop.requirement.0171.header-scheme.version-on-every-response",
62
+ "openwop.it.v2-id-grammar.every-id-on-the-run-snapshot-matches-its-ids-schema-json-kind": "openwop.requirement.0170.id-grammar.snapshot",
63
+ "openwop.it.v2-id-grammar.every-id-on-the-run-events-matches-its-ids-schema-json-kind": "openwop.requirement.0170.id-grammar.events",
64
+ "openwop.it.v2-id-grammar.a-run-id-whose-tenant-segment-is-not-the-caller-s-is-refused": "openwop.requirement.0170.id-grammar.tenant-binding",
65
+ "openwop.it.v2-idempotency-key-grammar.a-22-character-key-inside-the-grammar-is-accepted": "openwop.requirement.0170.idempotency-key-grammar.valid-accepted",
66
+ "openwop.it.v2-idempotency-key-grammar.a-key-outside-the-grammar-is-refused-with-400-idempotency-key-invalid": "openwop.requirement.0170.idempotency-key-grammar.invalid-refused",
67
+ "openwop.it.v2-interrupt-token-scheme.a-token-without-the-ow2-prefix-is-refused": "openwop.requirement.0170.interrupt-token-scheme.unprefixed-refused",
68
+ "openwop.it.v2-interrupt-token-scheme.a-well-formed-token-under-a-kid-the-host-does-not-hold-is-401-interrupt-token-in": "openwop.requirement.0170.interrupt-token-scheme.unheld-kid-refused",
69
+ "openwop.it.v2-lane-issuer-advertised.every-auth-lanes-member-names-lane-issuers-revocation-and-minimumassurance": "openwop.requirement.0170.lane-issuer-advertised.members",
70
+ "openwop.it.v2-lane-issuer-advertised.a-windowed-revocation-rule-advertises-revocationwindowseconds": "openwop.requirement.0170.lane-issuer-advertised.window",
71
+ "openwop.it.v2-legacy-profiles-absent.no-legacy-id-appears-in-a2a-profiles-or-mcp-profiles-and-each-id-matches-its-fac": "openwop.requirement.0175.legacy-profiles-absent",
72
+ "openwop.it.v2-legacy-profiles-absent.no-root-profiles-exists-in-the-v2-representation": "openwop.requirement.0175.legacy-profiles-absent.no-root-profiles",
73
+ "openwop.it.v2-manifest-ceiling-refused.an-engines-openwop-range-with-no-upper-bound-1-0-0-reads-2-0-0-and-is-refused-at": "openwop.requirement.0177.manifest-ceiling-refused.unbounded",
74
+ "openwop.it.v2-manifest-ceiling-refused.a-v1-ceiling-1-0-0-2-0-0-is-refused-at-install-with-pack-engine-unsupported": "openwop.requirement.0177.manifest-ceiling-refused.v1-ceiling",
75
+ "openwop.it.v2-manifest-ceiling-refused.a-range-admitting-the-host-major-2-0-0-3-0-0-installs": "openwop.requirement.0177.manifest-ceiling-refused.v2-installs",
76
+ "openwop.it.v2-manifest-hatch-carried.an-x-field-inside-agents-0-of-a-node-pack-is-ignored-not-rejected-the-pack-insta": "openwop.requirement.0177.manifest-hatch-carried.agents-x-field",
77
+ "openwop.it.v2-manifest-hatch-carried.an-x-field-inside-a-prompt-template-of-a-prompt-pack-is-ignored-not-rejected-the": "openwop.requirement.0177.manifest-hatch-carried.prompt-template-x-field",
78
+ "openwop.it.v2-min-client-version.a-client-below-minclientversion-is-refused-with-426-client-version-unsupported": "openwop.requirement.0172.min-client-version",
79
+ "openwop.it.v2-minimum-version-refused.an-a2a-peer-offering-only-a-version-below-minimumversion-is-refused": "openwop.requirement.0175.minimum-version-refused",
80
+ "openwop.it.v2-minimum-version-refused.an-mcp-server-offering-only-a-revision-below-minimumrevision-is-refused": "openwop.requirement.0175.minimum-version-refused.mcp",
81
+ "openwop.it.v2-mrtr-rounds-ceiling.mcp-mrtr-maxrounds-is-an-integer-ceiling-in-1-16": "openwop.requirement.0175.mrtr-rounds-ceiling",
82
+ "openwop.it.v2-mrtr-rounds-ceiling.round-maxrounds-1-is-refused-with-mcp-mrtr-rounds-exceeded": "openwop.requirement.0175.mrtr-rounds-ceiling.refused",
83
+ "openwop.it.v2-no-transport-advertisement.the-v2-root-carries-no-supportedtransports-and-no-grpc-block": "openwop.requirement.0175.no-transport-advertisement",
84
+ "openwop.it.v2-owner-subject-required.owner-subject-is-present-and-validates-against-subject-schema-json": "openwop.requirement.0170.owner-subject-required.subject",
85
+ "openwop.it.v2-owner-subject-required.owner-carries-no-principal-principalkind": "openwop.requirement.0170.owner-subject-required.no-principal",
86
+ "openwop.it.v2-pack-isolation.sandbox-isolationmodel-names-a-real-mechanism-never-node-vm": "openwop.requirement.0173.pack-isolation",
87
+ "openwop.it.v2-pack-isolation.node-pack-sandbox-timeout-exceeding-wallclocklimitms-fails-with-sandbox-timeout": "openwop.requirement.0173.pack-isolation.timeout",
88
+ "openwop.it.v2-pack-isolation.node-pack-sandbox-memory-cap-exceeding-memorylimitbytes-fails-with-sandbox-memor": "openwop.requirement.0173.pack-isolation.memory-cap",
89
+ "openwop.it.v2-pack-isolation.node-pack-sandbox-isolated-context-a-pack-cannot-mutate-state-another-invocation": "openwop.requirement.0173.pack-isolation.isolated-context",
90
+ "openwop.it.v2-payload-registry-closed.every-registered-event-carries-a-payload-that-validates-against-its-typeindex-en": "openwop.requirement.0171.payload-registry-closed",
91
+ "openwop.it.v2-peer-dependency-declared.a-peerdependencies-key-the-declaration-file-does-not-name-is-refused-with-pack-p": "openwop.requirement.0177.peer-dependency-declared.undefined-key",
92
+ "openwop.it.v2-peer-dependency-declared.an-alias-table-row-host-fs-fs-resolves-through-the-overlap-and-the-pack-installs": "openwop.requirement.0177.peer-dependency-declared.alias-overlap",
93
+ "openwop.it.v2-pinned-run-disposition.a-pin-naming-a-change-id-the-host-does-not-implement-is-cancelled-with-v1-pin-un": "openwop.requirement.0176.pinned-run-disposition.cancelled",
94
+ "openwop.it.v2-pinned-run-disposition.a-pin-naming-a-change-id-the-host-still-implements-continues-under-the-reader-ru": "openwop.requirement.0176.pinned-run-disposition.continued",
95
+ "openwop.it.v2-poll-cursor-v2.the-response-is-the-closed-runid-events-lastsequence-status-isterminal": "openwop.requirement.0171.poll-cursor-v2.shape",
96
+ "openwop.it.v2-poll-cursor-v2.omitting-the-cursor-returns-from-the-first-event-sequence-0": "openwop.requirement.0171.poll-cursor-v2.from-first",
97
+ "openwop.it.v2-poll-cursor-v2.aftersequence-n-returns-only-events-with-sequence-n": "openwop.requirement.0171.poll-cursor-v2.after-sequence",
98
+ "openwop.it.v2-poll-cursor-v2.a-cursor-past-the-end-of-the-log-returns-200-with-an-empty-events-array": "openwop.requirement.0171.poll-cursor-v2.past-end",
99
+ "openwop.it.v2-preferred-version-default.preferredversion-is-a-member-of-protocolversions": "openwop.requirement.0172.preferred-version-default.member",
100
+ "openwop.it.v2-preferred-version-default.a-header-less-get-well-known-openwop-is-the-preferredversion-representation": "openwop.requirement.0172.preferred-version-default.headerless",
101
+ "openwop.it.v2-preferred-version-default.through-the-overlap-preferredversion-names-a-1-x-member": "openwop.requirement.0172.preferred-version-default.overlap",
102
+ "openwop.it.v2-profiles-derived-only.the-v2-document-carries-no-root-profiles": "openwop.requirement.0169.profiles-derived-only.no-root-profiles",
103
+ "openwop.it.v2-profiles-derived-only.every-registry-profile-is-derivable-from-the-document-the-discovery-core-predica": "openwop.requirement.0169.profiles-derived-only.derivable",
104
+ "openwop.it.v2-provider-conflict.two-definitions-of-one-bare-provider-id-fail-closed-the-later-registration-is-re": "openwop.requirement.0177.provider-conflict.fail-closed",
105
+ "openwop.it.v2-provider-conflict.the-qualified-form-packname-acme-widgets-resolves-to-the-named-pack-s-definition": "openwop.requirement.0177.provider-conflict.qualified-form",
106
+ "openwop.it.v2-refresh-sla.refreshedat-on-each-embedded-protocol-facet-is-within-90-days-of-now": "openwop.requirement.0175.refresh-sla",
107
+ "openwop.it.v2-relaxation-recorded.a-bundle-recording-a-relaxation-cannot-certify-the-relaxed-profile": "openwop.requirement.0173.relaxation-recorded",
108
+ "openwop.it.v2-relaxation-recorded.durability-is-a-closed-set-session-deployment-persisted": "openwop.requirement.0173.relaxation-recorded.durability-closed",
109
+ "openwop.it.v2-revocation-honored.a-revoked-next-request-credential-is-refused-on-the-next-request-with-credential": "openwop.requirement.0170.revocation-honored",
110
+ "openwop.it.v2-run-annotation-not-event.an-annotation-is-created-and-listed-and-never-enters-the-run-s-event-log": "openwop.requirement.0170.run-annotation-not-event",
111
+ "openwop.it.v2-run-bulk-cancel.101-ids-are-refused-400-validation-error-with-details-maxrunids": "openwop.requirement.0170.run-bulk-cancel",
112
+ "openwop.it.v2-run-bulk-cancel.results-come-back-in-request-order-each-id-processed-independently-a-foreign-id": "openwop.requirement.0170.run-bulk-cancel",
113
+ "openwop.it.v2-run-cancel.cancelling-a-terminal-run-is-refused-409-run-terminal": "openwop.requirement.0170.run-cancel",
114
+ "openwop.it.v2-run-cancel.cancelling-a-running-run-answers-200-with-cancelling-cancelled-emits-run-cancell": "openwop.requirement.0170.run-cancel",
115
+ "openwop.it.v2-run-completed-outputs.the-run-completed-event-of-a-run-that-completed-carries-an-outputs-object": "openwop.requirement.0171.run-completed-outputs",
116
+ "openwop.it.v2-run-diff-identical.two-identical-logs-diff-to-divergedatseq-null-and-empty-eventdiffs-in-a-response": "openwop.requirement.0170.run-diff-identical",
117
+ "openwop.it.v2-run-fork-prefix.a-replay-fork-inherits-exactly-0-fromseq-the-event-at-fromseq-is-re-executed-nev": "openwop.requirement.0170.fork-prefix-boundary",
118
+ "openwop.it.v2-run-fork-refusals.replay-overlay-400-a-fromseq-outside-the-log-422-fork-point-invalid-a-valid-repl": "openwop.requirement.0170.run-fork-refusals",
119
+ "openwop.it.v2-run-options-limits.odd-format-tags-and-free-form-metadata-are-accepted-and-surface-unchanged-on-the": "openwop.requirement.0171.run-options-limits",
120
+ "openwop.it.v2-run-pause-resume.pause-and-resume-on-a-terminal-run-answer-409-with-an-error-envelope": "openwop.requirement.0170.run-pause-resume",
121
+ "openwop.it.v2-run-pause-resume.a-running-run-pauses-202-paused-refuses-a-second-pause-409-resumes-202-running-a": "openwop.requirement.0170.run-pause-resume",
122
+ "openwop.it.v2-run-snapshot-etag.a-matching-if-none-match-receives-304-with-no-body-and-the-version-header-a-non": "openwop.requirement.0170.run-snapshot-etag",
123
+ "openwop.it.v2-sse-last-event-id.last-event-id-resumes-at-the-next-sequence-never-re-emits-the-resumption-point-l": "openwop.requirement.0171.sse-last-event-id",
124
+ "openwop.it.v2-stream-mode-refusal.a-value-outside-the-pattern-a-forbidden-combination-and-an-unimplemented-mode-ar": "openwop.requirement.0171.stream-mode-refusal",
125
+ "openwop.it.v2-stream-mode-refusal.updates-streams-200-text-event-stream-with-frames-bufferms-yields-at-least-one-b": "openwop.requirement.0171.stream-mode-refusal",
126
+ "openwop.it.v2-stream-sse-projection.every-data-frame-on-the-major-2-stream-carries-the-tenant-bound-runid-of-the-run": "openwop.requirement.0171.stream-sse-projection",
127
+ "openwop.it.v2-subject-link-record.the-link-formed-across-scim-and-saml-is-a-closed-subjectlink-record": "openwop.requirement.0170.subject-link-record.shape",
128
+ "openwop.it.v2-subject-link-record.deactivation-sets-deniedat-and-the-saml-decision-path-consults-it": "openwop.requirement.0170.subject-link-record.denied-at",
129
+ "openwop.it.v2-unmapped-type-refused.poll-over-a-log-with-an-unmapped-unprefixed-type-fails-with-500-event-type-unmap": "openwop.requirement.0176.unmapped-type-refused",
130
+ "openwop.it.v2-unmapped-type-refused.a-registered-vendor-type-the-codemap-does-not-name-is-read-under-its-own-name-un": "openwop.requirement.0176.vendor-type-passthrough",
131
+ "openwop.it.v2-unmapped-type-refused.a-fork-of-the-same-log-is-refused-for-the-same-reason-the-rule-binds-every-reade": "openwop.requirement.0176.unmapped-type-refused.fork",
132
+ "openwop.it.v2-v1-events-translated.poll-reads-an-era-2-log-with-v2-type-names-and-sequence-0-present": "openwop.requirement.0176.v1-events-translated.poll",
133
+ "openwop.it.v2-v1-events-translated.sse-reads-the-same-era-2-log-with-v2-type-names": "openwop.requirement.0176.v1-events-translated.sse",
134
+ "openwop.it.v2-v1-events-translated.a-fork-of-the-era-2-run-reads-its-inherited-prefix-with-v2-type-names": "openwop.requirement.0176.v1-events-translated.fork",
135
+ "openwop.it.v2-v1-signed-webhook-accepted.the-webhooks-facet-lists-scheme-v1-the-scheme-a-v1-signed-delivery-is-verified-u": "openwop.requirement.0176.v1-signed-webhook-accepted.facet",
136
+ "openwop.it.v2-v1-signed-webhook-accepted.the-host-s-v2-receiver-path-accepts-an-x-openwop-only-scheme-v1-delivery-and-ref": "openwop.requirement.0176.v1-signed-webhook-accepted",
137
+ "openwop.it.v2-version-header-honored.openwop-version-is-honored-or-refused-never-ignored": "openwop.requirement.0172.version-header-honored",
138
+ "openwop.it.v2-version-header-honored.a-host-advertising-two-majors-serves-two-different-representations": "openwop.requirement.0172.version-header-honored",
139
+ "openwop.it.v2-webhook-durable-delivery.a-failed-attempt-is-retried-and-the-event-is-delivered-at-least-once": "openwop.requirement.0173.webhook-durable-delivery",
140
+ "openwop.it.v2-webhook-durable-delivery.an-exhausted-delivery-is-dead-lettered-never-dropped": "openwop.requirement.0173.webhook-durable-delivery.dead-letter",
141
+ "openwop.it.v2-well-known-one-resource.a-header-less-get-and-an-openwop-version-2-0-get-are-two-representations-of-one": "openwop.requirement.0176.well-known-one-resource",
142
+ "openwop.it.v2-well-known-one-resource.the-v2-representation-carries-no-capabilities-wrapper-no-dotted-host-key-no-prof": "openwop.requirement.0176.well-known-one-resource.v2-representation",
143
+ "openwop.it.v2-alias-covers-reword.the-corpus-gate-script-exits-0": "openwop.requirement.0168.alias-covers-reword",
144
+ "openwop.it.v2-bundle-signature-attributable.the-v2-discovery-root-publishes-signingkeys-the-surface-the-rfc-named": "openwop.requirement.0168.bundle-signature-attributable.surface",
145
+ "openwop.it.v2-bundle-signature-attributable.the-front-door-gate-verifies-the-attestation-instead-of-inspecting-the-string": "openwop.requirement.0168.bundle-signature-attributable.verifies",
146
+ "openwop.it.v2-bundle-signature-attributable.the-four-signature-outcomes-stay-distinct-collapsing-any-two-restores-the-defect": "openwop.requirement.0168.bundle-signature-attributable.outcomes",
147
+ "openwop.it.v2-bundle-signature-attributable.signingkeys-is-reachable-from-a-v1-root-too-a-bundle-is-v3-regardless-of-major": "openwop.requirement.0168.bundle-signature-attributable.v1-root",
148
+ "openwop.it.v2-corpus-tag-pinned.every-vendoring-consumer-in-the-cross-repo-inventory-records-a-published-corpus": "openwop.requirement.0176.corpus-tag-pinned",
149
+ "openwop.it.v2-declaration-parity.the-corpus-gate-script-exits-0": "openwop.requirement.0169.declaration-parity",
150
+ "openwop.it.v2-eos-clock.the-clock-file-is-current-with-the-matrix-and-the-public-history": "openwop.requirement.0174.v1-eos-clock",
151
+ "openwop.it.v2-eos-clock.check-removal-dates-fails-the-v1-tree-sources-of-v1-end-of-support-rows-once-the": "openwop.requirement.0174.v1-eos-clock",
152
+ "openwop.it.v2-eos-clock.check-removal-dates-passes-under-the-same-clock-when-today-is-before-the-date-an": "openwop.requirement.0174.v1-eos-clock",
153
+ "openwop.it.v2-error-registry-prose-parity.errors-md-states-the-registry-count-it-was-generated-from-and-renders-every-code": "openwop.requirement.0171.error-registry-prose-parity",
154
+ "openwop.it.v2-event-naming-rule.every-closed-enum-v2-event-type-is-two-kebab-segments-and-every-recorded-artifac": "openwop.requirement.0171.event-naming-rule",
155
+ "openwop.it.v2-event-naming-rule.the-closed-enum-and-the-vendor-branch-are-disjoint-every-registered-type-validat": "openwop.requirement.0171.event-naming-rule",
156
+ "openwop.it.v2-events-channel-parity.the-corpus-gate-script-exits-0": "openwop.requirement.0171.events-channel-parity",
157
+ "openwop.it.v2-externally-gated-never-stable.the-corpus-gate-script-exits-0": "openwop.requirement.0169.externally-gated-never-stable",
158
+ "openwop.it.v2-id-kinds-bound.every-v2-id-field-refs-its-kind-and-every-id-property-is-triaged": "openwop.requirement.0170.id-kinds-bound",
159
+ "openwop.it.v2-one-signing-scheme.registry-version-manifest-signing-has-exactly-one-scheme-ed25519-canonical-json": "openwop.requirement.0177.one-signing-scheme",
160
+ "openwop.it.v2-path-parity.the-corpus-gate-script-exits-0": "openwop.requirement.0172.path-parity",
161
+ "openwop.it.v2-release-identity.the-corpus-gate-script-exits-0": "openwop.requirement.0172.release-identity",
162
+ "openwop.it.v2-req-only-assertions.the-corpus-gate-script-exits-0": "openwop.requirement.0168.req-only-assertions",
163
+ "openwop.it.v2-retention-floors.the-registry-validates-and-the-script-prints-the-floor-state-offline": "openwop.requirement.0174.retention-floors",
164
+ "openwop.it.v2-retention-floors.a-pinned-old-major-version-missing-from-its-registry-while-the-floor-is-open-fai": "openwop.requirement.0174.retention-floors",
165
+ "openwop.it.v2-retention-floors.the-same-probe-with-every-pinned-version-present-passes-while-the-floor-is-open": "openwop.requirement.0174.retention-floors",
166
+ "openwop.it.v2-seams-not-in-canonical.the-corpus-gate-script-exits-0": "openwop.requirement.0168.seams-not-in-canonical",
167
+ "openwop.it.v2-security-defaults-table.the-obligation-table-has-a-witness-column-and-no-row-is-unwitnessable": "openwop.requirement.0173.security-defaults-table",
168
+ "openwop.it.v2-spec-artifacts-digest.the-corpus-gate-script-exits-0": "openwop.requirement.0168.spec-artifacts-digest",
169
+ "openwop.it.v2-threat-model-template.the-corpus-gate-script-exits-0": "openwop.requirement.0173.threat-model-template",
170
+ "openwop.it.v2-witness-required.the-corpus-gate-script-exits-0": "openwop.requirement.0168.witness-required"
6
171
  }
7
172
  }