@openwop/spec-artifacts 2.0.0-rc.3 → 2.0.0-rc.32

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 (32) hide show
  1. package/CORPUS-STAMP.json +32 -30
  2. package/api/seams-v2.yaml +1 -1
  3. package/api/v2/asyncapi.yaml +1 -1
  4. package/api/v2/openapi.yaml +9 -10
  5. package/package.json +18 -5
  6. package/schemas/capabilities.schema.json +40 -1
  7. package/schemas/certification-bundle-v2.schema.json +119 -27
  8. package/schemas/run-snapshot.schema.json +103 -33
  9. package/schemas/v2/agent-deployment-transition.schema.json +5 -6
  10. package/schemas/v2/agent-deployment.schema.json +8 -9
  11. package/schemas/v2/agent-eval-suite.schema.json +11 -12
  12. package/schemas/v2/artifact-type-pack-manifest.schema.json +22 -18
  13. package/schemas/v2/capabilities.schema.json +39 -0
  14. package/schemas/v2/certification-bundle.schema.json +1 -1
  15. package/schemas/v2/chat-card-pack-manifest.schema.json +19 -15
  16. package/schemas/v2/debug-bundle.schema.json +6 -6
  17. package/schemas/v2/eval-summary.schema.json +9 -10
  18. package/schemas/v2/goal.schema.json +5 -5
  19. package/schemas/v2/ids.schema.json +120 -22
  20. package/schemas/v2/node-pack-manifest.schema.json +27 -31
  21. package/schemas/v2/proposal.schema.json +7 -8
  22. package/schemas/v2/run-event-payloads.schema.json +241 -240
  23. package/schemas/v2/run-event.schema.json +2 -126
  24. package/schemas/v2/run-snapshot.schema.json +34 -13
  25. package/schemas/v2/webhook-delivery.schema.json +27 -0
  26. package/schemas/v2/workflow-chain-pack-manifest.schema.json +41 -45
  27. package/schemas/v2/workflow-definition.schema.json +31 -36
  28. package/spec/v1/core-standard-manifest.json +2 -2
  29. package/spec/v1/extensions.json +3 -2
  30. package/spec/v2/declaration.json +7 -0
  31. package/spec/v2/id-field-bindings.json +103 -0
  32. package/spec/v2/release.json +2 -2
@@ -2,11 +2,11 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://openwop.dev/spec/v2/run-event-payloads.schema.json",
4
4
  "title": "RunEventPayloads",
5
- "description": "Per-RunEventType payload schemas. The base RunEventDoc shape (run-event.schema.json) leaves `payload` permissive for forward-compat. This schema defines the canonical payload contract for each known RunEventType. Consumers MAY pin strict payload validation via `$defs.<typeId>` and `ajv.validate(schema.$defs[event.type], event.payload)`. Unknown event types MUST be tolerated (no $defs match fold best-effort).\n\n117 variants from `run-event.schema.json#$defs.RunEventType` are covered, grouped into ~20 shape families with shared $defs. Naming convention: camelCase keys mirror dotted RunEventType names (e.g., `run.started` `runStarted`). v2: every definition closed; _typeIndex normative; the legacy interrupt payloads (approval*/clarification*) removed per deprecation row legacy-interrupt-payloads.",
5
+ "description": "Per-RunEventType payload schemas. The base RunEventDoc shape (run-event.schema.json) leaves `payload` permissive for forward-compat. This schema defines the canonical payload contract for each known RunEventType. Consumers MAY pin strict payload validation via `$defs.<typeId>` and `ajv.validate(schema.$defs[event.type], event.payload)`. Unknown event types MUST be tolerated (no $defs match \u2192 fold best-effort).\n\n118 variants from the generated `type` branch of `run-event.schema.json` are covered (the v2 vocabulary is `spec/v2/event-codemap.json`; the old `$defs.RunEventType` twin is deleted \u2014 it held 36 retired v1 spellings and nothing referenced it), grouped into ~20 shape families with shared $defs. Naming convention: camelCase keys mirror dotted RunEventType names (e.g., `run.started` \u2192 `runStarted`). v2: every definition closed; _typeIndex normative; the legacy interrupt payloads (approval*/clarification*) removed per deprecation row legacy-interrupt-payloads.",
6
6
  "type": "object",
7
7
  "$defs": {
8
8
  "_typeIndex": {
9
- "description": "Lookup map: RunEventType $defs key. Informative consumers can derive this themselves but having it explicit aids tooling.",
9
+ "description": "Lookup map: RunEventType \u2192 $defs key. Informative \u2014 consumers can derive this themselves but having it explicit aids tooling.",
10
10
  "type": "object",
11
11
  "additionalProperties": false,
12
12
  "properties": {
@@ -364,7 +364,7 @@
364
364
  }
365
365
  },
366
366
  "voiceSpeechStart": {
367
- "description": "RFC 0106 §D. Emitted when inbound user speech onset is detected in a live voice session. Content-free (a timestamp only). MUST NOT be emitted unless `aiProviders.realtimeVoice.transcription: \"streaming\"` is advertised.",
367
+ "description": "RFC 0106 \u00a7D. Emitted when inbound user speech onset is detected in a live voice session. Content-free (a timestamp only). MUST NOT be emitted unless `aiProviders.realtimeVoice.transcription: \"streaming\"` is advertised.",
368
368
  "type": "object",
369
369
  "additionalProperties": false,
370
370
  "required": [
@@ -379,7 +379,7 @@
379
379
  }
380
380
  },
381
381
  "voiceTranscript": {
382
- "description": "RFC 0106 §B/§D. A settled or provisional transcript part for the current turn, emitted on the durable event log as the single canonical record (the `ctx.callTranscriber` Promise resolves separately at `turn_commit`). `text` is the recognized speech UNTRUSTED input (anyone in acoustic range is an unauthenticated writer): it MUST carry `contentTrust: \"untrusted\"` and MUST NOT be promoted to system/developer authority (SECURITY invariant `voice-transcript-untrusted`). A part with `isFinal: false` is provisional and MUST NOT be persisted to durable memory / the replay log / RAG or drive a side-effecting tool call before it finalizes (`voice-interim-not-durable`).",
382
+ "description": "RFC 0106 \u00a7B/\u00a7D. A settled or provisional transcript part for the current turn, emitted on the durable event log as the single canonical record (the `ctx.callTranscriber` Promise resolves separately at `turn_commit`). `text` is the recognized speech \u2014 UNTRUSTED input (anyone in acoustic range is an unauthenticated writer): it MUST carry `contentTrust: \"untrusted\"` and MUST NOT be promoted to system/developer authority (SECURITY invariant `voice-transcript-untrusted`). A part with `isFinal: false` is provisional and MUST NOT be persisted to durable memory / the replay log / RAG or drive a side-effecting tool call before it finalizes (`voice-interim-not-durable`).",
383
383
  "type": "object",
384
384
  "additionalProperties": false,
385
385
  "required": [
@@ -395,7 +395,7 @@
395
395
  },
396
396
  "isFinal": {
397
397
  "type": "boolean",
398
- "description": "true this segment's text is settled and will not change."
398
+ "description": "true \u21d2 this segment's text is settled and will not change."
399
399
  },
400
400
  "committedPrefix": {
401
401
  "type": "string",
@@ -409,7 +409,7 @@
409
409
  },
410
410
  "formatted": {
411
411
  "type": "boolean",
412
- "description": "Punctuation/casing/ITN applied; absent raw."
412
+ "description": "Punctuation/casing/ITN applied; absent \u21d2 raw."
413
413
  },
414
414
  "atMs": {
415
415
  "type": "integer",
@@ -417,12 +417,12 @@
417
417
  },
418
418
  "contentTrust": {
419
419
  "const": "untrusted",
420
- "description": "MUST be `\"untrusted\"` live transcript is untrusted ingress (`voice-transcript-untrusted`); never promote to higher authority."
420
+ "description": "MUST be `\"untrusted\"` \u2014 live transcript is untrusted ingress (`voice-transcript-untrusted`); never promote to higher authority."
421
421
  }
422
422
  }
423
423
  },
424
424
  "voiceEndpointCandidate": {
425
- "description": "RFC 0106 §B/§D. A silence boundary / likely end-of-turn appeared (only when `turnDetection: \"semantic\"`), DISTINCT from `voice.turn_commit` (Deepgram `UtteranceEnd` vs `speech_final`). Content-free.",
425
+ "description": "RFC 0106 \u00a7B/\u00a7D. A silence boundary / likely end-of-turn appeared (only when `turnDetection: \"semantic\"`), DISTINCT from `voice.turn_commit` (Deepgram `UtteranceEnd` vs `speech_final`). Content-free.",
426
426
  "type": "object",
427
427
  "additionalProperties": false,
428
428
  "required": [
@@ -442,7 +442,7 @@
442
442
  }
443
443
  },
444
444
  "voiceTurnCommit": {
445
- "description": "RFC 0106 §B/§D. The user yielded the floor (turn boundary). This is where the `ctx.callTranscriber` Promise resolves. `finalText` is the settled transcript and is UNTRUSTED (it inherits the `voice.transcript` boundary).",
445
+ "description": "RFC 0106 \u00a7B/\u00a7D. The user yielded the floor (turn boundary). This is where the `ctx.callTranscriber` Promise resolves. `finalText` is the settled transcript and is UNTRUSTED (it inherits the `voice.transcript` boundary).",
446
446
  "type": "object",
447
447
  "additionalProperties": false,
448
448
  "required": [
@@ -461,7 +461,7 @@
461
461
  }
462
462
  },
463
463
  "voiceSynthesisChunk": {
464
- "description": "RFC 0106 §C. Announces a clause-boundary streaming-synthesis chunk. METADATA ONLY the audio bytes are referenced by a session-scoped `streamRef`/`url`, NOT inlined on the event log past the host's inline cap (RFC 0055 256 KiB precedent; spill to a tenant-scoped `url`), so replay/`:fork` stays bounded over long sessions. MUST NOT be emitted unless `aiProviders.realtimeVoice.synthesis: \"streaming\"` is advertised.",
464
+ "description": "RFC 0106 \u00a7C. Announces a clause-boundary streaming-synthesis chunk. METADATA ONLY \u2014 the audio bytes are referenced by a session-scoped `streamRef`/`url`, NOT inlined on the event log past the host's inline cap (RFC 0055 256 KiB precedent; spill to a tenant-scoped `url`), so replay/`:fork` stays bounded over long sessions. MUST NOT be emitted unless `aiProviders.realtimeVoice.synthesis: \"streaming\"` is advertised.",
465
465
  "type": "object",
466
466
  "additionalProperties": false,
467
467
  "required": [
@@ -503,7 +503,7 @@
503
503
  }
504
504
  },
505
505
  "voiceBargeIn": {
506
- "description": "RFC 0106 §D. User speech overlapped active assistant playback (probable cut-in). A host advertising `realtimeVoice.bargeIn: \"supported\"` MUST emit this on detected overlap. Content-free. Distinct from `voice.cancelled` (a backchannel \"uh-huh\" MAY produce `barge_in` with no `cancelled`).",
506
+ "description": "RFC 0106 \u00a7D. User speech overlapped active assistant playback (probable cut-in). A host advertising `realtimeVoice.bargeIn: \"supported\"` MUST emit this on detected overlap. Content-free. Distinct from `voice.cancelled` (a backchannel \"uh-huh\" MAY produce `barge_in` with no `cancelled`).",
507
507
  "type": "object",
508
508
  "additionalProperties": false,
509
509
  "required": [
@@ -517,7 +517,7 @@
517
517
  }
518
518
  },
519
519
  "voiceCancelled": {
520
- "description": "RFC 0106 §D. Downstream LLM/TTS work was cancelled (barge-in or explicit). A cancellation MUST NOT emit partial tool outputs or partial un-guardrailed model output and MUST roll back or fully complete an in-flight side effect (SECURITY invariant `voice-bargein-no-partial-leak`). Content-free.",
520
+ "description": "RFC 0106 \u00a7D. Downstream LLM/TTS work was cancelled (barge-in or explicit). A cancellation MUST NOT emit partial tool outputs or partial un-guardrailed model output and MUST roll back or fully complete an in-flight side effect (SECURITY invariant `voice-bargein-no-partial-leak`). Content-free.",
521
521
  "type": "object",
522
522
  "additionalProperties": false,
523
523
  "required": [
@@ -539,7 +539,7 @@
539
539
  }
540
540
  },
541
541
  "authorizationDecided": {
542
- "description": "RFC 0049 emitted on a role-based authorization decision (allow or deny). Redaction-safe: `principal` is an opaque RFC 0048 id; `reason` carries no credential material. Every deny SHOULD be emitted and SHOULD feed the audit log (RFC 0009/0010). MUST NOT be emitted unless `capabilities.authorization.supported: true`.",
542
+ "description": "RFC 0049 \u2014 emitted on a role-based authorization decision (allow or deny). Redaction-safe: `principal` is an opaque RFC 0048 id; `reason` carries no credential material. Every deny SHOULD be emitted and SHOULD feed the audit log (RFC 0009/0010). MUST NOT be emitted unless `capabilities.authorization.supported: true`.",
543
543
  "type": "object",
544
544
  "additionalProperties": false,
545
545
  "required": [
@@ -552,7 +552,7 @@
552
552
  "principal": {
553
553
  "type": "string",
554
554
  "minLength": 1,
555
- "description": "Opaque RFC 0048 principal id never PII."
555
+ "description": "Opaque RFC 0048 principal id \u2014 never PII."
556
556
  },
557
557
  "action": {
558
558
  "type": "string",
@@ -569,12 +569,12 @@
569
569
  },
570
570
  "reason": {
571
571
  "type": "string",
572
- "description": "Human-readable, redaction-safe no credential material."
572
+ "description": "Human-readable, redaction-safe \u2014 no credential material."
573
573
  }
574
574
  }
575
575
  },
