Files
reporting-governance-plugin/plugins/reporting-governance

Reporting Governance Plugin

This package is the emerging package boundary for the reporting-governance mainline.

Current purpose:

  • give the plugin a real package home
  • publish capability descriptors as package artifacts
  • fix boundaries between core/, adapters/, storage/, and reference implementations
  • prepare the next implementation round for evaluator / decision-runner extraction
  • provide a minimal package-level policy evaluator and decision runner skeleton that can be verified in isolation
  • add one minimal package-owned deployment profile artifact / loader / binding contract slice that is executable in tests
  • let profile artifacts drive one real orchestrator adapter entrypoint instead of staying test-only
  • add one minimal runtime-integrated slice wiring contract planning into real orchestrator execution

Package skeleton

plugins/reporting-governance/
  package.json
  README.md
  capabilities/
  profiles/
  profiles-src/
  schemas/
  scripts/
  docs/
  examples/
  src/
    core/
      index.mjs
      policy-evaluator.mjs
      decision-runner.mjs
      execute-governance-contract.mjs
      runtime-integrated.mjs
    adapters/
    storage/
    reference/
    index.mjs
  test/

Boundary rules

src/core/

Runtime-agnostic governance logic:

  • canonical event normalization
  • evidence building
  • policy evaluation
  • decision running
  • capability/profile compatibility

src/adapters/

Runtime-facing adapter modules:

  • watchdog adapter
  • dispatcher adapter
  • bridge adapter
  • sender-binding adapter
  • orchestrator adapter

These may initially wrap existing repo scripts while extraction is still in progress.

src/storage/

Durable I/O contracts for governance artifacts:

  • events
  • evidence
  • queue items
  • spool artifacts
  • receipts
  • decision/profile/package artifacts
  • future decisions / audit manifests

src/reference/

Reference runtime compositions and migration notes.

The watchdog reference runtime composition belongs here, as a reference implementation for OpenClaw rather than as package core logic.

Public surface and compatibility

Current public package surface is intentionally narrow:

  • root export: @openclaw/plugin-reporting-governance
  • adapter exports:
    • @openclaw/plugin-reporting-governance/adapters
    • @openclaw/plugin-reporting-governance/adapters/watchdog
    • @openclaw/plugin-reporting-governance/adapters/dispatcher
    • @openclaw/plugin-reporting-governance/adapters/bridge-supervisor
    • @openclaw/plugin-reporting-governance/adapters/sender-binding
    • @openclaw/plugin-reporting-governance/adapters/orchestrator

What is currently exposed from the root export:

  • evaluatePolicyPack(...)
  • evaluatePolicies(...)
  • planDecisionExecution(...)
  • executeGovernanceContract(...)
  • executeRuntimeIntegratedGovernance(...)
  • package metadata helpers such as packageName
  • package-owned adapter entrypoints and runWatchdogChain(...)

Compatibility posture for this slice:

  • 0.1.0-mainline should be treated as pre-1.0, surface-tightening phase.
  • Deep imports into src/ are not supported API even if files exist in-repo.
  • Tests now explicitly enforce that private paths like src/adapters/runtime-binding.mjs stay outside exports.
  • Adding a symbol to a file under src/ does not mean it is public unless wired through package exports.
  • Future tightening of root/adapters exports may still be a breaking change until a stable 1.0 surface is declared.

Compatibility envelope vs legacy compatibility mode

This slice now makes the boundary explicit:

  • compatibility envelope present = caller provides a deployment profile and/or package version pin, so runCompatibilityPreflight(...) must enforce canonical schema paths, declared plugin compatibility, required expectations, and action support fail-closed.
  • legacy compatibility mode = caller omits profile + package version entirely, so preflight keeps old call sites alive, records the missing version pin as a note, and does not fail only because descriptor schema/version metadata drifted.

Hard rule:

  • legacy mode is a caller-compatibility concession, not a relaxed truth model.
  • once any profile/package compatibility envelope is supplied, schema mismatch becomes blocking again.

Practical migration rule:

  • new integrations should always send a profile artifact or package version pin.
  • old integrations may temporarily call without one, but should treat returned notes as migration debt.
  • depend on package root exports or declared adapter subpaths only
  • do not couple runtime integrations to repo-private file paths
  • treat capability descriptors and schemas as package artifacts, but not as guaranteed JS import entrypoints unless exported later

Current reference composition

The current reference composition is the OpenClaw watchdog chain:

watchdog -> queue -> dispatcher -> bridge -> sender binding -> acked|blocked|pending_external_send

Package-home documentation:

  • src/reference/openclaw-watchdog-chain.md
  • capabilities/openclaw-watchdog-reference.json
  • profiles/strict-manager-mode.profile.json

Mainline background specs remain in:

  • docs/specs/reporting-governance-capability-descriptor.md
  • docs/specs/reporting-governance-adapter-interface.md
  • docs/specs/reporting-governance-deployment-model.md

Minimal profile artifact / loader / binding contract slice

This round adds one small but real package artifact path:

  • package artifact: profiles/strict-manager-mode.profile.json
  • loader: src/storage/profile-artifact.mjs#loadDeploymentProfileArtifact(...)
  • validator: src/storage/profile-artifact.mjs#validateDeploymentProfileArtifact(...)
  • binding contract: src/storage/profile-artifact.mjs#createDeploymentBindingContract(...)

What this slice does:

  1. package ships a profile artifact snapshot under package boundary
  2. loader resolves that artifact from package-local path
  3. validator fail-closes minimal boundary drift on kind, apiVersion, spec.bindings.entrypoint, scripts, artifact_roots, and spec.package.pluginVersion
  4. binding contract translates profile-declared script/artifact roots into concrete repo/runtime paths
  5. validator rejects artifact_roots absolute paths, lexical escapes, and symlink escapes that resolve outside repo realpath boundary
  6. adapter runtime binding can be instantiated from that contract in tests
  7. orchestrator adapter can now bootstrap from package profile artifact input directly
  8. queueItems now has two checks: load-time artifact validation and orchestrator use-time realpath recheck before runtime consumption

What this slice does not claim yet:

  • full profile schema validation pipeline
  • automatic YAML -> artifact generation
  • generalized multi-profile packaging
  • production deployment installer

It is intentionally the smallest verifiable step that proves package profile artifacts are executable inputs rather than documentation only.

Minimal evaluator / decision runner now included

The current package now includes a small but runnable core/ implementation:

  • src/core/policy-evaluator.mjs
  • src/core/decision-runner.mjs
  • src/core/execute-governance-contract.mjs
  • src/core/runtime-integrated.mjs
  • src/core/index.mjs

Current package-core responsibilities:

  • normalize evaluator facts from canonical event payload + evidence + local context
  • match policy-pack rules by trigger and structured conditions
  • produce canonical decision-model shaped decision objects
  • choose the highest-precedence decision when multiple rules match
  • convert a canonical decision into an execution plan, enforcement intent, and receipt skeleton
  • truthfully degrade unsupported enforcement paths based on the capability descriptor
  • provide one minimal contract path from capability descriptor -> policy decision -> execution planning
  • surface deployment binding metadata when caller passes a validated profile artifact
  • optionally hand that deployment binding into the orchestrator adapter when caller explicitly supplies runtime execution inputs

Still runtime-adapter responsibility at this stage:

  • intercepting real outgoing messages or status transitions inline
  • actually sending operator notices
  • acking final delivery to external channels
  • persisting decisions/receipts into a production decision store
  • installing schedulers / watchdog loops / bridge sender bindings

This means core/ now owns evaluation and planning semantics, while adapters still own actual enforcement side effects.

Minimal end-to-end contract slice now included

This slice now has one small but testable contract path:

  1. capability descriptor advertises real enforcement support
  2. policy evaluator emits a canonical decision from event/evidence/context
  3. decision runner converts that decision into execution planning
  4. validated profile artifact can supply deployment binding metadata
  5. runtime-integrated helper can take that binding and route it into the orchestrator adapter
  6. orchestrator adapter consumes the same binding and runs one real runtime layer
  7. the result declares:
    • adapter-dispatch actions required
    • package-core actions possible locally
    • blocked mandatory actions when capability support is missing
    • truthful delivery / receipt state
    • runtime execution result when explicitly requested

Current runtime contract in this repo is intentionally narrower than a future generalized aggregation model:

  • single notice settlement path only
  • one governance-triggered operator notice route is evaluated as one truth boundary
  • overall truth state may promote to acked only when the observed terminal outcome set for that single path is fully acked
  • mixed observed outcomes such as acked + pending or acked + blocked must stay non-acked
  • this slice does not yet claim generalized multi-notice aggregation, fan-in settlement, or cross-notice quorum semantics

This is intentionally planning-level end-to-end plus one adapter bootstrap layer, not full live inline interception. It proves contract alignment without pretending all runtime enforcement is already extracted.

What this means for implementers right now:

  • treat dispatched / pending_external_send / blocked as honest end states unless the single notice path reaches sender-backed ack proof
  • do not collapse partial success into overall acked
  • if future work introduces multiple notice paths, that must land as a separate runtime-contract slice with its own tests

Not yet included

This package still does not claim full implementation of:

  • generalized event normalization modules
  • generalized evidence builder modules
  • production decision persistence
  • complete rewrite / placeholder / review / status-downgrade adapter execution
  • non-watchdog full runtime governance interception

It now provides the first package-mainline evaluator / decision-runner core, a compatibility-envelope boundary, a minimal package profile artifact/binding slice, and one profile-driven orchestrator path, but the remaining enforcement surface is still intentionally honest about adapter gaps.

Package-first smoke

Minimal package-local smoke path:

cd plugins/reporting-governance
npm test
npm run smoke
# or after package install/link
reporting-governance-package-smoke --compact

This smoke path uses package-local profiles-src/, schemas/, and scripts/ only. It writes temp runtime artifacts under a caller-provided or temp workspace and verifies the dry-run orchestrator path end to end.