Operant Studio
OPER-MONITOR-DRIFT-1

[OPER-MONITOR-DRIFT-1] Fix queue_liveness stale-data + in_review phantom-task false alarms

Suggested
Justin Cooke

Body

## Context

**12 post-incident tickets in AWAITING_HUMAN across Studio + Portico all trace to the same 2 broken monitors:**

**1. `queue_liveness` monitor stale-data drift** — Ledger's `lastSuccessfulDispatchAt` field for Portico shows `2026-09-02T16:40:55.693Z` (7 days stale). GitHub Actions shows Portico dispatcher successfully dispatched agents as recently as 11:56 UTC today (POR-772 stack). The monitor is reading from a field that isn't being kept fresh by the dispatcher write path.

**2. `in_review_without_pr_activity` monitor phantom-task drift** — Monitor cites `POR-132d` as a stuck in-review task; that identifier does not exist in Ledger. Every day the monitor fires again on the same phantom, generating a fresh post-incident ticket.

Cumulative noise: OPER-144, POR-757, POR-758, POR-759, POR-761, POR-765, POR-766, POR-767, POR-768, POR-769, POR-770, POR-774, POR-775.

## Goal

Both monitors read authoritative sources, produce zero false-alarms in a 72-hour observation window, and self-close when the underlying condition clears.

## Acceptance Criteria

- `queue_liveness` monitor's `lastSuccessfulDispatchAt` source switched to a computed max over the last 30 dispatch attempts (from `AgentDispatchAttempt` table) rather than a cached field. Vitest proves the cache-vs-computed drift case.
- `in_review_without_pr_activity` monitor's task-existence check runs first: if the cited task ID does not resolve to an active Ledger row, monitor no-ops instead of filing a post-incident ticket. Vitest proves the phantom-task case.
- Both monitors gain a self-close path: after 3 consecutive green readings, any open post-incident ticket authored by that monitor auto-transitions to CANCELED with a `system:monitor_recovered` comment.
- Backfill: file cancellation comments on the 13 open post-incident tickets that trace to these two monitors.
- Named failure-mode + known-bad self-test added per gate-registry pattern (rules/build-risk-matrix.md).

## Why this matters

Every stale post-incident ticket in AWAITING_HUMAN consumes attention from real work. Also: false monitors erode trust — the next real queue-liveness alarm gets ignored because it's just more noise.

blocked_by: []


---
<!-- admission-rejected -->
**Admission rejected (missing_feature_id):** ticket body is missing `feature_id: FEAT-...` frontmatter — declare which feature this ticket implements

Attachments

Loading attachments…

Comments

Loading comments…