Files
reporting-governance-plugin/docs/specs/reporting-governance-decision-model.md
2026-05-07 16:31:48 +08:00

25 KiB

Reporting Governance Decision Model

Purpose

This document defines the canonical policy decision model for the reporting-governance plugin. It specifies the stable output shape that policy evaluators, adapters, and enforcement layers use after inspecting canonical events and correlated evidence.

The decision model exists so governance can do more than merely detect risky conditions. It provides a machine-readable contract for what enforcement action must happen next, while preserving enough explanation and audit detail for operator review.

This model is designed to align with:

  • docs/specs/reporting-governance-event-model.md
  • docs/specs/reporting-governance-evidence-model.md
  • schemas/reporting-governance/event-envelope.schema.json
  • schemas/reporting-governance/evidence.schema.json

It must be able to express the four core gates discussed for the plugin:

  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 canonical decision object for all governance evaluations.
  • Separate the primary disposition from optional remediation instructions.
  • Support both blocking and non-blocking enforcement paths.
  • Preserve audit trail when messages are rewritten or statuses are downgraded.
  • Make operator-visible obligations explicit instead of implicit.
  • Remain compatible with event/evidence correlation using task_id, correlation_id, evidence references, and policy identifiers.

Canonical decision object

Every policy evaluation result should use the following logical shape.

Field Type Required Notes
decision string yes Canonical enforcement disposition from this document.
policy_id string yes Stable identifier for the policy rule that produced the decision.
severity string yes Risk/urgency classification used by enforcement and operator UX.
reason string yes Human-readable rationale describing why the decision was produced.
rewritten_message string or null yes Replacement or augmented operator-facing message text when rewrite or placeholder annotation is used.
suggested_status string or null yes Recommended workflow status after enforcement, if any.
required_actions array yes Ordered list of concrete enforcement actions to perform.
operator_notice object or null yes Operator-visible notice requirements produced by the policy.

Core decisions

The following decision values are the stable governance API surface.

1. allow

The evaluated action may proceed unchanged.

Use when:

  • required evidence threshold is met
  • no gate violation is active
  • the operator-visible reporting path is intact

Typical effect:

  • permit dispatch, reporting, or status transition without mutation

2. rewrite

The evaluated outgoing report may proceed only after governance rewrites, augments, or normalizes the message.

Use when:

  • the message is partially true but materially incomplete
  • a placeholder or weak progress report must be converted into a compliant disclosure
  • operator-facing text must include missing caveats, evidence references, or review markers

Required semantic:

  • A rewrite may alter outgoing report text but must preserve audit trail. The original attempted message should remain recoverable through runtime logs, event payload history, or explicit audit metadata.

Typical effect:

  • replace a misleading completion claim with a pending-verification notice
  • append a warning that a child result exists but forwarding integrity is degraded

3. block

The evaluated action must not proceed.

Use when:

  • required preconditions are absent
  • silent launch is forbidden by policy
  • a completion/status transition lacks minimum evidence
  • dispatch or report would violate a hard gate

Required semantic:

  • block prevents message dispatch or status transition, depending on the evaluated action.

Typical effect:

  • prevent subagent dispatch without a report anchor
  • reject a completed status update with only narrative evidence

4. require_review

The action may not be treated as accepted until explicit review occurs.

Use when:

  • evidence is moderate but not authoritative
  • policy wants human signoff before acceptance
  • there is ambiguity that should not be silently auto-resolved

Typical effect:

  • convert a completion claim into pending_verification
  • emit an operator-visible review request with linked evidence

5. force_checkpoint

Governance requires an immediate operator-visible update.

Use when:

  • a failure or integrity risk cannot remain internal-only
  • a silence window has expired
  • a child result arrived but no operator-facing follow-up was emitted

Required semantic:

  • force_checkpoint creates an immediate required operator-visible update.

Typical effect:

  • send a failure disclosure now
  • send a “result received, forwarding repair in progress” checkpoint now

6. escalate

Governance requires routing to a higher-severity handling path, watcher, or human attention tier.

Use when:

  • repeated violations occur
  • the policy breach is severe enough that ordinary review is insufficient
  • watchdog, silence, or forwarding failures require urgent visibility

Typical effect:

  • raise alert severity
  • route to incident or supervisor review channel

7. downgrade_status

Governance changes an optimistic or unsupported status to a safer state.

Use when:

  • claimed completion lacks enough evidence
  • verification is missing or inconclusive
  • a report suggests closure before policy thresholds are met

Required semantic:

  • downgrade_status changes completed -> pending_verification when evidence is insufficient.
  • Policies may also use it for other conservative reversions when explicitly configured, but completed -> pending_verification is the required baseline behavior.

Typical effect:

  • replace “done” with “pending verification”
  • preserve evidence while preventing premature closure

8. annotate_placeholder

Governance permits a placeholder or continuity marker only if it is clearly labeled as incomplete.

Use when:

  • the system must emit a temporary message to avoid blackhole behavior
  • a result is known to exist but a full normalized summary is not yet ready
  • a checkpoint is required before final synthesis is available

Typical effect:

  • produce an operator-visible placeholder such as “child result received; verified forwarding summary pending”
  • clearly distinguish placeholder reporting from real completion

Severity vocabulary

Recommended canonical severity values:

  • info
  • low
  • medium
  • high
  • critical

Interpretation:

  • info / low: mostly advisory or formatting enforcement
  • medium: normal governance correction or review requirement
  • high: active policy violation or blocked transition
  • critical: urgent anti-blackhole, incident, or escalation condition

suggested_status vocabulary

The decision model does not own the full workflow state machine, but it should use stable status suggestions that align with the event model's task_status_changed and the evidence model's verification logic.

Recommended values:

  • in_progress
  • pending_verification
  • blocked
  • failed
  • awaiting_review
  • completed

Rules:

  • allow may leave suggested_status as null when no change is needed.
  • downgrade_status should usually set suggested_status to pending_verification.
  • block may suggest blocked.
  • require_review may suggest awaiting_review or pending_verification.
  • force_checkpoint does not itself require a status change, but may pair with one.

Required actions

required_actions is an ordered list describing what enforcement must happen next. It gives adapters a consistent execution contract even when the top-level decision is the same.

Each action should use this logical shape.

Field Type Required Notes
action string yes Canonical action verb.
target string yes What the action applies to.
mandatory boolean yes Whether the action must succeed before the workflow may continue.
details object no Action-specific parameters.

Recommended action values:

  • dispatch_message
  • rewrite_message
  • append_audit_note
  • block_transition
  • set_status
  • request_review
  • emit_event
  • notify_operator
  • start_watchdog
  • raise_escalation
  • record_placeholder

Recommended target values:

  • outgoing_report
  • status_transition
  • operator_channel
  • task_record
  • event_stream
  • watchdog
  • review_queue

Action semantics:

  • If decision = block, at least one action should explicitly stop the attempted message or transition, usually block_transition or omission of dispatch_message plus a mandatory emit_event/notify_operator path.
  • If decision = rewrite, at least one action should preserve the audit trail, usually append_audit_note or equivalent audit emission.
  • If decision = force_checkpoint, at least one mandatory action should produce operator-visible output immediately.
  • If decision = downgrade_status, at least one mandatory set_status action should point to pending_verification when insufficient evidence caused a premature completion claim.

Operator notice

operator_notice makes operator-facing obligations explicit.

Recommended shape:

Field Type Required Notes
required boolean yes Whether governance requires an operator-visible notice.
channel string or null yes Intended destination channel if known.
urgency string or null yes Operator-facing urgency hint.
message string or null yes Notice text or summary to send.
must_reference array no Evidence/event refs that must be mentioned or linked.
deadline string or null yes RFC 3339 deadline for the notice, if any.

Semantics:

  • operator_notice.required = true is expected for force_checkpoint, most escalate decisions, and high-risk block decisions that would otherwise be invisible.
  • annotate_placeholder should usually set operator_notice.message to clearly disclose that the update is provisional.
  • require_review should usually request review explicitly rather than implying it.

Alignment with event and evidence models

Relationship to canonical events

Decisions are produced by evaluating canonical event(s) and attached evidence. The decision object should be storable alongside or derivable from events such as:

  • report_anchor_missing
  • subagent_spawn_failed
  • silence_timeout
  • task_claimed_complete
  • subagent_completed
  • subagent_result_not_forwarded
  • forced_operator_update
  • operator_review_requested

The policy_id should identify the exact rule that interpreted those inputs.

Relationship to evidence thresholds

The decision model is intentionally downstream of the evidence model.

Recommended mappings:

  • no new evidence for a progress-bearing checkpoint -> rewrite, annotate_placeholder, or force_checkpoint, depending on policy and silence risk
  • completion claim with less than moderate support -> block or downgrade_status
  • verified completion claim without strong support -> require_review or downgrade_status
  • child completion artifact without forwarding proof -> force_checkpoint or escalate

Correlation expectations

Although not required top-level fields in the canonical decision schema, implementations should retain linkage from the evaluated event/evidence set through surrounding runtime metadata, policy logs, or action details. In particular, decisions should remain traceable to:

  • task_id
  • correlation_id
  • relevant event_id values
  • relevant evidence_id / evidence_refs

Gate mapping

1. Pre-dispatch report-anchor gate

Typical trigger:

  • attempted subagent_spawned or dispatch path where operator_context.report_anchor.present = false

Typical decisions:

  • block when anchor is mandatory and absent
  • escalate when absence persists or policy classifies it as severe
  • force_checkpoint if governance must notify the operator immediately about the blocked dispatch

Typical actions:

  • emit_event with report_anchor_missing
  • block_transition on dispatch
  • notify_operator if policy requires visible disclosure

2. Subagent failure immediate-report gate

Typical trigger:

  • subagent_spawn_failed

Typical decisions:

  • force_checkpoint as the normal baseline
  • escalate if repeated or severe

Typical actions:

  • emit_event for failure and disclosure path
  • notify_operator immediately
  • optionally raise_escalation

3. Silent-task launch blocker

Typical trigger:

  • task_started.payload.silent_task = true while policy forbids unannounced silent operation
  • silence_timeout fired with no acceptable checkpoint

Typical decisions:

  • block for forbidden silent launch
  • force_checkpoint once silence timeout has already occurred
  • annotate_placeholder when a temporary disclosure is allowed but full details are not yet ready

Typical actions:

  • stop launch or transition
  • emit silence_timeout / forced_operator_update
  • notify operator channel

4. Result-forwarding integrity gate

Typical trigger:

  • subagent_completed indicates result_available = true
  • no matching subagent_result_forwarded within policy window
  • subagent_result_not_forwarded emitted or about to be emitted

Typical decisions:

  • force_checkpoint when operator-visible follow-up is missing
  • annotate_placeholder when a stopgap message is needed immediately
  • escalate when forwarding integrity remains broken past deadline

Typical actions:

  • emit_event for integrity failure
  • record_placeholder and/or dispatch_message
  • notify_operator
  • raise_escalation for persistent failures

Enforcement semantics by decision

allow

  • permit the evaluated action unchanged
  • no rewrite or downgrade required
  • may still record a low-severity audit decision

rewrite

  • replace or augment outgoing message content
  • preserve original content in audit trail
  • do not silently rewrite without recording that a rewrite occurred

block

  • prevent the attempted message, dispatch, or status transition
  • produce an explicit reason
  • if the block itself could become invisible, pair with operator_notice.required = true

require_review

  • prevent automatic acceptance
  • route to review queue or operator channel
  • keep underlying evidence attached for audit

force_checkpoint

  • create an immediate operator-visible update
  • do not defer the notice behind the ordinary checkpoint schedule
  • may coexist with suggested_status changes or escalation

escalate

  • raise visibility, severity, or routing tier
  • should normally preserve the original violation context
  • may include mandatory operator notice and watchdog/incident actions

downgrade_status

  • change optimistic status to a safer status
  • required baseline: completed -> pending_verification when evidence is insufficient
  • should preserve the original attempted claim in audit history

annotate_placeholder

  • permit limited continuity messaging without overstating certainty
  • must label the message as provisional, incomplete, or awaiting verification/forwarding
  • should not be mistaken for successful completion

Examples

Example 1: fake progress checkpoint rewritten into an honest placeholder

Scenario:

  • A checkpoint message says “still making progress” but includes no new evidence since the previous checkpoint.
  • Policy wants to avoid fake progress while still preventing silence.

Decision example:

{
  "decision": "annotate_placeholder",
  "policy_id": "anti-fake-progress-v1",
  "severity": "medium",
  "reason": "checkpoint contains no new evidence and cannot count as substantive progress",
  "rewritten_message": "Progress update: work is still in progress, but no new auditable artifact was attached since the previous checkpoint. Next update must include a file change, tool output, or decision record.",
  "suggested_status": "in_progress",
  "required_actions": [
    {
      "action": "rewrite_message",
      "target": "outgoing_report",
      "mandatory": true,
      "details": {
        "mode": "replace_with_placeholder"
      }
    },
    {
      "action": "append_audit_note",
      "target": "task_record",
      "mandatory": true,
      "details": {
        "note": "Original progress wording preserved for audit; placeholder annotation applied."
      }
    }
  ],
  "operator_notice": {
    "required": true,
    "channel": "telegram",
    "urgency": "medium",
    "message": "Progress update sent with placeholder annotation because no new evidence was attached.",
    "must_reference": [],
    "deadline": null
  }
}

Why this matters:

  • Prevents fake progress from being treated as real progress.
  • Still avoids silent blackhole behavior.

Example 2: silence timeout requires immediate checkpoint

Scenario:

  • A governed task exceeded its checkpoint window and triggered silence_timeout.

Decision example:

{
  "decision": "force_checkpoint",
  "policy_id": "silence-timeout-v1",
  "severity": "high",
  "reason": "required reporting silence exceeded policy and the operator must receive an immediate update",
  "rewritten_message": "Required update: task exceeded the allowed silence window. Immediate checkpoint issued while work status is reconciled.",
  "suggested_status": "in_progress",
  "required_actions": [
    {
      "action": "notify_operator",
      "target": "operator_channel",
      "mandatory": true,
      "details": {
        "kind": "forced_checkpoint"
      }
    },
    {
      "action": "emit_event",
      "target": "event_stream",
      "mandatory": true,
      "details": {
        "event_type": "forced_operator_update"
      }
    }
  ],
  "operator_notice": {
    "required": true,
    "channel": "telegram",
    "urgency": "high",
    "message": "Task exceeded the allowed silence window and required an immediate checkpoint.",
    "must_reference": ["silence_timeout"],
    "deadline": "2026-05-07T16:00:00+08:00"
  }
}

Why this matters:

  • Covers the silent-task / overdue checkpoint path.
  • Makes the operator-visible update mandatory and immediate.

Example 3: unverified completion is downgraded

Scenario:

  • A task claims completed, but attached evidence is only narrative or otherwise below the moderate+ completion threshold.

Decision example:

{
  "decision": "downgrade_status",
  "policy_id": "completion-evidence-threshold-v1",
  "severity": "high",
  "reason": "completion was claimed without sufficient auditable evidence",
  "rewritten_message": "Completion claim received, but the task remains pending verification until auditable evidence is attached.",
  "suggested_status": "pending_verification",
  "required_actions": [
    {
      "action": "set_status",
      "target": "status_transition",
      "mandatory": true,
      "details": {
        "from": "completed",
        "to": "pending_verification"
      }
    },
    {
      "action": "request_review",
      "target": "review_queue",
      "mandatory": true,
      "details": {
        "review_scope": "completion_evidence"
      }
    },
    {
      "action": "append_audit_note",
      "target": "task_record",
      "mandatory": true,
      "details": {
        "note": "Original completion claim preserved; downgraded by governance due to insufficient evidence."
      }
    }
  ],
  "operator_notice": {
    "required": true,
    "channel": "telegram",
    "urgency": "high",
    "message": "Completion claim was downgraded to pending verification because sufficient evidence was not attached.",
    "must_reference": [],
    "deadline": null
  }
}

Why this matters:

  • Encodes the required completed -> pending_verification semantics.
  • Prevents premature closure.

Example 4: result arrived but operator-visible follow-up was missing

Scenario:

  • A child result exists (subagent_completed.result_available = true), but no operator-facing forwarded result was emitted within the watchdog window.
  • This is the recent failure mode the plugin must catch.

Decision example:

{
  "decision": "force_checkpoint",
  "policy_id": "result-forwarding-integrity-v1",
  "severity": "critical",
  "reason": "child result was available but no operator-visible forwarding record was produced before the watchdog deadline",
  "rewritten_message": "Checkpoint: child task result has been received, but the operator-visible forwarding step was missed. Governance is surfacing this immediately and preserving the result for follow-up.",
  "suggested_status": "pending_verification",
  "required_actions": [
    {
      "action": "notify_operator",
      "target": "operator_channel",
      "mandatory": true,
      "details": {
        "kind": "missing_forwarded_result"
      }
    },
    {
      "action": "emit_event",
      "target": "event_stream",
      "mandatory": true,
      "details": {
        "event_type": "subagent_result_not_forwarded"
      }
    },
    {
      "action": "record_placeholder",
      "target": "outgoing_report",
      "mandatory": true,
      "details": {
        "label": "result_received_forwarding_pending"
      }
    },
    {
      "action": "append_audit_note",
      "target": "task_record",
      "mandatory": true,
      "details": {
        "note": "Result existed before operator-visible follow-up; immediate checkpoint forced by governance."
      }
    }
  ],
  "operator_notice": {
    "required": true,
    "channel": "telegram",
    "urgency": "critical",
    "message": "Child result was received but not forwarded visibly in time. Immediate checkpoint issued and follow-up is now required.",
    "must_reference": [
      "subagent_completed",
      "subagent_result_not_forwarded"
    ],
    "deadline": "2026-05-07T15:49:30+08:00"
  }
}

Why this matters:

  • Covers the exact blackhole-style failure where work finished but the operator path was not updated.
  • Forces visible recovery instead of silent inconsistency.

Example 5: report-anchor gate blocks dispatch

Scenario:

  • A subagent dispatch is attempted without a required operator-visible report anchor.

Decision example:

{
  "decision": "block",
  "policy_id": "pre-dispatch-report-anchor-v1",
  "severity": "high",
  "reason": "subagent dispatch requires a report anchor, but no operator-visible anchor was present",
  "rewritten_message": null,
  "suggested_status": "blocked",
  "required_actions": [
    {
      "action": "block_transition",
      "target": "status_transition",
      "mandatory": true,
      "details": {
        "attempted_action": "subagent_dispatch"
      }
    },
    {
      "action": "emit_event",
      "target": "event_stream",
      "mandatory": true,
      "details": {
        "event_type": "report_anchor_missing"
      }
    }
  ],
  "operator_notice": {
    "required": false,
    "channel": null,
    "urgency": null,
    "message": null,
    "deadline": null
  }
}

Why this matters:

  • Expresses the hard pre-dispatch gate in a machine-enforceable way.

Example 6: subagent failure immediately escalates to operator notice

Scenario:

  • Subagent spawn failed and policy requires visible failure reporting immediately.

Decision example:

{
  "decision": "escalate",
  "policy_id": "subagent-failure-immediate-report-v1",
  "severity": "critical",
  "reason": "subagent dispatch failed and the failure cannot remain internal-only",
  "rewritten_message": "Immediate failure report: subagent dispatch failed before work could begin. Operator review and retry decision are required.",
  "suggested_status": "blocked",
  "required_actions": [
    {
      "action": "notify_operator",
      "target": "operator_channel",
      "mandatory": true,
      "details": {
        "kind": "dispatch_failure"
      }
    },
    {
      "action": "raise_escalation",
      "target": "review_queue",
      "mandatory": true,
      "details": {
        "tier": "operator_immediate"
      }
    },
    {
      "action": "emit_event",
      "target": "event_stream",
      "mandatory": true,
      "details": {
        "event_type": "forced_operator_update"
      }
    }
  ],
  "operator_notice": {
    "required": true,
    "channel": "telegram",
    "urgency": "critical",
    "message": "Subagent dispatch failed and was escalated immediately for operator attention.",
    "must_reference": ["subagent_spawn_failed"],
    "deadline": "2026-05-07T15:41:10+08:00"
  }
}

Schema alignment note

The JSON Schema in schemas/reporting-governance/decision.schema.json encodes the canonical decision shape and enumerations from this document.

In particular it should preserve:

  • the eight required core decision values
  • the required top-level output fields
  • action ordering and explicit mandatory flags
  • operator notice shape for visible enforcement obligations
  • status downgrade support for pending_verification

Stability

The core decision values and required output fields in this document are canonical governance API values. Future revisions may extend optional metadata, but should avoid breaking the decision vocabulary or enforcement semantics without an explicit version change.