576
576
  "proposalCreated": {
577
- "description": "RFC 0096 §D. Emitted when the host synthesizes a reviewable-learning draft. Content-free: ids / kind / content-free references only NEVER the artifact body or the rationale text (those live behind the authed read). Redaction-safe (SECURITY invariant `proposal-inert-until-applied` covers the behavior; SR-1 covers the payload). MUST NOT be emitted unless `capabilities.agents.proposals` is advertised.",
577
+ "description": "RFC 0096 \u00a7D. Emitted when the host synthesizes a reviewable-learning draft. Content-free: ids / kind / content-free references only \u2014 NEVER the artifact body or the rationale text (those live behind the authed read). Redaction-safe (SECURITY invariant `proposal-inert-until-applied` covers the behavior; SR-1 covers the payload). MUST NOT be emitted unless `capabilities.agents.proposals` is advertised.",
578
578
  "type": "object",
579
579
  "additionalProperties": false,
580
580
  "required": [
@@ -600,9 +600,9 @@
600
600
  "sourceRunIds": {
601
601
  "type": "array",
602
602
  "items": {
603
- "type": "string"
603
+ "$ref": "ids.schema.json#/$defs/runId"
604
604
  },
605
- "description": "Runs whose traces produced the draft (RFC 0040 causation-compatible). Ids only no trace content."
605
+ "description": "Runs whose traces produced the draft (RFC 0040 causation-compatible). Ids only \u2014 no trace content."
606
606
  },
607
607
  "duplicateOf": {
608
608
  "type": [
@@ -614,7 +614,7 @@
614
614
  }
615
615
  },
616
616
  "proposalActivated": {
617
- "description": "RFC 0096 §D. Emitted on a successful `apply`. Content-free: ids / content-free references only NEVER the installed artifact body. MUST NOT be emitted unless `capabilities.agents.proposals` is advertised.",
617
+ "description": "RFC 0096 \u00a7D. Emitted on a successful `apply`. Content-free: ids / content-free references only \u2014 NEVER the installed artifact body. MUST NOT be emitted unless `capabilities.agents.proposals` is advertised.",
618
618
  "type": "object",
619
619
  "additionalProperties": false,
620
620
  "required": [
@@ -651,7 +651,7 @@
651
651
  }
652
652
  },
653
653
  "goalEvaluated": {
654
- "description": "RFC 0097 §D. Emitted after each judge check on a standing goal. Content-free: NO objective text. The verdict (`satisfied`/`confidence`) is non-deterministic judge output it is RECORDED here and MUST NOT be recomputed on replay/fork (`replay.md`). MUST NOT be emitted unless `capabilities.agents.goals` is advertised.",
654
+ "description": "RFC 0097 \u00a7D. Emitted after each judge check on a standing goal. Content-free: NO objective text. The verdict (`satisfied`/`confidence`) is non-deterministic judge output \u2014 it is RECORDED here and MUST NOT be recomputed on replay/fork (`replay.md`). MUST NOT be emitted unless `capabilities.agents.goals` is advertised.",
655
655
  "type": "object",
656
656
  "additionalProperties": false,
657
657
  "required": [
@@ -687,7 +687,7 @@
687
687
  }
688
688
  },
689
689
  "goalClosed": {
690
- "description": "RFC 0097 §D. Emitted when a standing goal stops continuation. Content-free. MUST NOT be emitted unless `capabilities.agents.goals` is advertised.",
690
+ "description": "RFC 0097 \u00a7D. Emitted when a standing goal stops continuation. Content-free. MUST NOT be emitted unless `capabilities.agents.goals` is advertised.",
691
691
  "type": "object",
692
692
  "additionalProperties": false,
693
693
  "required": [
@@ -712,7 +712,7 @@
712
712
  }
713
713
  },
714
714
  "importApplied": {
715
- "description": "RFC 0098 §D. Emitted when an estate import is applied. Content-free: counts + ref-only NO item payloads, NO secret values (SECURITY invariant `export-bundle-no-credential-material`). MUST NOT be emitted unless `capabilities.portability` is advertised.",
715
+ "description": "RFC 0098 \u00a7D. Emitted when an estate import is applied. Content-free: counts + ref-only \u2014 NO item payloads, NO secret values (SECURITY invariant `export-bundle-no-credential-material`). MUST NOT be emitted unless `capabilities.portability` is advertised.",
716
716
  "type": "object",
717
717
  "additionalProperties": false,
718
718
  "required": [
@@ -723,7 +723,7 @@
723
723
  "bundleOrigin": {
724
724
  "type": "string",
725
725
  "minLength": 1,
726
- "description": "The bundle's `source.origin` informational only."
726
+ "description": "The bundle's `source.origin` \u2014 informational only."
727
727
  },
728
728
  "counts": {
729
729
  "type": "object",
@@ -753,12 +753,12 @@
753
753
  "items": {
754
754
  "type": "string"
755
755
  },
756
- "description": "Provider/ref ids whose secrets must be re-bound at the destination. Refs only never secret values."
756
+ "description": "Provider/ref ids whose secrets must be re-bound at the destination. Refs only \u2014 never secret values."
757
757
  }
758
758
  }
759
759
  },
760
760
  "connectorAuthorized": {
761
- "description": "RFC 0047 emitted when the host acquires (or re-authorizes) a third-party OAuth token on a user's behalf via the `host.oauth` flow. Redaction-safe: carries the credential REFERENCE (RFC 0046), never token material. MUST NOT be emitted unless `capabilities.oauth.supported: true`.",
761
+ "description": "RFC 0047 \u2014 emitted when the host acquires (or re-authorizes) a third-party OAuth token on a user's behalf via the `host.oauth` flow. Redaction-safe: carries the credential REFERENCE (RFC 0046), never token material. MUST NOT be emitted unless `capabilities.oauth.supported: true`.",
762
762
  "type": "object",
763
763
  "additionalProperties": false,
764
764
  "required": [
@@ -786,7 +786,7 @@
786
786
  }
787
787
  },
788
788
  "connectorAuthExpired": {
789
- "description": "RFC 0047 emitted when a stored OAuth token's refresh fails terminally (revoked/expired refresh token). Redaction-safe: no token material. MUST NOT be emitted unless `capabilities.oauth.supported: true`.",
789
+ "description": "RFC 0047 \u2014 emitted when a stored OAuth token's refresh fails terminally (revoked/expired refresh token). Redaction-safe: no token material. MUST NOT be emitted unless `capabilities.oauth.supported: true`.",
790
790
  "type": "object",
791
791
  "additionalProperties": false,
792
792
  "required": [
@@ -811,7 +811,7 @@
811
811
  }
812
812
  },
813
813
  "coreWorkflowChainEvent": {
814
- "description": "RFC 0037 emitted on every planner→worker handoff state-machine transition. Required when `capabilities.multiAgent.executionModel.supported: true`; MUST NOT be emitted otherwise. RFC 0040 §A extends with optional `causationHostId` (when `crossHostCausation.supported: true`): present + non-empty when the `causationId` points at an event on a different host; absent when the chained-event is on the same host (existing semantics).",
814
+ "description": "RFC 0037 \u2014 emitted on every planner\u2192worker handoff state-machine transition. Required when `capabilities.multiAgent.executionModel.supported: true`; MUST NOT be emitted otherwise. RFC 0040 \u00a7A extends with optional `causationHostId` (when `crossHostCausation.supported: true`): present + non-empty when the `causationId` points at an event on a different host; absent when the chained-event is on the same host (existing semantics).",
815
815
  "type": "object",
816
816
  "additionalProperties": false,
817
817
  "required": [
@@ -831,20 +831,19 @@
831
831
  "child.cancelled",
832
832
  "output.harvested"
833
833
  ],
834
- "description": "Which handoff-state-machine transition this event records. See spec/v1/multi-agent-execution.md §'Handoff state machine'."
834
+ "description": "Which handoff-state-machine transition this event records. See spec/v1/multi-agent-execution.md \u00a7'Handoff state machine'."
835
835
  },
836
836
  "workerId": {
837
837
  "type": "string",
838
838
  "minLength": 1,
839
- "description": "The dispatched worker's workflowId matches the entry in the supervisor's OrchestratorDecision.nextWorkerIds[]."
839
+ "description": "The dispatched worker's workflowId \u2014 matches the entry in the supervisor's OrchestratorDecision.nextWorkerIds[]."
840
840
  },
841
841
  "parentRunId": {
842
842
  "$ref": "ids.schema.json#/$defs/runId",
843
843
  "description": "The orchestrator-driven parent run's runId."
844
844
  },
845
845
  "childRunId": {
846
- "type": "string",
847
- "minLength": 1,
846
+ "$ref": "ids.schema.json#/$defs/runId",
848
847
  "description": "The dispatched child run's runId. REQUIRED on phases `dispatch.succeeded` and beyond; absent on `dispatch.began` and `dispatch.failed`."
849
848
  },
850
849
  "harvestedKeys": {
@@ -852,11 +851,11 @@
852
851
  "items": {
853
852
  "type": "string"
854
853
  },
855
- "description": "On phase `output.harvested`: which parent-variable keys were populated by the dispatch config's outputMapping per RFC 0022 §A. SHOULD be present; conformance asserts presence when outputMapping is non-empty."
854
+ "description": "On phase `output.harvested`: which parent-variable keys were populated by the dispatch config's outputMapping per RFC 0022 \u00a7A. SHOULD be present; conformance asserts presence when outputMapping is non-empty."
856
855
  },
857
856
  "attestation": {
858
857
  "type": "object",
859
- "description": "RFC 0063 (when `capabilities.agents.subRunAttestation: true` AND the `core.subWorkflow` node sets `outputAttestation.checksum: true`). A content checksum over the child's harvested output object, computed BEFORE `outputMapping` is applied so the parent (or a downstream node) can verify integrity host-independent because the recipe is RFC 8785 JCS canonicalization + SHA-256 (the `replay.md` recipe, RFC 0041), enabling verification of a child that ran on a different host (RFC 0040). Advisory: the host does NOT itself reject on checksum mismatch; that is parent policy.",
858
+ "description": "RFC 0063 (when `capabilities.agents.subRunAttestation: true` AND the `core.subWorkflow` node sets `outputAttestation.checksum: true`). A content checksum over the child's harvested output object, computed BEFORE `outputMapping` is applied so the parent (or a downstream node) can verify integrity \u2014 host-independent because the recipe is RFC 8785 JCS canonicalization + SHA-256 (the `replay.md` recipe, RFC 0041), enabling verification of a child that ran on a different host (RFC 0040). Advisory: the host does NOT itself reject on checksum mismatch; that is parent policy.",
860
859
  "additionalProperties": false,
861
860
  "required": [
862
861
  "checksum",
@@ -884,12 +883,12 @@
884
883
  "causationHostId": {
885
884
  "type": "string",
886
885
  "minLength": 1,
887
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` (top-level on RunEventDoc) points at an event on a DIFFERENT host; absent when the chained-event is on the SAME host (existing semantics). Value MUST equal the originating host's `capabilities.multiAgent.executionModel.crossHostCausation.hostId` advertisement. Hosts that don't advertise crossHostCausation MUST NOT emit this field."
886
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` (top-level on RunEventDoc) points at an event on a DIFFERENT host; absent when the chained-event is on the SAME host (existing semantics). Value MUST equal the originating host's `capabilities.multiAgent.executionModel.crossHostCausation.hostId` advertisement. Hosts that don't advertise crossHostCausation MUST NOT emit this field."
888
887
  }
889
888
  }
890
889
  },
891
890
  "coreWorkflowChainConfidenceEscalated": {
892
- "description": "RFC 0039 §A emitted when a supervisor's OrchestratorDecision carries `confidence` below the active confidence floor (spec floor 0.5 OR operator-stricter `capabilities.multiAgent.executionModel.confidenceEscalationFloor`). Recorded BEFORE the host fires the matching clarify-or-escalate interrupt so the run event log carries the decision point even if the user later confirms the original decision. MUST NOT be emitted unless `capabilities.multiAgent.executionModel.version >= 2`.",
891
+ "description": "RFC 0039 \u00a7A \u2014 emitted when a supervisor's OrchestratorDecision carries `confidence` below the active confidence floor (spec floor 0.5 OR operator-stricter `capabilities.multiAgent.executionModel.confidenceEscalationFloor`). Recorded BEFORE the host fires the matching clarify-or-escalate interrupt so the run event log carries the decision point even if the user later confirms the original decision. MUST NOT be emitted unless `capabilities.multiAgent.executionModel.version >= 2`.",
893
892
  "type": "object",
894
893
  "additionalProperties": false,
895
894
  "required": [
@@ -909,7 +908,7 @@
909
908
  "type": "number",
910
909
  "minimum": 0.5,
911
910
  "maximum": 1,
912
- "description": "The floor that triggered escalation either the spec floor (0.5) when the host doesn't advertise a stricter `confidenceEscalationFloor`, or the host-advertised stricter value."
911
+ "description": "The floor that triggered escalation \u2014 either the spec floor (0.5) when the host doesn't advertise a stricter `confidenceEscalationFloor`, or the host-advertised stricter value."
913
912
  },
914
913
  "escalationKind": {
915
914
  "type": "string",
@@ -917,12 +916,12 @@
917
916
  "clarify",
918
917
  "escalate"
919
918
  ],
920
- "description": "Which interrupt-kind the host fired in response. `clarify` is preferred per RFC 0039 §A; `escalate` is permitted when the host doesn't expose a clarification UI."
919
+ "description": "Which interrupt-kind the host fired in response. `clarify` is preferred per RFC 0039 \u00a7A; `escalate` is permitted when the host doesn't expose a clarification UI."
921
920
  },
922
921
  "workerId": {
923
922
  "type": "string",
924
923
  "minLength": 1,
925
- "description": "The decision's intended next-worker workflowId (when the escalated decision's kind is `next-worker`). OMITTED for `kind: 'terminate'` escalations terminate decisions have no worker to name, so absent-field is the correct signal rather than empty-string."
924
+ "description": "The decision's intended next-worker workflowId (when the escalated decision's kind is `next-worker`). OMITTED for `kind: 'terminate'` escalations \u2014 terminate decisions have no worker to name, so absent-field is the correct signal rather than empty-string."
926
925
  },
927
926
  "parentRunId": {
928
927
  "$ref": "ids.schema.json#/$defs/runId",
@@ -930,12 +929,12 @@
930
929
  },
931
930
  "originalDecision": {
932
931
  "$ref": "orchestrator-decision.schema.json",
933
- "description": "The OrchestratorDecision that triggered escalation, captured verbatim. The host's existing event-payload redaction harness (the same one enforcing SECURITY invariant `secret-leakage-eventlog-payload` per `conformance/src/scenarios/redaction.test.ts`) applies uniformly across all RunEventType payloads including this one no per-event-type opt-in is required. The protocol-tier MUST-NOT for raw key material in persisted payloads is the canonical contract; this field inherits that protection."
932
+ "description": "The OrchestratorDecision that triggered escalation, captured verbatim. The host's existing event-payload redaction harness (the same one enforcing SECURITY invariant `secret-leakage-eventlog-payload` per `conformance/src/scenarios/redaction.test.ts`) applies uniformly across all RunEventType payloads including this one \u2014 no per-event-type opt-in is required. The protocol-tier MUST-NOT for raw key material in persisted payloads is the canonical contract; this field inherits that protection."
934
933
  },
935
934
  "causationHostId": {
936
935
  "type": "string",
937
936
  "minLength": 1,
938
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host (existing semantics). Value MUST equal the originating host's `crossHostCausation.hostId` advertisement."
937
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host (existing semantics). Value MUST equal the originating host's `crossHostCausation.hostId` advertisement."
939
938
  }
940
939
  }
941
940
  },
@@ -1000,7 +999,7 @@
1000
999
  "engineVersion": {
1001
1000
  "type": "integer",
1002
1001
  "minimum": 0,
1003
- "description": "v2: integer everywhere (RFC 0172 §B axis 3)."
1002
+ "description": "v2: integer everywhere (RFC 0172 \u00a7B axis 3)."
1004
1003
  },
1005
1004
  "owner": {
1006
1005
  "type": "object",
@@ -1020,7 +1019,7 @@
1020
1019
  "$ref": "subject.schema.json"
1021
1020
  }
1022
1021
  },
1023
- "description": "RFC 0170 §A.1 the same block as RunSnapshot.owner."
1022
+ "description": "RFC 0170 \u00a7A.1 \u2014 the same block as RunSnapshot.owner."
1024
1023
  },
1025
1024
  "tags": {
1026
1025
  "type": "array",
@@ -1060,7 +1059,7 @@
1060
1059
  "$ref": "#/$defs/_errorObject"
1061
1060
  },
1062
1061
  "failedNodeId": {
1063
- "type": "string"
1062
+ "$ref": "ids.schema.json#/$defs/nodeId"
1064
1063
  },
1065
1064
  "durationMs": {
1066
1065
  "type": "integer",
@@ -1075,11 +1074,11 @@
1075
1074
  "properties": {
1076
1075
  "reason": {
1077
1076
  "type": "string",
1078
- "description": "`v1_pin_unsupported` (RFC 0176 §B.1) is a registered reason."
1077
+ "description": "`v1_pin_unsupported` (RFC 0176 \u00a7B.1) is a registered reason."
1079
1078
  },
1080
1079
  "cancelledBy": {
1081
1080
  "type": "string",
1082
- "description": "RFC 0176 §B.1 `v2-cutover` when a v2 host cancels an inherited run whose pin it no longer implements."
1081
+ "description": "RFC 0176 \u00a7B.1 \u2014 `v2-cutover` when a v2 host cancels an inherited run whose pin it no longer implements."
1083
1082
  },
1084
1083
  "durationMs": {
1085
1084
  "type": "integer",
@@ -1087,7 +1086,7 @@
1087
1086
  },
1088
1087
  "parentRunId": {
1089
1088
  "$ref": "ids.schema.json#/$defs/runId",
1090
- "description": "When this cancellation was triggered by a parent-cancel cascade (`interrupt-profiles.md §openwop-interrupt-cascade-cancel`), the parent runId that initiated it. Pairs with `reason: 'parent-cancelled'`. Absent for direct cancellations."
1089
+ "description": "When this cancellation was triggered by a parent-cancel cascade (`interrupt-profiles.md \u00a7openwop-interrupt-cascade-cancel`), the parent runId that initiated it. Pairs with `reason: 'parent-cancelled'`. Absent for direct cancellations."
1091
1090
  }
1092
1091
  },
1093
1092
  "additionalProperties": false
@@ -1115,7 +1114,7 @@
1115
1114
  "drain",
1116
1115
  "interrupt"
1117
1116
  ],
1118
- "description": "v1 rest-endpoints.md MUST the pause drain policy persisted on the event."
1117
+ "description": "v1 rest-endpoints.md MUST \u2014 the pause drain policy persisted on the event."
1119
1118
  }
1120
1119
  },
1121
1120
  "additionalProperties": false
@@ -1136,13 +1135,13 @@
1136
1135
  "engineVersion": {
1137
1136
  "type": "integer",
1138
1137
  "minimum": 0,
1139
- "description": "v2: integer everywhere (RFC 0172 §B axis 3)."
1138
+ "description": "v2: integer everywhere (RFC 0172 \u00a7B axis 3)."
1140
1139
  }
1141
1140
  },
1142
1141
  "additionalProperties": false
1143
1142
  },
1144
1143
  "runDeadLettered": {
1145
- "description": "RFC 0053 emitted when a run/node exhausts its retry policy (RFC 0009) and is routed to the durable dead-letter sink. The run remains fork-eligible (RFC 0011) for `capabilities.deadLetter.retentionDays`. Redaction-safe: `reason` carries no credential material. MUST NOT be emitted unless `capabilities.deadLetter.supported: true`.",
1144
+ "description": "RFC 0053 \u2014 emitted when a run/node exhausts its retry policy (RFC 0009) and is routed to the durable dead-letter sink. The run remains fork-eligible (RFC 0011) for `capabilities.deadLetter.retentionDays`. Redaction-safe: `reason` carries no credential material. MUST NOT be emitted unless `capabilities.deadLetter.supported: true`.",
1146
1145
  "type": "object",
1147
1146
  "additionalProperties": false,
1148
1147
  "required": [
@@ -1182,8 +1181,7 @@
1182
1181
  "$ref": "ids.schema.json#/$defs/nodeId"
1183
1182
  },
1184
1183
  "typeId": {
1185
- "type": "string",
1186
- "minLength": 1
1184
+ "$ref": "ids.schema.json#/$defs/typeId"
1187
1185
  },
1188
1186
  "attempt": {
1189
1187
  "type": "integer",
@@ -1260,7 +1258,7 @@
1260
1258
  "conversation.close",
1261
1259
  "low-confidence"
1262
1260
  ],
1263
- "description": "RFC 0094 §E the full kind union `interrupt.md` defines (mirrors suspend-request.schema.json). Conversation kinds are gated on the conversation capability per capabilities.md."
1261
+ "description": "RFC 0094 \u00a7E \u2014 the full kind union `interrupt.md` defines (mirrors suspend-request.schema.json). Conversation kinds are gated on the conversation capability per capabilities.md."
1264
1262
  },
1265
1263
  "key": {
1266
1264
  "type": "string",
@@ -1361,7 +1359,7 @@
1361
1359
  "additionalProperties": false
1362
1360
  },
1363
1361
  "interruptRequested": {
1364
- "description": "Canonical HITL primitive discriminated union over kind. Payload mirrors `suspend-request.schema.json` (InterruptPayload) plus engine-assigned identity fields.",
1362
+ "description": "Canonical HITL primitive \u2014 discriminated union over kind. Payload mirrors `suspend-request.schema.json` (InterruptPayload) plus engine-assigned identity fields.",
1365
1363
  "$ref": "https://openwop.dev/spec/v2/suspend-request.schema.json"
1366
1364
  },
1367
1365
  "interruptResolved": {
@@ -1390,7 +1388,7 @@
1390
1388
  "conversation.close",
1391
1389
  "low-confidence"
1392
1390
  ],
1393
- "description": "RFC 0094 §E the full kind union `interrupt.md` defines (mirrors suspend-request.schema.json). Conversation kinds are gated on the conversation capability per capabilities.md."
1391
+ "description": "RFC 0094 \u00a7E \u2014 the full kind union `interrupt.md` defines (mirrors suspend-request.schema.json). Conversation kinds are gated on the conversation capability per capabilities.md."
1394
1392
  },
1395
1393
  "resumeValue": {},
1396
1394
  "resolvedBy": {
@@ -1412,7 +1410,7 @@
1412
1410
  },
1413
1411
  "contextSummarized": {
1414
1412
  "type": "object",
1415
- "description": "RFC 0111. Emitted when the host replaces older in-window orchestrator transcript turns with a host-produced summary to honor `multiAgent.executionModel.contextBudget.transcriptTokenBudget`. CONTENT-FREE: the summary text is NEVER inlined `summaryRef` is an artifactId resolved via `GET /v1/runs/{runId}/artifacts/{artifactId}`. The summary is a NONDETERMINISTIC host output governed like an RFC 0041 envelope: on `:fork mode:replay` the host MUST reuse this recorded `summaryRef` and MUST NOT re-summarize (see multi-agent-execution.md §\"Context economy (RFC 0111)\"). `replacedTurns` lists the event ids the summary stands in for, so a replay engine reconstructs the exact transcript.",
1413
+ "description": "RFC 0111. Emitted when the host replaces older in-window orchestrator transcript turns with a host-produced summary to honor `multiAgent.executionModel.contextBudget.transcriptTokenBudget`. CONTENT-FREE: the summary text is NEVER inlined \u2014 `summaryRef` is an artifactId resolved via `GET /v1/runs/{runId}/artifacts/{artifactId}`. The summary is a NONDETERMINISTIC host output governed like an RFC 0041 envelope: on `:fork mode:replay` the host MUST reuse this recorded `summaryRef` and MUST NOT re-summarize (see multi-agent-execution.md \u00a7\"Context economy (RFC 0111)\"). `replacedTurns` lists the event ids the summary stands in for, so a replay engine reconstructs the exact transcript.",
1416
1414
  "required": [
1417
1415
  "iteration",
1418
1416
  "replacedTurns",
@@ -1458,7 +1456,7 @@
1458
1456
  "tokensAfter": {
1459
1457
  "type": "integer",
1460
1458
  "minimum": 0,
1461
- "description": "Token count of the summary that replaced the range, in `tokenCounter` units. Expected `tokensBefore`."
1459
+ "description": "Token count of the summary that replaced the range, in `tokenCounter` units. Expected \u2264 `tokensBefore`."
1462
1460
  }
1463
1461
  },
1464
1462
  "additionalProperties": false
@@ -1490,7 +1488,7 @@
1490
1488
  },
1491
1489
  "registered": {
1492
1490
  "type": "boolean",
1493
- "description": "RFC 0071. True when `artifactType` resolves to a registered artifact type (pack- or host-registered) and the payload was validated against its schema; false for unregistered/host-local types accepted without schema validation. Optional; absent treat as true, preserving pre-RFC-0071 semantics. See artifact-type-packs.md §\"Binding the existing artifact surfaces\"."
1491
+ "description": "RFC 0071. True when `artifactType` resolves to a registered artifact type (pack- or host-registered) and the payload was validated against its schema; false for unregistered/host-local types accepted without schema validation. Optional; absent \u21d2 treat as true, preserving pre-RFC-0071 semantics. See artifact-type-packs.md \u00a7\"Binding the existing artifact surfaces\"."
1494
1492
  },
1495
1493
  "registrationSource": {
1496
1494
  "type": "string",
@@ -1498,14 +1496,14 @@
1498
1496
  "pack",
1499
1497
  "host"
1500
1498
  ],
1501
- "description": "RFC 0075. Provenance of a registered type: `pack` (matches an installed artifact-type pack) or `host` (a host-native type the host validates against a host-known schema, independent of any pack e.g. an AI host's built-in artifact types). Optional; meaningful only when `registered: true`. Absent unspecified provenance (existing semantics)."
1499
+ "description": "RFC 0075. Provenance of a registered type: `pack` (matches an installed artifact-type pack) or `host` (a host-native type the host validates against a host-known schema, independent of any pack \u2014 e.g. an AI host's built-in artifact types). Optional; meaningful only when `registered: true`. Absent \u21d2 unspecified provenance (existing semantics)."
1502
1500
  }
1503
1501
  },
1504
1502
  "additionalProperties": false
1505
1503
  },
1506
1504
  "outputChunk": {
1507
1505
  "type": "object",
1508
- "description": "Emitted for streaming output (e.g., LLM token chunks). Stream-mode `messages` consumers see these. RFC 0094 §D single-sources the `ai.message.chunk` payload here: bare {nodeId, runId, chunk, isLast} is the minimum compliant payload per stream-modes.md §messages (the prior {nodeId, chunk}-only required set was the defective restatement). Tiered metadata per stream-modes.md §messages (S2 closure): `meta` adds Tier 1 typed slots and a Tier 2 provider-pass-through escape hatch.",
1506
+ "description": "Emitted for streaming output (e.g., LLM token chunks). Stream-mode `messages` consumers see these. RFC 0094 \u00a7D single-sources the `ai.message.chunk` payload here: bare {nodeId, runId, chunk, isLast} is the minimum compliant payload per stream-modes.md \u00a7messages (the prior {nodeId, chunk}-only required set was the defective restatement). Tiered metadata per stream-modes.md \u00a7messages (S2 closure): `meta` adds Tier 1 typed slots and a Tier 2 provider-pass-through escape hatch.",
1509
1507
  "required": [
1510
1508
  "nodeId",
1511
1509
  "runId",
@@ -1525,7 +1523,7 @@
1525
1523
  },
1526
1524
  "isLast": {
1527
1525
  "type": "boolean",
1528
- "description": "True for the final chunk of a given AI node call. Required both reference consumers rely on it for fold termination."
1526
+ "description": "True for the final chunk of a given AI node call. Required \u2014 both reference consumers rely on it for fold termination."
1529
1527
  },
1530
1528
  "channel": {
1531
1529
  "type": "string",
@@ -1539,7 +1537,7 @@
1539
1537
  },
1540
1538
  "_chunkMeta": {
1541
1539
  "type": "object",
1542
- "description": "Tiered metadata for ai.message.chunk / outputChunk payloads. See stream-modes.md §messages.",
1540
+ "description": "Tiered metadata for ai.message.chunk / outputChunk payloads. See stream-modes.md \u00a7messages.",
1543
1541
  "properties": {
1544
1542
  "finishReason": {
1545
1543
  "type": "string",
@@ -1557,7 +1555,7 @@
1557
1555
  },
1558
1556
  "toolCalls": {
1559
1557
  "type": "array",
1560
- "description": "Tier 1: structured tool / function calls emitted in this chunk. Each item: `{id, name, arguments}` `arguments` is a string (JSON-encoded args, may be partial when streaming)."
1558
+ "description": "Tier 1: structured tool / function calls emitted in this chunk. Each item: `{id, name, arguments}` \u2014 `arguments` is a string (JSON-encoded args, may be partial when streaming)."
1561
1559
  },
1562
1560
  "model": {
1563
1561
  "type": "string",
@@ -1584,11 +1582,11 @@
1584
1582
  },
1585
1583
  "provider": {
1586
1584
  "type": "string",
1587
- "description": "Tier 2: provider name when `providerExtensions` is present. Examples: `openai`, `anthropic`, `google`, `minimax`. Consumers MUST NOT branch on this for behavior use Tier 1 fields. Provided for observability + debugging only."
1585
+ "description": "Tier 2: provider name when `providerExtensions` is present. Examples: `openai`, `anthropic`, `google`, `minimax`. Consumers MUST NOT branch on this for behavior \u2014 use Tier 1 fields. Provided for observability + debugging only."
1588
1586
  },
1589
1587
  "providerExtensions": {
1590
1588
  "type": "object",
1591
- "description": "Tier 2: provider pass-through for fields the spec hasn't typed yet. Consumers using this opt into per-provider knowledge; spec evolution may move fields up into Tier 1 over time (additive typed slot wins).",
1589
+ "description": "Tier 2: provider pass-through for fields the spec hasn't typed yet. Consumers using this opt into per-provider knowledge; spec evolution may move fields up into Tier 1 over time (additive \u2014 typed slot wins).",
1592
1590
  "additionalProperties": true
1593
1591
  }
1594
1592
  },
@@ -1676,7 +1674,7 @@
1676
1674
  "engineVersion": {
1677
1675
  "type": "integer",
1678
1676
  "minimum": 0,
1679
- "description": "v2: integer everywhere (RFC 0172 §B axis 3)."
1677
+ "description": "v2: integer everywhere (RFC 0172 \u00a7B axis 3)."
1680
1678
  }
1681
1679
  },
1682
1680
  "additionalProperties": false
@@ -1712,14 +1710,14 @@
1712
1710
  "minimum": 0
1713
1711
  },
1714
1712
  "lastNodeId": {
1715
- "type": "string"
1713
+ "$ref": "ids.schema.json#/$defs/nodeId"
1716
1714
  }
1717
1715
  },
1718
1716
  "additionalProperties": false
1719
1717
  },
