@openwop/openwop-conformance 2.42.5 → 2.42.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.
Files changed (123) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +3 -3
  3. package/coverage.md +1 -1
  4. package/dist/lib/soft-skip.js +13 -0
  5. package/dist/spec-artifacts.lock.json +2 -2
  6. package/package.json +2 -2
  7. package/requirements.json +430 -162
  8. package/scenario-majors.json +16 -3
  9. package/schemas/CORPUS-STAMP.json +64 -63
  10. package/src/lib/audit-checkpoint.ts +72 -0
  11. package/src/lib/era2-seed.ts +30 -0
  12. package/src/lib/ext-claims.ts +96 -0
  13. package/src/lib/soft-skip.ts +14 -0
  14. package/src/scenarios/a2a-peer-authority.test.ts +6 -13
  15. package/src/scenarios/a2a-task-roundtrip.test.ts +6 -34
  16. package/src/scenarios/a2a-version-negotiation.test.ts +6 -12
  17. package/src/scenarios/a2ui-surface-delta-transport.test.ts +23 -12
  18. package/src/scenarios/agent-channel-dispatch.test.ts +13 -4
  19. package/src/scenarios/agent-live-invocation-bracket.test.ts +1 -1
  20. package/src/scenarios/agent-manifest-runtime.test.ts +3 -0
  21. package/src/scenarios/aiEnvelope.capBreached.test.ts +2 -2
  22. package/src/scenarios/aiEnvelope.contractRefusal.test.ts +2 -2
  23. package/src/scenarios/aiEnvelope.schemaDrift.test.ts +2 -2
  24. package/src/scenarios/aiEnvelope.universalKinds.test.ts +2 -2
  25. package/src/scenarios/aiproviders-selfhosted-honesty.test.ts +2 -2
  26. package/src/scenarios/append-ordering.test.ts +26 -21
  27. package/src/scenarios/artifact-auth.test.ts +3 -1
  28. package/src/scenarios/artifact-type-registration-source.test.ts +2 -2
  29. package/src/scenarios/audit-checkpoint-signature.test.ts +63 -0
  30. package/src/scenarios/audit-checkpoint-vectors.test.ts +93 -0
  31. package/src/scenarios/auth-mtls.test.ts +7 -6
  32. package/src/scenarios/auth-subject-link-key-class.test.ts +3 -3
  33. package/src/scenarios/auth-subject-link.test.ts +19 -18
  34. package/src/scenarios/blob-presign-expiry.test.ts +2 -2
  35. package/src/scenarios/byok-roundtrip.test.ts +4 -1
  36. package/src/scenarios/compensation-behavior.test.ts +10 -5
  37. package/src/scenarios/conformance-advertised-seam-required.test.ts +6 -0
  38. package/src/scenarios/connection-pack-apihosts.test.ts +2 -2
  39. package/src/scenarios/connection-provider-resolution.test.ts +2 -2
  40. package/src/scenarios/context-budget-transcript-bound.test.ts +7 -3
  41. package/src/scenarios/context-summarization-replay.test.ts +2 -0
  42. package/src/scenarios/cost-attribution.test.ts +3 -1
  43. package/src/scenarios/debugBundle.test.ts +12 -4
  44. package/src/scenarios/discovery.test.ts +6 -2
  45. package/src/scenarios/dispatch-cross-worker-handoff.test.ts +2 -2
  46. package/src/scenarios/dispatch-input-mapping.test.ts +2 -2
  47. package/src/scenarios/dispatch-output-mapping.test.ts +15 -2
  48. package/src/scenarios/distillation-token-budget.test.ts +2 -2
  49. package/src/scenarios/durability-poison-exhaustion.test.ts +2 -2
  50. package/src/scenarios/envelope-nl-to-format-engaged.test.ts +2 -2
  51. package/src/scenarios/envelope-recovery-applied.test.ts +2 -2
  52. package/src/scenarios/envelope-refusal-shape.test.ts +2 -2
  53. package/src/scenarios/envelope-retry-attempted.test.ts +2 -2
  54. package/src/scenarios/envelope-retry-exhausted.test.ts +2 -2
  55. package/src/scenarios/envelope-tier-one-subset-static.test.ts +1 -1
  56. package/src/scenarios/envelope-truncation-cap-exhaustion.test.ts +2 -2
  57. package/src/scenarios/eventOrdering.test.ts +17 -10
  58. package/src/scenarios/form-content-instantiation.test.ts +2 -2
  59. package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +2 -2
  60. package/src/scenarios/highConcurrency.test.ts +9 -9
  61. package/src/scenarios/idempotency-concurrent-claim.test.ts +5 -5
  62. package/src/scenarios/idempotency-key-determinism.test.ts +8 -8
  63. package/src/scenarios/idempotency.test.ts +6 -6
  64. package/src/scenarios/idempotencyRetry.test.ts +16 -11
  65. package/src/scenarios/interrupt-token-matrix.test.ts +24 -11
  66. package/src/scenarios/mcp-cache-tenant-scope.test.ts +3 -3
  67. package/src/scenarios/mcp-current-auth-boundary.test.ts +9 -6
  68. package/src/scenarios/mcp-extension-opacity.test.ts +6 -5
  69. package/src/scenarios/mcp-mrtr-roundtrip.test.ts +9 -8
  70. package/src/scenarios/mcp-version-negotiation.test.ts +5 -10
  71. package/src/scenarios/media-url-inline-cap.test.ts +3 -2
  72. package/src/scenarios/memory-compaction-provenance-tag.test.ts +2 -0
  73. package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +2 -2
  74. package/src/scenarios/memory-consolidation-idempotent.test.ts +2 -2
  75. package/src/scenarios/memory-injection-budget.test.ts +2 -2
  76. package/src/scenarios/multi-party-conversation-behavioral.test.ts +2 -2
  77. package/src/scenarios/multi-region-idempotency-behavior.test.ts +9 -9
  78. package/src/scenarios/multi-region-idempotency.test.ts +2 -2
  79. package/src/scenarios/pack-registry-isolation.test.ts +13 -12
  80. package/src/scenarios/pack-registry.test.ts +3 -2
  81. package/src/scenarios/pause-resume.test.ts +30 -11
  82. package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +43 -34
  83. package/src/scenarios/provider-usage.test.ts +2 -2
  84. package/src/scenarios/redaction.test.ts +7 -5
  85. package/src/scenarios/redactionAdversarial.test.ts +5 -4
  86. package/src/scenarios/registry-public.test.ts +5 -1
  87. package/src/scenarios/replay-divergence-at-refusal.test.ts +10 -7
  88. package/src/scenarios/replay-fanout-suppression.test.ts +7 -4
  89. package/src/scenarios/replay-fork-arbitrary.test.ts +2 -2
  90. package/src/scenarios/replay-side-effect-suppression.test.ts +2 -2
  91. package/src/scenarios/replayDeterminism.test.ts +9 -4
  92. package/src/scenarios/runner-ledger.test.ts +4 -0
  93. package/src/scenarios/runtime-capabilities.test.ts +2 -0
  94. package/src/scenarios/speech-synthesis-roundtrip.test.ts +1 -1
  95. package/src/scenarios/streamReconnect.test.ts +2 -2
  96. package/src/scenarios/subrun-approval-gate.test.ts +2 -2
  97. package/src/scenarios/subworkflow-input-mapping.test.ts +2 -2
  98. package/src/scenarios/tool-catalog-projection.test.ts +10 -7
  99. package/src/scenarios/tool-session-lifecycle.test.ts +1 -1
  100. package/src/scenarios/trigger-ingestion.test.ts +2 -2
  101. package/src/scenarios/v2-a2ui-v09-surface.test.ts +15 -0
  102. package/src/scenarios/v2-effect-identity-business-key.test.ts +12 -0
  103. package/src/scenarios/v2-era-2-append-vocabulary.test.ts +39 -24
  104. package/src/scenarios/v2-ext-family-claims.test.ts +62 -0
  105. package/src/scenarios/v2-ext-rest-transport.test.ts +151 -0
  106. package/src/scenarios/v2-idempotency-in-flight.test.ts +3 -0
  107. package/src/scenarios/v2-legacy-profiles-absent.test.ts +4 -6
  108. package/src/scenarios/v2-mcp-tasks.test.ts +1 -1
  109. package/src/scenarios/v2-min-client-version.test.ts +2 -0
  110. package/src/scenarios/v2-refresh-sla.test.ts +6 -5
  111. package/src/scenarios/v2-sse-last-event-id-cursor.test.ts +3 -3
  112. package/src/scenarios/v2-sse-last-event-id.test.ts +2 -0
  113. package/src/scenarios/v2-version-header-honored.test.ts +3 -0
  114. package/src/scenarios/v2-webhook-durable-delivery.test.ts +2 -0
  115. package/src/scenarios/v2-webhook-secret-rotation.test.ts +8 -1
  116. package/src/scenarios/verifier-gating.test.ts +2 -2
  117. package/src/scenarios/version-fold.test.ts +2 -2
  118. package/src/scenarios/wasm-pack-invoke-suspended.test.ts +7 -6
  119. package/src/scenarios/webhook-signed-delivery.test.ts +2 -0
  120. package/src/scenarios/workflow-chain-host-expansion.test.ts +10 -1
  121. package/src/scenarios/workflow-variable-format.test.ts +2 -2
  122. package/src/scenarios/workload-identity-chain-bounds.test.ts +6 -3
  123. package/vectors/audit-checkpoint-v1.json +260 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # `@openwop/openwop-conformance` Changelog
2
2
 
3
+ ## [2.42.7] — 2026-09-27 — audit residuals, and extension families can graduate on evidence
4
+
5
+ - **`v2-sse-last-event-id-cursor` joins the core-standard floor.** It was held off until the three bundle hosts were measured. All three record it `executed-pass`: the v2 reference host on 2.42.2, MyndHyve on 2.42.0 and openwop-app on 2.42.2. Two carry `partial-witness` only on the SHOULD leg (a malformed `Last-Event-ID` is accepted, which is recorded rather than failed). No existing claim moves.
6
+ - **The v2 capabilities schema loses a no-op conditional.** `multiAgent.executionModel`'s `tier: experimental ⇒ experimentalUntil` rule projected to `if: {properties: {}}, then: {}` once both fields were retired. The generator now drops a conditional whose branches both project to nothing. Validation is unchanged.
7
+ - **`check-v2-surface-monotone` could not see a tightened capability family.** The surface-baseline walker counted an object's own `then`/`else` as a second branch reaching the object's path. Its intersection rule then dropped the object's unconditional `closed` and `required` tuples from every object carrying an `if`, which covered 98 objects, every capability family record among them. Adding a REQUIRED member to `a2a` passed the gate (sabotage-checked before and after). The walker now treats a same-path conditional as layered on its parent. The baseline gains 540 restriction tuples (98 `closed`, 442 `required`), with no removals, and is still stamped at release 2.42.6.
8
+ - **RFC 0218: audit checkpoints can be verified.** `vectors/audit-checkpoint-v1.json` (the RFC 8032 TEST 1 key) holds entry hashes, roots and signatures, plus refusals. `audit-checkpoint-vectors.test.ts` (server-free, both majors) recomputes them through the new `lib/audit-checkpoint.ts`, and three lib sabotages each turned one leg red. `audit-checkpoint-signature.test.ts` (major 1, gated on `openwop-audit-log-integrity`) verifies every checkpoint `GET /v1/audit/verify` returns, under the advertised `checkpointPublicKey`, over its hex-decoded root. Until now the suite checked only a signature's length.
9
+ - **Softskip-after-assert ratchet, tranche A: 15 scenarios lower their baseline (87 → 30 in these files).** Each soft-skip that followed an assertion, and so recorded a partial-witness PASS, was reviewed against its spec clause. A requirement a conforming host always makes observable now records `blocked` (`blockedDespiteAssertions`). Examples: `/events/poll` in `eventOrdering`, `replayDeterminism` and `debugBundle`; a second replay fork after the first was accepted; §21 `fail: false` firing a trigger; the a2ui full-surface read. A skip whose condition is knowable first now returns before any assertion and records `inapplicable`: `redaction`'s omitted `secrets`, `debugBundle`'s empty `spans`, a2ui's SSE-only or frame-less host, and `pause-resume` on a host that does not advertise `runs.pauseResume`, where a 404 is out of scope rather than a pass. An advertiser that 404s records `blocked`. A genuine partial witness is annotated `partial-witness-ok`. `prompt-read-workspace-membership-enforced` records a refused or empty read as the pass it is. Dead notes after `ctx.skip()`, which throws, and after assertions that already failed are removed. Measured before and after on the v2 reference host (majors 1 and 2) and openwop-app (major 1): no row became `executed-fail`, and no conforming row became `blocked`. The 30 that remain are parser artifacts of the gate, which brace-counts through string literals and matches `softSkip(` inside comments.
10
+ - **`check-softskip-after-assert` counts real sites only.** The gate scanned raw text. A `{` inside a string literal (`'{"valid":'`) unbalanced its brace count and merged an `it()` block into the next one, and `softSkip(` quoted in a comment counted as a call. That produced 30 phantom sites on the merged tree: envelope-truncated 11, envelope-completion-distinguishes-truncation 10, v2-a2a-operation-map 3, agent-manifest-runtime 2, redaction 2, context-budget-transcript-bound 1 and runner-ledger 1. The same merges hid 9 real ones: aiEnvelope.capBreached, aiEnvelope.contractRefusal, aiEnvelope.universalKinds, artifact-auth, envelope-tier-one-subset-static, pack-registry-isolation, pack-registry, registry-public and v2-effect-identity-business-key. The gate now blanks comments, strings and regex literals (offsets kept) before finding blocks, and reads the skip kind from the raw text. The baseline moves 31 → 10 (after tranche B) via `--write --allow-raise`. The 9 raised files are the gate becoming honest, not new debt. New self-test `src/lib/softskip-after-assert-parser.test.ts` pins both shapes and a positive control, and fails against the old parser.
11
+ - **softskip-after-assert ratchet, tranche B: 84 sites cleared** (with tranche A, the baseline falls from 172 to 31). The rule for each site: when a conforming host could have made the requirement observable and this one did not, it records `blockedDespiteAssertions` (44 sites). A skip whose condition is known up front now runs before the first assertion (7). A genuine partial witness, a SHOULD, or an IF-present clause whose field is absent carries a `partial-witness-ok:` reason (20). Eight skips followed an assertion that had already failed the leg, so they could never run; they now throw an `unreachable` error. Four followed a conformant outcome the leg had fully observed; those branches now end without a skip note. A skip string inside a comment tripped the gate and was reworded. New helper `seamAbsentDespiteAssertions` fails in strict mode and records a standing `blocked` otherwise, for a seam that goes missing after setup assertions. At major 1 a plain `seamAbsent` there was a partial-witness pass. **`interrupt-token-matrix`'s replay leg could not fail on any host.** It polled for `waiting-external-event`, which is not a run status, and read `snapshot.interrupts[].token`, which the snapshot does not carry. So it never found a token and recorded a pass on the run's `201` alone. It now reads the token the way `interrupt-external-event-correlation` does and resolves with the fixture's matching correlation. **`a2a-task-roundtrip`'s fake-peer path probed the suite's own fake A2A peer**, so no host was exercised. It is now `inapplicable`, as `mcp-tool-roundtrip`'s fake path became in 2.42.4.
12
+ - **softskip-after-assert, tranche B follow-up: 9 sites the old gate could not see.** The fixed parser surfaced them. Three `aiEnvelope` projection legs whose event-log query failed after the seam accepted now record `blockedDespiteAssertions`. `artifact-auth` (a bare 401 has no SHOULD envelope to check) and `registry-public` (a `manual`-signed pack's signature is outside what the scenario verifies) carry `partial-witness-ok`. `pack-registry`'s optional-keychain 404 now skips before its first assertion. `pack-registry-isolation`'s 200-without-the-pack branch observed isolation, so it no longer ends in a skip note. `envelope-tier-one-subset-static`'s skip could never run and now throws `unreachable`. `v2-effect-identity-business-key` is annotated: at runtime no assertion passes before its skip.
13
+ - **`dispatch-output-mapping`'s cancelled-child leg is `inapplicable`, not `blocked`, when the child cannot be found mid-flight** (a tranche-B re-verdict). The leg cancels the child through the `childRunId` on `node.dispatched`. The `nodeDispatched` schema defines `childStatus` as the child's status "at the moment the dispatch step returned", so a conforming host may emit the event only after the child terminates. openwop-app does exactly that. Recording `blocked` there denied certification to a conforming host (measured against an openwop-app boot at major 1).
14
+ - **A missing OPTIONAL seam field is neither a failure nor `blocked`** (steward ruling; the 2.42.6 `appendEra2Event` precedent). `a2a-peer-authority` (`peerAuthority`) and `mcp-extension-opacity` (`extensionAuthority`) now record `inapplicable` before any assertion when the invoke seam omits the field. They used to fail the leg on a conforming host. `mcp-mrtr-roundtrip` (`mrtr`) still witnesses the retry on the wire and checks the seam's report only when the host sends one. A field that is present but reports a violation still fails. Measured against an openwop-app boot with the fields sabotaged: absent records `inapplicable` or `executed-pass`, and broken records `executed-fail`. `v2-webhook-secret-rotation`'s post-overlap skip now names the advertised `overlapSeconds` and the suite wait cap.
15
+ - **`host-callback-declaration` fails on every full-catalog run: `v2-effect-identity-business-key` never declared its callback.** 2.42.4 gave its retry leg a suite-owned effect receiver (`lib/effect-receiver.ts`), which the host calls back, and the self-check requires a scenario importing a harness double to export `REQUIRES_HOST_CALLBACK`. The scenario did not, so the gate recorded `executed-fail` on every host (measured on openwop-app's full-catalog lane at 2.42.6). It now declares the callback in the same words as `v2-durability-recovery`. No host behaviour is asserted differently.
16
+ - **Seven v1 idempotency scenarios cite `spec/v1/idempotency.md` explicitly** (citation only; no assertion changes). `idempotency`, `idempotencyRetry`, `highConcurrency`, `idempotency-concurrent-claim`, `idempotency-key-determinism`, `multi-region-idempotency` and `multi-region-idempotency-behavior` cited bare `idempotency.md` with v1-only section names (`§"Concurrent duplicates (Layer 2)"`, `§"Record shape, digest, and lease"`, `§Server responsibilities #2`) that do not exist in `spec/v2/core/idempotency.md`.
17
+ - **RFC 0220: extension families can graduate on evidence.** Before this, no scenario recorded an `openwop.family.<key>` pass, so `spec/v2/ext/README.md`'s `Stable` predicate could never be met.
18
+ - New `v2-ext-family-claims` (major 2): the `claims-check` witness for the 11 discovery-only reservations. Each leg reads `extensions["<org>.<extensionName>"]` through the new `lib/ext-claims.ts`, records `executed-pass` under `openwop.family.<key>` for a well-formed claim, and records `inapplicable` when no registered org advertises the family.
19
+ - New `v2-ext-rest-transport` (major 2): the v2 port of `run-transport-economy`, reading the extensions record instead of the v1 root key.
20
+ - `v2-a2ui-v09-surface` gains a family-witness leg with a refused control.
21
+ - `src/lib/ext-claims.test.ts` has nine self-test cases, and the reserved-org and root-copy sabotages each turn one red.
22
+ - **Suite `2.42.7`**. `@openwop/spec-artifacts` moves in lockstep at the same exact pin.
23
+
24
+ ## [2.42.6] — 2026-09-27 — the era-2 writer rule is witnessable again
25
+
26
+ - **`0176.era-2-append-vocabulary` is a real witness again on a host that serves the new seam.** New OPTIONAL seams-profile seam `appendEra2Event` (`POST /conformance/seams/sample/event-log/append`, `api/seams-v2.yaml`; `host-sample-test-seams.md` §27) appends ONE v2-named event to a seeded era-2 run through the host's PRODUCTION writer; the leg appends `agent.reasoning-delta` (a codemap-renamed type, stored v1 `agent.reasoning.delta`) and requires the translated read to return the v2 name. Sabotaged: a host whose writer stores v2 names fails the read `500 event_type_unmapped` → `executed-fail`. Dispositions: seam served → a real assertion (the 2.42.5 `partial-witness-ok` annotation is gone for that path); seam served but contract broken → `blocked`; seam NOT served → the 2.42.5 partial witness, never `blocked` (an optional seam newer than the leg must not take away a certification); seams profile not claimed → `inapplicable`.
27
+ - **Suite `2.42.6`**. `@openwop/spec-artifacts` moves in lockstep at the same exact pin.
28
+
3
29
  ## [2.42.5] — 2026-09-27 — hotfix: a host can certify again
4
30
 
5
31
  - **`0176.era-2-append-vocabulary` no longer blocks every host.** 2.42.3's unfailable-leg audit made this leg `blockedDespiteAssertions` whenever a host's appended types are spelled the same in v1 and v2. No catalogued seam lets any host make a seeded era-2 run append a type the codemap renames, so the row recorded `blocked` on every host, and one `blocked` row denies the whole bundle (RFC 0168 §E.1). **No host could certify on 2.42.3 or 2.42.4.** The leg now records a partial witness whose detail says the codemap-renaming writer rule is unwitnessed. The append, the read-back and the sequence rules are observed, and the acceptance predicate still refuses a partial-witness row. It is annotated `partial-witness-ok` for the softskip gate. openwop-1f is adding the seam that makes the rule witnessable. Verified on the v2 reference host: the row now records `executed-pass` with that detail.
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  # --legacy-peer-deps is REQUIRED, not optional: the exact peer pin is what npm's
12
12
  # default resolver refuses. npm 10.9 fails outright with
13
13
  # "Cannot read properties of null (reading 'edgesOut')" — use npm >= 11.
14
- npm install --legacy-peer-deps @openwop/openwop-conformance@2.42.5 @openwop/spec-artifacts@2.42.5
14
+ npm install --legacy-peer-deps @openwop/openwop-conformance@2.42.7 @openwop/spec-artifacts@2.42.7
15
15
  # or run without install:
16
16
  npx @openwop/openwop-conformance --base-url https://api.example.com --api-key hk_test_...
17
17
  ```
@@ -135,7 +135,7 @@ Exit code is non-zero on any failed assertion. `--certify` distinguishes: `0`
135
135
 
136
136
  ## What's Covered
137
137
 
138
- The current suite has 561 scenario files under `src/scenarios/`.
138
+ The current suite has 565 scenario files under `src/scenarios/`.
139
139
  - 2026-09-23 (suite 2.37.0 cycle, RFC 0213): NEW `v2-sse-last-event-id-cursor.test.ts` (a `Last-Event-ID` past the log is an exclusive cursor; a malformed id, when refused, is `400 validation_error`; the cursor never changes the answer for an unknown or foreign-tenant run — public test of `event-cursor-after-authorization`), `v2-idempotency-in-flight.test.ts` (five concurrent same-key creates yield one run; each loser is a marked replay or `409 idempotency_in_flight` with no retry timing in `details`; `partial-witness` when no loser was refused in flight) and `v2-interrupt-resolve-terminal.test.ts` (a run-scoped resolve after cancel or completion is `409 interrupt_already_resolved`, never `interrupt_cancelled`). All three sit off the core-standard floor until measured on the three bundle hosts.
140
140
  - 2026-09-03 (suite `1.157.0 -> 1.158.0`, gap G17): NEW `idempotency-concurrent-claim.test.ts` — drives the new `host-sample-test-seams.md` §25 concurrent duplicate-delivery seam for the RFC 0150 §B / `idempotency.md` §"Concurrent duplicates (Layer 2)" atomic-claim MUST, which is unconditional and had no witness of any kind. Asserts every executor mints the SAME `logicalInvocationId` **before** asserting `delivered === 1` — without the identity check a host passes by minting different ids and never colliding, one effect because nothing raced. Not profile-gated and so not opt-out-able (the obligation is unconditional); an unmounted seam records `blocked`, which is not certifiable. Graduates `layer2-invocation-claim-atomic` reference-impl -> protocol.
141
141
  - 2026-08-19 (suite `1.137.0 → 1.138.0`): NEW `durability-poison-exhaustion.test.ts` — RFC 0158 §C.8, the FIRST row of that RFC's conformance table to land. Asserts what `failure-path.test.ts` cannot: not just that deterministically failing work reaches terminal, but that attempts STOP — counted on the log, re-counted after a scaled quiet window, asserted unchanged. A host still redelivering records more. Seam-gated on the existing event-log seam (`blocked` = unobservable, not unmet) and outside every profile floor.
@@ -481,7 +481,7 @@ Server-required (added in 1.7.0):
481
481
  | ------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
482
482
  | **Redaction** | [`capabilities.md`](../spec/v1/capabilities.md) §"Secrets" + NFR-7 + §"aiProviders" | Vendor-neutral assertions that the server doesn't leak secret material. Three scenario groups: (a) discovery shape contract — `secrets` + `aiProviders` advertisements are well-formed regardless of `secrets.supported`; when `supported === true`, scopes MUST be non-empty + `resolution === 'host-managed'`; `byok ⊆ supported`. (b) bearer-token redaction — invalid Bearer canary in `Authorization` header is not echoed in the 401 response body. (c) credentialRef echo control — gated on `secrets.supported === true`; canary planted in `configurable.ai.credentialRef` MUST NOT appear in any RunEvent payload (poll-based capture; transport-agnostic). Uses runtime-built canary fixtures (`lib/canaries.ts`) that defeat static secret scanners. 6 scenarios. |
483
483
 
484
- Current source tree: 561 scenario files. Use [`coverage.md`](./coverage.md) for current grade/gap tracking.
484
+ Current source tree: 565 scenario files. Use [`coverage.md`](./coverage.md) for current grade/gap tracking.
485
485
 
486
486
  ## Remaining Gaps
487
487
 
package/coverage.md CHANGED
@@ -37,7 +37,7 @@
37
37
  | Per-workflow `configurableSchema` | `configurable-schema.test.ts` | A− | Negative validation + positive accepted-overlay + `GET /v1/workflows/{id}` schema-surface assertion all covered (CF-7 close-out, 2026-05-15). Grade moves C+ → A−. |
38
38
  | Append-reducer ordering | `append-ordering.test.ts` | B | Intra-engine sequence-order check; remaining: cross-engine ordering under a multi-engine fixture. |
39
39
  | Webhook signature algorithms | `webhook-sig-algorithm.test.ts`, `webhook-signed-delivery.test.ts`, `webhook-negative.test.ts`, `webhook-receiver-adversarial.test.ts` | A | Forward direction: discovery shape + end-to-end signed delivery with HMAC verification (`webhook-signed-delivery`); negative paths (SSRF guard / validation / unknown-unregister via `webhook-negative`). Reverse direction (CF-5 close-out 2026-05-15): `webhook-receiver-adversarial.test.ts` covers 6 paths — positive control + tampered body + tampered HMAC + stale timestamp + replayed signature + wrong algorithm + malformed signature header. Reference receiver implementation at `conformance/src/lib/webhook-receiver.ts` mirrors the SDK's `verifyWebhookSignature` helper. |
40
- | Audit-log integrity profile | `audit-log-integrity.test.ts` | A | Profile claim + `/v1/audit/verify` shape + checkpoint-signature verification; chain re-walk with `chainValid` and `checkpointsValid` bits. Tamper detection covered host-internally at `openwop-examples:examples/hosts/sqlite/test/audit-tamper.test.ts` (mutate-entry + forge-signature paths). CF-11 close-out 2026-05-15: cross-host checkpoint export via `openwop-examples:examples/hosts/postgres/src/audit-export.ts` + standalone verifier at `scripts/verify-audit-checkpoints.mjs`; `openwop-examples:examples/hosts/postgres/test/audit-checkpoint-export.test.ts` verifies 7 paths (positive + tampered-signature + non-monotonic-atSequence). The standalone verifier is additionally regression-guarded in `openwop:check` (step 7) against the committed `conformance/audit-export-samples/{valid,tampered}.json` bundles — accept-valid (exit 0) + reject-tampered (exit 1) — so a verifier regression is caught at the spec gate, not only in the postgres host's own test. |
40
+ | Audit-log integrity profile | `audit-log-integrity.test.ts` | A | Profile claim + `/v1/audit/verify` shape; checkpoint-signature verification under the advertised key (`audit-checkpoint-signature.test.ts`, RFC 0218) and the pinned preimage vectors (`audit-checkpoint-vectors.test.ts`); chain re-walk with `chainValid` and `checkpointsValid` bits. Tamper detection covered host-internally at `openwop-examples:examples/hosts/sqlite/test/audit-tamper.test.ts` (mutate-entry + forge-signature paths). CF-11 close-out 2026-05-15: cross-host checkpoint export via `openwop-examples:examples/hosts/postgres/src/audit-export.ts` + standalone verifier at `scripts/verify-audit-checkpoints.mjs`; `openwop-examples:examples/hosts/postgres/test/audit-checkpoint-export.test.ts` verifies 7 paths (positive + tampered-signature + non-monotonic-atSequence). The standalone verifier is additionally regression-guarded in `openwop:check` (step 7) against the committed `conformance/audit-export-samples/{valid,tampered}.json` bundles — accept-valid (exit 0) + reject-tampered (exit 1) — so a verifier regression is caught at the spec gate, not only in the postgres host's own test. |
41
41
  | Multi-region idempotency capability | `multi-region-idempotency.test.ts` | C | Discovery enum coverage; remaining: cross-region partition simulation (requires multi-region harness). |
42
42
  | Public hosted registry (`packs.openwop.dev`) | `registry-public.test.ts` | A− | Discovery, index, and per-pack manifest assertions against the public registry. Opt-in via `OPENWOP_TEST_PUBLIC_REGISTRY=true` so default conformance runs don't depend on outbound `packs.openwop.dev` reachability. Remaining: tarball-fetch + signature-verify roundtrip. |
43
43
  | Workflow-chain packs (RFC 0013 — `spec/v1/workflow-chain-packs.md`) | `workflow-chain-pack-manifest-validation.test.ts`, `workflow-chain-pack-signature-verification.test.ts`, `workflow-chain-expansion.test.ts`, `workflow-chain-unresolvable-typeid.test.ts`, `workflow-chain-host-expansion.test.ts` | A (4 server-free + live-host harness-witnessed by openwop-app #1298, 6/6) | RFC 0013 promoted Draft → Active → Accepted 2026-05-18 on the 4 server-free scenarios (pure-library algorithm). **Erratum (2026-07-05):** the live-host leg (`workflow-chain-host-expansion.test.ts`, `POST /v1/host/sample/workflow-chain:expand`, 6 cases) actually **soft-skips against every host** — no reference host serves the seam and the `vendor.openwop.workflow-chain-sample` fixture was never bundled here — so it is re-gated onto the OPTIONAL `capabilities.workflowChainPacks.hostExpansionSeam` sub-flag (a test-harness advertisement), decoupled from the semantic `supported` claim so it no longer blocks the RFC 0124 `deferredParameters` flip. **A-lite (2026-07-05, suite `1.52.0`):** the `vendor.openwop.workflow-chain-sample` pack is now bundled at `fixtures/pack-manifests/workflow-chain-sample.pack.json` and the scenario **loads** it + derives expected output from the `expandChain()` reference library (no hardcode) — and a host wiring the `/…:expand` route + advertising `hostExpansionSeam` witnesses it. **Witnessed 2026-07-05:** openwop-app (#1298) serves the seam-gated route (404 prod, RFC 0117 posture) resolving the bundled `@1.52.0` fixture through its `expandChain()` → the 6 positive+negative legs run **6/6 non-vacuously** under `OPENWOP_REQUIRE_BEHAVIOR`, checked against the reference library via the host's returned `expansionId` — harness-tier (in-process, test-only seam; RFC 0035/0118 evidence tier). Closes RFC 0013's Phase-3 host-expansion acceptance item. RFC 0124's deferred path is separately covered by `workflow-chain-deferred-parameters.test.ts` (openwop-app `/chain/deferred-expand` seam #1292, gated legs 12/0). The matching spec doc `workflow-chain-packs.md` remains at `DRAFT v1.x` pending Phase B/C closure (parameter schema validation + cross-host expansion equivalence). |
@@ -100,6 +100,19 @@ export function blockedDespiteAssertions(reason) {
100
100
  notes.set(file, arr);
101
101
  return undefined;
102
102
  }
103
+ /**
104
+ * `seamAbsent` for a seam that goes missing AFTER the leg has asserted setup
105
+ * facts: strict mode fails exactly as `seamAbsent` does, and default mode
106
+ * records a `blocked` that stands at both majors (`blockedDespiteAssertions`).
107
+ * A plain `seamAbsent` there notes `blocked`, which major 1 records as a
108
+ * partial-witness pass.
109
+ */
110
+ export function seamAbsentDespiteAssertions(reason) {
111
+ if (process.env['OPENWOP_REQUIRE_BEHAVIOR'] === 'true') {
112
+ throw new Error(`RFC 0148 §B: advertised behaviour is not observable — ${reason} (OPENWOP_REQUIRE_BEHAVIOR=true fails an advertised-missing seam)`);
113
+ }
114
+ return blockedDespiteAssertions(reason);
115
+ }
103
116
  const RANK = { blocked: 0, skipped: 1, inapplicable: 2 };
104
117
  function fold(arr) {
105
118
  if (arr.length === 0)
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "package": "@openwop/spec-artifacts",
3
- "version": "2.42.5",
4
- "stampSha256": "3f879249fa54b8619a9a4b156aa3064f2ad660e2e5a7d232eb4da0d3c5734f58"
3
+ "version": "2.42.7",
4
+ "stampSha256": "8f82b45d0b4004faf11a49d998e0bebefd3ad7a89d82e67322aabafcd18544a1"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/openwop-conformance",
3
- "version": "2.42.5",
3
+ "version": "2.42.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.42.5"
59
+ "@openwop/spec-artifacts": "2.42.7"
60
60
  }
61
61
  }