Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4640035
feat(operator-queue): platform alert registry and sweep planner (#3246)
Oct 5, 2026
2eedb0d
feat(operator-queue): subject columns, backlog sweep and one-pending-…
Oct 5, 2026
0d54903
feat(operator-queue): locked platform-alert accessors and the platfor…
Oct 5, 2026
7055064
test(operator-queue): register the #3246 C2/C3 unit files (#3246)
Oct 5, 2026
86bf259
feat(operator-queue): platform alert seam, reserved prefixes and the …
Oct 5, 2026
c1eebd8
feat(operator-queue): agent circuit breaker reports through the platf…
Oct 5, 2026
4f52195
feat(operator-queue): system agent stale base image reports through t…
Oct 5, 2026
19ef54a
feat(operator-queue): subscription headroom reports through the platf…
Oct 5, 2026
bdd77a3
feat(operator-queue): legacy skills-library adoption reports through …
Oct 5, 2026
1f49c74
feat(operator-queue): platform-ended alerts and the seen count on the…
Oct 5, 2026
edb7a5b
docs(operator-queue): platform alerts are conditions — one row per su…
Oct 5, 2026
0fbb99c
fix(operator-queue): the upgrade sweep reads raised_by, never an id s…
Oct 5, 2026
8cef624
fix(operator-queue): the platform-alert sync broadcast names its host…
Oct 5, 2026
b8ec6bf
fix(operator-queue): pin the snooze window at the headroom emitter (#…
Oct 5, 2026
2d9f665
fix(operator-queue): the #3246 refresh-vs-CAS test patched a module n…
Oct 5, 2026
cadd234
Merge remote-tracking branch 'origin/dev' into feature/3246-platform-…
trinity-ability Oct 6, 2026
f9521e9
fix(operator-queue): the platform ending reaches the loop from any th…
trinity-ability Oct 6, 2026
8f4307f
test(1816): a private loop cancels and flushes what the run spawned b…
trinity-ability Oct 6, 2026
f380f8b
test(operator-queue): an open but stopped host loop is not a spawn ta…
trinity-ability Oct 6, 2026
f6ed856
merge-train: merge dev into feature/3246-platform-alerts-one-row (#32…
trinity-ability Oct 6, 2026
f798e79
merge-train: restore #3276's registry descriptions reverted by the #3…
trinity-ability Oct 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,12 @@ OPERATOR_QUEUE_EXECUTION_ID_MAX=128 # max execution_id preserved in a
OPERATOR_QUEUE_EMAIL_MAX=320 # ent#364: addressee email length clamp (RFC 5321)
OPERATOR_QUEUE_FLOOD_ALERT_COOLDOWN_SECONDS=300 # one flood alert per agent per this window
OPERATOR_ALERT_MAX_PENDING_PER_TYPE=5 # per-(agent, type) pending budget for agent-influenceable platform alerts (#1677)
# #3246: a platform alert is one row per condition — it expires this many days after
# its LAST reading (bad value → default + WARNING) …
OPERATOR_PLATFORM_ALERT_LIFETIME_DAYS=14
# … and after a person ends one, the same reading files nothing for this many days
# unless its priority rises or a material field changes.
OPERATOR_PLATFORM_ALERT_SNOOZE_DAYS=7

# ===========================================
# SERVICE URLS (Usually no need to change)
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.hosted.yml
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ services:
- OPERATOR_QUEUE_EMAIL_MAX=${OPERATOR_QUEUE_EMAIL_MAX:-320} # ent#364: addressee email length clamp (RFC 5321)
- OPERATOR_QUEUE_FLOOD_ALERT_COOLDOWN_SECONDS=${OPERATOR_QUEUE_FLOOD_ALERT_COOLDOWN_SECONDS:-300} # one flood alert / agent / window
- OPERATOR_ALERT_MAX_PENDING_PER_TYPE=${OPERATOR_ALERT_MAX_PENDING_PER_TYPE:-5} # per-(agent,type) platform-alert budget (#1677)
- OPERATOR_PLATFORM_ALERT_LIFETIME_DAYS=${OPERATOR_PLATFORM_ALERT_LIFETIME_DAYS:-14} # #3246: platform alert expires N days after its last reading
- OPERATOR_PLATFORM_ALERT_SNOOZE_DAYS=${OPERATOR_PLATFORM_ALERT_SNOOZE_DAYS:-7} # #3246: a person's ending holds N days unless priority rises
- GITHUB_PAT=${GITHUB_PAT}
# Log Retention & Archival Configuration (#1039)
# These were MISSING from prod — prod launches standalone (no base-compose
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ services:
- OPERATOR_QUEUE_EMAIL_MAX=${OPERATOR_QUEUE_EMAIL_MAX:-320} # ent#364: addressee email length clamp (RFC 5321)
- OPERATOR_QUEUE_FLOOD_ALERT_COOLDOWN_SECONDS=${OPERATOR_QUEUE_FLOOD_ALERT_COOLDOWN_SECONDS:-300} # one flood alert / agent / window
- OPERATOR_ALERT_MAX_PENDING_PER_TYPE=${OPERATOR_ALERT_MAX_PENDING_PER_TYPE:-5} # per-(agent,type) platform-alert budget (#1677)
- OPERATOR_PLATFORM_ALERT_LIFETIME_DAYS=${OPERATOR_PLATFORM_ALERT_LIFETIME_DAYS:-14} # #3246: platform alert expires N days after its last reading
- OPERATOR_PLATFORM_ALERT_SNOOZE_DAYS=${OPERATOR_PLATFORM_ALERT_SNOOZE_DAYS:-7} # #3246: a person's ending holds N days unless priority rises
- GITHUB_PAT=${GITHUB_PAT}
# Log Retention & Archival Configuration (#1039)
# These were MISSING from prod — prod launches standalone (no base-compose
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ services:
- OPERATOR_QUEUE_EMAIL_MAX=${OPERATOR_QUEUE_EMAIL_MAX:-320} # ent#364: addressee email length clamp (RFC 5321)
- OPERATOR_QUEUE_FLOOD_ALERT_COOLDOWN_SECONDS=${OPERATOR_QUEUE_FLOOD_ALERT_COOLDOWN_SECONDS:-300} # one flood alert / agent / window
- OPERATOR_ALERT_MAX_PENDING_PER_TYPE=${OPERATOR_ALERT_MAX_PENDING_PER_TYPE:-5} # per-(agent,type) platform-alert budget (#1677)
- OPERATOR_PLATFORM_ALERT_LIFETIME_DAYS=${OPERATOR_PLATFORM_ALERT_LIFETIME_DAYS:-14} # #3246: platform alert expires N days after its last reading
- OPERATOR_PLATFORM_ALERT_SNOOZE_DAYS=${OPERATOR_PLATFORM_ALERT_SNOOZE_DAYS:-7} # #3246: a person's ending holds N days unless priority rises
- GITHUB_PAT=${GITHUB_PAT:-}
- HOST_TEMPLATES_PATH=${PWD}/config/agent-templates
# First-run default system seed (trinity-enterprise#124): a path to an
Expand Down
3 changes: 2 additions & 1 deletion docs/memory/architecture/backend.md

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion docs/memory/architecture/database.md
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ CREATE TABLE operator_queue (
-- trinity-enterprise#611 (SQLite `operator_queue_ask_object` / Alembic `0076_operator_queue_ask_object`; nullable, no backfill):
disposition TEXT, -- answered|cancelled|expired — written in the SAME CAS UPDATE that flips `status`; NULL = ended before the ledger
disposed_at TEXT,
disposed_by TEXT, -- person|timeout (an enum of two: only a person or the clock ends an ask)
disposed_by TEXT, -- person|timeout|platform — only a person or the clock ends an ASK; `platform` ends only a platform alert (#3130 superseded flood alarms, #3246 condition_cleared)
disposed_by_email TEXT, -- NULL for timeout; withheld from machine keys on get/list
disposition_reason TEXT, -- the operator's optional cancel reason (≤ 500); never in an audit row, never to a Workspace client
batch_id TEXT, -- one uuid per bulk-cancel sweep; its re-select is the sweep's CAS winners
Expand All @@ -761,6 +761,8 @@ CREATE TABLE operator_queue (
resolved_to TEXT, -- PR B: JSON list of person refs; withheld from machine keys
proposal TEXT, -- PR B: JSON, the frozen action
supersedes_expired TEXT, -- PR B: the agent's own expired predecessor (row uuid)
subject TEXT, -- #3246: a platform alert's condition key `<kind>:<key>`; at most one PENDING row per (agent_name, subject) — partial unique index uq_operator_queue_pending_subject
last_seen_at TEXT, -- #3246: the latest reading of that condition (the count rides in context.seen_count)
FOREIGN KEY (responded_by_id) REFERENCES users(id)
);
CREATE INDEX idx_operator_queue_agent ON operator_queue(agent_name);
Expand Down
2 changes: 1 addition & 1 deletion docs/memory/feature-flows/internal-system-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ would assert only that a correct container is correct.

| Boundary | Behaviour |
|---|---|
| Backend boot, container **running** | **Read-only.** `check_base_image_state()` → `result["base_image_state"]` ∈ `stale \| current \| unknown`; `action: "none"`. WARNING names the remedy; an edge-triggered `base-image-stale-` operator-queue alarm fires on `stale` **only** (a fail-open probe must never manufacture an alert, so `unknown` never alarms). **No recreate call exists in this branch** — source-pinned. The alarm's cooldown cursor is **per-process**, and `ensure_deployed` runs once per worker's lifespan, so a stale boot files one item **per worker** (`--workers 2` ⇒ 2). Deliberate: a cross-worker cursor would put Redis or a DB read on the boot path for an advisory alarm, and the un-guessable timestamped id — which is what stops an agent pre-creating and silencing it — cannot be deduped by `on_conflict_do_nothing` anyway. |
| Backend boot, container **running** | **Read-only.** `check_base_image_state()` → `result["base_image_state"]` ∈ `stale \| current \| unknown`; `action: "none"`. WARNING names the remedy; an edge-triggered `base-image-stale-` operator-queue alarm fires on `stale` **only** (a fail-open probe must never manufacture an alert, so `unknown` never alarms). **No recreate call exists in this branch** — source-pinned. The alarm's cooldown cursor is **per-process**, and `ensure_deployed` runs once per worker's lifespan, so a stale boot files one item **per worker** (`--workers 2` ⇒ 2). *(Since #3246 the alarm goes through `platform_alerts.observe` under the subject `base_image_stale:trinity-system`: every worker's reading lands on the SAME pending row (seen count + 1), the platform ends it when the image is current again, and it expires after a 30-day net — no longer one item per worker that stays until acknowledged.)* Deliberate: a cross-worker cursor would put Redis or a DB read on the boot path for an advisory alarm, and the un-guessable timestamped id — which is what stops an agent pre-creating and silencing it — cannot be deduped by `on_conflict_do_nothing` anyway. |
| Backend boot, container **stopped** | Delegates to `start_agent_internal(SYSTEM_AGENT_NAME)` instead of a bare `container_start`, inheriting the #1809 cold-start image gate, #1560 clear-before-recreate ordering, the 409/NotFound concurrent-recreate hardening and the post-recreate handle re-lookup. `recreated` / `recreate_reason` are surfaced into the result. **This is where adoption happens.** |
| `POST /api/system-agent/restart` | Explicit stop, then `start_agent_internal` — same adoption path. The response re-fetches the container so it reports the replacement's status, not the removed handle's. |

Expand Down
Loading
Loading