1720
1718
  "capBreached": {
1721
1719
  "type": "object",
1722
- "description": "Emitted when a CapabilityLimit is exceeded. Protocol-level limits use the engine kinds (clarificationRounds / schemaRounds / envelopesPerTurn / maxNodeExecutions). RFC 0008 §K WASM-runtime caps use the wasm-* kinds (memory ceiling, fuel exhaustion, execution-time wall-clock). RFC 0058 run-execution bounds use the run-scoped run-duration (wall-clock timeout; limit=resolvedMs, observed=elapsedMs) and loop-iterations (agent-loop ceiling; limit=resolvedMax, observed=iterationCount) kinds.",
1720
+ "description": "Emitted when a CapabilityLimit is exceeded. Protocol-level limits use the engine kinds (clarificationRounds / schemaRounds / envelopesPerTurn / maxNodeExecutions). RFC 0008 \u00a7K WASM-runtime caps use the wasm-* kinds (memory ceiling, fuel exhaustion, execution-time wall-clock). RFC 0058 run-execution bounds use the run-scoped run-duration (wall-clock timeout; limit=resolvedMs, observed=elapsedMs) and loop-iterations (agent-loop ceiling; limit=resolvedMax, observed=iterationCount) kinds.",
1723
1721
  "required": [
1724
1722
  "kind",
1725
1723
  "limit",
@@ -1747,7 +1745,7 @@
1747
1745
  "limit": {
1748
1746
  "type": "number",
1749
1747
  "minimum": 0,
1750
- "description": "The effective ceiling. A whole number for the engine/WASM/RFC 0058 integer kinds; a fractional value for budget-cost (dollars, matching budget.exhausted + maxCostUsd RFC 0084 §D)."
1748
+ "description": "The effective ceiling. A whole number for the engine/WASM/RFC 0058 integer kinds; a fractional value for budget-cost (dollars, matching budget.exhausted + maxCostUsd \u2014 RFC 0084 \u00a7D)."
1751
1749
  },
1752
1750
  "observed": {
1753
1751
  "type": "number",
@@ -1798,7 +1796,7 @@
1798
1796
  },
1799
1797
  "leaseHandedOff": {
1800
1798
  "type": "object",
1801
- "description": "Emitted when a run's executing lease is transferred from one host to another (e.g., browser cloud failover).",
1799
+ "description": "Emitted when a run's executing lease is transferred from one host to another (e.g., browser \u2192 cloud failover).",
1802
1800
  "required": [
1803
1801
  "leaseId",
1804
1802
  "fromHost",
@@ -1831,7 +1829,7 @@
1831
1829
  },
1832
1830
  "replayDivergedAtRefusal": {
1833
1831
  "type": "object",
1834
- "description": "RFC 0041 §B emitted by `:fork` mode `replay` when the replay's LLM call returns a refusal but the original run got a valid envelope (or vice-versa: the original refused, the replay succeeded). Distinct from the generic `replay.diverged` event (which covers structural output/missing/extra/type-mismatch divergence) to let operators audit safety-policy shifts without filtering through the generic divergence stream. When this event fires, the host MUST also fail the replay with `error.code: \"replay_diverged_at_refusal\"` per `spec/v1/rest-endpoints.md` §\"Common error codes\". Capability-gated on `capabilities.multiAgent.executionModel.replayDeterminism.refusalDivergenceEmission: true`; non-Phase-4 hosts MUST NOT emit this event.",
1832
+ "description": "RFC 0041 \u00a7B \u2014 emitted by `:fork` mode `replay` when the replay's LLM call returns a refusal but the original run got a valid envelope (or vice-versa: the original refused, the replay succeeded). Distinct from the generic `replay.diverged` event (which covers structural output/missing/extra/type-mismatch divergence) to let operators audit safety-policy shifts without filtering through the generic divergence stream. When this event fires, the host MUST also fail the replay with `error.code: \"replay_diverged_at_refusal\"` per `spec/v1/rest-endpoints.md` \u00a7\"Common error codes\". Capability-gated on `capabilities.multiAgent.executionModel.replayDeterminism.refusalDivergenceEmission: true`; non-Phase-4 hosts MUST NOT emit this event.",
1835
1833
  "required": [
1836
1834
  "sourceRunId",
1837
1835
  "atSequence",
@@ -1849,7 +1847,7 @@
1849
1847
  "description": "Event-log index at which the refusal-divergence was detected (the index of the LLM call whose envelope shifted)."
1850
1848
  },
1851
1849
  "originalEventId": {
1852
- "type": "string",
1850
+ "$ref": "ids.schema.json#/$defs/eventId",
1853
1851
  "description": "Optional eventId of the original event whose envelope is being compared. SHOULD be set when the host has a stable identifier for the event; MAY be omitted when only the sequence index is known."
1854
1852
  },
1855
1853
  "nodeId": {
@@ -1870,7 +1868,7 @@
1870
1868
  "valid",
1871
1869
  "refusal"
1872
1870
  ],
1873
- "description": "Whether the replay's LLM envelope was a valid response or a refusal. MUST differ from `originalEnvelopeKind` otherwise there is no divergence to report."
1871
+ "description": "Whether the replay's LLM envelope was a valid response or a refusal. MUST differ from `originalEnvelopeKind` \u2014 otherwise there is no divergence to report."
1874
1872
  },
1875
1873
  "refusalReason": {
1876
1874
  "type": "string",
@@ -1881,7 +1879,7 @@
1881
1879
  },
1882
1880
  "replayDiverged": {
1883
1881
  "type": "object",
1884
- "description": "Emitted by `:fork` when a replay re-execution produces a different output than the original at a given sequence. See replay.md §divergence detection. `divergencePoint` (RFC 0027 §F) is the canonical optional field for naming which event-emission diverged; the two fields are complementary, not mutually exclusive.",
1882
+ "description": "Emitted by `:fork` when a replay re-execution produces a different output than the original at a given sequence. See replay.md \u00a7divergence detection. `divergencePoint` (RFC 0027 \u00a7F) is the canonical optional field for naming which event-emission diverged; the two fields are complementary, not mutually exclusive.",
1885
1883
  "required": [
1886
1884
  "sourceRunId",
1887
1885
  "atSequence"
@@ -1895,7 +1893,7 @@
1895
1893
  "minimum": 0
1896
1894
  },
1897
1895
  "originalEventId": {
1898
- "type": "string"
1896
+ "$ref": "ids.schema.json#/$defs/eventId"
1899
1897
  },
1900
1898
  "divergenceKind": {
1901
1899
  "type": "string",
@@ -1908,7 +1906,7 @@
1908
1906
  },
1909
1907
  "divergencePoint": {
1910
1908
  "type": "string",
1911
- "description": "RFC 0027 §F. Verbatim `RunEventType` enum string identifying which event-emission the replay diverged at (e.g., `\"prompt.composed\"` per RFC 0027, `\"agent.promptResolved\"` per RFC 0029, `\"envelope.retry.exhausted\"` / `\"envelope.recovery.applied\"` per RFC 0032). Set when divergence is detected on a specific cross-kind operational event's payload. When divergence is purely structural (output/missing/extra at the event-array level rather than within a typed payload), `divergenceKind` carries the shape and `divergencePoint` MAY be omitted. The two fields are complementary: a single `replay.diverged` event MAY carry both (e.g., `{ divergenceKind: \"output\", divergencePoint: \"prompt.composed\" }` reads as \"the `prompt.composed` event at sequence N had a different output on replay than the original\"). The field is defined by RFC 0027; values are contributed by consuming RFCs (0029 adds `agent.promptResolved`, 0032 adds the envelope-reliability event names)."
1909
+ "description": "RFC 0027 \u00a7F. Verbatim `RunEventType` enum string identifying which event-emission the replay diverged at (e.g., `\"prompt.composed\"` per RFC 0027, `\"agent.promptResolved\"` per RFC 0029, `\"envelope.retry.exhausted\"` / `\"envelope.recovery.applied\"` per RFC 0032). Set when divergence is detected on a specific cross-kind operational event's payload. When divergence is purely structural (output/missing/extra at the event-array level rather than within a typed payload), `divergenceKind` carries the shape and `divergencePoint` MAY be omitted. The two fields are complementary: a single `replay.diverged` event MAY carry both (e.g., `{ divergenceKind: \"output\", divergencePoint: \"prompt.composed\" }` reads as \"the `prompt.composed` event at sequence N had a different output on replay than the original\"). The field is defined by RFC 0027; values are contributed by consuming RFCs (0029 adds `agent.promptResolved`, 0032 adds the envelope-reliability event names)."
1912
1910
  }
1913
1911
  },
1914
1912
  "additionalProperties": false
@@ -1941,14 +1939,14 @@
1941
1939
  "causationHostId": {
1942
1940
  "type": "string",
1943
1941
  "minLength": 1,
1944
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
1942
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
1945
1943
  }
1946
1944
  },
1947
1945
  "additionalProperties": false
1948
1946
  },
1949
1947
  "agentReasoningDelta": {
1950
1948
  "type": "object",
1951
- "description": "RFC 0024. Incremental reasoning chunk for live-streaming UX. Emitted while a reasoning block is still open, BEFORE the corresponding `agent.reasoned` finalization. Consumers concatenate `delta` strings in arrival order to reconstruct the in-progress trace; the closing `agent.reasoned` event carries the FULL authoritative `reasoning`. Gated on `capabilities.agents.reasoning.streaming: true`. NOTE: `additionalProperties: true` mirrors the Phase-1 multi-agent-shift carve-out applied to the sibling `agentReasoned` schema a deliberate forward-compat exception per RFC 0024 §Compatibility, not a precedent generalizable to other event payloads.",
1949
+ "description": "RFC 0024. Incremental reasoning chunk for live-streaming UX. Emitted while a reasoning block is still open, BEFORE the corresponding `agent.reasoned` finalization. Consumers concatenate `delta` strings in arrival order to reconstruct the in-progress trace; the closing `agent.reasoned` event carries the FULL authoritative `reasoning`. Gated on `capabilities.agents.reasoning.streaming: true`. NOTE: `additionalProperties: true` mirrors the Phase-1 multi-agent-shift carve-out applied to the sibling `agentReasoned` schema \u2014 a deliberate forward-compat exception per RFC 0024 \u00a7Compatibility, not a precedent generalizable to other event payloads.",
1952
1950
  "required": [
1953
1951
  "agentId",
1954
1952
  "delta",
@@ -1982,7 +1980,7 @@
1982
1980
  },
1983
1981
  "providerUsage": {
1984
1982
  "type": "object",
1985
- "description": "RFC 0026. Per-call usage record emitted after every LLM provider invocation. Durably persisted in the run event log; consumed by replay, webhook subscribers, billing reconciliation. The OTel `openwop.cost.*` attribute group (per `observability.md §\"Cost attribution attributes\"`) is the observability sibling this event type is the durable record. Replay determinism: `inputTokens` + `outputTokens` MUST replay identically; `costEstimateUsd` MAY be omitted on replay, and so MAY the RFC 0116 cost-only `cacheReadTokens`/`cacheWriteTokens` (they are NOT replay-asserted a prompt-prefix cache hit vs miss MUST NOT change `inputTokens`/`outputTokens` or the recorded envelope). The payload MUST NOT carry credentialRefs, hashed credential identifiers, or prompt/response substrings per `SECURITY/threat-model-secret-leakage.md §SR-1` (enforced by SECURITY invariant `provider-usage-no-credential-leak`).",
1983
+ "description": "RFC 0026. Per-call usage record emitted after every LLM provider invocation. Durably persisted in the run event log; consumed by replay, webhook subscribers, billing reconciliation. The OTel `openwop.cost.*` attribute group (per `observability.md \u00a7\"Cost attribution attributes\"`) is the observability sibling \u2014 this event type is the durable record. Replay determinism: `inputTokens` + `outputTokens` MUST replay identically; `costEstimateUsd` MAY be omitted on replay, and so MAY the RFC 0116 cost-only `cacheReadTokens`/`cacheWriteTokens` (they are NOT replay-asserted \u2014 a prompt-prefix cache hit vs miss MUST NOT change `inputTokens`/`outputTokens` or the recorded envelope). The payload MUST NOT carry credentialRefs, hashed credential identifiers, or prompt/response substrings per `SECURITY/threat-model-secret-leakage.md \u00a7SR-1` (enforced by SECURITY invariant `provider-usage-no-credential-leak`).",
1986
1984
  "required": [
1987
1985
  "provider",
1988
1986
  "model",
@@ -1998,7 +1996,7 @@
1998
1996
  "model": {
1999
1997
  "type": "string",
2000
1998
  "minLength": 1,
2001
- "description": "Provider-stamped model id as the model expects it. Same value used in the LLM cache-key recipe per `replay.md §A`."
1999
+ "description": "Provider-stamped model id as the model expects it. Same value used in the LLM cache-key recipe per `replay.md \u00a7A`."
2002
2000
  },
2003
2001
  "inputTokens": {
2004
2002
  "type": "integer",
@@ -2018,7 +2016,7 @@
2018
2016
  "costEstimateUsd": {
2019
2017
  "type": "number",
2020
2018
  "minimum": 0,
2021
- "description": "ADVISORY estimate in USD computed by the host's static rate table. MUST NOT be used for billing real billing is external. Hosts SHOULD omit when no rate is known rather than emit 0."
2019
+ "description": "ADVISORY estimate in USD computed by the host's static rate table. MUST NOT be used for billing \u2014 real billing is external. Hosts SHOULD omit when no rate is known rather than emit 0."
2022
2020
  },
2023
2021
  "currency": {
2024
2022
  "type": "string",
@@ -2027,12 +2025,12 @@
2027
2025
  },
2028
2026
  "cacheHit": {
2029
2027
  "type": "boolean",
2030
- "description": "True iff this call was served from the LLM response cache per `replay.md §\"LLM cache-key recipe\"`. When true, inputTokens/outputTokens reflect the ORIGINAL call's billed values; the cached invocation incurred zero new provider cost."
2028
+ "description": "True iff this call was served from the LLM response cache per `replay.md \u00a7\"LLM cache-key recipe\"`. When true, inputTokens/outputTokens reflect the ORIGINAL call's billed values; the cached invocation incurred zero new provider cost."
2031
2029
  },
2032
2030
  "cacheReadTokens": {
2033
2031
  "type": "integer",
2034
2032
  "minimum": 0,
2035
- "description": "RFC 0116. Optional, cost-only. Provider-reported tokens served from the prompt-prefix context cache on this call a cache HIT shows > 0. This is a cost hint, NOT a semantic input: it MAY be omitted on replay (NOT replay-asserted, like `costEstimateUsd`), and a hit-vs-miss difference MUST NOT change `inputTokens`/`outputTokens` or the recorded envelope (RFC 0116 replay-invariance MUST). MUST NOT carry prompt/response substrings per `SECURITY/threat-model-secret-leakage.md §SR-1`."
2033
+ "description": "RFC 0116. Optional, cost-only. Provider-reported tokens served from the prompt-prefix context cache on this call \u2014 a cache HIT shows > 0. This is a cost hint, NOT a semantic input: it MAY be omitted on replay (NOT replay-asserted, like `costEstimateUsd`), and a hit-vs-miss difference MUST NOT change `inputTokens`/`outputTokens` or the recorded envelope (RFC 0116 replay-invariance MUST). MUST NOT carry prompt/response substrings per `SECURITY/threat-model-secret-leakage.md \u00a7SR-1`."
2036
2034
  },
2037
2035
  "cacheWriteTokens": {
2038
2036
  "type": "integer",
@@ -2052,7 +2050,7 @@
2052
2050
  },
2053
2051
  "promptComposed": {
2054
2052
  "type": "object",
2055
- "description": "RFC 0027. Emitted once per (nodeId, kind) composition when a host resolves a PromptRef on a node and assembles its body for an LLM call. Gated on `capabilities.prompts.supported: true` AND `capabilities.prompts.observability !== 'off'`. Body fields (`systemPrompt`, `userPrompt`, `variableBindings`) are populated only under `observability: 'full'`; under `hashed` the event carries only `hash` + `variableHashes`. Replay-deterministic over `(refs, variableHashes, contentTrust)` per `spec/v1/prompts.md §\"Replay determinism\"`. Secret-source variable values MUST be replaced with `[REDACTED:<secretId>]` markers per SECURITY invariant `prompt-composed-secret-redaction`; untrusted-input segments MUST be wrapped with `<UNTRUSTED>...</UNTRUSTED>` markers per SECURITY invariant `prompt-composed-trust-marker`.",
2053
+ "description": "RFC 0027. Emitted once per (nodeId, kind) composition when a host resolves a PromptRef on a node and assembles its body for an LLM call. Gated on `capabilities.prompts.supported: true` AND `capabilities.prompts.observability !== 'off'`. Body fields (`systemPrompt`, `userPrompt`, `variableBindings`) are populated only under `observability: 'full'`; under `hashed` the event carries only `hash` + `variableHashes`. Replay-deterministic over `(refs, variableHashes, contentTrust)` per `spec/v1/prompts.md \u00a7\"Replay determinism\"`. Secret-source variable values MUST be replaced with `[REDACTED:<secretId>]` markers per SECURITY invariant `prompt-composed-secret-redaction`; untrusted-input segments MUST be wrapped with `<UNTRUSTED>...</UNTRUSTED>` markers per SECURITY invariant `prompt-composed-trust-marker`.",
2056
2054
  "required": [
2057
2055
  "nodeId",
2058
2056
  "refs",
@@ -2080,7 +2078,7 @@
2080
2078
  "user-only",
2081
2079
  "agent-reasoning"
2082
2080
  ],
2083
- "description": "Composition shape what the host actually assembled. `system+user`: both system and user templates resolved. `system-only`: only a system template applied (e.g., agent intrinsic). `user-only`: only a user template applied. `agent-reasoning`: composition was emitted ahead of an agent reasoning trace per RFC 0024."
2081
+ "description": "Composition shape \u2014 what the host actually assembled. `system+user`: both system and user templates resolved. `system-only`: only a system template applied (e.g., agent intrinsic). `user-only`: only a user template applied. `agent-reasoning`: composition was emitted ahead of an agent reasoning trace per RFC 0024."
2084
2082
  },
2085
2083
  "hash": {
2086
2084
  "type": "string",
@@ -2089,7 +2087,7 @@
2089
2087
  },
2090
2088
  "composed": {
2091
2089
  "type": "string",
2092
- "description": "Generic composed-body field. Present only when `capabilities.prompts.observability` is `full`. Populated for ALL four PromptKind values (system / user / few-shot / schema-hint) so consumers have a single body field to read necessary for few-shot + schema-hint templates that don't fit the system/user split below. Same secret-redaction + trust-marker invariants apply as for the kind-specific fields. The kind-specific `systemPrompt` + `userPrompt` fields below remain populated for system/user kinds so existing consumers that key off them continue to work; both fields carry identical content for those kinds."
2090
+ "description": "Generic composed-body field. Present only when `capabilities.prompts.observability` is `full`. Populated for ALL four PromptKind values (system / user / few-shot / schema-hint) so consumers have a single body field to read \u2014 necessary for few-shot + schema-hint templates that don't fit the system/user split below. Same secret-redaction + trust-marker invariants apply as for the kind-specific fields. The kind-specific `systemPrompt` + `userPrompt` fields below remain populated for system/user kinds so existing consumers that key off them continue to work; both fields carry identical content for those kinds."
2093
2091
  },
2094
2092
  "systemPrompt": {
2095
2093
  "type": "string",
@@ -2102,7 +2100,7 @@
2102
2100
  "variableBindings": {
2103
2101
  "type": "object",
2104
2102
  "additionalProperties": true,
2105
- "description": "Variable-name bound-value map. Secret-source bindings MUST appear as `[REDACTED:<secretId>]`. Only present under `observability: 'full'`."
2103
+ "description": "Variable-name \u2192 bound-value map. Secret-source bindings MUST appear as `[REDACTED:<secretId>]`. Only present under `observability: 'full'`."
2106
2104
  },
2107
2105
  "variableHashes": {
2108
2106
  "type": "object",
@@ -2110,7 +2108,7 @@
2110
2108
  "type": "string",
2111
2109
  "pattern": "^sha256:[0-9a-f]{64}$"
2112
2110
  },
2113
- "description": "Variable-name sha256(value) map. Always present (under both `hashed` and `full`). Enables replay-determinism checks without exposing values."
2111
+ "description": "Variable-name \u2192 sha256(value) map. Always present (under both `hashed` and `full`). Enables replay-determinism checks without exposing values."
2114
2112
  },
2115
2113
  "contentTrust": {
2116
2114
  "type": "string",
@@ -2118,19 +2116,19 @@
2118
2116
  "trusted",
2119
2117
  "untrusted"
2120
2118
  ],
2121
- "description": "Aggregate trust marker. `untrusted` iff ANY contributing input was tagged untrusted per RFC 0020 §D / AIEnvelope.meta.contentTrust propagation. When `untrusted`, the composed bodies MUST contain `<UNTRUSTED>...</UNTRUSTED>` markers around the untrusted segments."
2119
+ "description": "Aggregate trust marker. `untrusted` iff ANY contributing input was tagged untrusted per RFC 0020 \u00a7D / AIEnvelope.meta.contentTrust propagation. When `untrusted`, the composed bodies MUST contain `<UNTRUSTED>...</UNTRUSTED>` markers around the untrusted segments."
2122
2120
  },
2123
2121
  "causationHostId": {
2124
2122
  "type": "string",
2125
2123
  "minLength": 1,
2126
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2124
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2127
2125
  }
2128
2126
  },
2129
2127
  "additionalProperties": false
2130
2128
  },
2131
2129
  "agentPromptResolved": {
2132
2130
  "type": "object",
2133
- "description": "RFC 0029 §B. Emitted once per (nodeId, kind) pair BEFORE the corresponding `prompt.composed` event (when emitted). Surfaces the four-layer resolution chain per `spec/v1/prompts.md` §\"Resolution chain (normative)\" so cross-host debuggers and multi-agent visualizers can render which PromptRef applied at this node and why. Gated on `capabilities.prompts.supported: true`; payload is durable in the event log and participates in replay. Carries refs (not bodies), so emission is safe regardless of `capabilities.prompts.observability` the secret-redaction + trust-marker invariants on `prompt.composed` (RFC 0027 §G) don't apply here.",
2131
+ "description": "RFC 0029 \u00a7B. Emitted once per (nodeId, kind) pair BEFORE the corresponding `prompt.composed` event (when emitted). Surfaces the four-layer resolution chain per `spec/v1/prompts.md` \u00a7\"Resolution chain (normative)\" so cross-host debuggers and multi-agent visualizers can render which PromptRef applied at this node and why. Gated on `capabilities.prompts.supported: true`; payload is durable in the event log and participates in replay. Carries refs (not bodies), so emission is safe regardless of `capabilities.prompts.observability` \u2014 the secret-redaction + trust-marker invariants on `prompt.composed` (RFC 0027 \u00a7G) don't apply here.",
2134
2132
  "required": [
2135
2133
  "nodeId",
2136
2134
  "kind",
@@ -2171,7 +2169,7 @@
2171
2169
  "workflow-defaults",
2172
2170
  "host-defaults"
2173
2171
  ],
2174
- "description": "Identifies which precedence layer this chain entry represents. The four normative layers per RFC 0029 §A are `node`, `agent-*`, `workflow-defaults`, `host-defaults`. `run-configurable` is reserved for the optional `RunOptions.configurable.promptOverrides` extension described in RFC 0029 §\"Alternatives considered\" #5; hosts that honor that extension MUST emit a chain entry with this layer value above the `node` entry."
2172
+ "description": "Identifies which precedence layer this chain entry represents. The four normative layers per RFC 0029 \u00a7A are `node`, `agent-*`, `workflow-defaults`, `host-defaults`. `run-configurable` is reserved for the optional `RunOptions.configurable.promptOverrides` extension described in RFC 0029 \u00a7\"Alternatives considered\" #5; hosts that honor that extension MUST emit a chain entry with this layer value above the `node` entry."
2175
2173
  },
2176
2174
  "source": {
2177
2175
  "type": "string",
@@ -2179,7 +2177,7 @@
2179
2177
  },
2180
2178
  "applied": {
2181
2179
  "type": "boolean",
2182
- "description": "True for exactly one entry in the chain the layer whose ref was selected. False for layers that yielded null OR were skipped after a higher-precedence layer already applied."
2180
+ "description": "True for exactly one entry in the chain \u2014 the layer whose ref was selected. False for layers that yielded null OR were skipped after a higher-precedence layer already applied."
2183
2181
  },
2184
2182
  "reason": {
2185
2183
  "type": "string",
@@ -2198,7 +2196,7 @@
2198
2196
  "causationHostId": {
2199
2197
  "type": "string",
2200
2198
  "minLength": 1,
2201
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2199
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2202
2200
  }
2203
2201
  },
2204
2202
  "additionalProperties": false
@@ -2206,7 +2204,7 @@
2206
2204
  "modelCapabilitySubstituted": {
2207
2205
  "type": "object",
2208
2206
  "additionalProperties": false,
2209
- "description": "RFC 0031 §D. Emitted when a host substitutes the active model with a NodeModule's declared `fallbackModel` because the active model lacks one or more of the `requiredModelCapabilities`. MUST event per RFC 0031 §B step 3. The `fallbackProvider` + `fallbackModel` pair MAY be redacted as all-or-nothing `\"[REDACTED]\"` when workspace policy treats multi-vendor posture as confidential per SECURITY invariant `model-capability-substituted-no-credential-disclosure`. The other fields are not redactable `originalProvider` is already public via `RunOptions.configurable.ai.provider`, and `nodeId` / `missingCapabilities` carry no provider-possession information.",
2207
+ "description": "RFC 0031 \u00a7D. Emitted when a host substitutes the active model with a NodeModule's declared `fallbackModel` because the active model lacks one or more of the `requiredModelCapabilities`. MUST event per RFC 0031 \u00a7B step 3. The `fallbackProvider` + `fallbackModel` pair MAY be redacted as all-or-nothing `\"[REDACTED]\"` when workspace policy treats multi-vendor posture as confidential per SECURITY invariant `model-capability-substituted-no-credential-disclosure`. The other fields are not redactable \u2014 `originalProvider` is already public via `RunOptions.configurable.ai.provider`, and `nodeId` / `missingCapabilities` carry no provider-possession information.",
2210
2208
  "required": [
2211
2209
  "nodeId",
2212
2210
  "originalProvider",
@@ -2249,7 +2247,7 @@
2249
2247
  "modelCapabilityInsufficient": {
2250
2248
  "type": "object",
2251
2249
  "additionalProperties": false,
2252
- "description": "RFC 0031 §D. Emitted when a host refuses to dispatch a NodeModule because the active model lacks declared `requiredModelCapabilities` AND no viable fallback is available (no `fallbackModel` declared, OR the host cannot authenticate to the fallback provider). MUST event per RFC 0031 §B step 4. Pairs with `RunSnapshot.error.code = \"capability_not_provided\"` per `capabilities.md` §\"Unsupported capability refusal contract\". Recursive fallback is NOT permitted (RFC 0031 §\"Unresolved questions\" #3): if a host attempts substitution and the fallback itself fails, the host MUST emit this event with `fallbackAttempted: true` and refuse, not chain to another fallback.",
2250
+ "description": "RFC 0031 \u00a7D. Emitted when a host refuses to dispatch a NodeModule because the active model lacks declared `requiredModelCapabilities` AND no viable fallback is available (no `fallbackModel` declared, OR the host cannot authenticate to the fallback provider). MUST event per RFC 0031 \u00a7B step 4. Pairs with `RunSnapshot.error.code = \"capability_not_provided\"` per `capabilities.md` \u00a7\"Unsupported capability \u2014 refusal contract\". Recursive fallback is NOT permitted (RFC 0031 \u00a7\"Unresolved questions\" #3): if a host attempts substitution and the fallback itself fails, the host MUST emit this event with `fallbackAttempted: true` and refuse, not chain to another fallback.",
2253
2251
  "required": [
2254
2252
  "nodeId",
2255
2253
  "provider",
@@ -2287,7 +2285,7 @@
2287
2285
  "envelopeRetryAttempted": {
2288
2286
  "type": "object",
2289
2287
  "additionalProperties": false,
2290
- "description": "RFC 0032 §B.1. Emitted when a host retries an envelope emission after a parse or validation failure on a prior attempt. The first attempt does NOT emit this event; the second attempt emits with `attempt: 2`, etc. SHOULD-tier hosts that don't implement retry don't emit; hosts that DO retry on validation failure SHOULD emit per attempt past the first.",
2288
+ "description": "RFC 0032 \u00a7B.1. Emitted when a host retries an envelope emission after a parse or validation failure on a prior attempt. The first attempt does NOT emit this event; the second attempt emits with `attempt: 2`, etc. SHOULD-tier \u2014 hosts that don't implement retry don't emit; hosts that DO retry on validation failure SHOULD emit per attempt past the first.",
2291
2289
  "required": [
2292
2290
  "nodeId",
2293
2291
  "attempt",
@@ -2322,21 +2320,21 @@
2322
2320
  "pattern": "^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$"
2323
2321
  }
2324
2322
  ],
2325
- "description": "Why the prior attempt failed. Spec-reserved values: `schema-violation` (model emitted wrong-shape JSON; corrective fragment + retry per RFC 0033 §C), `truncation` (stop_reason: max_tokens; budget-double + retry per RFC 0033 §B), `type-drift` (envelope `type` discriminator drifted from what was advertised mid-run), `type-mismatch` (a typed payload field was emitted with the wrong runtime type e.g., string where number was declared), `refusal` (provider safety-stop; NO retry per RFC 0032 §B.3), `parse-error` (response was not extractable as JSON even after lenient parsing), `unknown` (host could not classify). Host-private extensions MUST prefix with `x-host-<host>-` per `host-extensions.md` §\"Canonical-prefix table\"; matches the RFC 0031 §B `requiredModelCapabilities` precedent."
2323
+ "description": "Why the prior attempt failed. Spec-reserved values: `schema-violation` (model emitted wrong-shape JSON; corrective fragment + retry per RFC 0033 \u00a7C), `truncation` (stop_reason: max_tokens; budget-double + retry per RFC 0033 \u00a7B), `type-drift` (envelope `type` discriminator drifted from what was advertised mid-run), `type-mismatch` (a typed payload field was emitted with the wrong runtime type \u2014 e.g., string where number was declared), `refusal` (provider safety-stop; NO retry per RFC 0032 \u00a7B.3), `parse-error` (response was not extractable as JSON even after lenient parsing), `unknown` (host could not classify). Host-private extensions MUST prefix with `x-host-<host>-` per `host-extensions.md` \u00a7\"Canonical-prefix table\"; matches the RFC 0031 \u00a7B `requiredModelCapabilities` precedent."
2326
2324
  },
2327
2325
  "previousError": {
2328
2326
  "type": [
2329
2327
  "string",
2330
2328
  "null"
2331
2329
  ],
2332
- "description": "Diagnostic text from the failing attempt. MUST NOT contain prompt or response substring excerpts; hosts SHOULD limit to validator output (e.g., \"required field 'steps' missing\"). Subject to SR-1 redaction per `ai-envelope.md` §\"Redaction (SR-1 carry-forward)\"."
2330
+ "description": "Diagnostic text from the failing attempt. MUST NOT contain prompt or response substring excerpts; hosts SHOULD limit to validator output (e.g., \"required field 'steps' missing\"). Subject to SR-1 redaction per `ai-envelope.md` \u00a7\"Redaction (SR-1 carry-forward)\"."
2333
2331
  }
2334
2332
  }
2335
2333
  },
2336
2334
  "envelopeRetryExhausted": {
2337
2335
  "type": "object",
2338
2336
  "additionalProperties": false,
2339
- "description": "RFC 0032 §B.2. Emitted when a host has exhausted its retry budget and is about to surface a terminal envelope failure to the node. MUST-tier alternative is silent terminal failure with no event surface, leaving conformance suites unable to assert correct give-up behavior. Hosts that don't retry MUST still emit this event when an envelope attempt terminally fails (with `totalAttempts: 1`). Pairs with `cap.breached` when the failure mode is schema-violation or truncation per RFC 0033 §B + §C.",
2337
+ "description": "RFC 0032 \u00a7B.2. Emitted when a host has exhausted its retry budget and is about to surface a terminal envelope failure to the node. MUST-tier \u2014 alternative is silent terminal failure with no event surface, leaving conformance suites unable to assert correct give-up behavior. Hosts that don't retry MUST still emit this event when an envelope attempt terminally fails (with `totalAttempts: 1`). Pairs with `cap.breached` when the failure mode is schema-violation or truncation per RFC 0033 \u00a7B + \u00a7C.",
2340
2338
  "required": [
2341
2339
  "nodeId",
2342
2340
  "totalAttempts",
@@ -2368,7 +2366,7 @@
2368
2366
  "pattern": "^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$"
2369
2367
  }
2370
2368
  ],
2371
- "description": "Same value set as `envelope.retry.attempted.reason` (§B.1). Spec-reserved closed enum plus `x-host-<host>-` extensions."
2369
+ "description": "Same value set as `envelope.retry.attempted.reason` (\u00a7B.1). Spec-reserved closed enum plus `x-host-<host>-` extensions."
2372
2370
  },
2373
2371
  "finalError": {
2374
2372
  "type": [
@@ -2382,7 +2380,7 @@
2382
2380
  "envelopeRefusal": {
2383
2381
  "type": "object",
2384
2382
  "additionalProperties": false,
2385
- "description": "RFC 0032 §B.3. Emitted when the underlying LLM provider returns an explicit refusal (e.g., OpenAI `message.refusal`, Anthropic safety-stop, Gemini safety-block). MUST-tier. Hosts MUST NOT retry on refusal retrying refusal with prompt mutation creates a circumvention concern (the host automatically searches for a prompt the model will accept, evading the safety filter's intent) per RFC 0032 §B.3 + RFC 0033 §D. The node MUST fail with `error.code = \"envelope_refusal\"` per RFC 0033 §F (renamed from `envelope_refused_by_provider` per the 2026-05-21 RFC adoption-feedback amendment).",
2383
+ "description": "RFC 0032 \u00a7B.3. Emitted when the underlying LLM provider returns an explicit refusal (e.g., OpenAI `message.refusal`, Anthropic safety-stop, Gemini safety-block). MUST-tier. Hosts MUST NOT retry on refusal \u2014 retrying refusal with prompt mutation creates a circumvention concern (the host automatically searches for a prompt the model will accept, evading the safety filter's intent) per RFC 0032 \u00a7B.3 + RFC 0033 \u00a7D. The node MUST fail with `error.code = \"envelope_refusal\"` per RFC 0033 \u00a7F (renamed from `envelope_refused_by_provider` per the 2026-05-21 RFC adoption-feedback amendment).",
2386
2384
  "required": [
2387
2385
  "nodeId",
2388
2386
  "provider",
@@ -2417,7 +2415,7 @@
2417
2415
  "envelopeTruncated": {
2418
2416
  "type": "object",
2419
2417
  "additionalProperties": false,
2420
- "description": "RFC 0032 §B.4. Emitted when the LLM emission was cut off before the envelope was complete (typically `stop_reason: \"max_tokens\"`). SHOULD-tier hosts that distinguish truncation from schema-violation per RFC 0033 §A MUST emit this event when truncation occurs. Hosts that conflate truncation with schema-violation (legacy behavior) MAY omit; they then fail RFC 0033 conformance.",
2418
+ "description": "RFC 0032 \u00a7B.4. Emitted when the LLM emission was cut off before the envelope was complete (typically `stop_reason: \"max_tokens\"`). SHOULD-tier \u2014 hosts that distinguish truncation from schema-violation per RFC 0033 \u00a7A MUST emit this event when truncation occurs. Hosts that conflate truncation with schema-violation (legacy behavior) MAY omit; they then fail RFC 0033 conformance.",
2421
2419
  "required": [
2422
2420
  "nodeId",
2423
2421
  "provider",
@@ -2447,7 +2445,7 @@
2447
2445
  "partialPayloadAvailable": {
2448
2446
  "type": "boolean",
2449
2447
  "default": false,
2450
- "description": "True if the host recovered a partial envelope before truncation. Hosts MAY use this signal to route to a recovery path (e.g., budget-doubled retry per RFC 0033 §B)."
2448
+ "description": "True if the host recovered a partial envelope before truncation. Hosts MAY use this signal to route to a recovery path (e.g., budget-doubled retry per RFC 0033 \u00a7B)."
2451
2449
  },
2452
2450
  "outputTokenCount": {
2453
2451
  "type": [
@@ -2462,7 +2460,7 @@
2462
2460
  "envelopeNlToFormatEngaged": {
2463
2461
  "type": "object",
2464
2462
  "additionalProperties": false,
2465
- "description": "RFC 0032 §B.5. Emitted when the host has escalated to a two-call NL-to-Format fallback after retry exhaustion (per Tam et al., arXiv 2408.02442 mitigation strategy: free-form reasoning in the first call schema coercion in the second call). MAY-tier NL-to-Format is one of many possible recovery strategies; hosts that don't implement it don't advertise it.",
2463
+ "description": "RFC 0032 \u00a7B.5. Emitted when the host has escalated to a two-call NL-to-Format fallback after retry exhaustion (per Tam et al., arXiv 2408.02442 mitigation strategy: free-form reasoning in the first call \u2192 schema coercion in the second call). MAY-tier \u2014 NL-to-Format is one of many possible recovery strategies; hosts that don't implement it don't advertise it.",
2466
2464
  "required": [
2467
2465
  "nodeId",
2468
2466
  "originalEnvelopeType"
@@ -2486,7 +2484,7 @@
2486
2484
  "envelopeRecoveryApplied": {
2487
2485
  "type": "object",
2488
2486
  "additionalProperties": false,
2489
- "description": "RFC 0032 §B.6. Emitted when lenient parsing recovered a malformed envelope (e.g., JSON repair via `jsonrepair`, markdown fence stripping, last-balanced-object extraction). Recovery is internal to the parsing step, BEFORE validation; recovery does NOT consume a retry attempt per RFC 0033 §D. MAY-tier lenient parsing is a host-discretion recovery path. The event payload MUST NOT carry the recovered envelope content or any substring from the model's pre-recovery output per SECURITY invariant `envelope-recovery-no-content-leak`; only the recovery path identifier and the optional `byteOffset` are emitted. The recovered content rides on the subsequent envelope acceptance + downstream `RunEventDoc`, NOT on this event.",
2487
+ "description": "RFC 0032 \u00a7B.6. Emitted when lenient parsing recovered a malformed envelope (e.g., JSON repair via `jsonrepair`, markdown fence stripping, last-balanced-object extraction). Recovery is internal to the parsing step, BEFORE validation; recovery does NOT consume a retry attempt per RFC 0033 \u00a7D. MAY-tier \u2014 lenient parsing is a host-discretion recovery path. The event payload MUST NOT carry the recovered envelope content or any substring from the model's pre-recovery output per SECURITY invariant `envelope-recovery-no-content-leak`; only the recovery path identifier and the optional `byteOffset` are emitted. The recovered content rides on the subsequent envelope acceptance + downstream `RunEventDoc`, NOT on this event.",
2490
2488
  "required": [
2491
2489
  "nodeId",
2492
2490
  "path"
@@ -2504,7 +2502,7 @@
2504
2502
  "brace-walker",
2505
2503
  "custom"
2506
2504
  ],
2507
- "description": "Which recovery path succeeded. `direct` is reserved for the no-recovery-needed path and is informational; hosts MAY omit emission when `path: \"direct\"`. MUST replay identically (deterministic parsing deterministic recovery outcome)."
2505
+ "description": "Which recovery path succeeded. `direct` is reserved for the no-recovery-needed path and is informational; hosts MAY omit emission when `path: \"direct\"`. MUST replay identically (deterministic parsing \u2192 deterministic recovery outcome)."
2508
2506
  },
2509
2507
  "byteOffset": {
2510
2508
  "type": [
@@ -2543,7 +2541,7 @@
2543
2541
  },
2544
2542
  "argsHash": {
2545
2543
  "type": "string",
2546
- "description": "RFC 0064 (when `capabilities.toolHooks.prePostEvents`). SHA-256 over RFC 8785 JCS-canonicalized args with resolved secrets already redacted (SR-1) the SIEM-safe, content-free alternative to `inputs`. Raw key material MUST NOT enter the hash input."
2544
+ "description": "RFC 0064 (when `capabilities.toolHooks.prePostEvents`). SHA-256 over RFC 8785 JCS-canonicalized args with resolved secrets already redacted (SR-1) \u2014 the SIEM-safe, content-free alternative to `inputs`. Raw key material MUST NOT enter the hash input."
2547
2545
  },
2548
2546
  "principal": {
2549
2547
  "type": "string",
@@ -2561,7 +2559,7 @@
2561
2559
  "causationHostId": {
2562
2560
  "type": "string",
2563
2561
  "minLength": 1,
2564
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2562
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2565
2563
  }
2566
2564
  },
2567
2565
  "additionalProperties": false
@@ -2611,29 +2609,39 @@
2611
2609
  "causationHostId": {
2612
2610
  "type": "string",
2613
2611
  "minLength": 1,
2614
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2612
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2615
2613
  }
2616
2614
  },
2617
2615
  "additionalProperties": false
2618
2616
  },
2619
2617
  "agentHandoff": {
2620
2618
  "type": "object",
2621
- "description": "Multi-Agent Shift Phase 1. Emitted when control transfers from one agent to another mid-run (e.g., orchestrator worker, worker worker via `core.dispatch`). Pairs with the receiving agent's subsequent `agent.decided` / `agent.toolCalled` / `node.started`.",
2619
+ "description": "Multi-Agent Shift Phase 1. Emitted when control transfers from one agent to another mid-run (e.g., orchestrator \u2192 worker, worker \u2192 worker via `core.dispatch`). Pairs with the receiving agent's subsequent `agent.decided` / `agent.toolCalled` / `node.started`.",
2622
2620
  "required": [
2623
2621
  "fromAgentId",
2624
2622
  "toAgentId"
2625
2623
  ],
2626
2624
  "properties": {
2627
2625
  "fromAgentId": {
2628
- "type": "string",
2629
- "minLength": 3,
2630
- "maxLength": 256,
2626
+ "allOf": [
2627
+ {
2628
+ "$ref": "ids.schema.json#/$defs/agentId"
2629
+ },
2630
+ {
2631
+ "minLength": 3
2632
+ }
2633
+ ],
2631
2634
  "description": "Agent surrendering control."
2632
2635
  },
2633
2636
  "toAgentId": {
2634
- "type": "string",
2635
- "minLength": 3,
2636
- "maxLength": 256,
2637
+ "allOf": [
2638
+ {
2639
+ "$ref": "ids.schema.json#/$defs/agentId"
2640
+ },
2641
+ {
2642
+ "minLength": 3
2643
+ }
2644
+ ],
2637
2645
  "description": "Agent receiving control."
2638
2646
  },
2639
2647
  "reason": {
@@ -2643,7 +2651,7 @@
2643
2651
  "causationHostId": {
2644
2652
  "type": "string",
2645
2653
  "minLength": 1,
2646
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2654
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2647
2655
  }
2648
2656
  },
2649
2657
  "additionalProperties": false
@@ -2666,12 +2674,12 @@
2666
2674
  "type": "number",
2667
2675
  "minimum": 0,
2668
2676
  "maximum": 1,
2669
- "description": "Optional confidence in `[0, 1]`. Below the threshold escalate via `node.suspended { reason: 'low-confidence' }`. Absent values are treated as 'no signal' no escalation."
2677
+ "description": "Optional confidence in `[0, 1]`. Below the threshold \u2192 escalate via `node.suspended { reason: 'low-confidence' }`. Absent values are treated as 'no signal' \u2014 no escalation."
2670
2678
  },
2671
2679
  "causationHostId": {
2672
2680
  "type": "string",
2673
2681
  "minLength": 1,
2674
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2682
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2675
2683
  }
2676
2684
  },
2677
2685
  "additionalProperties": false
@@ -2692,7 +2700,7 @@
2692
2700
  "target": {
2693
2701
  "type": "string",
2694
2702
  "minLength": 1,
2695
- "description": "Opaque reference to what was checked the eventId of the verified `agent.decided`, a child runId, or a tool callId. Chains the verdict to its subject."
2703
+ "description": "Opaque reference to what was checked \u2014 the eventId of the verified `agent.decided`, a child runId, or a tool callId. Chains the verdict to its subject."
2696
2704
  },
2697
2705
  "verdict": {
2698
2706
  "type": "string",
@@ -2710,18 +2718,18 @@
2710
2718
  "minLength": 1
2711
2719
  },
2712
2720
  "uniqueItems": true,
2713
- "description": "Optional closed list of the criteria KEYS evaluated (e.g. `[\"schema-valid\",\"grounded\"]`). Keys only never per-criterion verdict text for SIEM safety."
2721
+ "description": "Optional closed list of the criteria KEYS evaluated (e.g. `[\"schema-valid\",\"grounded\"]`). Keys only \u2014 never per-criterion verdict text \u2014 for SIEM safety."
2714
2722
  },
2715
2723
  "confidence": {
2716
2724
  "type": "number",
2717
2725
  "minimum": 0,
2718
2726
  "maximum": 1,
2719
- "description": "Optional verifier confidence in `[0,1]` the critic's confidence in its OWN verdict, distinct from the actor's `agent.decided.confidence`. MAY drive the RFC 0039 escalation contract."
2727
+ "description": "Optional verifier confidence in `[0,1]` \u2014 the critic's confidence in its OWN verdict, distinct from the actor's `agent.decided.confidence`. MAY drive the RFC 0039 escalation contract."
2720
2728
  },
2721
2729
  "causationHostId": {
2722
2730
  "type": "string",
2723
2731
  "minLength": 1,
2724
- "description": "RFC 0040 §A cross-host causation pointer when the verified target lives on a different host."
2732
+ "description": "RFC 0040 \u00a7A \u2014 cross-host causation pointer when the verified target lives on a different host."
2725
2733
  }
2726
2734
  },
2727
2735
  "additionalProperties": false
@@ -2736,7 +2744,7 @@
2736
2744
  "properties": {
2737
2745
  "agentId": {
2738
2746
  "$ref": "ids.schema.json#/$defs/agentId",
2739
- "description": "AgentRef.agentId of the orchestrator. MUST equal `RunSnapshot.runOrchestrator.agentId` for the run's lifetime orchestrator identity is set at first decision and does not change."
2747
+ "description": "AgentRef.agentId of the orchestrator. MUST equal `RunSnapshot.runOrchestrator.agentId` for the run's lifetime \u2014 orchestrator identity is set at first decision and does not change."
2740
2748
  },
2741
2749
  "decision": {
2742
2750
  "$ref": "orchestrator-decision.schema.json"
@@ -2744,32 +2752,30 @@
2744
2752
  "iteration": {
2745
2753
  "type": "integer",
2746
2754
  "minimum": 1,
2747
- "description": "RFC 0061 (`multiAgent.executionModel.version >= 5`). 1-based, monotonic count of orchestrator turns in this run the observable loop-iteration counter that `maxLoopIterations` (RFC 0058) bounds; a breach emits `cap.breached { kind: 'loop-iterations', observed: <this+1> }`. A `version >= 5` host MUST set it on every `runOrchestrator.decided`, incrementing by exactly 1 per turn and surviving a stateful HITL resume unchanged. Recorded in the event and re-emitted verbatim on replay/`:fork`, never recomputed (`replay.md`). Omitted by hosts on `version < 5`."
2755
+ "description": "RFC 0061 (`multiAgent.executionModel.version >= 5`). 1-based, monotonic count of orchestrator turns in this run \u2014 the observable loop-iteration counter that `maxLoopIterations` (RFC 0058) bounds; a breach emits `cap.breached { kind: 'loop-iterations', observed: <this+1> }`. A `version >= 5` host MUST set it on every `runOrchestrator.decided`, incrementing by exactly 1 per turn and surviving a stateful HITL resume unchanged. Recorded in the event and re-emitted verbatim on replay/`:fork`, never recomputed (`replay.md`). Omitted by hosts on `version < 5`."
2748
2756
  },
2749
2757
  "causationHostId": {
2750
2758
  "type": "string",
2751
2759
  "minLength": 1,
2752
- "description": "RFC 0040 §A optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2760
+ "description": "RFC 0040 \u00a7A \u2014 optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2753
2761
  }
2754
2762
  },
2755
2763
  "additionalProperties": false
2756
2764
  },
2757
2765
  "nodeDispatched": {
2758
2766
  "type": "object",
2759
- "description": "Emitted by `core.dispatch` (RFC 0007 §D + RFC 0022 §A) for each child workflow spawned by a `next-worker` OrchestratorDecision. The envelope's top-level `nodeId` carries the dispatching `core.dispatch` node's id; the payload names the spawned child run + its terminal status at the moment of emission. Lets observers reconstruct the parent child linkage without scanning the runs table.",
2767
+ "description": "Emitted by `core.dispatch` (RFC 0007 \u00a7D + RFC 0022 \u00a7A) for each child workflow spawned by a `next-worker` OrchestratorDecision. The envelope's top-level `nodeId` carries the dispatching `core.dispatch` node's id; the payload names the spawned child run + its terminal status at the moment of emission. Lets observers reconstruct the parent \u2192 child linkage without scanning the runs table.",
2760
2768
  "required": [
2761
2769
  "childRunId",
2762
2770
  "childWorkflowId"
2763
2771
  ],
2764
2772
  "properties": {
2765
2773
  "childRunId": {
2766
- "type": "string",
2767
- "minLength": 1,
2774
+ "$ref": "ids.schema.json#/$defs/runId",
2768
2775
  "description": "RunId of the spawned child run."
2769
2776
  },
2770
2777
  "childWorkflowId": {
2771
- "type": "string",
2772
- "minLength": 1,
2778
+ "$ref": "ids.schema.json#/$defs/workflowId",
2773
2779
  "description": "WorkflowId of the spawned child."
2774
2780
  },
2775
2781
  "childStatus": {
@@ -2781,7 +2787,7 @@
2781
2787
  },
2782
2788
  "dispatchFanOut": {
2783
2789
  "type": "object",
2784
- "description": "RFC 0118. Emitted by `core.dispatch` when a `fanOutPolicy: 'parallel'` wave BEGINS, so the parent stays observable while children run concurrently. The envelope's `nodeId` carries the dispatching `core.dispatch` node id; `causationId` is set to the consumed `runOrchestrator.decided` event so replay reconstructs decision fan-out. Emitted ONLY on the parallel path.",
2790
+ "description": "RFC 0118. Emitted by `core.dispatch` when a `fanOutPolicy: 'parallel'` wave BEGINS, so the parent stays observable while children run concurrently. The envelope's `nodeId` carries the dispatching `core.dispatch` node id; `causationId` is set to the consumed `runOrchestrator.decided` event so replay reconstructs decision \u2192 fan-out. Emitted ONLY on the parallel path.",
2785
2791
  "required": [
2786
2792
  "fanOutPolicy",
2787
2793
  "childCount"
@@ -2789,7 +2795,7 @@
2789
2795
  "properties": {
2790
2796
  "fanOutPolicy": {
2791
2797
  "const": "parallel",
2792
- "description": "Always `\"parallel\"` this event is emitted only on the parallel fan-out path."
2798
+ "description": "Always `\"parallel\"` \u2014 this event is emitted only on the parallel fan-out path."
2793
2799
  },
2794
2800
  "childCount": {
2795
2801
  "type": "integer",
@@ -2799,7 +2805,7 @@
2799
2805
  "maxConcurrency": {
2800
2806
  "type": "integer",
2801
2807
  "minimum": 1,
2802
- "description": "Effective concurrency ceiling for the wave (`min(config.maxConcurrency ?? ∞, capabilities.dispatch.maxFanOut ?? )`), when bounded."
2808
+ "description": "Effective concurrency ceiling for the wave (`min(config.maxConcurrency ?? \u221e, capabilities.dispatch.maxFanOut ?? \u221e)`), when bounded."
2803
2809
  },
2804
2810
  "joinMode": {
2805
2811
  "type": "string",
@@ -2831,7 +2837,7 @@
2831
2837
  "failed",
2832
2838
  "partial"
2833
2839
  ],
2834
- "description": "`'satisfied'` `mode` met and `onChildFailure` did not fail the node. `'failed'` `onChildFailure: 'fail-fast'` tripped, or `mode` could not be satisfied (e.g. quorum unreachable); the dispatch node fails. `'partial'` `mode` satisfied but ≥1 child is non-`completed` under `collect`/`absorb`; the node SUCCEEDS."
2840
+ "description": "`'satisfied'` \u2014 `mode` met and `onChildFailure` did not fail the node. `'failed'` \u2014 `onChildFailure: 'fail-fast'` tripped, or `mode` could not be satisfied (e.g. quorum unreachable); the dispatch node fails. `'partial'` \u2014 `mode` satisfied but \u22651 child is non-`completed` under `collect`/`absorb`; the node SUCCEEDS."
2835
2841
  },
2836
2842
  "completedCount": {
2837
2843
  "type": "integer",
@@ -2853,7 +2859,7 @@
2853
2859
  "items": {
2854
2860
  "type": "string"
2855
2861
  },
2856
- "description": "`childRunId`s in the parent host's observed wall-clock terminal order the replay-deterministic tiebreak for colliding `outputMapping` keys. Recorded at terminal-fold time; never recomputed from child timestamps."
2862
+ "description": "`childRunId`s in the parent host's observed wall-clock terminal order \u2014 the replay-deterministic tiebreak for colliding `outputMapping` keys. Recorded at terminal-fold time; never recomputed from child timestamps."
2857
2863
  }
2858
2864
  },
2859
2865
  "additionalProperties": false
@@ -2928,7 +2934,7 @@
2928
2934
  },
2929
2935
  "memoryCompacted": {
2930
2936
  "type": "object",
2931
- "description": "RFC 0012 (Memory Compaction Profile). Emitted by a host advertising `capabilities.memory.compaction.supported: true` each time a compaction run completes, regardless of trigger. `outputId` MUST be readable via `MemoryAdapter.get(memoryRef, outputId)` until normal TTL eviction. SR-1 carry-forward (RFC 0012 §D) applies: the host MUST route compacted entry content through the same BYOK redaction harness applied to a fresh `put`.",
2937
+ "description": "RFC 0012 (Memory Compaction Profile). Emitted by a host advertising `capabilities.memory.compaction.supported: true` each time a compaction run completes, regardless of trigger. `outputId` MUST be readable via `MemoryAdapter.get(memoryRef, outputId)` until normal TTL eviction. SR-1 carry-forward (RFC 0012 \u00a7D) applies: the host MUST route compacted entry content through the same BYOK redaction harness applied to a fresh `put`.",
2932
2938
  "required": [
2933
2939
  "memoryRef",
2934
2940
  "outputId",
@@ -2940,7 +2946,7 @@
2940
2946
  "memoryRef": {
2941
2947
  "type": "string",
2942
2948
  "minLength": 1,
2943
- "description": "Opaque MemoryAdapter handle per RFC 0004 §C. Bounds compaction to a single memory scope."
2949
+ "description": "Opaque MemoryAdapter handle per RFC 0004 \u00a7C. Bounds compaction to a single memory scope."
2944
2950
  },
2945
2951
  "outputId": {
2946
2952
  "type": "string",
@@ -2953,7 +2959,7 @@
2953
2959
  "type": "string",
2954
2960
  "minLength": 1
2955
2961
  },
2956
- "description": "Ids of entries collapsed into outputId. Hosts MAY omit when sourceCount > 100; the `compacted-from:<runId>` tag convention (RFC 0012 §C) becomes the authoritative provenance signal. When present, MUST be exhaustive within the array (no 'and N more' semantics)."
2962
+ "description": "Ids of entries collapsed into outputId. Hosts MAY omit when sourceCount > 100; the `compacted-from:<runId>` tag convention (RFC 0012 \u00a7C) becomes the authoritative provenance signal. When present, MUST be exhaustive within the array (no 'and N more' semantics)."
2957
2963
  },
2958
2964
  "sourceCount": {
2959
2965
  "type": "integer",
@@ -2976,7 +2982,7 @@
2976
2982
  },
2977
2983
  "distillation": {
2978
2984
  "type": "object",
2979
- "description": "RFC 0062 (when `capabilities.memory.distillation.supported: true`). Present when this compaction is part of a budgeted distillation run (a scheduled or on-demand 'dream'). Absent for a plain RFC 0012 compaction. Carries the token-budget accounting + whether the memory index was refreshed not a parallel `memory.distilled` event.",
2985
+ "description": "RFC 0062 (when `capabilities.memory.distillation.supported: true`). Present when this compaction is part of a budgeted distillation run (a scheduled or on-demand 'dream'). Absent for a plain RFC 0012 compaction. Carries the token-budget accounting + whether the memory index was refreshed \u2014 not a parallel `memory.distilled` event.",
2980
2986
  "additionalProperties": false,
2981
2987
  "required": [
2982
2988
  "tokenBudget",
@@ -2986,12 +2992,12 @@
2986
2992
  "tokenBudget": {
2987
2993
  "type": "integer",
2988
2994
  "minimum": 1,
2989
- "description": "Effective per-run budget honored ( advertised `maxTokenBudget`), counted against the advertised `tokenizerName`."
2995
+ "description": "Effective per-run budget honored (\u2264 advertised `maxTokenBudget`), counted against the advertised `tokenizerName`."
2990
2996
  },
2991
2997
  "tokensUsed": {
2992
2998
  "type": "integer",
2993
2999
  "minimum": 0,
2994
- "description": "Total input+output tokens the distillation consumed, best-effort-honest per the advertised tokenizer (±10% tolerance). MUST be `tokenBudget` on a successful run."
3000
+ "description": "Total input+output tokens the distillation consumed, best-effort-honest per the advertised tokenizer (\u00b110% tolerance). MUST be \u2264 `tokenBudget` on a successful run."
2995
3001
  },
2996
3002
  "indexUpdated": {
2997
3003
  "type": "boolean",
@@ -3004,7 +3010,7 @@
3004
3010
  },
3005
3011
  "memoryWritten": {
3006
3012
  "type": "object",
3007
- "description": "RFC 0057. Emitted by a host advertising `capabilities.memory.attribution.emitsWriteEvents: true` for each memory write a run makes, attributing it to the node (and agent, when known) that caused it. Content-free: identifiers + non-secret tags only the entry content is served by the read-side (`MemoryAdapter.get`), already SR-1-redacted. On replay the event is re-read from the log, never regenerated (the host MUST NOT mint a new `memoryId` or timestamp at replay time). SECURITY invariants `memory-attribution-no-content` + `memory-attribution-tenant-scoped` apply.",
3013
+ "description": "RFC 0057. Emitted by a host advertising `capabilities.memory.attribution.emitsWriteEvents: true` for each memory write a run makes, attributing it to the node (and agent, when known) that caused it. Content-free: identifiers + non-secret tags only \u2014 the entry content is served by the read-side (`MemoryAdapter.get`), already SR-1-redacted. On replay the event is re-read from the log, never regenerated (the host MUST NOT mint a new `memoryId` or timestamp at replay time). SECURITY invariants `memory-attribution-no-content` + `memory-attribution-tenant-scoped` apply.",
3008
3014
  "required": [
3009
3015
  "memoryRef",
3010
3016
  "memoryId"
@@ -3013,7 +3019,7 @@
3013
3019
  "memoryRef": {
3014
3020
  "type": "string",
3015
3021
  "minLength": 1,
3016
- "description": "Opaque MemoryAdapter handle (RFC 0004 §C) the entry was written under; resolvable via the read-side."
3022
+ "description": "Opaque MemoryAdapter handle (RFC 0004 \u00a7C) the entry was written under; resolvable via the read-side."
3017
3023
  },
3018
3024
  "memoryId": {
3019
3025
  "type": "string",
@@ -3022,25 +3028,25 @@
3022
3028
  },
3023
3029
  "nodeId": {
3024
3030
  "$ref": "ids.schema.json#/$defs/nodeId",
3025
- "description": "SHOULD the node whose execution caused the write. Omitted only for writes with no node attribution (e.g. host session-end auto-memory)."
3031
+ "description": "SHOULD \u2014 the node whose execution caused the write. Omitted only for writes with no node attribution (e.g. host session-end auto-memory)."
3026
3032
  },
3027
3033
  "agentId": {
3028
3034
  "$ref": "ids.schema.json#/$defs/agentId",
3029
- "description": "MAY the agent identity (AgentRef per RFC 0002) behind the write, when known."
3035
+ "description": "MAY \u2014 the agent identity (AgentRef per RFC 0002) behind the write, when known."
3030
3036
  },
3031
3037
  "tags": {
3032
3038
  "type": "array",
3033
3039
  "items": {
3034
3040
  "type": "string"
3035
3041
  },
3036
- "description": "MAY the entry's non-secret labels. MUST NOT carry secret material (the no-content invariant covers payload bodies)."
3042
+ "description": "MAY \u2014 the entry's non-secret labels. MUST NOT carry secret material (the no-content invariant covers payload bodies)."
3037
3043
  }
3038
3044
  },
3039
3045
  "additionalProperties": false
3040
3046
  },
3041
3047
  "agentMemoryConsolidated": {
3042
3048
  "type": "object",
3043
- "description": "RFC 0068 (`Draft`). Emitted by a host advertising `capabilities.agents.memoryConsolidation.supported: true` after a background consolidation pass over LONG-TERM memory (merge/dedup/supersede/strengthen). Content-free: identifiers + counts only entry content is served by the SR-1-redacted read-side (`MemoryAdapter.get`). On replay the event is re-read from the log, never regenerated. Distinct from RFC 0062 `memory.compacted` (token-budgeted distillation of transactional memory). SR-1 carry-forward (RFC 0004) + CTI-1 apply to the consolidated entries.",
3049
+ "description": "RFC 0068 (`Draft`). Emitted by a host advertising `capabilities.agents.memoryConsolidation.supported: true` after a background consolidation pass over LONG-TERM memory (merge/dedup/supersede/strengthen). Content-free: identifiers + counts only \u2014 entry content is served by the SR-1-redacted read-side (`MemoryAdapter.get`). On replay the event is re-read from the log, never regenerated. Distinct from RFC 0062 `memory.compacted` (token-budgeted distillation of transactional memory). SR-1 carry-forward (RFC 0004) + CTI-1 apply to the consolidated entries.",
3044
3050
  "required": [
3045
3051
  "memoryRef",
3046
3052
  "inputCount",
@@ -3050,7 +3056,7 @@
3050
3056
  "memoryRef": {
3051
3057
  "type": "string",
3052
3058
  "minLength": 1,
3053
- "description": "Opaque MemoryAdapter handle (RFC 0004 §C) the consolidation pass operated over. Bounds the pass to a single memory scope (CTI-1)."
3059
+ "description": "Opaque MemoryAdapter handle (RFC 0004 \u00a7C) the consolidation pass operated over. Bounds the pass to a single memory scope (CTI-1)."
3054
3060
  },
3055
3061
  "inputCount": {
3056
3062
  "type": "integer",
@@ -3068,7 +3074,7 @@
3068
3074
  "type": "string",
3069
3075
  "minLength": 1
3070
3076
  },
3071
- "description": "MAY ids of entries collapsed/superseded by the pass. Hosts MAY omit when inputCount is large; consumers MUST tolerate absence."
3077
+ "description": "MAY \u2014 ids of entries collapsed/superseded by the pass. Hosts MAY omit when inputCount is large; consumers MUST tolerate absence."
3072
3078
  },
3073
3079
  "trigger": {
3074
3080
  "type": "string",
@@ -3077,14 +3083,14 @@
3077
3083
  "scheduled",
3078
3084
  "on-demand"
3079
3085
  ],
3080
- "description": "MAY which initiation path drove this pass (mirrors `agents.memoryConsolidation.schedule`)."
3086
+ "description": "MAY \u2014 which initiation path drove this pass (mirrors `agents.memoryConsolidation.schedule`)."
3081
3087
  }
3082
3088
  },
3083
3089
  "additionalProperties": false
3084
3090
  },
3085
3091
  "commitmentFired": {
3086
3092
  "type": "object",
3087
- "description": "RFC 0068 (`Draft`). Emitted by a host advertising `capabilities.agents.commitments.supported: true` when an inferred standing commitment fires. Content-free: identifiers + condition kind only the intention text lives in SR-1-redacted memory (`MemoryAdapter.get(memoryRef, memoryId)`). The fired arm composes RFC 0052 (time) or RFC 0060 (predicate). On replay the event is re-read from the log, never regenerated (the host MUST NOT re-infer or re-fire a commitment at replay time). CTI-1: the commitment, its memory provenance, and any run it enqueues MUST share the source memory's tenant.",
3093
+ "description": "RFC 0068 (`Draft`). Emitted by a host advertising `capabilities.agents.commitments.supported: true` when an inferred standing commitment fires. Content-free: identifiers + condition kind only \u2014 the intention text lives in SR-1-redacted memory (`MemoryAdapter.get(memoryRef, memoryId)`). The fired arm composes RFC 0052 (time) or RFC 0060 (predicate). On replay the event is re-read from the log, never regenerated (the host MUST NOT re-infer or re-fire a commitment at replay time). CTI-1: the commitment, its memory provenance, and any run it enqueues MUST share the source memory's tenant.",
3088
3094
  "required": [
3089
3095
  "commitmentId",
3090
3096
  "memoryRef",
@@ -3104,7 +3110,7 @@
3104
3110
  "memoryId": {
3105
3111
  "type": "string",
3106
3112
  "minLength": 1,
3107
- "description": "MAY id of the source `MemoryEntry` the commitment was inferred from, when a single entry is attributable. Resolvable via `MemoryAdapter.get`; content is read SR-1-redacted from the read-side."
3113
+ "description": "MAY \u2014 id of the source `MemoryEntry` the commitment was inferred from, when a single entry is attributable. Resolvable via `MemoryAdapter.get`; content is read SR-1-redacted from the read-side."
3108
3114
  },
3109
3115
  "condition": {
3110
3116
  "type": "string",
@@ -3115,16 +3121,15 @@
3115
3121
  "description": "Which fire-condition kind triggered. `time` composes RFC 0052; `predicate` composes RFC 0060."
3116
3122
  },
3117
3123
  "enqueuedRunId": {
3118
- "type": "string",
3119
- "minLength": 1,
3120
- "description": "MAY — id of the run the fired commitment enqueued, when the host initiates one. Absent when the commitment fires as a notification without a run."
3124
+ "$ref": "ids.schema.json#/$defs/runId",
3125
+ "description": "MAY \u2014 id of the run the fired commitment enqueued, when the host initiates one. Absent when the commitment fires as a notification without a run."
3121
3126
  }
3122
3127
  },
3123
3128
  "additionalProperties": false
3124
3129
  },
3125
3130
  "agentInvocationStarted": {
3126
3131
  "type": "object",
3127
- "description": "RFC 0077. Emitted by a host advertising `capabilities.agents.liveRuntime.supported: true` as the FIRST agent-scoped event of a live manifest invocation, bracketing the existing `agent.*` family with `agent.invocation.completed`. Content-free: identifiers + selection metadata only prompt/task content is served by the run's normal projection, never on this event. A recorded-fact event per `replay.md` §\"Recorded-fact events\": on replay it is re-emitted from the log and the host MUST NOT regenerate its `invocationId` (or any identifier). Distinct from the deterministic RFC 0070 sample floor.",
3132
+ "description": "RFC 0077. Emitted by a host advertising `capabilities.agents.liveRuntime.supported: true` as the FIRST agent-scoped event of a live manifest invocation, bracketing the existing `agent.*` family with `agent.invocation.completed`. Content-free: identifiers + selection metadata only \u2014 prompt/task content is served by the run's normal projection, never on this event. A recorded-fact event per `replay.md` \u00a7\"Recorded-fact events\": on replay it is re-emitted from the log and the host MUST NOT regenerate its `invocationId` (or any identifier). Distinct from the deterministic RFC 0070 sample floor.",
3128
3133
  "required": [
3129
3134
  "invocationId",
3130
3135
  "agentId",
@@ -3134,7 +3139,7 @@
3134
3139
  "invocationId": {
3135
3140
  "type": "string",
3136
3141
  "minLength": 1,
3137
- "description": "Host-defined id correlating this agent invocation within its run, UNIQUE-WITHIN-RUN (not a mandated global id-space). Distinct from `runId` one run MAY dispatch several invocations (multiple agent nodes, or a handoff chain) but a host MAY derive it from an existing per-node-execution receipt id (e.g. `runId:nodeId:seq`) or mint a UUID; a single-invocation run MAY reuse `runId`. Recorded-fact: re-read from the log on replay, never regenerated (`replay.md` §\"Recorded-fact events\"). Correlates to the matching `agent.invocation.completed`."
3142
+ "description": "Host-defined id correlating this agent invocation within its run, UNIQUE-WITHIN-RUN (not a mandated global id-space). Distinct from `runId` \u2014 one run MAY dispatch several invocations (multiple agent nodes, or a handoff chain) \u2014 but a host MAY derive it from an existing per-node-execution receipt id (e.g. `runId:nodeId:seq`) or mint a UUID; a single-invocation run MAY reuse `runId`. Recorded-fact: re-read from the log on replay, never regenerated (`replay.md` \u00a7\"Recorded-fact events\"). Correlates to the matching `agent.invocation.completed`."
3138
3143
  },
3139
3144
  "agentId": {
3140
3145
  "$ref": "ids.schema.json#/$defs/agentId",
@@ -3151,39 +3156,39 @@
3151
3156
  },
3152
3157
  "modelClass": {
3153
3158
  "type": "string",
3154
- "description": "MAY the manifest's abstract `modelClass`. Always populatable at start."
3159
+ "description": "MAY \u2014 the manifest's abstract `modelClass`. Always populatable at start."
3155
3160
  },
3156
3161
  "resolvedModel": {
3157
3162
  "type": "string",
3158
- "description": "MAY the concrete model the host selected. OPTIONAL: modelClass→concrete resolution MAY happen downstream (with capability-gated fallback substitution), so a dispatch-time start event genuinely may not know it; a host MAY also omit for deployment-privacy."
3163
+ "description": "MAY \u2014 the concrete model the host selected. OPTIONAL: modelClass\u2192concrete resolution MAY happen downstream (with capability-gated fallback substitution), so a dispatch-time start event genuinely may not know it; a host MAY also omit for deployment-privacy."
3159
3164
  },
3160
3165
  "resolvedProvider": {
3161
3166
  "type": "string",
3162
- "description": "MAY the concrete provider the host routed to (aligns with `capabilities.aiProviders.supported` / RFC 0067 `authModes`). OPTIONAL, same rationale as `resolvedModel`."
3167
+ "description": "MAY \u2014 the concrete provider the host routed to (aligns with `capabilities.aiProviders.supported` / RFC 0067 `authModes`). OPTIONAL, same rationale as `resolvedModel`."
3163
3168
  },
3164
3169
  "resolvedAgentVersion": {
3165
3170
  "type": "string",
3166
- "description": "MAY RFC 0082 §B. When this invocation's `AgentRef` bound a `channel` (rather than an exact `version`), the concrete agent-definition version the host pinned per-(run, agentId, channel) at first resolution. A RECORDED FACT: re-read from the log on replay and NEVER re-resolved against a moved channel (the whole event is recorded-fact). Absent when the ref used an exact `version` or host-default resolution."
3171
+ "description": "MAY \u2014 RFC 0082 \u00a7B. When this invocation's `AgentRef` bound a `channel` (rather than an exact `version`), the concrete agent-definition version the host pinned per-(run, agentId, channel) at first resolution. A RECORDED FACT: re-read from the log on replay and NEVER re-resolved against a moved channel (the whole event is recorded-fact). Absent when the ref used an exact `version` or host-default resolution."
3167
3172
  },
3168
3173
  "resolvedChannel": {
3169
3174
  "type": "string",
3170
- "description": "MAY RFC 0082 §B. The named `channel` the `AgentRef` bound (mirrors `AgentRef.channel`), for which `resolvedAgentVersion` is the pinned resolution. Content-free label; present only when the ref bound a channel."
3175
+ "description": "MAY \u2014 RFC 0082 \u00a7B. The named `channel` the `AgentRef` bound (mirrors `AgentRef.channel`), for which `resolvedAgentVersion` is the pinned resolution. Content-free label; present only when the ref bound a channel."
3171
3176
  },
3172
3177
  "toolSurfaceCount": {
3173
3178
  "type": "integer",
3174
3179
  "minimum": 0,
3175
- "description": "MAY number of tools in the constructed surface after `toolAllowlist` filtering. Content-free count, not the tool ids."
3180
+ "description": "MAY \u2014 number of tools in the constructed surface after `toolAllowlist` filtering. Content-free count, not the tool ids."
3176
3181
  },
3177
3182
  "memoryBound": {
3178
3183
  "type": "boolean",
3179
- "description": "MAY whether a long-term memory backend was bound for the invocation."
3184
+ "description": "MAY \u2014 whether a long-term memory backend was bound for the invocation."
3180
3185
  }
3181
3186
  },
3182
3187
  "additionalProperties": false
3183
3188
  },
3184
3189
  "agentInvocationCompleted": {
3185
3190
  "type": "object",
3186
- "description": "RFC 0077. Emitted by a host advertising `capabilities.agents.liveRuntime.supported: true` as the LAST agent-scoped event of a live manifest invocation (after the terminal `agent.decided`). Content-free: identifiers + outcome metadata only the result body is served by the run's normal projection. A recorded-fact event per `replay.md` §\"Recorded-fact events\": re-read from the log on replay, never regenerated.",
3191
+ "description": "RFC 0077. Emitted by a host advertising `capabilities.agents.liveRuntime.supported: true` as the LAST agent-scoped event of a live manifest invocation (after the terminal `agent.decided`). Content-free: identifiers + outcome metadata only \u2014 the result body is served by the run's normal projection. A recorded-fact event per `replay.md` \u00a7\"Recorded-fact events\": re-read from the log on replay, never regenerated.",
3187
3192
  "required": [
3188
3193
  "invocationId",
3189
3194
  "agentId",
@@ -3208,28 +3213,27 @@
3208
3213
  "refused",
3209
3214
  "failed"
3210
3215
  ],
3211
- "description": "Terminal disposition. `completed`: produced a (schema-valid, if enforced) terminal result. `handed-off`: control passed to another agent (`agent.handoff`). `escalated`: confidence escalation fired (RFC 0002 §F). `refused`: the model refused (RFC 0032 refusal envelope) never a silent substitution. `failed`: an error terminated the invocation."
3216
+ "description": "Terminal disposition. `completed`: produced a (schema-valid, if enforced) terminal result. `handed-off`: control passed to another agent (`agent.handoff`). `escalated`: confidence escalation fired (RFC 0002 \u00a7F). `refused`: the model refused (RFC 0032 refusal envelope) \u2014 never a silent substitution. `failed`: an error terminated the invocation."
3212
3217
  },
3213
3218
  "schemaValidated": {
3214
3219
  "type": "boolean",
3215
- "description": "MAY whether the terminal result was validated against `handoff.returnSchemaRef` (true only when `liveRuntime.structuredOutput` is advertised and a `returnSchemaRef` exists)."
3220
+ "description": "MAY \u2014 whether the terminal result was validated against `handoff.returnSchemaRef` (true only when `liveRuntime.structuredOutput` is advertised and a `returnSchemaRef` exists)."
3216
3221
  },
3217
3222
  "confidence": {
3218
3223
  "type": "number",
3219
3224
  "minimum": 0,
3220
3225
  "maximum": 1,
3221
- "description": "MAY the terminal `agent.decided` confidence, mirrored for convenience. Content-free scalar."
3226
+ "description": "MAY \u2014 the terminal `agent.decided` confidence, mirrored for convenience. Content-free scalar."
3222
3227
  },
3223
3228
  "enqueuedRunId": {
3224
- "type": "string",
3225
- "minLength": 1,
3226
- "description": "MAY — id of a follow-on run the invocation enqueued (e.g. a sub-run), when applicable."
3229
+ "$ref": "ids.schema.json#/$defs/runId",
3230
+ "description": "MAY \u2014 id of a follow-on run the invocation enqueued (e.g. a sub-run), when applicable."
3227
3231
  }
3228
3232
  },
3229
3233
  "additionalProperties": false
3230
3234
  },
3231
3235
  "workspaceUpdated": {
3232
- "description": "RFC 0059. Emitted by a host advertising `capabilities.workspace.supported: true` on each successful `PUT`/`DELETE` of a workspace file, attributing the change to the file `path` + resulting `version`. Content-free: carries the path + version only the file body is served by the read-side (`GET /v1/host/workspace/files/{path}`), already SR-1-redacted (RFC 0059 §E WSR-1). On replay the event is re-read from the log, never regenerated. MUST NOT be emitted unless `capabilities.workspace.supported: true`. The proposed SECURITY invariant `workspace-cross-tenant-isolation` (WCT-1) applies to the read-side that resolves these paths.",
3236
+ "description": "RFC 0059. Emitted by a host advertising `capabilities.workspace.supported: true` on each successful `PUT`/`DELETE` of a workspace file, attributing the change to the file `path` + resulting `version`. Content-free: carries the path + version only \u2014 the file body is served by the read-side (`GET /v1/host/workspace/files/{path}`), already SR-1-redacted (RFC 0059 \u00a7E WSR-1). On replay the event is re-read from the log, never regenerated. MUST NOT be emitted unless `capabilities.workspace.supported: true`. The proposed SECURITY invariant `workspace-cross-tenant-isolation` (WCT-1) applies to the read-side that resolves these paths.",
3233
3237
  "type": "object",
3234
3238
  "additionalProperties": false,
3235
3239
  "required": [
@@ -3251,7 +3255,7 @@
3251
3255
  },
3252
3256
  "evalStarted": {
3253
3257
  "type": "object",
3254
- "description": "RFC 0081 §C. Emitted ONCE at the start of an eval run (a `mode: \"eval\"` run, RFC 0081 §B) by a host advertising `capabilities.agents.evalSuite.supported: true`. Content-free: suite provenance + counts only. A recorded-fact event per `replay.md` §\"Recorded-fact events\".",
3258
+ "description": "RFC 0081 \u00a7C. Emitted ONCE at the start of an eval run (a `mode: \"eval\"` run, RFC 0081 \u00a7B) by a host advertising `capabilities.agents.evalSuite.supported: true`. Content-free: suite provenance + counts only. A recorded-fact event per `replay.md` \u00a7\"Recorded-fact events\".",
3255
3259
  "required": [
3256
3260
  "suiteId",
3257
3261
  "suiteVersion",
@@ -3287,19 +3291,18 @@
3287
3291
  "live-shadow"
3288
3292
  ]
3289
3293
  },
3290
- "description": "The eval modes this run exercises (RFC 0081 §D)."
3294
+ "description": "The eval modes this run exercises (RFC 0081 \u00a7D)."
3291
3295
  },
3292
3296
  "baselineRunId": {
3293
- "type": "string",
3294
- "minLength": 1,
3295
- "description": "MAY — for `regression` mode, the prior eval run this run is scored against."
3297
+ "$ref": "ids.schema.json#/$defs/runId",
3298
+ "description": "MAY \u2014 for `regression` mode, the prior eval run this run is scored against."
3296
3299
  }
3297
3300
  },
3298
3301
  "additionalProperties": false
3299
3302
  },
3300
3303
  "evalScored": {
3301
3304
  "type": "object",
3302
- "description": "RFC 0081 §C. Emitted ONCE PER TASK, after that task's terminal `agent.decided`, so a streaming consumer sees results land incrementally. Content-free: the task id + scalars + counts ONLY NEVER the task output, rubric prose, or model completion (SECURITY invariant `eval-summary-no-content-leak`). A recorded-fact event.",
3305
+ "description": "RFC 0081 \u00a7C. Emitted ONCE PER TASK, after that task's terminal `agent.decided`, so a streaming consumer sees results land incrementally. Content-free: the task id + scalars + counts ONLY \u2014 NEVER the task output, rubric prose, or model completion (SECURITY invariant `eval-summary-no-content-leak`). A recorded-fact event.",
3303
3306
  "required": [
3304
3307
  "taskId",
3305
3308
  "score",
@@ -3315,7 +3318,7 @@
3315
3318
  "type": "number",
3316
3319
  "minimum": 0,
3317
3320
  "maximum": 1,
3318
- "description": "Task score (0.0–1.0)."
3321
+ "description": "Task score (0.0\u20131.0)."
3319
3322
  },
3320
3323
  "passed": {
3321
3324
  "type": "boolean",
@@ -3324,28 +3327,28 @@
3324
3327
  "costUsd": {
3325
3328
  "type": "number",
3326
3329
  "minimum": 0,
3327
- "description": "MAY task cost (scalar; summed from RFC 0026 `provider.usage`). NEVER a pricing breakdown."
3330
+ "description": "MAY \u2014 task cost (scalar; summed from RFC 0026 `provider.usage`). NEVER a pricing breakdown."
3328
3331
  },
3329
3332
  "latencyMs": {
3330
3333
  "type": "integer",
3331
3334
  "minimum": 0,
3332
- "description": "MAY task wall-clock latency."
3335
+ "description": "MAY \u2014 task wall-clock latency."
3333
3336
  },
3334
3337
  "schemaValid": {
3335
3338
  "type": "boolean",
3336
- "description": "MAY whether the output validated against `handoff.returnSchemaRef`."
3339
+ "description": "MAY \u2014 whether the output validated against `handoff.returnSchemaRef`."
3337
3340
  },
3338
3341
  "safetyFindingCount": {
3339
3342
  "type": "integer",
3340
3343
  "minimum": 0,
3341
- "description": "MAY count of safety findings for the task (the redaction-safe descriptors live on `EvalSummary`; the event carries the count only)."
3344
+ "description": "MAY \u2014 count of safety findings for the task (the redaction-safe descriptors live on `EvalSummary`; the event carries the count only)."
3342
3345
  }
3343
3346
  },
3344
3347
  "additionalProperties": false
3345
3348
  },
3346
3349
  "evalCompleted": {
3347
3350
  "type": "object",
3348
- "description": "RFC 0081 §C. Emitted ONCE, after all tasks and before `run.completed`. Content-free: aggregate scalars only. A recorded-fact event. The full scorecard is the run's output (`eval-summary.schema.json`), served by `GET /v1/runs/{runId}/eval-summary`.",
3351
+ "description": "RFC 0081 \u00a7C. Emitted ONCE, after all tasks and before `run.completed`. Content-free: aggregate scalars only. A recorded-fact event. The full scorecard is the run's output (`eval-summary.schema.json`), served by `GET /v1/runs/{runId}/eval-summary`.",
3349
3352
  "required": [
3350
3353
  "aggregateScore",
3351
3354
  "passed",
@@ -3357,11 +3360,11 @@
3357
3360
  "type": "number",
3358
3361
  "minimum": 0,
3359
3362
  "maximum": 1,
3360
- "description": "The suite-level score (0.0–1.0)."
3363
+ "description": "The suite-level score (0.0\u20131.0)."
3361
3364
  },
3362
3365
  "passed": {
3363
3366
  "type": "boolean",
3364
- "description": "Whether the run cleared the suite thresholds the flag an RFC 0082 deployment gate MAY require."
3367
+ "description": "Whether the run cleared the suite thresholds \u2014 the flag an RFC 0082 deployment gate MAY require."
3365
3368
  },
3366
3369
  "taskCount": {
3367
3370
  "type": "integer",
@@ -3377,14 +3380,14 @@
3377
3380
  "type": "number",
3378
3381
  "minimum": -1,
3379
3382
  "maximum": 1,
3380
- "description": "MAY for `regression` mode, `aggregateScore` minus the baseline's (negative regression)."
3383
+ "description": "MAY \u2014 for `regression` mode, `aggregateScore` minus the baseline's (negative \u21d2 regression)."
3381
3384
  }
3382
3385
  },
3383
3386
  "additionalProperties": false
3384
3387
  },
3385
3388
  "toolSessionOpened": {
3386
3389
  "type": "object",
3387
- "description": "RFC 0078 §D. Emitted when the host opens a multi-step tool session, bracketing one or more RFC 0064 `agent.toolCalled`/`agent.toolReturned` call events. Content-free: identifiers only never tool arguments, results, or credential material (SR-1). Emitted only when `capabilities.toolCatalog.sessionLifecycle: true`.",
3390
+ "description": "RFC 0078 \u00a7D. Emitted when the host opens a multi-step tool session, bracketing one or more RFC 0064 `agent.toolCalled`/`agent.toolReturned` call events. Content-free: identifiers only \u2014 never tool arguments, results, or credential material (SR-1). Emitted only when `capabilities.toolCatalog.sessionLifecycle: true`.",
3388
3391
  "required": [
3389
3392
  "sessionId",
3390
3393
  "toolId"
@@ -3405,7 +3408,7 @@
3405
3408
  },
3406
3409
  "toolSessionClosed": {
3407
3410
  "type": "object",
3408
- "description": "RFC 0078 §D. Emitted when the host closes a multi-step tool session opened by `tool.session.opened`. Content-free: identifiers + a closed-enum outcome only never tool arguments, results, or credential material (SR-1).",
3411
+ "description": "RFC 0078 \u00a7D. Emitted when the host closes a multi-step tool session opened by `tool.session.opened`. Content-free: identifiers + a closed-enum outcome only \u2014 never tool arguments, results, or credential material (SR-1).",
3409
3412
  "required": [
3410
3413
  "sessionId",
3411
3414
  "toolId",
@@ -3429,14 +3432,14 @@
3429
3432
  "failed",
3430
3433
  "cancelled"
3431
3434
  ],
3432
- "description": "Terminal disposition of the session. Content-free no failure detail/result on the payload."
3435
+ "description": "Terminal disposition of the session. Content-free \u2014 no failure detail/result on the payload."
3433
3436
  }
3434
3437
  },
3435
3438
  "additionalProperties": false
3436
3439
  },
3437
3440
  "egressDecided": {
3438
3441
  "type": "object",
3439
- "description": "RFC 0079 §B. Emitted when a host evaluates a credentialed egress (via `ctx.http.safeFetch` / a tool) against credential provenance + the SSRF guard. Content-free: identifiers + decision only no credential value, no request/response body (SR-1). On replay re-read from the log, never regenerated (the decision is a recorded fact). Emitted only when `capabilities.httpClient.egressPolicy.supported: true`.",
3442
+ "description": "RFC 0079 \u00a7B. Emitted when a host evaluates a credentialed egress (via `ctx.http.safeFetch` / a tool) against credential provenance + the SSRF guard. Content-free: identifiers + decision only \u2014 no credential value, no request/response body (SR-1). On replay re-read from the log, never regenerated (the decision is a recorded fact). Emitted only when `capabilities.httpClient.egressPolicy.supported: true`.",
3440
3443
  "required": [
3441
3444
  "decision",
3442
3445
  "destination"
@@ -3450,17 +3453,17 @@
3450
3453
  "downgraded",
3451
3454
  "approval-required"
3452
3455
  ],
3453
- "description": "`allowed`: egress proceeds with the credential; `denied`: blocked (out-of-audience / expired / SSRF / unevaluable provenance fail-closed); `downgraded`: proceeds WITHOUT the credential (anonymous egress, when host policy permits); `approval-required`: suspended pending an RFC 0051 approval interrupt."
3456
+ "description": "`allowed`: egress proceeds with the credential; `denied`: blocked (out-of-audience / expired / SSRF / unevaluable provenance \u2014 fail-closed); `downgraded`: proceeds WITHOUT the credential (anonymous egress, when host policy permits); `approval-required`: suspended pending an RFC 0051 approval interrupt."
3454
3457
  },
3455
3458
  "destination": {
3456
3459
  "type": "string",
3457
3460
  "minLength": 1,
3458
- "description": "The egress destination **host/authority ONLY** (`api.stripe.com`) NOT a path, query, or full URL (SR-1: a path/query can carry secrets; the host MUST strip them for this canonical content-free event). A host whose internal audit retains the path keeps that on its vendor `x-host-*` variant, never here."
3461
+ "description": "The egress destination **host/authority ONLY** (`api.stripe.com`) \u2014 NOT a path, query, or full URL (SR-1: a path/query can carry secrets; the host MUST strip them for this canonical content-free event). A host whose internal audit retains the path keeps that on its vendor `x-host-*` variant, never here."
3459
3462
  },
3460
3463
  "credentialId": {
3461
3464
  "type": "string",
3462
3465
  "minLength": 1,
3463
- "description": "MAY the provenance `credentialId` considered (absent for an anonymous / denied-pre-credential egress)."
3466
+ "description": "MAY \u2014 the provenance `credentialId` considered (absent for an anonymous / denied-pre-credential egress)."
3464
3467
  },
3465
3468
  "reason": {
3466
3469
  "type": "string",
@@ -3473,19 +3476,19 @@
3473
3476
  "scope-denied",
3474
3477
  "policy-denied"
3475
3478
  ],
3476
- "description": "MAY a machine-stable reason code (a CLOSED enum a free-form reason is a leak vector that would let a host spill the blocked URL/host/header into it, defeating `egress-decision-no-secret-leak`). The load-bearing field is `decision`."
3479
+ "description": "MAY \u2014 a machine-stable reason code (a CLOSED enum \u2014 a free-form reason is a leak vector that would let a host spill the blocked URL/host/header into it, defeating `egress-decision-no-secret-leak`). The load-bearing field is `decision`."
3477
3480
  },
3478
3481
  "auditCorrelationId": {
3479
3482
  "type": "string",
3480
3483
  "minLength": 1,
3481
- "description": "MAY correlates to the provenance descriptor + host audit log."
3484
+ "description": "MAY \u2014 correlates to the provenance descriptor + host audit log."
3482
3485
  }
3483
3486
  },
3484
3487
  "additionalProperties": false
3485
3488
  },
3486
3489
  "triggerSubscriptionStateChanged": {
3487
3490
  "type": "object",
3488
- "description": "RFC 0083 §C. Emitted when a trigger subscription changes state (the §B four-state machine). Content-free: identifiers + states only no inbound payload, headers, or credential material (SR-1). Emitted only when `capabilities.triggerBridge.supported: true`.",
3491
+ "description": "RFC 0083 \u00a7C. Emitted when a trigger subscription changes state (the \u00a7B four-state machine). Content-free: identifiers + states only \u2014 no inbound payload, headers, or credential material (SR-1). Emitted only when `capabilities.triggerBridge.supported: true`.",
3489
3492
  "required": [
3490
3493
  "subscriptionId",
3491
3494
  "source",
@@ -3540,14 +3543,14 @@
3540
3543
  "source-removed",
3541
3544
  "provenance-unevaluable"
3542
3545
  ],
3543
- "description": "MAY a machine-stable reason code (a CLOSED enum a free-form reason is a leak vector that would let a host spill an inbound URL/host/header into it). The load-bearing field is `toState`."
3546
+ "description": "MAY \u2014 a machine-stable reason code (a CLOSED enum \u2014 a free-form reason is a leak vector that would let a host spill an inbound URL/host/header into it). The load-bearing field is `toState`."
3544
3547
  }
3545
3548
  },
3546
3549
  "additionalProperties": false
3547
3550
  },
3548
3551
  "triggerDeliveryAttempted": {
3549
3552
  "type": "object",
3550
- "description": "RFC 0083 §C. Emitted on each inbound-delivery attempt against an active subscription. Content-free: the subscription id, the dedup key, the attempt counter, the outcome, and the resulting runId only NEVER the inbound body, headers, or credential material (SR-1).",
3553
+ "description": "RFC 0083 \u00a7C. Emitted on each inbound-delivery attempt against an active subscription. Content-free: the subscription id, the dedup key, the attempt counter, the outcome, and the resulting runId only \u2014 NEVER the inbound body, headers, or credential material (SR-1).",
3551
3554
  "required": [
3552
3555
  "subscriptionId",
3553
3556
  "dedupKey",
@@ -3562,7 +3565,7 @@
3562
3565
  "dedupKey": {
3563
3566
  "type": "string",
3564
3567
  "minLength": 1,
3565
- "description": "The de-duplication key (§C-1). MUST be a **host-opaque** stable key (e.g. `hash(subscriptionId + inbound-event-id)`); it MUST NOT embed inbound body / path / header content in cleartext (SR-1 a key like `POST /webhook/orders/12345?token=…` would leak). A repeat within retention is a no-op returning the prior runId."
3568
+ "description": "The de-duplication key (\u00a7C-1). MUST be a **host-opaque** stable key (e.g. `hash(subscriptionId + inbound-event-id)`); it MUST NOT embed inbound body / path / header content in cleartext (SR-1 \u2014 a key like `POST /webhook/orders/12345?token=\u2026` would leak). A repeat within retention is a no-op returning the prior runId."
3566
3569
  },
3567
3570
  "attempt": {
3568
3571
  "type": "integer",
@@ -3580,14 +3583,14 @@
3580
3583
  },
3581
3584
  "runId": {
3582
3585
  "$ref": "ids.schema.json#/$defs/runId",
3583
- "description": "MAY the run started by a `delivered` outcome (the run's `run.started` carries this delivery's id as `causationId`, RFC 0040). Absent for `retrying` / `dead-lettered`."
3586
+ "description": "MAY \u2014 the run started by a `delivered` outcome (the run's `run.started` carries this delivery's id as `causationId`, RFC 0040). Absent for `retrying` / `dead-lettered`."
3584
3587
  }
3585
3588
  },
3586
3589
  "additionalProperties": false
3587
3590
  },
3588
3591
  "budgetReserved": {
3589
3592
  "type": "object",
3590
- "description": "RFC 0084 §C. Emitted once at run start with the resolved effective budget (`min` across run/workflow/agent/project scopes, clamped to the host ceiling). A recorded fact replay re-reads it, never re-resolves (§B). Content-free: dimension ceilings + scope only, no pricing breakdown (SR-1, `budget-no-pricing-leak`).",
3593
+ "description": "RFC 0084 \u00a7C. Emitted once at run start with the resolved effective budget (`min` across run/workflow/agent/project scopes, clamped to the host ceiling). A recorded fact \u2014 replay re-reads it, never re-resolves (\u00a7B). Content-free: dimension ceilings + scope only, no pricing breakdown (SR-1, `budget-no-pricing-leak`).",
3591
3594
  "required": [
3592
3595
  "effectiveBudget",
3593
3596
  "scope"
@@ -3624,14 +3627,14 @@
3624
3627
  "agent",
3625
3628
  "project"
3626
3629
  ],
3627
- "description": "The binding scope the effective budget resolved from (§B)."
3630
+ "description": "The binding scope the effective budget resolved from (\u00a7B)."
3628
3631
  }
3629
3632
  },
3630
3633
  "additionalProperties": false
3631
3634
  },
3632
3635
  "budgetConsumed": {
3633
3636
  "type": "object",
3634
- "description": "RFC 0084 §C. A running projection of spend, derived from the existing events (`provider.usage` tokens/cost, `agent.toolCalled`, `node.retried`) NOT a new measurement (no double-counting). The host MAY coalesce. Content-free: dimension name + integers only, no pricing breakdown / rate card (SR-1).",
3637
+ "description": "RFC 0084 \u00a7C. A running projection of spend, derived from the existing events (`provider.usage` tokens/cost, `agent.toolCalled`, `node.retried`) \u2014 NOT a new measurement (no double-counting). The host MAY coalesce. Content-free: dimension name + integers only, no pricing breakdown / rate card (SR-1).",
3635
3638
  "required": [
3636
3639
  "dimension",
3637
3640
  "consumed",
@@ -3660,14 +3663,14 @@
3660
3663
  },
3661
3664
  "remaining": {
3662
3665
  "type": "number",
3663
- "description": "MAY `limit - consumed`."
3666
+ "description": "MAY \u2014 `limit - consumed`."
3664
3667
  }
3665
3668
  },
3666
3669
  "additionalProperties": false
3667
3670
  },
3668
3671
  "budgetThresholdCrossed": {
3669
3672
  "type": "object",
3670
- "description": "RFC 0084 §C. Emitted once per dimension when consumption crosses `thresholdPercent`. Content-free.",
3673
+ "description": "RFC 0084 \u00a7C. Emitted once per dimension when consumption crosses `thresholdPercent`. Content-free.",
3671
3674
  "required": [
3672
3675
  "dimension",
3673
3676
  "consumed",
@@ -3703,7 +3706,7 @@
3703
3706
  },
3704
3707
  "budgetExhausted": {
3705
3708
  "type": "object",
3706
- "description": "RFC 0084 §C. Emitted when a dimension hits its limit. For a hard dimension this is followed by `cap.breached{kind:\"budget-*\"}` `run.failed{budget_exhausted}` (or, with `onExhaustion:\"interrupt\"`, an approval interrupt). Content-free.",
3709
+ "description": "RFC 0084 \u00a7C. Emitted when a dimension hits its limit. For a hard dimension this is followed by `cap.breached{kind:\"budget-*\"}` \u2192 `run.failed{budget_exhausted}` (or, with `onExhaustion:\"interrupt\"`, an approval interrupt). Content-free.",
3707
3710
  "required": [
3708
3711
  "dimension",
3709
3712
  "consumed",
@@ -3732,7 +3735,7 @@
3732
3735
  },
3733
3736
  "deploymentPromoted": {
3734
3737
  "type": "object",
3735
- "description": "RFC 0082 §D. Emitted on the deployment-management run when a version is promoted into a new lifecycle state (the §E contract: authorized via RFC 0049 `deploy:*`, gated via RFC 0051 `approvalGate`, eval-verified via RFC 0081 when `requiredEval` is configured). Content-free: ids / state / scalars / content-free references only NEVER a manifest body, prompt, or credential (SECURITY invariant `deployment-event-no-content-leak`; `additionalProperties:false` enforces it). A recorded-fact event per `replay.md` §\"Recorded-fact events\". Audit-logged with the acting principal (`auth.md`).",
3738
+ "description": "RFC 0082 \u00a7D. Emitted on the deployment-management run when a version is promoted into a new lifecycle state (the \u00a7E contract: authorized via RFC 0049 `deploy:*`, gated via RFC 0051 `approvalGate`, eval-verified via RFC 0081 when `requiredEval` is configured). Content-free: ids / state / scalars / content-free references only \u2014 NEVER a manifest body, prompt, or credential (SECURITY invariant `deployment-event-no-content-leak`; `additionalProperties:false` enforces it). A recorded-fact event per `replay.md` \u00a7\"Recorded-fact events\". Audit-logged with the acting principal (`auth.md`).",
3736
3739
  "additionalProperties": false,
3737
3740
  "required": [
3738
3741
  "agentId",
@@ -3747,7 +3750,7 @@
3747
3750
  "fromVersion": {
3748
3751
  "type": "string",
3749
3752
  "minLength": 1,
3750
- "description": "MAY the version previously occupying the target channel/state (absent on a first promotion)."
3753
+ "description": "MAY \u2014 the version previously occupying the target channel/state (absent on a first promotion)."
3751
3754
  },
3752
3755
  "toVersion": {
3753
3756
  "type": "string",
@@ -3770,29 +3773,28 @@
3770
3773
  "channel": {
3771
3774
  "type": "string",
3772
3775
  "minLength": 1,
3773
- "description": "MAY the named channel this promotion targets (when promoting to a channel)."
3776
+ "description": "MAY \u2014 the named channel this promotion targets (when promoting to a channel)."
3774
3777
  },
3775
3778
  "canaryPercent": {
3776
3779
  "type": "integer",
3777
3780
  "minimum": 0,
3778
3781
  "maximum": 100,
3779
- "description": "MAY the canary traffic share assigned (when promoting `active` at < 100)."
3782
+ "description": "MAY \u2014 the canary traffic share assigned (when promoting `active` at < 100)."
3780
3783
  },
3781
3784
  "evalRunId": {
3782
- "type": "string",
3783
- "minLength": 1,
3784
- "description": "MAY — the RFC 0081 eval run whose `EvalSummary.passed` gated this promotion (the §E evidence)."
3785
+ "$ref": "ids.schema.json#/$defs/runId",
3786
+ "description": "MAY \u2014 the RFC 0081 eval run whose `EvalSummary.passed` gated this promotion (the \u00a7E evidence)."
3785
3787
  },
3786
3788
  "approvalGateId": {
3787
3789
  "type": "string",
3788
3790
  "minLength": 1,
3789
- "description": "MAY the RFC 0051 approvalGate that authorized this promotion."
3791
+ "description": "MAY \u2014 the RFC 0051 approvalGate that authorized this promotion."
3790
3792
  }
3791
3793
  }
3792
3794
  },
3793
3795
  "deploymentRolledBack": {
3794
3796
  "type": "object",
3795
- "description": "RFC 0082 §D. Emitted when an `active` version is rolled back and a prior version restored to `active`. Content-free (`deployment-event-no-content-leak`). Recorded-fact; audit-logged.",
3797
+ "description": "RFC 0082 \u00a7D. Emitted when an `active` version is rolled back and a prior version restored to `active`. Content-free (`deployment-event-no-content-leak`). Recorded-fact; audit-logged.",
3796
3798
  "additionalProperties": false,
3797
3799
  "required": [
3798
3800
  "agentId",
@@ -3823,13 +3825,13 @@
3823
3825
  "reason": {
3824
3826
  "type": "string",
3825
3827
  "minLength": 1,
3826
- "description": "MAY a short redaction-safe rollback reason label (NOT free-text content; same posture as `run.dead_lettered.reason`)."
3828
+ "description": "MAY \u2014 a short redaction-safe rollback reason label (NOT free-text content; same posture as `run.dead_lettered.reason`)."
3827
3829
  }
3828
3830
  }
3829
3831
  },
3830
3832
  "deploymentCanaryAdjusted": {
3831
3833
  "type": "object",
3832
- "description": "RFC 0082 §D. Emitted when an `active` version's canary traffic share changes. Content-free (`deployment-event-no-content-leak`). Recorded-fact; audit-logged.",
3834
+ "description": "RFC 0082 \u00a7D. Emitted when an `active` version's canary traffic share changes. Content-free (`deployment-event-no-content-leak`). Recorded-fact; audit-logged.",
3833
3835
  "additionalProperties": false,
3834
3836
  "required": [
3835
3837
  "agentId",
@@ -3863,7 +3865,7 @@
3863
3865
  },
3864
3866
  "deploymentStateChanged": {
3865
3867
  "type": "object",
3866
- "description": "RFC 0082 §D. Emitted on any non-promotion lifecycle transition (pause / resume / deprecate). Content-free (`deployment-event-no-content-leak`). Recorded-fact; audit-logged.",
3868
+ "description": "RFC 0082 \u00a7D. Emitted on any non-promotion lifecycle transition (pause / resume / deprecate). Content-free (`deployment-event-no-content-leak`). Recorded-fact; audit-logged.",
3867
3869
  "additionalProperties": false,
3868
3870
  "required": [
3869
3871
  "agentId",
@@ -3911,7 +3913,7 @@
3911
3913
  },
3912
3914
  "rosterRunInitiated": {
3913
3915
  "type": "object",
3914
- "description": "RFC 0086 §C. Emitted once, immediately after `run.started` and before any agent invocation, when a trigger (RFC 0052 schedule / RFC 0083 durable work item) fires a workflow in a roster member's portfolio attributing the run to the standing agent. Content-free (`roster-attribution-no-content`): ids + persona + trigger source ONLY never the work-item body, prompt, or credential material (SR-1). A recorded-fact event (replay.md §'Recorded-fact events'): re-emitted from the log on replay, identifiers never regenerated, so the run stays attributed to the same member even if the entry was since renamed or deleted.",
3916
+ "description": "RFC 0086 \u00a7C. Emitted once, immediately after `run.started` and before any agent invocation, when a trigger (RFC 0052 schedule / RFC 0083 durable work item) fires a workflow in a roster member's portfolio \u2014 attributing the run to the standing agent. Content-free (`roster-attribution-no-content`): ids + persona + trigger source ONLY \u2014 never the work-item body, prompt, or credential material (SR-1). A recorded-fact event (replay.md \u00a7'Recorded-fact events'): re-emitted from the log on replay, identifiers never regenerated, so the run stays attributed to the same member even if the entry was since renamed or deleted.",
3915
3917
  "additionalProperties": false,
3916
3918
  "required": [
3917
3919
  "rosterId",
@@ -3945,16 +3947,15 @@
3945
3947
  "description": "What fired the run: an RFC 0083 source (`schedule`/`webhook`/`queue`/`email`/`form`) or a host-extension source name (e.g. a vendor Kanban bridge)."
3946
3948
  },
3947
3949
  "triggerSubscriptionId": {
3948
- "type": "string",
3949
- "minLength": 1,
3950
- "description": "MAY. The RFC 0083 trigger-subscription id when the fire came through the durable trigger bridge, so trigger → run → roster is traceable via /ancestry (RFC 0040)."
3950
+ "$ref": "ids.schema.json#/$defs/subscriptionId",
3951
+ "description": "MAY. The RFC 0083 trigger-subscription id when the fire came through the durable trigger bridge, so trigger \u2192 run \u2192 roster is traceable via /ancestry (RFC 0040)."
3951
3952
  }
3952
3953
  }
3953
3954
  },
3954
3955
  "compensationRequested": {
3955
3956
  "type": "object",
3956
3957
  "additionalProperties": false,
3957
- "description": "RFC 0151 §D plan persisted, before the first inverse action. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) these land in the durable log, the least revocable place a credential can reach.",
3958
+ "description": "RFC 0151 \u00a7D \u2014 plan persisted, before the first inverse action. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (\u00a7D/\u00a7G) \u2014 these land in the durable log, the least revocable place a credential can reach.",
3958
3959
  "properties": {
3959
3960
  "compensationId": {
3960
3961
  "type": "string",
@@ -3981,7 +3982,7 @@
3981
3982
  "compensationStarted": {
3982
3983
  "type": "object",
3983
3984
  "additionalProperties": false,
3984
- "description": "RFC 0151 §D first inverse action started. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) these land in the durable log, the least revocable place a credential can reach.",
3985
+ "description": "RFC 0151 \u00a7D \u2014 first inverse action started. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (\u00a7D/\u00a7G) \u2014 these land in the durable log, the least revocable place a credential can reach.",
3985
3986
  "properties": {
3986
3987
  "compensationId": {
3987
3988
  "type": "string",
@@ -4008,7 +4009,7 @@
4008
4009
  "compensationCompleted": {
4009
4010
  "type": "object",
4010
4011
  "additionalProperties": false,
4011
- "description": "RFC 0151 §D every inverse action succeeded. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) these land in the durable log, the least revocable place a credential can reach.",
4012
+ "description": "RFC 0151 \u00a7D \u2014 every inverse action succeeded. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (\u00a7D/\u00a7G) \u2014 these land in the durable log, the least revocable place a credential can reach.",
4012
4013
  "properties": {
4013
4014
  "compensationId": {
4014
4015
  "type": "string",
@@ -4035,7 +4036,7 @@
4035
4036
  "compensationFailed": {
4036
4037
  "type": "object",
4037
4038
  "additionalProperties": false,
4038
- "description": "RFC 0151 §D an inverse action exhausted its retries. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) these land in the durable log, the least revocable place a credential can reach.",
4039
+ "description": "RFC 0151 \u00a7D \u2014 an inverse action exhausted its retries. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (\u00a7D/\u00a7G) \u2014 these land in the durable log, the least revocable place a credential can reach.",
4039
4040
  "properties": {
4040
4041
  "compensationId": {
4041
4042
  "type": "string",
@@ -4072,7 +4073,7 @@
4072
4073
  "compensationPaused": {
4073
4074
  "type": "object",
4074
4075
  "additionalProperties": false,
4075
- "description": "RFC 0151 §D paused for authorized intervention. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) these land in the durable log, the least revocable place a credential can reach.",
4076
+ "description": "RFC 0151 \u00a7D \u2014 paused for authorized intervention. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (\u00a7D/\u00a7G) \u2014 these land in the durable log, the least revocable place a credential can reach.",
4076
4077
  "properties": {
4077
4078
  "compensationId": {
4078
4079
  "type": "string",
@@ -4109,7 +4110,7 @@
4109
4110
  "compensationManualInterventionRequired": {
4110
4111
  "type": "object",
4111
4112
  "additionalProperties": false,
4112
- "description": "RFC 0151 §D operator action required. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) these land in the durable log, the least revocable place a credential can reach.",
4113
+ "description": "RFC 0151 \u00a7D \u2014 operator action required. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (\u00a7D/\u00a7G) \u2014 these land in the durable log, the least revocable place a credential can reach.",
4113
4114
  "properties": {
4114
4115
  "compensationId": {
4115
4116
  "type": "string",
@@ -4145,31 +4146,31 @@
4145
4146
  },
4146
4147
  "approvalRequested": {
4147
4148
  "$ref": "#/$defs/interruptRequested",
4148
- "description": "RFC 0171 §A.4 E4 sub-typing is $ref composition, not duplication: the legacy approvalRequested shape (deprecation row legacy-interrupt-payloads) is the unified interruptRequested payload; the event type is kept, its payload is not a second shape."
4149
+ "description": "RFC 0171 \u00a7A.4 E4 \u2014 sub-typing is $ref composition, not duplication: the legacy approvalRequested shape (deprecation row legacy-interrupt-payloads) is the unified interruptRequested payload; the event type is kept, its payload is not a second shape."
4149
4150
  },
4150
4151
  "clarificationRequested": {
4151
4152
  "$ref": "#/$defs/interruptRequested",
4152
- "description": "RFC 0171 §A.4 E4 sub-typing is $ref composition, not duplication: the legacy clarificationRequested shape (deprecation row legacy-interrupt-payloads) is the unified interruptRequested payload; the event type is kept, its payload is not a second shape."
4153
+ "description": "RFC 0171 \u00a7A.4 E4 \u2014 sub-typing is $ref composition, not duplication: the legacy clarificationRequested shape (deprecation row legacy-interrupt-payloads) is the unified interruptRequested payload; the event type is kept, its payload is not a second shape."
4153
4154
  },
4154
4155
  "approvalReceived": {
4155
4156
  "$ref": "#/$defs/interruptResolved",
4156
- "description": "RFC 0171 §A.4 E4 sub-typing is $ref composition, not duplication: the legacy approvalReceived shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4157
+ "description": "RFC 0171 \u00a7A.4 E4 \u2014 sub-typing is $ref composition, not duplication: the legacy approvalReceived shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4157
4158
  },
4158
4159
  "approvalGranted": {
4159
4160
  "$ref": "#/$defs/interruptResolved",
4160
- "description": "RFC 0171 §A.4 E4 sub-typing is $ref composition, not duplication: the legacy approvalGranted shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4161
+ "description": "RFC 0171 \u00a7A.4 E4 \u2014 sub-typing is $ref composition, not duplication: the legacy approvalGranted shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4161
4162
  },
4162
4163
  "approvalRejected": {
4163
4164
  "$ref": "#/$defs/interruptResolved",
4164
- "description": "RFC 0171 §A.4 E4 sub-typing is $ref composition, not duplication: the legacy approvalRejected shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4165
+ "description": "RFC 0171 \u00a7A.4 E4 \u2014 sub-typing is $ref composition, not duplication: the legacy approvalRejected shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4165
4166
  },
4166
4167
  "approvalOverridden": {
4167
4168
  "$ref": "#/$defs/interruptResolved",
4168
- "description": "RFC 0171 §A.4 E4 sub-typing is $ref composition, not duplication: the legacy approvalOverridden shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4169
+ "description": "RFC 0171 \u00a7A.4 E4 \u2014 sub-typing is $ref composition, not duplication: the legacy approvalOverridden shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4169
4170
  },
4170
4171
  "clarificationResolved": {
4171
4172
  "$ref": "#/$defs/interruptResolved",
4172
- "description": "RFC 0171 §A.4 E4 sub-typing is $ref composition, not duplication: the legacy clarificationResolved shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4173
+ "description": "RFC 0171 \u00a7A.4 E4 \u2014 sub-typing is $ref composition, not duplication: the legacy clarificationResolved shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4173
4174
  },
4174
4175
  "negotiationDecided": {
4175
4176
  "type": "object",
@@ -4204,7 +4205,7 @@
4204
4205
  "peerDigest": {
4205
4206
  "type": "string",
4206
4207
  "pattern": "^[0-9a-f]{64}$",
4207
- "description": "SHA-256 of the peer origin; never the origin in clear (RFC 0175 §D.3)."
4208
+ "description": "SHA-256 of the peer origin; never the origin in clear (RFC 0175 \u00a7D.3)."
4208
4209
  },
4209
4210
  "reason": {
4210
4211
  "type": "string",
@@ -4220,12 +4221,12 @@
4220
4221
  "format": "date-time"
4221
4222
  }
4222
4223
  },
4223
- "description": "RFC 0175 §D.3 the content-free negotiation audit event."
4224
+ "description": "RFC 0175 \u00a7D.3 \u2014 the content-free negotiation audit event."
4224
4225
  }
4225
4226
  },
4226
4227
  "additionalProperties": false,
4227
4228
  "_typeIndex": {
4228
- "description": "NORMATIVE (RFC 0171 §A.4): v2 event type $defs key, generated from spec/v2/event-codemap.json.",
4229
+ "description": "NORMATIVE (RFC 0171 \u00a7A.4): v2 event type \u2192 $defs key, generated from spec/v2/event-codemap.json.",
4229
4230
  "type": "object",
4230
4231
  "additionalProperties": false,
4231
4232
  "properties": {