Skip to content

Operator queue: acknowledging a platform-minted alert leaves it responded forever — the write-back re-injects it into the agent's queue file and the #1631 guard rejects it on every boot #2372

Closed

Description

@webmixgamer

Summary

A platform-minted operator-queue alert — any row whose id carries one of _RESERVED_ID_PREFIXES (base-image-stale-, queue-flood-, poison-, sync-failing-, git-bloat-, skill-not-found-, db-backup-, …) — that an operator acknowledges in the Operations UI lands in status='responded' and can never leave it. The only responded → acknowledged transition in the codebase is the agent's file acknowledgement, and for these ids that path is structurally dead. The ~5s write-back loop then reconstructs the row into the agent's ~/.trinity/operator-queue.json whenever it is absent (so the entry cannot be removed), and the ingestion side rejects that very entry on every backend process start with

WARNING Rejecting operator-queue request '<id>' from '<agent>': ids with a reserved platform prefix are minted only by the platform (#1631)

— i.e. the platform blames the agent for an entry the platform wrote. The row stays responded (Clear All only hides terminal rows, and responded is deliberately kept) until the retention sweep deletes it at max(OPERATOR_QUEUE_RESPONDED_MIN_RETENTION_DAYS, operator_queue_retention_days) = 90 days by default, per alert.

Context

Observed on a local dev instance at dev b7bac09d with the #1816 stale-base-image alert for trinity-system (base-image-stale-trinity-system-<ts>): acknowledged on 2026-07-31, still responded and still re-injected into the system agent's queue file three weeks later; the WARNING fired twice (once per uvicorn worker) at every boot.

Mechanics (src/backend/services/operator_queue_service.py, src/backend/db/operator_queue.py):

  1. Trigger — the Operations "Acknowledge" action is respondToItem(id, 'acknowledged', '') in src/frontend/src/stores/operatorQueue.js, i.e. POST /api/operator-queue/{id}/respond. respond_to_item is type/origin-agnostic and moves pending → responded. No API route, MCP tool or UI action reaches mark_acknowledged; only the sync loop calls it, from an agent file entry.
  2. Write-back — _write_responses_to_agent takes get_responded_items_for_agent(agent) (every responded row — no type or origin filter) and appends a reconstructed entry for any row missing from the file ("Reconstruct items missing from the file (e.g. after container restart)"). Reproduced: delete the entry from the file → 6 s later Wrote 1 responses and 0 terminal-status flips back to trinity-system and it is back.
  3. Ingestion — _sync_agent rejects any file entry whose id carries a reserved prefix and continues before the status == "acknowledged" branch, so even an agent that flips the entry to acknowledged cannot close it; the rejection is logged once per (agent, id) per process — i.e. on every boot.
  4. Retention — _operator_queue_prune_predicate deletes responded rows only past max(responded_retention_days, retention_days), so the stuck state lasts 90 days by default.

Net effect: an operator action that looks terminal is not; the platform writes into an agent's queue file an entry that its own guard then refuses and logs as an impersonation attempt; and the only way out today is direct DB surgery (OperatorQueueOperations().mark_acknowledged(agent, request_id) plus hand-editing the agent file) — which is how the observed instance was cleaned up.

Acceptance Criteria

Technical Notes

Activity

  1. removed
    status-readyGreenlit and ready for development (vetted; counterpart to status-incubating)
    on Oct 7, 2026
  2. obasilakis commented on Oct 7, 2026

    @obasilakis
    Contributor

    /claim

  3. github-actions commented on Oct 7, 2026

    @github-actions

    Claimed by @obasilakis. Label status-in-progress added.

    Next steps:

    1. Create branch: feature/2372-<short-slug>
    2. Implement the feature
    3. Open a PR with Fixes #2372
  4. added
    status-in-devMerged to dev, awaiting release cut to main
    and removed on Oct 7, 2026
  5. removed
    status-in-devMerged to dev, awaiting release cut to main
    on Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions