# Reporting Governance Adapter Interface ## Purpose This document defines the adapter contract for the reporting-governance plugin. It is the missing mainline bridge between: - the canonical governance model already defined in the event, evidence, decision, and policy-pack specs - real runtime integrations that must observe activity, evaluate policy, and produce honest operator-visible outcomes - the now-proven watchdog auto-notify chain (`runner -> queue -> dispatcher -> bridge -> sender -> ack|blocked|pending`) The goal is to move the plugin from concept-plus-scripts into a packageable integration surface. ## Why this spec exists now The plugin already has strong mainline specifications for: - product definition - event model - evidence model - decision model - policy packs Separately, the repo now also has real runtime infrastructure for anti-blackhole reporting: - long-task watchdog runner - canonical `watchdog_fired` event emission - operator notification queue - dispatcher spool handoff - bridge supervisor - sender binding - single-entry orchestrator - cron-installed auto-notify path - live acked execution evidence Without an adapter interface, those runtime pieces remain implementation islands. This spec makes them first-class plugin architecture rather than incidental scripts. For the current mainline slice, the package-owned runtime source of truth is the package adapter surface and package scripts under `plugins/reporting-governance/`. Repo-root `scripts/*.mjs` files should be read as compatibility wrappers or operator conveniences unless explicitly stated otherwise. When this spec names package entrypoints as `scripts/...`, that path is package-root-relative within `plugins/reporting-governance/`; repo-root wrappers remain the separate compatibility layer. ## Scope This document defines: 1. adapter responsibilities 2. adapter lifecycle stages 3. canonical input/output contracts 4. capability declaration requirements 5. runtime integration seams for watchdog / queue / dispatcher / bridge / sender / orchestrator 6. minimum package structure expectations for a deployable plugin implementation This document does **not** define: - one mandatory runtime vendor - one mandatory transport - one mandatory storage backend - one mandatory implementation language - detailed internal APIs for every package module ## Design stance The adapter layer is where runtime-specific reality gets normalized into portable governance behavior. Design priorities: - **canonical in, canonical out** - **honest delivery semantics** - **explicit capability declaration** - **policy-driven enforcement** - **file/runtime/transport boundaries must stay auditable** - **watchdog escalation must be integrable, not bolted on** Most importantly, the adapter must never claim more than the runtime can actually prove. ## Adapter role in the plugin architecture The reporting-governance plugin should be understood as five layers: 1. **Runtime observation layer** Captures runtime-native facts such as task start, checkpoint due, subagent completion, watchdog overdue, or outgoing message attempt. 2. **Adapter normalization layer** Converts runtime-native facts into canonical events, evidence items, and governance evaluation inputs. 3. **Policy evaluation layer** Applies policy packs to canonical facts and emits canonical decisions. 4. **Enforcement / delivery layer** Executes required actions such as block, rewrite, force checkpoint, notify operator, or mark pending verification. 5. **Audit / receipt layer** Persists enough traceability to prove what was observed, decided, attempted, delivered, blocked, or left pending. The adapter owns layers 1, 2, and the runtime-facing part of layer 4. ## Core adapter responsibilities Every adapter implementation MUST support these responsibilities, either directly or by explicitly declaring capability gaps. ### 1. Observe runtime activity The adapter must be able to ingest or derive runtime-native signals such as: - task lifecycle events - checkpoint/report attempts - subagent spawn/completion/failure states - watchdog timer breaches - outgoing operator-notice attempts - delivery receipts or delivery failures ### 2. Emit canonical events The adapter must translate observed runtime signals into the canonical event envelope defined in: - `docs/specs/reporting-governance-event-model.md` - `schemas/reporting-governance/event-envelope.schema.json` - `schemas/reporting-governance/events.schema.json` ### 3. Preserve or synthesize evidence The adapter must attach or reference evidence strong enough to support governance decisions, especially for: - progress claims - completion claims - forced checkpoints - forwarding integrity - watchdog-triggered escalation - actual operator-notice delivery vs mere handoff ### 4. Evaluate and enforce governance decisions The adapter must be able to invoke policy evaluation and then carry out runtime-appropriate enforcement actions such as: - block dispatch - block status transition - rewrite or annotate outgoing reports - force an operator-visible checkpoint - request review - downgrade status - escalate severity ### 5. Produce auditable receipts The adapter must preserve enough artifacts to reconstruct: - what happened - what policy fired - what action was attempted - whether operator-visible delivery actually occurred - where the runtime boundary stopped ### 6. Declare capabilities honestly The adapter must publish a machine-readable capability descriptor using: - `schemas/reporting-governance/adapter-capabilities.schema.json` This is mandatory because the plugin cannot safely assume every runtime can: - block before dispatch - rewrite outgoing text - send notifications directly - prove message delivery - schedule watchdogs - write receipts - recover dropped child results ## Canonical adapter lifecycle An adapter integrates the plugin through the following lifecycle. ### Stage A: Observe Input sources may include: - hook callbacks - runtime logs - task/session state files - queue items - cron / scheduler invocations - explicit CLI entrypoints - outbound message wrappers Output of this stage: - runtime-native observation records ### Stage B: Normalize The adapter converts runtime-native observations into canonical objects: - event envelope - evidence item(s) - evaluation context facts Output of this stage: - canonical event(s) - canonical evidence ref(s) - policy-evaluable context ### Stage C: Evaluate The adapter invokes the policy layer against canonical inputs. Output of this stage: - canonical decision object - required actions - operator notice requirement, if any ### Stage D: Enforce The adapter performs the required actions using runtime-specific mechanisms. Possible outputs: - blocked transition - rewritten message - emitted queue item - emitted spool artifact - sent operator notice - pending placeholder - escalation receipt ### Stage E: Record The adapter records: - emitted canonical events - evidence references - delivery or non-delivery receipts - action results - capability-aware audit notes ## Adapter surfaces An implementation may expose one or more of the following surfaces. ### 1. Hook adapter Used when the runtime can intercept actions before they complete. Typical uses: - block silent task launch - block completion claim without evidence - rewrite placeholder messaging - require report anchor before subagent dispatch ### 2. Watchdog adapter Used when policy must be checked on elapsed time or missing follow-up rather than only inline actions. Typical uses: - missed checkpoint detection - subagent result not forwarded - long-task overdue escalation - promised follow-up not delivered ### 3. Queue / dispatch adapter Used when policy requires an operator-visible notice but direct send is not embedded in the local runtime. Typical uses: - emit `notify_operator` queue items - produce spool / handoff artifact - preserve delivery truthfulness across runtime boundaries ### 4. Sender / bridge adapter Used when a privileged or upper runtime actually performs the operator-visible delivery. Typical uses: - invoke `message.send` or equivalent - write `acked` / `blocked` / `pending_external_send` receipts - preserve exact evidence of send outcome ### 5. Orchestrator adapter Used when several adapter surfaces must be run in a deterministic chain. Typical uses: - single-entry watchdog auto-notify execution - cron or scheduler integration - repeatable end-to-end runtime closure ## Runtime truth model The adapter interface adopts a strict truth model for operator notifications. ### Delivery states At minimum, adapters must distinguish: - `prepared` — a notice requirement exists, but no queue/handoff has been created yet - `queued` — a queue item exists for future delivery - `dispatched` — a handoff/spool artifact exists and a downstream runtime may now deliver it - `pending_external_send` — the chain reached the bridge boundary honestly, but real send is not proven - `acked` — an upper sender path proved success and the queue/receipt writeback completed - `blocked` — the adapter or upper runtime determined safe delivery could not proceed ### Hard rule `dispatched` is **not** `acked`. `pending_external_send` is **not** `acked`. A local script writing a handoff artifact is **not** proof that a human-visible message was delivered. This truth model is the main way the recent watchdog chain gets reabsorbed into the plugin architecture without regressing into fake reporting. ## Required adapter inputs An adapter invocation SHOULD accept or derive the following logical inputs. | Field | Required | Notes | | --- | --- | --- | | `runtime` | yes | Runtime identity such as `openclaw`. | | `adapter_id` | yes | Stable adapter identifier. | | `adapter_version` | yes | Version of the adapter implementation. | | `task_id` | yes for governed task flow | Required for canonical events. | | `correlation_id` | yes for governed task flow | Required for cross-event linkage. | | `event_source` | yes | Hook, watchdog, queue, bridge, cron, etc. | | `observed_at` | yes | Observation timestamp. | | `payload` | yes | Runtime-native observation payload. | | `operator_context` | recommended | Channel, target, report anchor, reporting mode, policy IDs. | | `evidence_refs` | recommended | Artifact refs from runtime or synthesized receipts. | | `capabilities` | yes | Adapter capability descriptor or profile binding. | ## Required adapter outputs An adapter stage SHOULD produce some subset of the following outputs, depending on surface. | Output | Required when | Notes | | --- | --- | --- | | canonical event | always for governed observations | Must use canonical envelope. | | canonical evidence item | when claims, escalation, or delivery truth need proof | May be referenced by event. | | canonical decision | when policy evaluation is run | Must align to decision model. | | enforcement result | when an action is attempted | Blocked, rewritten, queued, acked, etc. | | receipt artifact | when handoff/delivery/escalation state changes | Needed for audit and watchdog closure. | | operator notice artifact | when a visible notice is required | May be queue, message, or send receipt. | ## Capability model Each adapter MUST declare its capabilities in a machine-readable document validated by: - `schemas/reporting-governance/adapter-capabilities.schema.json` Capabilities exist so policy/runtime wiring can answer questions like: - Can this adapter block before a subagent spawn? - Can it rewrite outgoing reports? - Can it schedule or evaluate watchdogs? - Can it emit queue items but not send directly? - Can it prove delivery with ack receipts? - Can it correlate sender receipts back to task and policy IDs? - Can it recover or inspect child-result state for forwarding integrity? ## Capability domains ### Identity and compatibility The adapter descriptor must declare: - adapter ID - version - runtime target - supported plugin spec version(s) ### Ingestion capabilities Whether the adapter can observe: - task lifecycle - subagent lifecycle - checkpoint obligations - outgoing report attempts - watchdog state - queue/spool/receipt state ### Enforcement capabilities Whether the adapter can: - block transitions - rewrite outgoing text - annotate placeholders - force visible checkpoints - request review - downgrade status - escalate ### Notification-path capabilities Whether the adapter can: - create queue items - create spool/handoff artifacts - invoke a sender binding - send directly - write ack/block/pending receipts - prove final delivery ### Watchdog capabilities Whether the adapter can: - start or install watchdogs - evaluate overdue rules - emit `watchdog_fired` - convert watchdog trigger into operator-visible recovery path - close watchdog alerts once send outcome is known ### Storage/audit capabilities Whether the adapter can: - persist canonical events - persist evidence items - persist decision outputs - persist receipts - retain original attempted messages when rewrite occurs ## Mapping the completed watchdog chain into the adapter model The newly completed watchdog chain should now be treated as a reference runtime adapter composition rather than a side implementation. ### Reference chain ```text watchdog runner -> canonical watchdog event -> operator notification queue -> dispatcher spool handoff -> bridge supervisor -> sender binding -> acked | blocked | pending_external_send receipt ``` ### Plugin-mainline interpretation This chain maps to adapter responsibilities as follows: | Existing runtime piece | Adapter role in mainline design | | --- | --- | | `scripts/long_task_watchdog.mjs` | watchdog adapter: observes overdue state, emits canonical `watchdog_fired`, seeds operator notice path | | `state/long-task-watchdog/*.json` | evidence storage for watchdog-triggered runtime artifacts | | `state/long-task-watchdog-events/*.json` | canonical event store for watchdog-originated governance events | | `state/operator-notify-queue/*.json` | queue adapter output representing required operator notice not yet delivered | | `scripts/operator_notify_dispatcher.mjs` | dispatch adapter converting queue intent into auditable spool/handoff artifact | | `state/operator-notify-dispatch-spool/*.json` | runtime handoff proof between local governance and upper send runtime | | `scripts/operator_notify_bridge_supervisor.mjs` | bridge adapter consuming spool, invoking sender boundary, and writing honest status receipts | | `scripts/operator_notify_sender_binding.mjs` | sender-binding adapter that maps upper runtime send contract into canonical send outcome states | | `state/operator-notify-bridge-receipts/*.json` | receipt/audit layer for final bridge outcome | | `scripts/watchdog_auto_notify_orchestrator.mjs` | orchestrator adapter composing the chain into one deterministic runtime path | | cron installer / wrapper | deployment binding for scheduled adapter execution | ### Why this matters Before this spec, the chain could be read as “helper scripts around a watchdog.” After this spec, the chain becomes: - the first concrete adapter composition for the plugin - the runtime reference design for forced operator-notice enforcement - the proof that policy decisions can survive a multi-hop runtime boundary without lying about delivery ## Adapter composition patterns The plugin should support at least these composition patterns. ### Pattern 1: Inline enforcement adapter Use when the runtime can intercept actions before they occur. Example: - pre-dispatch report-anchor gate - verified-completion-only gate ### Pattern 2: Deferred operator-notice adapter Use when the runtime can decide a notice is required but cannot itself safely prove final send. Example: - local policy emits queue item - upper runtime later sends notice and acks it This is the current watchdog auto-notify chain. ### Pattern 3: Full-stack runtime adapter Use when one runtime can observe, decide, send, and receipt all in one trusted boundary. Example: - future integrated runtime with direct hook + send + receipt APIs ### Pattern 4: Hybrid adapter pack Use when one plugin deployment combines: - inline hook enforcement for task/report claims - scheduled watchdog enforcement for missed follow-up - queue/bridge sender path for operator notifications This is the most realistic mainline target for the reporting-governance plugin. ## Minimum package structure target This spec does not force an exact repository layout, but the next mainline implementation should converge toward a package structure similar to: ```text plugins/reporting-governance/ src/ core/ event-normalizer.* evidence-builder.* policy-evaluator.* decision-runner.* adapters/ hook-adapter.* watchdog-adapter.* queue-adapter.* bridge-adapter.* sender-binding-adapter.* orchestrator-adapter.* capabilities/ default-openclaw-watchdog.json storage/ event-store.* evidence-store.* receipt-store.* index.* docs/ examples/ ``` ### Mainline integration direction The current scripts do not need to disappear immediately. They should instead be treated as: - first reference adapters - migration bridge for package extraction - executable fixtures proving the adapter contract before full packaging ## Required invariants All adapter implementations MUST preserve the following invariants. ### Invariant 1: Canonical event compatibility If the adapter claims event emission support, emitted events must validate against the canonical event schemas. ### Invariant 2: Honest operator-notice state The adapter must never collapse queue/spool/send states into false success. ### Invariant 3: Correlation continuity The adapter must preserve `task_id` and `correlation_id` across watchdog, queue, spool, send, and receipt artifacts wherever possible. ### Invariant 4: Evidence traceability If the adapter emits a force-checkpoint or watchdog-driven escalation, it must preserve evidence refs sufficient for later audit. ### Invariant 5: Capability-aware enforcement If a policy requires an action the adapter cannot perform, the adapter must: - declare the gap in capabilities - emit a safe fallback such as queueing, blocking, or escalation - avoid pretending the missing capability exists ## Watchdog-specific integration requirements Because watchdog enforcement is now a validated mainline feature, adapters that claim watchdog support MUST address the following. ### 1. Trigger normalization A watchdog trigger must be representable as canonical `watchdog_fired` and/or related escalation events. ### 2. Operator-notice linkage A watchdog trigger that requires visible follow-up must link to a concrete notice path: - direct send - queue item - forced placeholder / visible checkpoint - explicit blocked state ### 3. End-state closure A watchdog path is not complete just because the trigger fired. It should close only when the adapter can classify the notice path as: - `acked` - `blocked` - `pending_external_send` ### 4. Policy-aware receipts Receipts should retain: - `policy_id` - trigger event type - `task_id` - `correlation_id` - evidence refs - sender outcome The current watchdog queue/spool/bridge implementation already demonstrates most of this and should be treated as baseline behavior. ## OpenClaw reference adapter profile Based on the completed work in this repo, the first reference profile is: - runtime: `openclaw` - observe via scripts + file state + cron + runtime artifacts - canonical event emission supported - queue-backed operator-notice path supported - bridge/sender boundary supported - honest `acked|blocked|pending_external_send` distinction supported - direct privileged send support is optional and capability-dependent This profile should be published as a capabilities descriptor, not just implied by repo docs. ## Verification expectations Any adapter implementation should be verified at three levels. ### Level 1: Schema validation Validate: - canonical event outputs - canonical evidence outputs - canonical decision outputs - capability descriptor outputs ### Level 2: Surface-level behavior tests Verify each adapter surface independently. Examples: - watchdog emits `watchdog_fired` - dispatcher produces spool and marks `dispatched` - bridge writes `pending_external_send` in dry-run - sender binding `sent` leads to queue `acked` - sender binding `blocked` leads to queue `blocked` ### Level 3: End-to-end composition tests Verify orchestrated chain behavior. For the **current runtime contract**, treat the reference chain as a **single notice settlement path**, not a generalized multi-notice aggregation framework. That means: - the runtime may promote overall truth state to `acked` only when the observed terminal set for that one notice path is fully acked - `acked + pending` must remain non-`acked` - `acked + blocked` must remain non-`acked` - any future multi-notice aggregation semantics must be introduced as a separate contract slice, not inferred from this one For example: - runner -> queue -> dispatcher -> bridge -> sender -> `acked` - runner -> queue -> dispatcher -> bridge -> `pending_external_send` - runner -> queue -> dispatcher -> bridge -> `blocked` - mixed observed outcomes `acked + pending` -> overall state must **not** promote to `acked` - mixed observed outcomes `acked + blocked` -> overall state must **not** promote to `acked` ## Roadmap impact This spec is the next high-value mainline step because it turns the product from: - conceptual governance docs - plus separate runtime repair scripts into: - a plugin with explicit adapter seams - declared runtime capabilities - a concrete migration target for package structure - a validated reference runtime composition Suggested mainline next steps after this document: 1. define default OpenClaw adapter capability profile JSON using the new schema 2. extract current runtime scripts behind named adapter modules 3. add adapter-level schema validation tests 4. formalize deployment profile format and package/deployment model around the now-stable watchdog adapter composition 5. add portable audit export manifest support ## Summary The adapter interface is the missing contract that reconnects the proven watchdog auto-notify chain back into the reporting-governance plugin mainline. It makes the following explicit: - adapters are first-class plugin architecture - watchdog/queue/dispatcher/bridge/sender/orchestrator are valid adapter surfaces, not side scripts - operator notification must remain truthful across runtime boundaries - capabilities must be declared, not assumed - package structure can now evolve around a real integration contract