Summary
v1's event type is anyOf: [enum, vendorRegex] where the regex bans vendor.* and accepts a typo; 117 members across 41 first segments in four casing styles, 91 past-tense and 26 not; 63 of 120 payload definitions open, including runStarted, the one that carries the Subject; an error envelope whose code space has no enum and whose details is a bare object, 42 codes in a prose list, three live spellings of one retry-timing field plus the header; seven header naming schemes with a canonical table that lists 7 of about 20; a configurable that reserves 15 keys, types 6, and is open at its own root because the closure can only live at the OpenAPI composition; four AsyncAPI channels on one address plus a null-address channel; and a poll endpoint whose cursor cannot express "nothing seen", whose alias exists only in prose, and whose response shape has five fields in the spec and two in OpenAPI. v2 closes every one of those with one rule each and a codemod where data was persisted.
Motivation
run-event.schema.json:34–47: the vendor branch's negative lookahead bansopenwop|core|community|vendor|private|local— sovendor.acme.xis invalid,acme.xis valid, andrun.startdvalidates. Thetypedescription justifies it by "clients MUST ignore unknown event types," conflating reader tolerance with producer permissiveness.spec/v1/event-codemap.json: 117 rows, 18review: true, 0 overridden;core.workflowChain.confidence-escalatedis camel, kebab, three-segment, and reserved-prefixed at once; 21 three-segment types.run-event-payloads.schema.json: 63 open of 120$defs(60 explicitlytrue), every core lifecycle payload among them;_typeIndexis labelled informative and is read as truth by the codemap generator andspec-corpus-validity.test.ts:646.ai-envelope.md:833–835:meta.source"required at v2", vendor namespacing "REQUIRED at v2";:834correlationIdhas no v2 disposition; E3's examplevendor.myndhyve.prd.createuses the namespace the event regex bans.error-envelope.schema.json:errorisminLength 1with a SHOULD for snake_case and the list in another file;detailsis a bare object;api/openapi.yaml:2615and:2641re-declare the shape with one-member enums to typedetails;retryAfter/retryAfterMs/retryAfterSeconds/Retry-Afterare four live spellings with three consistency rules in three documents;idempotency.md:93–104records three spellings of one code.- Headers:
openwop-Idempotent-Replay(bare lowercase),X-openwop-(mixed),OpenWOP-,X-Dedup/X-Pack-/X-Force-Engine-Version,Capabilities-Etag, the SDK-onlyopenwop-Webhook-Signature, andx-openwop-manifest annotation keys sharing the token shape;rest-endpoints.md:311–320enumerates 7; OpenAPI declares two header parameters. run-options.md:96–122: 15 reserved keys, 6 typed, four dotted (ai.*,distillation.tokenBudget), a reserved namespace expressed as a string prefix inside an open map; RFC 0094 §A put the closure at the OpenAPI composition, so every standalone validation ofrun-options.schema.jsonis open.api/asyncapi.yaml:83–193: four channels on/runs/{runId}/eventsselected bystreamMode, each operation re-declaring an enum that "does not describe the accepted values";heartbeatEventshasaddress: null.version-negotiation.md:294:sincetolerated in prose, absent from OpenAPI;:300–308vsopenapi.yaml:427–435:{runId, events, lastEventSeq, runStatus, isTerminal}vs{events, isComplete};:310giveslastEventSeqtwo meanings. RFC 0165 G7:lastSequence=0skips a 0-numbered first event.compensation.md:584(G6): adding a member to a closed reason enum is additive for producers and breaking for strict consumers; no growth rule exists.
Proposal
§A. One event envelope
§A.1 type is oneOf: [ { $ref: RunEventType }, { pattern: <org>.<domain-or-name> } ] where the vendor pattern is positive: ^(?!openwop\.)[a-z][a-z0-9](-[a-z0-9]+)\.[a-z][a-z0-9](-[a-z0-9]+)(\.[a-z][a-z0-9](-[a-z0-9]+))?$ with the first segment an org registered in the C.2 declaration file's extensions namespace; openwop. is the only reserved prefix; core., community., vendor., private., local. are gone (the v1 registry prefixes are pack namespaces, not event namespaces — C.10). A protocol event that is not in the enum fails; a vendor event whose org is not registered fails.
§A.2 Naming rule: domain.verb-ed (kebab, exactly two segments) for a transition; domain.noun permitted where the event names an emitted artifact rather than a transition (output.chunk, provider.usage, channel.presence, agent.handoff, envelope.refusal, agent.reasoning-delta, voice.synthesis-chunk, voice.endpoint-candidate); state descriptors become transitions (run.resuming → run.resume-started). The 18 review rows are decided in spec/v1/event-codemap.json as v2Override in this PR (§Migration table lists them); the four core. types fold into dispatch. and workflow-chain.*; runOrchestrator.decided → orchestrator.decided (a distinct domain from run, confirmed); the 15 non-review three-segment folds are re-verified by the same pass and recorded.
§A.3 sequence is the one ordering field (integer ≥ 0, first event 0 — unchanged, so no persisted log renumbers); schemaVersion per event stays first-class (RFC 0172 §B axis 5); engineVersion is an integer (RFC 0172 axis 3).
§A.4 run-event-payloads.schema.json: every payload $defs entry is additionalProperties: false; _typeIndex is normative and generated; the CloudEvents mapping and the webhook delivery envelope are generated from the same definition (one source, three renderings); ai-envelope.md's v2 promises are honored: meta.source required, envelope kinds namespaced under the same <org>. rule as events, correlationId required (its v1 "synthesize if absent" becomes "reject if absent"). E1–E5: E1 (partial reassembly) and E2 (multi-turn correlation) get a sequence/correlationId contract in spec/v2/core/events.md; E3 (vendor-kind registry) is the declaration file; E4 (sub-typing) is $ref composition, not duplication; E5 (refusal × retry) gets the worked example and a maxRefusals in configurable.
E4 note, 2026-09-29 (Class 3, openwop #1770).
spec/v2/core/interrupt.md§Events said a host emittinginterrupt.requested"SHOULD also emit the kind-specific type until its consumers migrate". That sentence has no RFC origin: it first appeared in the P3-D core prose (#1193) and survived the #1665 rewrite, strengthening v1's MAY (the v1approvalRequesteddescription: "MAY also emit this for back-compat"). It is now a MAY. Under E4 each kind-specific v2 payload is a$refalias of the closedinterruptRequested/interruptResolved, and six of the seven legacy types cannot carry one payload valid on both majors:approval.requested,clarification.requestedandclarification.resolved(v1 requires keys the closed v2 shape forbids), andapproval.granted,approval.rejectedandapproval.overridden(v1 requiresgateIdandprincipal). Onlyapproval.receivedfits both (v1 is open, and theactionenums match).persistence.mdalready bars serving a payload the v1 wire cannot carry, so a host serving both majors from one stored row could not honour the SHOULD.approval.rejectedwas made a MAY for the same reason in #1740. This does not relax the v1 override rule inspec/v1/interrupt-profiles.md(RFC 0051 §B, RFC 0093 §D.2): taking the override path still MUST emitapproval.overridden { principal, reason }in its v1 shape on the v1 wire, with an audit-log entry. The MAY covers only v2's "also emit" duplicate ofinterrupt.*.E4 note, 2026-09-29 (Class 3 clarification, openwop #1741). An era-2
approval.granted/approval.rejected/approval.overriddenin the RFC 0051 governance shape{gateId, principal, …}has no v2 projection.gateId → nodeIdandprincipal → resolvedByare renames, butinterruptId, which the closedinterruptResolvedrequires, cannot be sourced from the row without defaulting it (persistence.md§The reader rule forbids that), and a governance gate need not have raised an interrupt at all. A v2 read of such a row is therefore500 payload_unprojectable(events.md§Era-2), and a webhook dead-letters it on the first attempt (webhooks.md§Durability). This is by design, not a gap: census at openwop-app62705064c, MyndHyved55ab6edband openwop-examplesb6302cdfound 0 persisted writers of the governance shape.spec/v1/migrations.jsonopenwop.migration.C4.4claimedpersistedData: translatedfor the legacy interrupt payloads and now carries a note naming the governance trio as not translatable. Tripwire: if a host reports persisted governance-shape rows, file an additive RFC for a sanctionedinterruptIdderivation from the run's own recordedapproval.requested/interrupt.requested, failing closed when absent.
§A.5 Closed-enum growth rule (stated once in spec/v2/core/§0): a registry-backed enum (event types, error codes, envelope kinds, reason vocabularies, lanes) grows by adding a row to its registry and regenerating; consumers MUST accept an unknown member of a registry-backed enum and MUST NOT act on it; producers MUST NOT emit an unregistered member. Adding a member is therefore additive in v2.x; removing or renaming one is a major. compensation.md G6 (approval-pending, parent-cancelled) is resolved by the rule, independent of G7's endpoint family.
§B. One error registry
§B.1 schemas/v2/errors.json: one row per code { code, httpStatus, retriable, details: <schema or null>, since, deprecated? }; error-envelope.schema.json is generated from it with error as the closed enum (vendor codes under <org>.<code> by the §A.1 pattern) and details as a oneOf discriminated on error. The flat shape {error, message, details?} stays. The two OpenAPI one-member-enum components (RunClaimConflict, UnsupportedStreamMode) become $refs to the generated envelope.
§B.2 Retry timing lives in Retry-After only; details.retryAfter, retryAfterMs, and retryAfterSeconds are removed (register row error-details-retry-after-spellings). The idempotency mismatch code is idempotency_key_mismatch only (its two retired spellings leave the suite's tolerance list at the cut). The C.3 and C.5 codes (credential_revoked, identity_, delegation_, protocol_version_unsupported, protocol_version_mismatch, client_version_unsupported, idempotency_key_invalid, interrupt_token_invalid) are rows.
§C. One header scheme
§C.1 Every non-standard header is OpenWOP-<Name> (Title-Case after the prefix): OpenWOP-Idempotent-Replay, OpenWOP-Dedup, OpenWOP-Pack-Sha256, OpenWOP-Pack-Signing-Method, OpenWOP-Version (RFC 0172), the five webhook headers (RFC 0165 §C.1). Capabilities-Etag, the X- family, X-openwop-*, and the SDK-only openwop-Webhook-Signature are removed on their register dates. Standard headers keep their standard names. Every header is declared in OpenAPI (as a parameter or a response header) — spec/v2/core/headers.md is generated from the same declaration, so the table that enumerates headers enumerates all of them.
§C.2 The manifest annotation keys x-openwop- are not headers; they are renamed openwop- annotation keys in the v2 pack schemas (C.10) so the two namespaces stop sharing a token shape.
§D. configurable
§D.1 configurable is a closed, nested, versioned object: { version: 1, run: { recursionLimit, runTimeoutMs, maxLoopIterations, escalationThreshold }, ai: { provider, model, temperature, maxTokens, credentialRef, promptOverrides, mockProvider, reasoningVerbosity, maxRefusals }, distillation: { tokenBudget }, budget: <budget-policy>, extensions: { <org>: {…} } }. Every reserved key is typed; a vendor key lives under extensions.<org>; the root is additionalProperties: false in the standalone schema — the RFC 0094 composition problem disappears because the request body $refs the closed object instead of allOf-merging an open one.
§E. One events channel, one poll cursor
§E.1 AsyncAPI: one channel runEvents at /runs/{runId}/events with a typed streamMode parameter whose schema is the closed set and its comma-separated combinations (a pattern, not four enums), and one heartbeat message on a hostEvents channel with a real address the host declares in discovery (heartbeat.deliveryChannel) — address: null is gone. OpenAPI, AsyncAPI, and the proto resolve identical absolute paths (RFC 0172 §C.2).
§E.2 Poll: the cursor is afterSequence (integer ≥ 0; the response carries events with sequence > afterSequence); omission means "from the first event"; lastSequence and since are removed. The response is { runId, events, lastSequence, status, isTerminal } where lastSequence is the highest sequence in the log at the time of the response (one meaning), and the same shape is declared in spec/v2/core/events.md and generated into OpenAPI from one definition. The past-end rule (200 + empty events) stands. The first event stays 0 (RFC 0165 G7's second option is rejected: it would renumber every persisted log).
Migration table
| Row | Kind | v1 | v2 | Codemod | Persisted data |
|---|---|---|---|---|---|
openwop.migration.C4.1 | behavior | X-openwop-* webhook headers | OpenWOP-* (dual-emitted through the overlap, RFC 0165 §C.1) | — (headers are emitted, not persisted; subscribers read either) | not-persisted |
openwop.migration.C4.2 | behavior | X-Dedup, X-Force-Engine-Version, X-Pack-Sha256, X-Pack-Signing-Method, openwop-Idempotent-Replay | OpenWOP-Dedup, OpenWOP-Force-Engine-Version (seams profile), OpenWOP-Pack-Sha256, OpenWOP-Pack-Signing-Method, OpenWOP-Idempotent-Replay | — | not-persisted |
openwop.migration.C4.3 | rename | run event type vocabulary (117; four casings; core.*) | domain.verb-ed closed enum (spec/v1/event-codemap.json with 18 overrides) | openwop.codemod.event-type-codemap (generated from the codemap; the C.9 reader applies the same map) | translated |
openwop.migration.C4.4 | remove | approvalRequested / clarificationRequested payload defs; free-text feedback | interrupt.requested {kind}; refineFeedback | openwop.codemod.event-type-codemap (payload-def rename rides the same map) | translated |
openwop.migration.C4.5 | behavior | lastSequence cursor (cannot express the empty prefix); since alias in prose only | afterSequence; omission = from the first event; since removed | — (a query parameter; clients change, nothing persisted) | not-persisted |
openwop.migration.C4.6 | behavior | 409 interrupt_already_resolved beside 410 interrupt_gone | one code per state in errors.json | — | not-persisted |
openwop.migration.C4.7 | rename | debug-bundle event seq | sequence | openwop.codemod.debug-bundle-seq | never-upgraded (a published bundle stays valid v1 evidence; the codemod is for re-emission) |
openwop.migration.C4.8 | behavior | openwop-Webhook-Signature (SDK-only) | none | — | not-persisted |
openwop.migration.C4.9 | require | 63 of 120 payload defs open (runStarted among them) | every payload def closed; _typeIndex normative | — (schema closure; a v1 event with extra keys is read through the C.9 adapter) | translated |
openwop.migration.C4.10 | add | none (42 codes in prose; details a bare object) | errors.json; generated envelope with a closed enum and per-code details | — | not-persisted |
openwop.migration.C4.11 | behavior | details.retryAfter / retryAfterMs / retryAfterSeconds beside Retry-After | Retry-After only | — (error responses are not persisted) | not-persisted |
openwop.migration.C4.12 | retype | configurable open map with 15 reserved keys, 6 typed, 4 dotted | closed, nested, versioned object | openwop.codemod.configurable-v2 (dotted keys → nested; unknown keys → extensions.<org>; refuses an unknown key with no org) | translated (persisted run rows carry configurable verbatim; read through the adapter) |
openwop.migration.C4.13 | behavior | four AsyncAPI channels on one address + address: null heartbeat | one runEvents channel with a typed streamMode; one hostEvents channel with a declared address | — | not-persisted |
openwop.migration.C4.14 | behavior | poll response {runId, events, lastEventSeq, runStatus, isTerminal} (prose) vs {events, isComplete} (OpenAPI) | { runId, events, lastSequence, status, isTerminal } from one definition | — (a response shape; generated) | not-persisted |
openwop.migration.C4.15 | add | none | the closed-enum growth rule (§A.5) | — | not-persisted |
openwop.migration.C4.16 | require | meta.source SHOULD; vendor kinds RECOMMENDED; correlationId synthesized | meta.source required; <org>. kinds required; correlationId required | — (envelopes are transient; a persisted envelope.* event is read through the adapter) | translated |
openwop.migration.C4.17 | remove | optional locale on InterruptPayload.data and on the resume payload (i18n.md) | none — interrupt data and resume bodies are closed; the rendered locale is request-scoped (Content-Language) | openwop.codemod.interrupt-locale-drop (recorded 2026-09-27: the C4.9 closure left the field no place, and v2 drops it rather than re-adding it) | translated |
openwop.migration.C4.18 | remove | RunSnapshot.parentRunId + parentNodeId on a core.subWorkflow child (node-packs.md) | none on the child — parentRunId is fork lineage; the child's parent is getRunAncestry parent.runId with cause: "core.subWorkflow" | openwop.codemod.subworkflow-parent-link-drop (recorded 2026-09-28: ancestry names the parent run, not the node) | translated |
The 18 codemap decisions (spec/v1/event-codemap.json v2Override, this PR): run.resuming → run.resume-started; channel.presence, output.chunk, provider.usage, envelope.refusal, agent.handoff keep their noun form (artifact events); lease.handed-off, deployment.rolled-back keep their form (already past-tense transitions); replay.divergedAtRefusal → replay.diverged-at-refusal; agent.reasoning.delta → agent.reasoning-delta; runOrchestrator.decided → orchestrator.decided; core.dispatch.fanOut → dispatch.fanned-out; core.dispatch.join → dispatch.joined; core.workflowChain.event → workflow-chain.event; core.workflowChain.confidence-escalated → workflow-chain.confidence-escalated; voice.endpoint_candidate → voice.endpoint-candidate; voice.synthesis_chunk → voice.synthesis-chunk; voice.barge_in → voice.barge-in.
Persisted-data disposition
| Store | v1 artifact | Disposition |
|---|---|---|
Event logs (openwop-app SQLite/Postgres events.type free text; MyndHyve Firestore runs/{id}/events) | 117 v1 type names; open payloads | translated: the C.9 reader applies event-codemap.json on read with sequence space preserved; openwop.codemod.event-type-codemap backfills exports; fork-a-v1-run reads through the same map |
Run rows (configurable column) | dotted / open map | translated by openwop.codemod.configurable-v2 on read or backfill |
| Debug and certification bundles | seq, v1 type names | never-upgraded as evidence; re-emission uses the codemods |
| Webhook subscriptions | header family per subscriber | not-persisted (dual emission through the overlap; a v2 receiver accepts a v1-signed delivery — §F coexistence) |
| Error responses, envelopes | — | not-persisted |
Compatibility
breaking (v2). In v1.x this PR edits only hand fields of spec/v1/event-codemap.json (no consumer reads it), adds three codemods, two proposed register rows, and migration rows; no schema, OpenAPI, AsyncAPI, or prose MUST changes. The v1 vendor regex, the open payloads, and the poll shapes stay as they are until the v1 tree is retired.
Conformance
v2 scenarios (suite 2.0.0): event-type-closed (unaided: a typo'd protocol type fails; an unregistered org fails; openwop.x fails), event-naming-rule (corpus: every enum member matches the grammar and the tense rule with its recorded exceptions), payload-registry-closed (corpus + unaided: every def closed; an event with an extra key fails), error-registry (unaided: every error in every response is a registered code; details validates against the per-code schema; no body retry-timing field), header-scheme (unaided: every non-standard header on every response is OpenWOP-*; none of the removed names appears after its date), configurable-closed (unaided: an unknown root key is refused; ai.provider dotted is refused), events-channel-parity (corpus), poll-cursor-v2 (unaided: omission returns from the first event; afterSequence=N returns > N; past-end 200 + empty; response shape), enum-growth-rule (unaided: a registered-but-unknown-to-the-client member is accepted by the suite's reader without action), fork-a-v1-run (C.9; gated on history — reads the codemap).
Falsifiability — one row per normative requirement
| Requirement | Observable | Who can cause the condition | Verdict |
|---|---|---|---|
§A.1 closed type; positive vendor pattern | schema validation of injected types — openwop.requirement.0171.event-type-closed, openwop.requirement.0171.enum-growth-rule | the suite, unaided | witnessable — unaided |
| §A.2 naming rule and recorded exceptions | corpus gate over the enum | the corpus gate | witnessable — unaided (corpus) |
§A.4 every payload closed; _typeIndex normative | corpus gate + an event with an extra key — openwop.requirement.0171.payload-registry-closed | the suite, unaided | witnessable — unaided |
| §A.5 growth rule: consumer accepts, producer never emits unregistered | the suite's reader on a registered-unknown member; a host emitting an unregistered member fails event-type-closed — openwop.requirement.0171.enum-growth-rule, openwop.requirement.0171.event-type-closed | the suite, unaided | witnessable — unaided |
§B.1 every code registered; details typed | every error response — openwop.requirement.0171.error-registry | the suite, unaided | witnessable — unaided |
§B.2 Retry-After only | a rate-limited response — openwop.requirement.0171.error-registry | the suite (gated on a host advertising limits) | witnessable — gated |
§C.1 OpenWOP-* only; every header declared | every response; OpenAPI vs prose parity — openwop.requirement.0171.header-scheme | the suite, unaided; the corpus gate | witnessable — unaided |
§D.1 configurable closed standalone | schema validation — openwop.requirement.0171.configurable-closed | the suite, unaided | witnessable — unaided |
| §E.1 one channel; path parity | corpus gate | the corpus gate | witnessable — unaided (corpus) |
§E.2 afterSequence semantics; response shape | poll responses — openwop.requirement.0171.poll-cursor-v2 | the suite, unaided | witnessable — unaided |
Adversarial review
domain.verb-edforcesoutput.chunkedandprovider.used. Disposition: the rule is relaxed for artifact events (§A.2) with the exception list recorded in the codemap asnote; the corpus gate checks the list, so an exception is a decision, not a drift.- **Dropping
core.*puts four v1 types into a namespace the v1 regex bans.** Disposition: the v2 regex is positive and reserves onlyopenwop.; the C.9 reader maps the four names; the codemod's refusal fixture proves acore.name never survives into a v2 log. runOrchestrator→run? Disposition: no — the orchestrator is its own domain (orchestrator.decided); folding it intorunwould makerun.decidedmean two things. Recorded in the codemap note.- The 15 non-review three-segment folds were done silently by the generator. Disposition: re-verified in this PR; two are recorded exceptions (
envelope.nlToFormat.engaged→envelope.nl-to-format-engaged;trigger.subscription.state.changed→trigger.subscription-state-changed), the rest fold cleanly; G1 records the list. - Closing
runStartedbreaks any host that echoes extra owner keys. Disposition: the v2 owner is C.3's closed shape; a v1 host's extra keys are stripped by the C.9 reader; C.3 §A.1's requirement and this closure land in the same PR C so neither is unwitnessable alone. afterSequenceis a rename with no codemod (row C4.5 isbehavior). Disposition: a query parameter is not a persisted artifact; SDK 2 issues the new name; the v1lastSequencestays on/v1/paths through the overlap (RFC 0172 §A.2).- The poll response shape mismatch was in no register. Disposition: filed as G2 and unified here (row C4.14); the OpenAPI shape was the one hosts implemented, so
isTerminalreplacesisCompleteand the three missing fields are added. Retry-Afteronly removes a MUST inproduction-profile.md:51andscale-profiles.md:71. Disposition: those MUSTs required the body field to equal the header; with the body field gone the header is the single source; the two profiles are re-stated inspec/v2/.- Charter corrections carried: the payload registry is 63 open / 57 closed of 120, not 62/64; the prose error list has 42 codes in 40 bullets; the four-spelling case is retry timing, not
capability_*; the two one-member enums arecomponents/schemas, not inline responses.
Alternatives considered
- Keep
anyOfand add a lint for typos. Rejected: a lint cannot distinguish a typo from a vendor event without the org registry, which is the closed root. - Number the first event 1 to make
lastSequence=0meaningful. Rejected: renumbers every persisted log (Axiom 6);afterSequencewith omission semantics is a pure rename. - Keep
details.retryAfterfor clients that cannot read headers. Rejected: every SDK reads headers; three body spellings is the measurement. - Do nothing. Rejected:
run.startdvalidates today.
Unresolved questions
- Whether
hostEvents(heartbeat) needs a normative delivery transport or stays a declared address the host serves by any transport. Decided in Phase 3 with C.8.
Implementation notes (non-normative)
Phase 3 generates the v2 event schema, the envelope, the error envelope, the channel, and the header table from the declaration file and errors.json; the codemods here are the backfill tools Phase 4 runs on openwop-app's SQL and MyndHyve's Firestore (C.9's per-store rows name them). openwop-app's eventLog and MyndHyve's serverEventLogIO read through the codemap adapter; both hosts' poll routes drop the +1/-1 cursor arithmetic (openwop-app's was a bug, MyndHyve's was correct) for a single > afterSequence read.
Acceptance criteria
- [x]
Draft → Active: RFC text; the 18 codemap decisions asv2Override; rowsC4.1–C4.16; codemodsevent-type-codemap,debug-bundle-seq,configurable-v2green; two register rows; ledger row; adversarial review. (This PR.) - [x]
Active → Accepted(Phase 3):schemas/v2/run-event*.json,spec/v2/errors.json+ generated envelope, closedconfigurable, one channel,afterSequence; the ten scenarios in suite 2.0.0; openwop-app passesevent-type-closed,error-registry,header-scheme,configurable-closed,poll-cursor-v2unaided. — evidence: the strongest host record of the eight children. All seven declared requirement ids areexecuted-passon ALL THREE committed bundles, openwop-app's included, and every one of the five ids this criterion names is among them. The single non-pass is oneerror-registryleg,inapplicablewith the reason "no 429rate_limitedresponse was observed during the suite's run" — identical on all three hosts; the §B.2 row's verdict declareswitnessable — gated, so RFC 0174 §B.1's second branch accounts for it. Path corrected in this edit: the error registry isspec/v2/errors.json, notschemas/v2/errors.json(the latter is the generated envelope half).
References
- RFC 0167 §A (Axioms 2, 3, 6), §B.4, §C, §E.2; RFC 0165 §C.1, G7; RFC 0169 (declaration file,
extensionsnamespace); RFC 0172 §A–§C; RFC 0021 UQ1; RFC 0030; RFC 0094 §A; RFC 0150 §A (idempotency spellings); RFC 0151 G6/G7. schemas/run-event.schema.json,run-event-payloads.schema.json,error-envelope.schema.json,run-options.schema.json;api/openapi.yaml(RunClaimConflict,UnsupportedStreamMode, poll),api/asyncapi.yaml(channels);spec/v1/event-codemap.json;spec/v1/ai-envelope.md§v2 promises, E1–E5;rest-endpoints.md§Headers, §Common error codes;run-options.md§Reserved keys;version-negotiation.md§events/poll;idempotency.md§naming note;compensation.mdG6;production-profile.md:51,scale-profiles.md:71.