@openwop/openwop-conformance 2.46.34 → 2.46.36
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 +30 -0
- package/README.md +3 -3
- package/coverage.md +4 -5
- package/dist/spec-artifacts.lock.json +2 -2
- package/fixtures/conformance-interrupt-form-refused.json +108 -0
- package/fixtures/conformance-interrupt-form-unbound.json +108 -0
- package/fixtures/conformance-interrupt-form.json +107 -0
- package/fixtures/conformance-stream-text.json +1 -2
- package/fixtures.md +44 -4
- package/package.json +2 -2
- package/requirement-aliases.json +98 -1
- package/requirements.json +663 -804
- package/scenario-majors.json +16 -19
- package/schemas/CORPUS-STAMP.json +72 -85
- package/src/lib/callai-attempts-witness.ts +13 -1
- package/src/lib/deployment-lifecycle-witness.ts +308 -0
- package/src/lib/family-advert-witness.ts +37 -50
- package/src/scenarios/stream-text-fixture.test.ts +13 -5
- package/src/scenarios/v2-deployment-lifecycle.test.ts +526 -0
- package/src/scenarios/v2-envelope-surfaces-absent.test.ts +55 -0
- package/src/scenarios/v2-interrupt-form-rules.test.ts +143 -0
- package/src/scenarios/v2-limits-clarification-rounds-advertisement.test.ts +42 -0
- package/src/scenarios/v2-peer-dependency-declared.test.ts +1 -1
- package/src/scenarios/v2-provider-output-reliability.test.ts +94 -0
- package/src/scenarios/v2-structured-output-advertisement.test.ts +82 -0
- package/src/lib/envelope-schema-static.ts +0 -167
- package/src/scenarios/v2-a2ui-v09-surface.test.ts +0 -323
- package/src/scenarios/v2-ai-envelope-advertisement.test.ts +0 -43
- package/src/scenarios/v2-envelope-contracts-advertisement.test.ts +0 -48
- package/src/scenarios/v2-envelope-reasoning-shape.test.ts +0 -81
- package/src/scenarios/v2-envelope-tier-one-subset-static.test.ts +0 -64
- package/src/scenarios/v2-envelopes-advertisement.test.ts +0 -85
- package/src/scenarios/v2-limits-envelope-caps-advertisement.test.ts +0 -61
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
## [2.46.36] — 2026-10-31 — The AI Envelope is deleted from v2
|
|
2
|
+
|
|
3
|
+
- **Envelope scenarios removed (RFC 0255).** Ten major-2 envelope and A2UI files are deleted, and their ids carry tombstones naming `openwop.correction.v2.5`. `v2-structured-output-advertisement` and `v2-limits-clarification-rounds-advertisement` replace the advertisement files they re-point, with alias rows. Major-1 scenarios are unchanged.
|
|
4
|
+
- **New scenarios.** `v2-envelope-surfaces-absent` (unaided) refuses a discovery document that still publishes a deleted family or limit. `v2-provider-output-reliability` drives the attempt-accounting fixture through truncation, exhaustion and refusal; the fixture's mock gains a `refusal` script kind.
|
|
5
|
+
- **Fixture.** `conformance-stream-text` runs `core.conformance.stream-text` and names no prompt. A host serving the mock without the fixture records `blocked`.
|
|
6
|
+
- **New scenario `v2-interrupt-form-rules` (RFC 0255 §E).** Gated on the fixtures `conformance-interrupt-form`, `-refused` and `-unbound`, and inapplicable on a host advertising none of them. It asserts that a form arrives unchanged beside `questions`, that it resolves with `{ answers: [{ id, answer }] }`, and that neither probe is raised with its form. The corpus file `a2ui-v09-profile` gains three `0255.interrupt-form-*` legs.
|
|
7
|
+
- **Filings.** The cycle carries the RFC 0255 and 0256 filings and the RFC 0255 §D licence. `requirement-aliases.json` gains a `tombstones` map: an id the sources no longer mint needs an alias or a tombstone naming the `steward-deletion` row that deleted its surface.
|
|
8
|
+
|
|
9
|
+
## [2.46.35] — 2026-10-29 — MyndHyve's legacy runtime retired
|
|
10
|
+
|
|
11
|
+
- **Registers.** MyndHyve's legacy `workflow-runtime` (`api.myndhyve.ai`) retired on 2026-10-29; MyndHyve runs on the openwop-app white-label. Register rows that measured the legacy host close or re-gate, so the packed `spec/v1/gaps.json` changes.
|
|
12
|
+
- **New scenario `v2-deployment-lifecycle` (RFC 0082 §B, §C, §E, §F).** It drives `core.conformance.channel-agent` through `listAgentDeployments` and `transitionAgentDeployment`, plus runs and a replay of the existing fixture `conformance-agent-channel-dispatch`, with no seam. Fourteen legs:
|
|
13
|
+
- `0082.list-valid`: the list answers 200 and every record validates against `agent-deployment.schema.json`.
|
|
14
|
+
- `0082.pin-recorded`: the run's `agent.invocation-started` carries `resolvedChannel: stable` and a version active on it.
|
|
15
|
+
- `0082.scope-fail-closed`: a promote sent with `OPENWOP_TEST_LOW_SCOPE_KEY` (no `deploy:*`) is refused `403 forbidden` and the record does not move. If the key is unset, the leg records `blocked`.
|
|
16
|
+
- `0082.transition-illegal-refused`: `pause` and `deprecate` of a draft are refused and the record does not move.
|
|
17
|
+
- `0082.state-unadvertised-refused`: an otherwise legal transition into a state missing from `states` is `400 validation_error`.
|
|
18
|
+
- `0082.transition-legal`: the promotion path answers 200 at each step with a valid record in the target state.
|
|
19
|
+
- `0082.replay-pin-reread`: after that promote moves `stable`, a replay of the first run still records its original version.
|
|
20
|
+
- `0082.canary-adjusted` (with `canary`) and `0082.canary-unsupported-refused` (without it): `adjust-canary` to 50.
|
|
21
|
+
- `0082.rollback-pointer` (with `rollback`): the version ends `rolled-back`, and its `rollbackPointer` names the restored version.
|
|
22
|
+
- **RFC 0254 rulings.** An illegal edge must be `409 deployment_state_conflict` with `details.state` and `details.transition`. Absent `states` means all seven, so the walk runs. `promote` moves one step over the advertised states, the first without `toState`. A rollback must restore the incumbent.
|
|
23
|
+
- **Scope challenge.** `0082.scope-fail-closed` also requires code `forbidden`, and a `WWW-Authenticate` challenge, when sent, must name `scope="deploy:*"`.
|
|
24
|
+
- **Four new legs.** `0082.promote-skip-refused`: a draft promoted straight to `active` gets the 409. `0082.resume-from-paused` (with `paused`): pause, then `promote` back to `active`. `0082.transition-run-linked`: every 200 record carries `transitionRunId`.
|
|
25
|
+
- **The management run.** `0082.transition-event-recorded`: the `transitionRunId` run's events include the transition's `deployment.*` event, valid against `run-event-payloads`. It is the first behavioural witness of `deployment-event-no-content-leak`.
|
|
26
|
+
- **Resume event.** A resume (`promote` of a paused version) must record `deployment.state.changed`; `deployment.promoted` is for forward steps only (RFC 0254 §A).
|
|
27
|
+
- **Judges.** They are in `lib/deployment-lifecycle-witness.ts`, with self-tests; every new or tightened leg is sabotage-proved on a scratch host.
|
|
28
|
+
- RFC 0253 (`Draft`) adds its gap register, which also lands in the packed `spec/v1/gaps.json`.
|
|
29
|
+
- **Host impact:** opt-in. The legs need `agents.deployment` and the fixture listed in `fixtures`. Listing it at major 2 states the `fixtures.md` preconditions: an incumbent `active` on `stable`, a `draft`, no gate, and `runs:read` on the management run. No host advertises the facet, so every leg is `inapplicable`.
|
|
30
|
+
|
|
1
31
|
## [2.46.34] — 2026-10-27 — RFC 0244 G3 closed
|
|
2
32
|
|
|
3
33
|
- **No assertion changes.** RFC 0244's G3 closes on openwop-app's certified cut `2c8bc27d6` (`0244.trial-memory-isolated` `executed-pass`), so the packed `spec/v1/gaps.json` changes.
|
package/README.md
CHANGED
|
@@ -137,7 +137,7 @@ Each scenario file records its disposition and assertion count in `<report-dir>/
|
|
|
137
137
|
|
|
138
138
|
## What's Covered
|
|
139
139
|
|
|
140
|
-
The current suite has
|
|
140
|
+
The current suite has 663 scenario files under `src/scenarios/`. By target major ([`scenario-majors.json`](./scenario-majors.json)): 223 files run against a v2 host and 455 against a v1 host; 15 of them run at both.
|
|
141
141
|
|
|
142
142
|
The v2 scenarios (`src/scenarios/v2-*.test.ts`) cover, by area:
|
|
143
143
|
|
|
@@ -156,7 +156,7 @@ The v2 scenarios (`src/scenarios/v2-*.test.ts`) cover, by area:
|
|
|
156
156
|
| Durability and execution | Recovery after a kill, effect seams that never re-fire, execution bounds, budgets | `v2-durability-recovery`, `v2-effect-seam-no-refire`, `v2-run-execution-bounds`, `v2-budget-enforcement` |
|
|
157
157
|
| Packs and composition | Pack isolation, peer dependencies, sub-workflow dispatch and input mapping, chain pins, WASM memory caps and ABI rejection, registry lifecycle | `v2-pack-isolation`, `v2-subworkflow-linkage`, `v2-chain-pin-exact`, `v2-wasm-memory-cap`, `v2-wasm-abi-reject` |
|
|
158
158
|
| AI, prompts and agents | AI envelopes, providers and usage, prompt libraries and rendering, model capabilities, conversations, multi-party councils | `v2-prompt-render-deterministic`, `v2-provider-usage-emission`, `v2-conversation-turn-parts`, `v2-multi-party-council` |
|
|
159
|
-
| Interop | A2A agent cards and operation map, MCP mounts and tasks,
|
|
159
|
+
| Interop | A2A agent cards and operation map, MCP mounts and tasks, trace context | `v2-a2a-operation-map`, `v2-mcp-mount-map`, `v2-interop-trace-context` |
|
|
160
160
|
| Family advertisements | Each optional capability family's discovery record validates against its schema seat | `v2-*-advertisement` |
|
|
161
161
|
| Certification | Signed v3 bundles, recorded relaxations, corpus-coherence rows never entering a bundle | `v2-bundle-v3-signed`, `v2-relaxation-recorded`, `v2-coherence-not-in-bundle` |
|
|
162
162
|
|
|
@@ -166,7 +166,7 @@ Three kinds of scenario share the tree:
|
|
|
166
166
|
- **Host** checks drive a live host over HTTP.
|
|
167
167
|
- **Gated** checks run only when the host advertises the family, profile or fixture they need, and otherwise record `inapplicable` or `blocked` with a reason. `--require-behavior` turns an advertised-but-unwitnessable behaviour into a failure.
|
|
168
168
|
|
|
169
|
-
Current source tree:
|
|
169
|
+
Current source tree: 663 scenario files. [`coverage.md`](./coverage.md) maps each spec document and every OpenAPI operation to its scenarios. [`CHANGELOG.md`](./CHANGELOG.md) records when each scenario landed.
|
|
170
170
|
|
|
171
171
|
## How the 2.x suite is built
|
|
172
172
|
|
package/coverage.md
CHANGED
|
@@ -17,16 +17,16 @@ Each scenario that targets major 2 is listed once, under the [`spec/v2/core/`](.
|
|
|
17
17
|
| Core document | Scenario files |
|
|
18
18
|
| --- | --- |
|
|
19
19
|
| [`artifact-type-packs.md`](../spec/v2/core/artifact-type-packs.md) | `v2-artifact-type-schema-url.test.ts`, `v2-artifact-types-advertisement.test.ts` |
|
|
20
|
-
| [`capabilities.md`](../spec/v2/core/capabilities.md) | `v2-agent-org-chart-served-shape.test.ts`, `v2-capabilities-root-closed.test.ts`, `v2-capability-maturity-bounded.test.ts`, `v2-capability-record-shape.test.ts`, `v2-discovery-etag.test.ts`, `v2-implementation-informational.test.ts`, `v2-profiles-derived-only.test.ts` |
|
|
20
|
+
| [`capabilities.md`](../spec/v2/core/capabilities.md) | `v2-agent-org-chart-served-shape.test.ts`, `v2-capabilities-root-closed.test.ts`, `v2-capability-maturity-bounded.test.ts`, `v2-capability-record-shape.test.ts`, `v2-discovery-etag.test.ts`, `v2-implementation-informational.test.ts`, `v2-profiles-derived-only.test.ts`, `v2-envelope-surfaces-absent.test.ts` |
|
|
21
21
|
| [`conformance.md`](../spec/v2/core/conformance.md) | `fixtures-valid.test.ts`, `jcs-vectors.test.ts`, `v2-advertised-fixtures-exist.test.ts`, `v2-bundle-v3-signed.test.ts`, `v2-coherence-not-in-bundle.test.ts`, `v2-production-backpressure.test.ts` |
|
|
22
22
|
| [`connection-packs.md`](../spec/v2/core/connection-packs.md) | `v2-provider-conflict.test.ts` |
|
|
23
23
|
| [`conversation.md`](../spec/v2/core/conversation.md) | `v2-channel-presence-advertisement.test.ts`, `v2-channel-presence-delivery.test.ts`, `v2-conversation-turn-model-provenance-advertisement.test.ts`, `v2-conversation-turn-model-provenance.test.ts`, `v2-multi-party-conversation-advertisement.test.ts`, `v2-multi-party-council.test.ts` |
|
|
24
24
|
| [`errors.md`](../spec/v2/core/errors.md) | `v2-error-registry.test.ts`, `v2-interrupt-resolve-terminal.test.ts`, `v2-unadvertised-operation-not-found.test.ts` |
|
|
25
|
-
| [`events.md`](../spec/v2/core/events.md) | `v2-enum-growth-rule.test.ts`, `v2-
|
|
25
|
+
| [`events.md`](../spec/v2/core/events.md) | `v2-enum-growth-rule.test.ts`, `v2-event-type-closed.test.ts`, `v2-host-event-delivery.test.ts`, `v2-payload-registry-closed.test.ts`, `v2-payload-seats-0186.test.ts`, `v2-payload-vendor-hatch.test.ts`, `v2-poll-cursor-v2.test.ts`, `v2-provider-usage-advertisement.test.ts`, `v2-provider-usage-emission.test.ts`, `v2-run-completed-outputs.test.ts`, `v2-sse-last-event-id-cursor.test.ts`, `v2-sse-last-event-id.test.ts`, `v2-stream-mode-refusal.test.ts`, `v2-stream-sse-projection.test.ts`, `v2-terminal-event-once.test.ts` |
|
|
26
26
|
| [`execution.md`](../spec/v2/core/execution.md) | `context-budget-transcript-bound.test.ts`, `v2-dispatch-input-mapping.test.ts`, `v2-dispatch-loop.test.ts`, `v2-self-hosted-runner-advertisement.test.ts`, `v2-sub-workflow-advertisement.test.ts`, `v2-subworkflow-input-mapping.test.ts`, `v2-subworkflow-linkage.test.ts` |
|
|
27
27
|
| [`form-content-packs.md`](../spec/v2/core/form-content-packs.md) | `v2-form-when-reuses-edge-conditions.test.ts` |
|
|
28
28
|
| [`headers.md`](../spec/v2/core/headers.md) | `v2-cors-preflight.test.ts`, `v2-header-scheme.test.ts` |
|
|
29
|
-
| [`host-services.md`](../spec/v2/core/host-services.md) | `v2-agent-runtime-advertisement.test.ts`, `v2-ai-
|
|
29
|
+
| [`host-services.md`](../spec/v2/core/host-services.md) | `v2-agent-runtime-advertisement.test.ts`, `v2-ai-providers-advertisement.test.ts`, `v2-provider-output-reliability.test.ts`, `v2-structured-output-advertisement.test.ts`, `v2-mcp-client-results.test.ts`, `v2-memory-cross-tenant-isolation.test.ts`, `v2-model-capabilities-advertisement.test.ts`, `v2-model-capability-insufficient.test.ts`, `v2-prompt-all-four-kinds-events.test.ts`, `v2-prompt-end-to-end-events.test.ts`, `v2-prompt-library-advertisement.test.ts`, `v2-prompt-list-and-fetch.test.ts`, `v2-prompt-mutable-lifecycle.test.ts`, `v2-prompt-pack-install.test.ts`, `v2-prompt-render-deterministic.test.ts`, `v2-prompt-resolution-chain-event.test.ts`, `v2-prompt-template-shape.test.ts`, `v2-queue-cross-tenant-isolation.test.ts`, `v2-safefetch-ssrf-refused.test.ts`, `v2-scheduling-advertisement.test.ts`, `v2-secret-canary-absent.test.ts`, `v2-secrets-run-witness.test.ts`, `v2-tool-authorization-fail-closed.test.ts`, `v2-workspace-scope-from-identity.test.ts` |
|
|
30
30
|
| [`i18n.md`](../spec/v2/core/i18n.md) | `v2-content-locale-keys.test.ts`, `v2-i18n-negotiation.test.ts`, `v2-localized-content-delivery.test.ts` |
|
|
31
31
|
| [`idempotency.md`](../spec/v2/core/idempotency.md) | `v2-durability-recovery.test.ts`, `v2-idempotency-in-flight.test.ts`, `v2-idempotency-key-grammar.test.ts` |
|
|
32
32
|
| [`identity.md`](../spec/v2/core/identity.md) | `auth-challenge-no-oracle.test.ts`, `v2-assurance-downgrade-audited.test.ts`, `v2-auth-challenge.test.ts`, `v2-authorization-advertisement.test.ts`, `v2-bound-id-kinds.test.ts`, `v2-bound-id-path-projection.test.ts`, `v2-id-grammar.test.ts`, `v2-interrupt-token-scheme.test.ts`, `v2-lane-exp-only-bound.test.ts`, `v2-lane-issuer-advertised.test.ts`, `v2-oidc-id-token-audience.test.ts`, `v2-owner-subject-required.test.ts`, `v2-protected-resource-metadata.test.ts`, `v2-revocation-honored.test.ts`, `v2-subject-link-record.test.ts` |
|
|
@@ -38,7 +38,7 @@ Each scenario that targets major 2 is listed once, under the [`spec/v2/core/`](.
|
|
|
38
38
|
| [`persistence.md`](../spec/v2/core/persistence.md) | `v2-era-2-append-vocabulary.test.ts`, `v2-era-key.test.ts`, `v2-era-stamp-universal.test.ts`, `v2-pinned-run-disposition.test.ts`, `v2-unmapped-type-refused.test.ts`, `v2-v1-events-translated.test.ts` |
|
|
39
39
|
| [`portability.md`](../spec/v2/core/portability.md) | `v2-portability-advertisement.test.ts` |
|
|
40
40
|
| [`replay.md`](../spec/v2/core/replay.md) | `context-summarization-replay.test.ts`, `memory-attribution-replay-stable.test.ts`, `v2-effect-seam-manifest.test.ts`, `v2-effect-seam-no-refire.test.ts`, `v2-fork-a-v1-run.test.ts`, `v2-nondeterminism-policy-advertisement.test.ts`, `v2-nondeterminism-sources.test.ts`, `v2-replay-suppression-ordinal.test.ts`, `v2-run-fork-prefix.test.ts` |
|
|
41
|
-
| [`runs.md`](../spec/v2/core/runs.md) | `v2-artifact-a2a-shape.test.ts`, `v2-budget-enforcement.test.ts`, `v2-budget-exhaustion-facet.test.ts`, `v2-configurable-closed.test.ts`, `v2-conversation-turn-parts.test.ts`, `v2-created-run-readable.test.ts`, `v2-data-residency-admission.test.ts`, `v2-data-residency-advertisement.test.ts`, `v2-dead-letter-advertisement.test.ts`, `v2-eval-mode-unadvertised-refused.test.ts`, `v2-
|
|
41
|
+
| [`runs.md`](../spec/v2/core/runs.md) | `v2-artifact-a2a-shape.test.ts`, `v2-budget-enforcement.test.ts`, `v2-budget-exhaustion-facet.test.ts`, `v2-configurable-closed.test.ts`, `v2-conversation-turn-parts.test.ts`, `v2-created-run-readable.test.ts`, `v2-data-residency-admission.test.ts`, `v2-data-residency-advertisement.test.ts`, `v2-dead-letter-advertisement.test.ts`, `v2-eval-mode-unadvertised-refused.test.ts`, `v2-run-annotation-not-event.test.ts`, `v2-run-bulk-cancel.test.ts`, `v2-run-cancel.test.ts`, `v2-run-diff-identical.test.ts`, `v2-run-execution-bounds.test.ts`, `v2-run-fork-ancestry.test.ts`, `v2-run-fork-refusals.test.ts`, `v2-run-list.test.ts`, `v2-run-options-limits.test.ts`, `v2-run-pause-resume.test.ts`, `v2-run-snapshot-etag.test.ts`, `v2-limits-clarification-rounds-advertisement.test.ts` |
|
|
42
42
|
| [`security-defaults.md`](../spec/v2/core/security-defaults.md) | `audit-anomaly-shape.test.ts`, `audit-checkpoint-signature.test.ts`, `audit-checkpoint-vectors.test.ts`, `audit-log-integrity.test.ts`, `inbound-credential-no-passthrough.test.ts`, `v2-compensation-read-projection.test.ts`, `v2-effect-identity-business-key.test.ts`, `v2-effect-ledger-keying.test.ts`, `v2-pack-isolation.test.ts`, `v2-purpose-propagation-advertisement.test.ts`, `v2-purpose-propagation-onward.test.ts`, `v2-relaxation-recorded.test.ts` |
|
|
43
43
|
| [`storage.md`](../spec/v2/core/storage.md) | `v2-fs-sandbox-escape-refused.test.ts`, `v2-storage-cross-tenant-isolation.test.ts`, `v2-table-schema-enforcement.test.ts` |
|
|
44
44
|
| [`tool-catalog.md`](../spec/v2/core/tool-catalog.md) | `tool-catalog-compact-projection.test.ts`, `tool-catalog-projection.test.ts`, `tool-descriptor-shape.test.ts`, `v2-tool-catalog-annotations.test.ts` |
|
|
@@ -53,7 +53,6 @@ Each scenario that targets major 2 is listed once, under the [`spec/v2/core/`](.
|
|
|
53
53
|
| Extension | Scenario files |
|
|
54
54
|
| --- | --- |
|
|
55
55
|
| [`ext/README.md`](../spec/v2/ext/README.md) | `v2-ext-family-claims.test.ts` |
|
|
56
|
-
| [`ext/a2uiSurface`](../spec/v2/ext/a2uiSurface/README.md) | `v2-a2ui-v09-surface.test.ts` |
|
|
57
56
|
| [`ext/restTransport`](../spec/v2/ext/restTransport/README.md) | `v2-ext-rest-transport.test.ts` |
|
|
58
57
|
|
|
59
58
|
---
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "conformance-interrupt-form-refused",
|
|
3
|
+
"name": "Conformance: Clarification with a form that solicits a secret",
|
|
4
|
+
"version": "1.0",
|
|
5
|
+
"description": "RFC 0255 §E probe. Identical to conformance-interrupt-form except the TextField is variant obscured, which interrupt-form.schema.json excludes. A host MUST NOT raise this form. It exists to be refused.",
|
|
6
|
+
"nodes": [
|
|
7
|
+
{
|
|
8
|
+
"id": "ask",
|
|
9
|
+
"typeId": "core.clarificationGate",
|
|
10
|
+
"name": "Clarification Gate (form)",
|
|
11
|
+
"position": {
|
|
12
|
+
"x": 0,
|
|
13
|
+
"y": 0
|
|
14
|
+
},
|
|
15
|
+
"config": {
|
|
16
|
+
"questions": [
|
|
17
|
+
{
|
|
18
|
+
"id": "q1",
|
|
19
|
+
"question": "What is your favorite color?"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"form": {
|
|
23
|
+
"version": "v0.9",
|
|
24
|
+
"catalogId": "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json",
|
|
25
|
+
"surfaceId": "favorite-color",
|
|
26
|
+
"messages": [
|
|
27
|
+
{
|
|
28
|
+
"version": "v0.9",
|
|
29
|
+
"createSurface": {
|
|
30
|
+
"surfaceId": "favorite-color",
|
|
31
|
+
"catalogId": "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"version": "v0.9",
|
|
36
|
+
"updateComponents": {
|
|
37
|
+
"surfaceId": "favorite-color",
|
|
38
|
+
"components": [
|
|
39
|
+
{
|
|
40
|
+
"id": "root",
|
|
41
|
+
"component": "Column",
|
|
42
|
+
"children": [
|
|
43
|
+
"heading",
|
|
44
|
+
"q1",
|
|
45
|
+
"submit"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "heading",
|
|
50
|
+
"component": "Text",
|
|
51
|
+
"text": "One detail, please",
|
|
52
|
+
"variant": "h2"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "q1",
|
|
56
|
+
"component": "TextField",
|
|
57
|
+
"label": "Favorite color",
|
|
58
|
+
"value": {
|
|
59
|
+
"path": "/q1"
|
|
60
|
+
},
|
|
61
|
+
"variant": "obscured"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "submit-label",
|
|
65
|
+
"component": "Text",
|
|
66
|
+
"text": "Send"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "submit",
|
|
70
|
+
"component": "Button",
|
|
71
|
+
"child": "submit-label",
|
|
72
|
+
"variant": "primary",
|
|
73
|
+
"action": {
|
|
74
|
+
"event": {
|
|
75
|
+
"name": "resume"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"inputs": {}
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"edges": [],
|
|
89
|
+
"triggers": [
|
|
90
|
+
{
|
|
91
|
+
"id": "manual",
|
|
92
|
+
"type": "manual",
|
|
93
|
+
"enabled": true
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"variables": [],
|
|
97
|
+
"metadata": {
|
|
98
|
+
"tags": [
|
|
99
|
+
"conformance",
|
|
100
|
+
"hitl",
|
|
101
|
+
"rfc-0255",
|
|
102
|
+
"probe"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"settings": {
|
|
106
|
+
"timeout": 0
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "conformance-interrupt-form-unbound",
|
|
3
|
+
"name": "Conformance: Clarification with a form input bound to no question",
|
|
4
|
+
"version": "1.0",
|
|
5
|
+
"description": "RFC 0255 §E probe. Identical to conformance-interrupt-form except the TextField id is q2, which names no questions[].id. The form is schema-valid; a host MUST NOT raise it. It exists to be refused.",
|
|
6
|
+
"nodes": [
|
|
7
|
+
{
|
|
8
|
+
"id": "ask",
|
|
9
|
+
"typeId": "core.clarificationGate",
|
|
10
|
+
"name": "Clarification Gate (form)",
|
|
11
|
+
"position": {
|
|
12
|
+
"x": 0,
|
|
13
|
+
"y": 0
|
|
14
|
+
},
|
|
15
|
+
"config": {
|
|
16
|
+
"questions": [
|
|
17
|
+
{
|
|
18
|
+
"id": "q1",
|
|
19
|
+
"question": "What is your favorite color?"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"form": {
|
|
23
|
+
"version": "v0.9",
|
|
24
|
+
"catalogId": "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json",
|
|
25
|
+
"surfaceId": "favorite-color",
|
|
26
|
+
"messages": [
|
|
27
|
+
{
|
|
28
|
+
"version": "v0.9",
|
|
29
|
+
"createSurface": {
|
|
30
|
+
"surfaceId": "favorite-color",
|
|
31
|
+
"catalogId": "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"version": "v0.9",
|
|
36
|
+
"updateComponents": {
|
|
37
|
+
"surfaceId": "favorite-color",
|
|
38
|
+
"components": [
|
|
39
|
+
{
|
|
40
|
+
"id": "root",
|
|
41
|
+
"component": "Column",
|
|
42
|
+
"children": [
|
|
43
|
+
"heading",
|
|
44
|
+
"q2",
|
|
45
|
+
"submit"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "heading",
|
|
50
|
+
"component": "Text",
|
|
51
|
+
"text": "One detail, please",
|
|
52
|
+
"variant": "h2"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "q2",
|
|
56
|
+
"component": "TextField",
|
|
57
|
+
"label": "Favorite color",
|
|
58
|
+
"value": {
|
|
59
|
+
"path": "/q2"
|
|
60
|
+
},
|
|
61
|
+
"variant": "shortText"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "submit-label",
|
|
65
|
+
"component": "Text",
|
|
66
|
+
"text": "Send"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "submit",
|
|
70
|
+
"component": "Button",
|
|
71
|
+
"child": "submit-label",
|
|
72
|
+
"variant": "primary",
|
|
73
|
+
"action": {
|
|
74
|
+
"event": {
|
|
75
|
+
"name": "resume"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"inputs": {}
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"edges": [],
|
|
89
|
+
"triggers": [
|
|
90
|
+
{
|
|
91
|
+
"id": "manual",
|
|
92
|
+
"type": "manual",
|
|
93
|
+
"enabled": true
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"variables": [],
|
|
97
|
+
"metadata": {
|
|
98
|
+
"tags": [
|
|
99
|
+
"conformance",
|
|
100
|
+
"hitl",
|
|
101
|
+
"rfc-0255",
|
|
102
|
+
"probe"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"settings": {
|
|
106
|
+
"timeout": 0
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "conformance-interrupt-form",
|
|
3
|
+
"name": "Conformance: Clarification with a form",
|
|
4
|
+
"version": "1.0",
|
|
5
|
+
"description": "RFC 0255 §E (interrupt.md §Forms). Suspends on a clarification whose data carries config.form verbatim as data.form: one v0.9 TextField whose id is the question id q1. Resume value: {answers: [{id: 'q1', answer: string}]}.",
|
|
6
|
+
"nodes": [
|
|
7
|
+
{
|
|
8
|
+
"id": "ask",
|
|
9
|
+
"typeId": "core.clarificationGate",
|
|
10
|
+
"name": "Clarification Gate (form)",
|
|
11
|
+
"position": {
|
|
12
|
+
"x": 0,
|
|
13
|
+
"y": 0
|
|
14
|
+
},
|
|
15
|
+
"config": {
|
|
16
|
+
"questions": [
|
|
17
|
+
{
|
|
18
|
+
"id": "q1",
|
|
19
|
+
"question": "What is your favorite color?"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"form": {
|
|
23
|
+
"version": "v0.9",
|
|
24
|
+
"catalogId": "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json",
|
|
25
|
+
"surfaceId": "favorite-color",
|
|
26
|
+
"messages": [
|
|
27
|
+
{
|
|
28
|
+
"version": "v0.9",
|
|
29
|
+
"createSurface": {
|
|
30
|
+
"surfaceId": "favorite-color",
|
|
31
|
+
"catalogId": "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"version": "v0.9",
|
|
36
|
+
"updateComponents": {
|
|
37
|
+
"surfaceId": "favorite-color",
|
|
38
|
+
"components": [
|
|
39
|
+
{
|
|
40
|
+
"id": "root",
|
|
41
|
+
"component": "Column",
|
|
42
|
+
"children": [
|
|
43
|
+
"heading",
|
|
44
|
+
"q1",
|
|
45
|
+
"submit"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "heading",
|
|
50
|
+
"component": "Text",
|
|
51
|
+
"text": "One detail, please",
|
|
52
|
+
"variant": "h2"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "q1",
|
|
56
|
+
"component": "TextField",
|
|
57
|
+
"label": "Favorite color",
|
|
58
|
+
"value": {
|
|
59
|
+
"path": "/q1"
|
|
60
|
+
},
|
|
61
|
+
"variant": "shortText"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "submit-label",
|
|
65
|
+
"component": "Text",
|
|
66
|
+
"text": "Send"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "submit",
|
|
70
|
+
"component": "Button",
|
|
71
|
+
"child": "submit-label",
|
|
72
|
+
"variant": "primary",
|
|
73
|
+
"action": {
|
|
74
|
+
"event": {
|
|
75
|
+
"name": "resume"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"inputs": {}
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"edges": [],
|
|
89
|
+
"triggers": [
|
|
90
|
+
{
|
|
91
|
+
"id": "manual",
|
|
92
|
+
"type": "manual",
|
|
93
|
+
"enabled": true
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"variables": [],
|
|
97
|
+
"metadata": {
|
|
98
|
+
"tags": [
|
|
99
|
+
"conformance",
|
|
100
|
+
"hitl",
|
|
101
|
+
"rfc-0255"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
"settings": {
|
|
105
|
+
"timeout": 0
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -6,11 +6,10 @@
|
|
|
6
6
|
"nodes": [
|
|
7
7
|
{
|
|
8
8
|
"id": "ai",
|
|
9
|
-
"typeId": "core.
|
|
9
|
+
"typeId": "core.conformance.stream-text",
|
|
10
10
|
"name": "AI Call (mock-routed)",
|
|
11
11
|
"position": { "x": 0, "y": 0 },
|
|
12
12
|
"config": {
|
|
13
|
-
"promptId": "conformance.stream-text-noop",
|
|
14
13
|
"expectsStreaming": true
|
|
15
14
|
},
|
|
16
15
|
"inputs": {}
|
package/fixtures.md
CHANGED
|
@@ -58,6 +58,9 @@ All fixtures MUST advertise:
|
|
|
58
58
|
| Clarification | `conformance-clarification` | Verifies HITL clarification interrupt + resume | `completed` after resolve | unbounded (suspends) |
|
|
59
59
|
| Clarification (nested schema) | `conformance-clarification-nested` | RFC 0199 §D.2(d) probe — an answer schema an MCP mount MUST NOT bridge in form mode | `completed` after resolve | unbounded (suspends) |
|
|
60
60
|
| Clarification (sensitive field) | `conformance-clarification-sensitive` | RFC 0199 §D.2(d) probe — `format: "password"`; form mode MUST be refused | `completed` after resolve | unbounded (suspends) |
|
|
61
|
+
| Clarification (form) | `conformance-interrupt-form` | RFC 0255 §E — `config.form` carried verbatim as `data.form`: one v0.9 TextField bound to question `q1` | `completed` after resolve | unbounded (suspends) |
|
|
62
|
+
| Clarification (form, secret input) | `conformance-interrupt-form-refused` | RFC 0255 §E probe — the same form with `variant: "obscured"`; the host MUST NOT raise it | not suspended with the form | ≤ 10s |
|
|
63
|
+
| Clarification (form, unbound input) | `conformance-interrupt-form-unbound` | RFC 0255 §E probe — a schema-valid form whose input `q2` names no question; the host MUST NOT raise it | not suspended with the form | ≤ 10s |
|
|
61
64
|
| Credential | `conformance-credential` | RFC 0199 §C — one node declaring `auth { type: oauth2, provider: synthetic, scopes }` | `waiting-input` (credential interrupt), or the node fails without the facet | unbounded (suspends) |
|
|
62
65
|
| Multi-node | `conformance-multi-node` | Verifies edge ordering + per-node events | `completed` | ≤ 10s |
|
|
63
66
|
| Idempotent | `conformance-idempotent` | Verifies `Idempotency-Key` cache | `completed` | ≤ 5s |
|
|
@@ -507,7 +510,8 @@ This fixture closes F5 without requiring any new server-side test infrastructure
|
|
|
507
510
|
|
|
508
511
|
- **Consuming scenario**: `conformance/src/scenarios/stream-text-fixture.test.ts` (added 2026-06-11; previously this fixture had no consuming scenario).
|
|
509
512
|
- **Purpose**: verify the `messages` SSE stream mode end-to-end through a deterministic AI mock. Without a mock provider, conformance suites can't exercise streaming AI without burning real API budget; with one, the test is fully reproducible.
|
|
510
|
-
- **Fixture topology**: a single `core.
|
|
513
|
+
- **Fixture topology**: a single `core.conformance.stream-text` node (conformance-RESERVED), config `{ expectsStreaming: true }`. It names no prompt: the conformance driver supplies the model output through `configurable.mockProvider`.
|
|
514
|
+
- **Disposition**: neither the fixture nor the `stream-text` mock advertised ⇒ `inapplicable`; the mock without the fixture ⇒ `blocked`; the fixture without the mock ⇒ `inapplicable`. The scenario targets major 1 only.
|
|
511
515
|
- **Inputs**: none.
|
|
512
516
|
- **Conformance test driver**:
|
|
513
517
|
1. POST `/runs` with body:
|
|
@@ -723,6 +727,31 @@ Hosts that don't ship a BYOK SecretResolver MAY return `404` / `422` on the star
|
|
|
723
727
|
3. **Replay** via `POST /runs/{runId}:fork {mode:"replay"}`; **assert** the fork's `agent.invocation.started` re-reads the SAME `resolvedAgentVersion`.
|
|
724
728
|
4. **(Seam-guarded)** Move the `stable` channel via the deployment seam; **assert** a replay of the original run STILL carries the original pin — never re-resolving the moved channel.
|
|
725
729
|
|
|
730
|
+
### At major 2: the deployment lifecycle (`v2-deployment-lifecycle`)
|
|
731
|
+
|
|
732
|
+
At major 2, `v2-deployment-lifecycle.test.ts` drives `core.conformance.channel-agent` through `listAgentDeployments` and `transitionAgentDeployment` (`GET` / `POST /agents/core.conformance.channel-agent/deployments`), under the transition rules RFC 0254 adds to the `agents.deployment` facet. It moves the `stable` channel itself, so it needs no seam. A host that advertises `agents.deployment` and lists `conformance-agent-channel-dispatch` in discovery `fixtures` states that, at the start of every cut:
|
|
733
|
+
|
|
734
|
+
- it holds exactly one record of `core.conformance.channel-agent` that is `active` on `stable`, at `canaryPercent` 100 or absent (the incumbent);
|
|
735
|
+
- it holds at least one `draft` record of that agent (the candidate);
|
|
736
|
+
- both are readable by the conformance credential at the `GET` above, and that credential holds the `deploy:*` scope and `runs:read`;
|
|
737
|
+
- no approval gate and no `requiredEval` applies to that credential's transitions of this agent, so a legal transition answers `200` with the updated record, never `202`;
|
|
738
|
+
- every `200` record carries `transitionRunId`, and the conformance credential can read that run through `GET /runs/{runId}/events/poll`; the run's events include the transition's `deployment.*` event;
|
|
739
|
+
- the run's `agent.invocation-started` carries `resolvedChannel` and `resolvedAgentVersion`, as above.
|
|
740
|
+
|
|
741
|
+
The suite, in order:
|
|
742
|
+
|
|
743
|
+
1. sends refused transitions, each of which must leave the records unchanged: a promote with `OPENWOP_TEST_LOW_SCOPE_KEY`, `pause` and `deprecate` of the candidate, a promote of the candidate with `toState: "active"`, and on a host advertising a subset of `states`, one transition into an unadvertised state;
|
|
744
|
+
2. promotes the candidate one step at a time over the advertised states to `active`, the last step with `channel: "stable"` and `canaryPercent: 100`; the first step omits `toState`;
|
|
745
|
+
3. runs this fixture again and replays the first run; a run started after that promote must resolve `stable` to the candidate, or the replay leg records `blocked`;
|
|
746
|
+
4. adjusts the candidate's canary share to 50, then rolls it back, which must restore the incumbent to `active`;
|
|
747
|
+
5. with `paused` advertised, pauses the version then `active` on `stable` (the incumbent after a rollback) and promotes it back to `active`.
|
|
748
|
+
|
|
749
|
+
A refused transition that the host applies instead moves the candidate, and later legs then record `blocked`.
|
|
750
|
+
|
|
751
|
+
**Restoring the preconditions between cuts.** A clean cut leaves the candidate `rolled-back` (or `active` on a host without `rollback`) and the incumbent `active` on `stable`. Before the next cut the host restores both preconditions, for example by minting a fresh `draft` version and resetting the incumbent to the only `active` record on `stable`. The suite does not reset them. A host whose records do not meet the preconditions records `blocked`, never a failure.
|
|
752
|
+
|
|
753
|
+
The scope leg sends a promote with `OPENWOP_TEST_LOW_SCOPE_KEY`, a key with no `deploy:*` scope. It expects `403` with code `forbidden`; a `WWW-Authenticate` challenge, if sent, names `scope="deploy:*"`. If that variable is unset, the leg records `blocked`.
|
|
754
|
+
|
|
726
755
|
---
|
|
727
756
|
|
|
728
757
|
## `conformance-artifact-emit` (RFC 0205 — an artifact the suite can read back)
|
|
@@ -754,6 +783,14 @@ Hosts that don't ship a BYOK SecretResolver MAY return `404` / `422` on the star
|
|
|
754
783
|
- **Note**: the sensitive fixture exists to be REFUSED. Authoring a clarification that solicits credential material is itself forbidden (RFC 0199 §C.6); it ships only as the machine-checkable probe.
|
|
755
784
|
- **Timing**: unbounded (they suspend).
|
|
756
785
|
|
|
786
|
+
## `conformance-interrupt-form` / `-refused` / `-unbound` (RFC 0255 §E)
|
|
787
|
+
|
|
788
|
+
- **Purpose**: witness `interrupt.md` §Forms. One `core.clarificationGate` node whose `config.questions` is `[{id: "q1", …}]` and whose `config.form` is a v0.9 form (`schemas/v2/interrupt-form.schema.json`). The node MUST pass `config.form` verbatim as `data.form` beside `questions`.
|
|
789
|
+
- **Positive** (`conformance-interrupt-form`): suspends `waiting-input`; `interrupt.requested` carries the form unchanged; `{answers: [{id: "q1", answer: "blue"}]}` resolves it and the run completes.
|
|
790
|
+
- **Probes**: `-refused` adds `TextField.variant: "obscured"` (fails the schema); `-unbound` renames the input `q2` (schema-valid, bound to no question). Neither may be raised. A host refusing it fails the node; no `interrupt.requested` carries the form.
|
|
791
|
+
- **Gate**: `v2-interrupt-form-rules` runs each leg only when its fixtures are advertised. No capability or seam.
|
|
792
|
+
- **Timing**: the positive suspends; the probes settle within 10 s.
|
|
793
|
+
|
|
757
794
|
## NodeModule registration
|
|
758
795
|
|
|
759
796
|
The fixtures reference these typeIds:
|
|
@@ -766,7 +803,8 @@ The fixtures reference these typeIds:
|
|
|
766
803
|
| `core.fail` | failure | Throw with `code: "example.conformance_failure"` (a vendor code under the registered `example` org; errors.md §The registry, openwop#1698), message: "Intentional conformance failure" |
|
|
767
804
|
| `core.approvalGate` | approval | Call `ctx.interrupt({kind: 'approval', ...})` |
|
|
768
805
|
| `core.conformance.hold` | replay-side-effect, replay-ordinal-loop | Conformance-RESERVED (openwop#1769). Completes after `inputs.delayMs`; its outputs are exactly its resolved inputs, `delayMs` included, under the same keys. It performs nothing observable outside the run's own event log. A host advertising a fixture that uses it MUST NOT classify it side-effecting (`replay.md` §Suppression rule 1) and MUST re-execute it live in a replay. |
|
|
769
|
-
| `core.clarificationGate` | clarification | Call `ctx.interrupt({kind: 'clarification', ...})` |
|
|
806
|
+
| `core.clarificationGate` | clarification | Call `ctx.interrupt({kind: 'clarification', ...})` with `data.questions` from `config.questions`, and `data.form` from `config.form` verbatim when present (RFC 0255 §E) |
|
|
807
|
+
| `core.conformance.stream-text` | stream-text | Conformance-RESERVED (RFC 0255). One model call whose output comes from `configurable.mockProvider` (`stream-text`), streamed as `output.chunk` frames in `messages` mode; `config.expectsStreaming: true`. It names no prompt |
|
|
770
808
|
| `conformance.requiresMissing` | capability-missing | Declares `requires: ['conformance.never-provided']`; engine MUST refuse dispatch. Opt-in fixture registration is recommended so production deployments don't expose the fixture surface. |
|
|
771
809
|
| `conformance.artifact.emit` | artifact-emit | Opt-in (RFC 0205). Produce one artifact of `config.artifactType` with payload `config.data`; emit `artifact.created` naming it; readable through `getArtifact`. |
|
|
772
810
|
| `conformance.oauth.use` | credential | Opt-in (RFC 0199). Resolve the credential `config.auth` names for the run's Subject, refreshing host-side; no credential ⇒ a `credential` interrupt (with the facet) or a failed node. Never carries token material on any surface. |
|
|
@@ -833,11 +871,13 @@ For `v2-tool-catalog-annotations`' unclassified-MCP leg, a host that advertises
|
|
|
833
871
|
|
|
834
872
|
| Field | Meaning |
|
|
835
873
|
|---|---|
|
|
836
|
-
| `kind` | `invalid-json` (a clean stop with the reply `{ this is not json }`: a parse error, so it never engages the natural-language fallback), `truncated` (a `max_tokens` stop),
|
|
874
|
+
| `kind` | `invalid-json` (a clean stop with the reply `{ this is not json }`: a parse error, so it never engages the natural-language fallback), `truncated` (a `max_tokens` stop), `valid` (a minimal instance of `responseSchema`, or `ok` without one), or `refusal` (the provider declines: a safety stop with refusal text, RFC 0255). A host whose mock cannot serve `refusal` leaves the `v2-provider-output-reliability` refusal leg `blocked` |
|
|
837
875
|
| `outputTokens` | The tokens the reply uses. The mock reports `min(outputTokens, the maxTokens that request carried)`, and serves an entry over that budget as truncated. With no `maxTokens` on the request, there is no clamp |
|
|
838
876
|
| `usage: false` | The request reports no usage |
|
|
839
877
|
| `structuredMode` | For a call with `responseSchema`: `native` or `prompt` (default) is the structured-output mode that request used |
|
|
840
878
|
|
|
879
|
+
`v2-provider-output-reliability` (RFC 0255) runs three more scripts through the same fixture and reads the run's reliability events (`host-services.md` §Structured output).
|
|
880
|
+
|
|
841
881
|
**Output.** The node completes with `outputs.attempts`, the `attempts` record of the `ctx.callAI` result verbatim. A call that throws fails the node with the error's code and details unchanged: a malformed `retry` is `validation_error` with `details.field` naming the key.
|
|
842
882
|
|
|
843
883
|
**Why the clamp.** A real provider cannot exceed its budget. Clamping makes a host that grows `maxTokens` against `growMaxTokens: false` visible: the over-budget reply completes only under a grown budget, and its `provider.usage.outputTokens` exceeds the request's `maxTokens`.
|
|
@@ -1135,7 +1175,7 @@ Prompt-template fixtures are exercised by the server-free `fixtures-valid.test.t
|
|
|
1135
1175
|
|
|
1136
1176
|
## A2UI v0.9 surface fixtures (RFC 0209)
|
|
1137
1177
|
|
|
1138
|
-
The `fixtures/a2ui-v09/` sub-directory (suite 2.36.0) holds
|
|
1178
|
+
The `fixtures/a2ui-v09/` sub-directory (suite 2.36.0) holds A2UI v0.9 surfaces — ordered runs of server-to-client messages in the OpenWOP profile of the basic catalog. They were written for the `ui.a2ui-surface` envelope kind RFC 0255 deleted; they now exercise the same profile as an interrupt form (`schemas/v2/interrupt-form.schema.json`; `interrupt.md` §Forms). They are NOT `WorkflowDefinition`s and are NOT seeded into a server. The corpus gate (`src/coherence/a2ui-v09-profile.test.ts`) validates the positive against the profile and each of its messages against the vendored upstream schemas; each negative must fail the profile AND pass a copy of the profile with only the restriction under test removed, so it can fail for no other reason. Like `interrupt-payloads/`, this directory carries deliberately-invalid `negative-` files; the top-level workflow sweep never reads sub-directories.
|
|
1139
1179
|
|
|
1140
1180
|
| Fixture | Expect | Upstream A2UI | Purpose |
|
|
1141
1181
|
| --- | --- | --- | --- |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openwop/openwop-conformance",
|
|
3
|
-
"version": "2.46.
|
|
3
|
+
"version": "2.46.36",
|
|
4
4
|
"description": "Black-box conformance suite for OpenWOP hosts (v2 current; v1 scenarios retained for the frozen v1 tree).",
|
|
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.46.
|
|
59
|
+
"@openwop/spec-artifacts": "2.46.36"
|
|
60
60
|
}
|
|
61
61
|
}
|