# Reporting Governance Event Model ## Purpose This document defines the canonical event model for the reporting-governance plugin. It gives adapters and policy evaluators a stable envelope, a shared event-type catalog, and validation rules for the reporting failure modes that recently caused blackhole behavior. The model is designed to support four enforcement gates: 1. **Pre-dispatch report-anchor gate** 2. **Subagent failure immediate-report gate** 3. **Silent-task launch blocker** 4. **Result-forwarding integrity gate** ## Design goals - Provide one portable envelope for all reporting-governance events. - Separate common metadata from event-specific payloads. - Make high-risk reporting failures explicit and machine-detectable. - Preserve enough evidence and operator context for audit and escalation. - Support adapters that translate runtime-specific activity into canonical events. ## Canonical envelope Every event MUST use the following top-level envelope. | Field | Type | Required | Notes | | --- | --- | --- | --- | | `event_id` | string | yes | Unique event identifier. UUID recommended. | | `event_type` | string | yes | Canonical event type name. | | `runtime` | string | yes | Runtime source, such as `openclaw`, `claude-code`, or another adapter target. | | `adapter_version` | string | yes | Version of the adapter emitting the canonical event. | | `agent_id` | string | yes | Canonical identifier for the agent responsible for the event. | | `task_id` | string | yes | Task identifier. May be runtime-generated, but must be present on all governed task events. | | `correlation_id` | string | yes | Correlates related events within a workflow, dispatch chain, or review thread. | | `timestamp` | string | yes | RFC 3339 timestamp. | | `payload` | object | yes | Event-specific body validated by event type. | | `evidence_refs` | array | yes | Zero or more evidence references unless the event type requires at least one. | | `operator_context` | object | yes | Reporting context visible to governance logic and auditors. | ## Envelope semantics ### `event_id` - Must be globally unique within the event store. - Should be immutable and idempotency-safe. ### `event_type` - Must be one of the canonical event types defined in this document. - Event types are stable governance API surface. ### `task_id` - Required for all events in this model, including alert and gate events. - Enables policy evaluation for checkpointing, silence windows, completion claims, and forwarding integrity. ### `correlation_id` - Binds related task, subagent, review, and escalation events. - A subagent chain should usually retain the same `correlation_id` while using event-specific payload fields for child linkage. ### `evidence_refs` Each evidence reference object should use this shape: ```json { "kind": "command_output", "ref": "artifacts/verify/test-output.txt", "label": "pytest output", "sha256": "b1946ac92492d2347c6235b4d2611184", "mime_type": "text/plain" } ``` Recommended `kind` values: - `command_output` - `file` - `url` - `message` - `commit` - `log_excerpt` - `screenshot` - `schema_validation` ### `operator_context` Minimum recommended fields: ```json { "channel": "telegram", "operator_id": "eric", "report_anchor": { "present": true, "anchor_id": "telegram:msg:12345" }, "reporting_mode": "interactive", "silent_task": false, "checkpoint_policy_id": "default-5m", "watchdog_policy_id": "subagent-forwarding-v1" } ``` `operator_context.report_anchor.present` is critical for enforcing the pre-dispatch report-anchor gate. ## Canonical event types ### Task lifecycle - `task_started` - `task_checkpoint_due` - `task_checkpoint_sent` - `task_status_changed` - `task_claimed_complete` - `task_evidence_attached` - `operator_review_requested` ### Subagent orchestration - `subagent_spawned` - `subagent_spawn_failed` - `subagent_completed` - `subagent_result_forwarded` - `subagent_result_not_forwarded` ### Silence / watchdog / escalation - `silence_timeout` - `watchdog_fired` - `forced_operator_update` ### Gate and governance failures - `report_anchor_missing` ## Event payload definitions ### 1. `task_started` Signals that a governed task started execution. Required payload fields: - `task_kind` (string) - `started_by` (string) - `initial_status` (string) - `silent_task` (boolean) - `report_required` (boolean) Recommended payload fields: - `plan_ref` (string) - `checkpoint_due_at` (string, RFC 3339) - `owner_agent_id` (string) Governance note: - If `silent_task` is `true` while policy forbids silent launches, this event should be blocked or accompanied by `forced_operator_update` / policy denial upstream. ### 2. `task_checkpoint_due` Signals that a checkpoint obligation became due. Required payload fields: - `checkpoint_type` (string) - `due_at` (string, RFC 3339) - `expected_report_type` (string) Recommended payload fields: - `grace_period_ms` (integer) - `policy_id` (string) ### 3. `task_checkpoint_sent` Signals that a checkpoint report was actually emitted. Required payload fields: - `checkpoint_type` (string) - `sent_at` (string, RFC 3339) - `report_type` (string) Recommended payload fields: - `anchor_id` (string) - `message_ref` (string) - `lateness_ms` (integer) ### 4. `task_status_changed` Signals a meaningful workflow state transition. Required payload fields: - `from_status` (string) - `to_status` (string) - `reason` (string) Recommended payload fields: - `status_source` (string) - `blocked` (boolean) - `gate_id` (string) ### 5. `task_claimed_complete` Signals that an agent claimed completion. Required payload fields: - `claimed_status` (string) Recommended payload fields: - `verification_state` (string) - `claim_basis` (string) - `pending_review` (boolean) Validation rule: - `task_id` is required by the envelope. - `payload.claimed_status` is required. Governance note: - This event should not imply accepted completion. It records the claim so policy can validate verification and review gates. ### 6. `task_evidence_attached` Signals that evidence was added to support status or completion. Required payload fields: - `evidence_count` (integer, minimum 1) - `evidence_role` (string) Validation rule: - `evidence_refs` must contain at least one item. ### 7. `operator_review_requested` Signals that operator review or approval was requested. Required payload fields: - `review_reason` (string) - `review_scope` (string) Recommended payload fields: - `requested_status` (string) - `deadline` (string, RFC 3339) ### 8. `subagent_spawned` Signals successful subagent dispatch. Required payload fields: - `subagent_id` (string) - `subagent_label` (string) - `dispatch_status` (string) - `report_anchor_required` (boolean) - `report_anchor_present` (boolean) Recommended payload fields: - `spawn_session_id` (string) - `parent_agent_id` (string) - `task_summary` (string) - `worktree` (string) Governance note: - `report_anchor_present` supports the pre-dispatch report-anchor gate. - Adapters may reject dispatch before emitting this event if the gate fails. ### 9. `subagent_spawn_failed` Signals that subagent dispatch failed. Required payload fields: - `failure_reason` (string) - `failure_stage` (string) - `immediate_report_required` (boolean) Recommended payload fields: - `attempted_subagent_label` (string) - `error_code` (string) - `retryable` (boolean) Governance note: - This event exists so dispatch failure cannot silently disappear. - Policies should require an immediate operator-facing report when this event occurs. ### 10. `subagent_completed` Signals child task completion or termination. Required payload fields: - `subagent_id` (string) - `completion_state` (string) - `result_available` (boolean) Recommended payload fields: - `result_ref` (string) - `completed_at` (string, RFC 3339) - `exit_reason` (string) ### 11. `subagent_result_forwarded` Signals that child output was forwarded into the governed reporting path. Required payload fields: - `subagent_id` (string) - `forwarded_at` (string, RFC 3339) - `forward_target` (string) Recommended payload fields: - `source_result_ref` (string) - `forward_message_ref` (string) - `integrity_status` (string) ### 12. `subagent_result_not_forwarded` Signals a forwarding integrity failure. Required payload fields: - `subagent_id` (string) - `detected_at` (string, RFC 3339) - `reason` (string) - `result_ref` (string) Recommended payload fields: - `forward_deadline` (string, RFC 3339) - `watchdog_window_ms` (integer) - `operator_notified` (boolean) Governance note: - This event is the explicit machine-detectable blackhole symptom for a completed child whose result was not surfaced properly. ### 13. `silence_timeout` Signals that required reporting silence exceeded policy. Required payload fields: - `duration_ms` (integer, minimum 1) - `expected_report_type` (string) Recommended payload fields: - `last_report_at` (string, RFC 3339) - `timeout_policy_id` (string) - `blocking_action` (string) Validation rule: - `duration_ms` and `expected_report_type` are required. Governance note: - Supports the silent-task launch blocker and overdue checkpoint escalation logic. ### 14. `watchdog_fired` Signals a watchdog policy trigger. Required payload fields: - `watchdog_type` (string) - `trigger_reason` (string) Recommended payload fields: - `triggered_at` (string, RFC 3339) - `policy_id` (string) - `severity` (string) ### 15. `report_anchor_missing` Signals that a required reporting anchor was missing before dispatch or required reporting. Required payload fields: - `required_for` (string) - `gate_action` (string) Recommended payload fields: - `missing_anchor_kind` (string) - `attempted_action` (string) - `blocking` (boolean) Governance note: - This event enables explicit auditing of the pre-dispatch report-anchor gate. ### 16. `forced_operator_update` Signals that the system forced an operator-visible update because a gate or failure policy required it. Required payload fields: - `reason` (string) - `update_channel` (string) - `trigger_event_type` (string) Recommended payload fields: - `update_ref` (string) - `severity` (string) - `deadline_breached` (boolean) Governance note: - Used for immediate disclosure when silent failure or blocked dispatch would otherwise become a blackhole. ## Governance gate mapping ### Pre-dispatch report-anchor gate Use: - `operator_context.report_anchor.present` - `subagent_spawned.payload.report_anchor_present` - `report_anchor_missing` Expected behavior: - If an operator-visible anchor is required and absent, dispatch should be blocked or explicitly escalated. ### Subagent failure immediate-report gate Use: - `subagent_spawn_failed` - `forced_operator_update` Expected behavior: - Dispatch failure cannot remain internal-only. A failure should trigger or require immediate reporting. ### Silent-task launch blocker Use: - `task_started.payload.silent_task` - `silence_timeout` - `forced_operator_update` Expected behavior: - Policies may block silent starts or force disclosure when a task enters a no-report state beyond allowed policy. ### Result-forwarding integrity gate Use: - `subagent_completed` - `subagent_result_forwarded` - `subagent_result_not_forwarded` - `watchdog_fired` Expected behavior: - If a child result exists but is not forwarded within policy, governance emits an explicit failure event and escalation path. ## Example events ### Example: `subagent_spawned` ```json { "event_id": "1adf4ed4-5b4d-4ce8-9b30-11f6fd9dd001", "event_type": "subagent_spawned", "runtime": "openclaw", "adapter_version": "1.0.0", "agent_id": "agent:coder:main", "task_id": "task-reporting-governance-2", "correlation_id": "corr-rg-2026-05-07-001", "timestamp": "2026-05-07T15:40:00+08:00", "payload": { "subagent_id": "agent:coder:subagent:d42f401a-2497-405b-8eed-1606fb710c8a", "subagent_label": "reporting-governance-task2-implementer", "dispatch_status": "spawned", "report_anchor_required": true, "report_anchor_present": true, "spawn_session_id": "sess_123", "parent_agent_id": "agent:coder:main", "task_summary": "Implement Task 2 spec/schema work", "worktree": "/home/alice/.openclaw/workspace/.worktrees/reporting-governance-plugin" }, "evidence_refs": [], "operator_context": { "channel": "telegram", "operator_id": "eric", "report_anchor": { "present": true, "anchor_id": "telegram:msg:998877" }, "reporting_mode": "interactive", "silent_task": false, "checkpoint_policy_id": "default-5m", "watchdog_policy_id": "forwarding-v1" } } ``` ### Example: `subagent_spawn_failed` ```json { "event_id": "1adf4ed4-5b4d-4ce8-9b30-11f6fd9dd002", "event_type": "subagent_spawn_failed", "runtime": "openclaw", "adapter_version": "1.0.0", "agent_id": "agent:coder:main", "task_id": "task-reporting-governance-2", "correlation_id": "corr-rg-2026-05-07-001", "timestamp": "2026-05-07T15:41:10+08:00", "payload": { "failure_reason": "sessions_spawn returned transport error", "failure_stage": "dispatch", "immediate_report_required": true, "attempted_subagent_label": "reporting-governance-task2-implementer", "error_code": "TRANSPORT_UNAVAILABLE", "retryable": true }, "evidence_refs": [ { "kind": "log_excerpt", "ref": "logs/spawn-error-2026-05-07.txt", "label": "subagent spawn error", "mime_type": "text/plain" } ], "operator_context": { "channel": "telegram", "operator_id": "eric", "report_anchor": { "present": true, "anchor_id": "telegram:msg:998877" }, "reporting_mode": "interactive", "silent_task": false, "checkpoint_policy_id": "default-5m", "watchdog_policy_id": "forwarding-v1" } } ``` ### Example: `subagent_result_not_forwarded` ```json { "event_id": "1adf4ed4-5b4d-4ce8-9b30-11f6fd9dd003", "event_type": "subagent_result_not_forwarded", "runtime": "openclaw", "adapter_version": "1.0.0", "agent_id": "agent:coder:main", "task_id": "task-reporting-governance-2", "correlation_id": "corr-rg-2026-05-07-001", "timestamp": "2026-05-07T15:49:30+08:00", "payload": { "subagent_id": "agent:coder:subagent:d42f401a-2497-405b-8eed-1606fb710c8a", "detected_at": "2026-05-07T15:49:30+08:00", "reason": "child session completed but no forwarded result was recorded before watchdog deadline", "result_ref": "session-result:d42f401a-2497-405b-8eed-1606fb710c8a", "forward_deadline": "2026-05-07T15:48:00+08:00", "watchdog_window_ms": 90000, "operator_notified": true }, "evidence_refs": [ { "kind": "message", "ref": "telegram:msg:998877", "label": "latest operator checkpoint", "mime_type": "text/plain" } ], "operator_context": { "channel": "telegram", "operator_id": "eric", "report_anchor": { "present": true, "anchor_id": "telegram:msg:998877" }, "reporting_mode": "interactive", "silent_task": false, "checkpoint_policy_id": "default-5m", "watchdog_policy_id": "forwarding-v1" } } ``` ### Example: `silence_timeout` ```json { "event_id": "1adf4ed4-5b4d-4ce8-9b30-11f6fd9dd004", "event_type": "silence_timeout", "runtime": "openclaw", "adapter_version": "1.0.0", "agent_id": "agent:coder:main", "task_id": "task-reporting-governance-2", "correlation_id": "corr-rg-2026-05-07-001", "timestamp": "2026-05-07T15:50:00+08:00", "payload": { "duration_ms": 300000, "expected_report_type": "task_checkpoint_sent", "last_report_at": "2026-05-07T15:45:00+08:00", "timeout_policy_id": "default-5m", "blocking_action": "force_update" }, "evidence_refs": [], "operator_context": { "channel": "telegram", "operator_id": "eric", "report_anchor": { "present": true, "anchor_id": "telegram:msg:998877" }, "reporting_mode": "interactive", "silent_task": false, "checkpoint_policy_id": "default-5m", "watchdog_policy_id": "forwarding-v1" } } ``` ### Example: `forced_operator_update` ```json { "event_id": "1adf4ed4-5b4d-4ce8-9b30-11f6fd9dd005", "event_type": "forced_operator_update", "runtime": "openclaw", "adapter_version": "1.0.0", "agent_id": "agent:coder:main", "task_id": "task-reporting-governance-2", "correlation_id": "corr-rg-2026-05-07-001", "timestamp": "2026-05-07T15:50:05+08:00", "payload": { "reason": "subagent result forwarding watchdog breached", "update_channel": "telegram", "trigger_event_type": "subagent_result_not_forwarded", "update_ref": "telegram:msg:998899", "severity": "high", "deadline_breached": true }, "evidence_refs": [ { "kind": "message", "ref": "telegram:msg:998899", "label": "forced operator update", "mime_type": "text/plain" } ], "operator_context": { "channel": "telegram", "operator_id": "eric", "report_anchor": { "present": true, "anchor_id": "telegram:msg:998877" }, "reporting_mode": "interactive", "silent_task": false, "checkpoint_policy_id": "default-5m", "watchdog_policy_id": "forwarding-v1" } } ``` ## Consistency requirements - All canonical events use the same envelope schema. - Event-specific validation lives in the event catalog schema. - Adapters may emit additional fields, but only inside payload or extension-friendly object properties unless future schema revision promotes them. - Unknown `event_type` values must fail validation. - Event types representing gate failures are first-class events, not log-only annotations. ## Versioning - Envelope and event catalog should evolve with explicit schema versioning. - Additive payload fields are preferred over breaking top-level envelope changes. - New event types should only be added with documentation and example coverage for operator-facing semantics.