Files
reporting-governance-plugin/docs/specs/reporting-governance-adapter-interface.md

693 lines
21 KiB
Markdown

# 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.
## 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 example:
- runner -> queue -> dispatcher -> bridge -> sender -> `acked`
- runner -> queue -> dispatcher -> bridge -> `pending_external_send`
- runner -> queue -> dispatcher -> bridge -> `blocked`
## 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