Skip to content

fix(operator-queue): acknowledging a platform alert ends it (#2372) - #3338

Merged
vybe merged 2 commits into
devfrom
feature/2372-ack-platform-alerts
Oct 7, 2026
Merged

vybe merged 2 commits into
devfrom
feature/2372-ack-platform-alerts

Conversation

@obasilakis

@obasilakis obasilakis commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Answering a platform-minted alert (a request_id with a reserved platform prefix) now lands it in acknowledged with acknowledged_at set, in the same compare-and-set as the answer. An agent's own ask still lands in responded. The endings ledger stays answered / person.
  • Ingestion skips a reserved-prefix file entry that is no longer pending, and logs no bug: operator_queue.id is a global primary key — cross-agent id collision silently swallows requests #1631 WARNING for it. These entries were left in agent files by the write-back before ent#499. A pending reserved entry can still pre-create a row, so it still gets the WARNING and is never created.
  • A one-time dual-track heal (platform_alert_responded_heal on SQLite, Alembic 0093) moves rows already stuck in responded to acknowledged.

Acceptance criteria

AC Where
1. Terminal on acknowledge db/operator_queue.py respond_to_item(terminal=), services/ask_service.py answer
2. Never written back Already on dev through ent#499 (is_platform_minted in _write_responses_to_agent). Regression test: test_no_warning_and_no_write_with_the_row_gone
3. No WARNING for entries the platform wrote services/operator_queue_service.py reserved-prefix guard
4. Stuck rows heal db/migrations.py + migrations/versions/0093_platform_alert_responded_heal.py. The #1017 terminal write-back is unchanged.
5. Clearable, normal retention Follows from AC1: Clear All and the prune predicate already treat acknowledged as terminal. Test: test_clear_all_hides_an_acknowledged_platform_alert
6. Rule documented docs/memory/feature-flows/operating-room.md and the docs/memory/architecture/backend.md catalog entry. architecture.md has no Operator Queue section, and its write-path rule sends area updates to area files.

Notes for review

  • Skill-gate approvals. gate- approvals are platform-minted, so they now land in acknowledged too. skill_gate_service.resolve reads disposition first and maps both statuses to answered.
  • Heal prefix list. The heal uses a frozen copy of the prefix list, because it is a one-time fix. A test pins it equal to the live _RESERVED_ID_PREFIXES today.
  • Heal and retention. Retention keys on created_at, so a healed row older than operator_queue_retention_days is deleted at the next sweep. That is the normal window AC5 asks for.

Test plan

  • cd tests && pytest unit/test_2372_platform_alert_ack.py unit/test_2915_operator_queue_sync_honesty.py -v: 96 passed
  • Mutation check:
    • terminal=False: 3 answer-sink tests go red.
    • Guard skip removed: 2 leftover-entry tests go red.
  • Operator-queue, ask and migration unit suites: 2401 passed. The failures are 6 ent751/ent679 tests plus a test_3215 collection error. They come from the local payments_py install and also fail without this change.
  • scripts/ci/check_alembic_heads.py: 1 head, 0093.
  • CI pg-migrations: the heal on PostgreSQL.
  • /cso --diff: 0 findings (docs/security-reports/cso-diff-2026-10-07-2372-platform-alert-ack.md).

Fixes #2372

🤖 Generated with Claude Code

A platform-minted alert (a request_id with a reserved platform prefix) has
no agent audience, so the operator's answer is its last event. The answer
sink now passes terminal=is_platform_minted(item) and the respond
compare-and-set writes status='acknowledged' + acknowledged_at for those
rows. An agent's own ask still lands 'responded'. The endings ledger is
unchanged (answered / person), so the skill gate's resolver and the
Workspace views read the same ending.

Agent files written before ent#499 can still hold such an alert as a
'responded' entry, and nothing removes it. Ingestion now skips a
reserved-prefix entry that is no longer pending without the #1631
WARNING. Only a pending entry can pre-create a platform row, so that case
keeps the WARNING.

Rows already stuck in 'responded' move to 'acknowledged' once, through the
dual-track heal platform_alert_responded_heal (SQLite) and Alembic 0093.
Ids are matched the way is_platform_minted matches them, in Python,
because SQL LIKE reads the '_' in 'val_' as a wildcard.

Mutation check: with terminal=False the three answer-sink tests in
test_2372 go red; with the guard skip removed the two leftover-entry tests
go red.

Fixes #2372

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vybe

vybe commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

merge-train (mechanical): changed the body's Fixes abilityai/trinity#2372 to Fixes #2372 — issue-status-on-merge.yml doesn't parse the qualified same-repo form, so #2372 would have stranded in status-in-progress. No branch change. Validation: READY.

@vybe vybe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge-train: batch validated on train/20261007-1609 (#3349)

@vybe
vybe merged commit f6d2908 into dev Oct 7, 2026
26 checks passed
webmixgamer added a commit that referenced this pull request Oct 7, 2026
…n to 0094

dev gained `0093_platform_alert_responded_heal` (#3338) on the same parent as
this branch's `0093_agent_skill_gates` — two heads, so `upgrade head` would
apply nothing (alembic-head-watch). The revision is now
`0094_agent_skill_gates` on top of `0093_platform_alert_responded_heal`; it was
never applied to a persistent PostgreSQL (local installs are SQLite, CI and
verify-local databases are throwaway), so a rename, not a merge revision.

Conflicts: `db/migrations.py` keeps both entries (dev's heal first, then
`agent_skill_gates`; the SQLite runner tracks by name, so an install that
already applied `agent_skill_gates` is unaffected) and `tests/registry.json`
keeps both sets of entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants