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.mddocs/specs/reporting-governance-evidence-model.mdschemas/reporting-governance/event-envelope.schema.jsonschemas/reporting-governance/evidence.schema.json
It must be able to express the four core gates discussed for the plugin:
- Pre-dispatch report-anchor gate
- Subagent failure immediate-report gate
- Silent-task launch blocker
- 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:
blockprevents message dispatch or status transition, depending on the evaluated action.
Typical effect:
- prevent subagent dispatch without a report anchor
- reject a
completedstatus 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_checkpointcreates 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_statuschangescompleted -> pending_verificationwhen evidence is insufficient.- Policies may also use it for other conservative reversions when explicitly configured, but
completed -> pending_verificationis 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:
infolowmediumhighcritical
Interpretation:
info/low: mostly advisory or formatting enforcementmedium: normal governance correction or review requirementhigh: active policy violation or blocked transitioncritical: 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_progresspending_verificationblockedfailedawaiting_reviewcompleted
Rules:
allowmay leavesuggested_statusasnullwhen no change is needed.downgrade_statusshould usually setsuggested_statustopending_verification.blockmay suggestblocked.require_reviewmay suggestawaiting_revieworpending_verification.force_checkpointdoes 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_messagerewrite_messageappend_audit_noteblock_transitionset_statusrequest_reviewemit_eventnotify_operatorstart_watchdograise_escalationrecord_placeholder
Recommended target values:
outgoing_reportstatus_transitionoperator_channeltask_recordevent_streamwatchdogreview_queue
Action semantics:
- If
decision = block, at least one action should explicitly stop the attempted message or transition, usuallyblock_transitionor omission ofdispatch_messageplus a mandatoryemit_event/notify_operatorpath. - If
decision = rewrite, at least one action should preserve the audit trail, usuallyappend_audit_noteor 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 mandatoryset_statusaction should point topending_verificationwhen 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 = trueis expected forforce_checkpoint, mostescalatedecisions, and high-riskblockdecisions that would otherwise be invisible.annotate_placeholdershould usually setoperator_notice.messageto clearly disclose that the update is provisional.require_reviewshould 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_missingsubagent_spawn_failedsilence_timeouttask_claimed_completesubagent_completedsubagent_result_not_forwardedforced_operator_updateoperator_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, orforce_checkpoint, depending on policy and silence risk - completion claim with less than
moderatesupport ->blockordowngrade_status - verified completion claim without
strongsupport ->require_reviewordowngrade_status - child completion artifact without forwarding proof ->
force_checkpointorescalate
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_idcorrelation_id- relevant
event_idvalues - relevant
evidence_id/evidence_refs
Gate mapping
1. Pre-dispatch report-anchor gate
Typical trigger:
- attempted
subagent_spawnedor dispatch path whereoperator_context.report_anchor.present = false
Typical decisions:
blockwhen anchor is mandatory and absentescalatewhen absence persists or policy classifies it as severeforce_checkpointif governance must notify the operator immediately about the blocked dispatch
Typical actions:
emit_eventwithreport_anchor_missingblock_transitionon dispatchnotify_operatorif policy requires visible disclosure
2. Subagent failure immediate-report gate
Typical trigger:
subagent_spawn_failed
Typical decisions:
force_checkpointas the normal baselineescalateif repeated or severe
Typical actions:
emit_eventfor failure and disclosure pathnotify_operatorimmediately- optionally
raise_escalation
3. Silent-task launch blocker
Typical trigger:
task_started.payload.silent_task = truewhile policy forbids unannounced silent operationsilence_timeoutfired with no acceptable checkpoint
Typical decisions:
blockfor forbidden silent launchforce_checkpointonce silence timeout has already occurredannotate_placeholderwhen 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_completedindicatesresult_available = true- no matching
subagent_result_forwardedwithin policy window subagent_result_not_forwardedemitted or about to be emitted
Typical decisions:
force_checkpointwhen operator-visible follow-up is missingannotate_placeholderwhen a stopgap message is needed immediatelyescalatewhen forwarding integrity remains broken past deadline
Typical actions:
emit_eventfor integrity failurerecord_placeholderand/ordispatch_messagenotify_operatorraise_escalationfor 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_statuschanges 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_verificationwhen 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 themoderate+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_verificationsemantics. - 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.