You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(aggregator): notification engine — class triggers, dedupe, quiet hours, escalation (#1254 slice c) #3317
Implementation slice (c) of the #1254 design (note: doc/2026-11-01T03-54-00Z_design_pwa_push_notifications.md, PR #3314; epic #1184). Depends on slice (b) push plumbing.
The engine: pollers over /api/attention.json, /api/quota.json, /api/health; class triggers exactly per design §1 — including the quota-doctrine rules (quota-wall only well before reset or on sole-door pools; routine exhaustion is silent); dedupe by (class, objectRef, state-fingerprint); 6h per-item cooldown; quiet hours (default 23:00–07:00 America/Chicago, per-subscription) with midday + window-end digests; the two-item breakthrough set (sole-door quota wall, 48h blocked-age); needs-drew escalation ladder (+24h batched reminder, +48h breakthrough-eligible, then weekly digest); every send appended to notifications.jsonl.
Defaults ship as the design §1 recommended set unless Drew rules otherwise on the design note Q1 before this lands — check the note/PR for his ruling first.
Acceptance:
Each class fires in a fixture-driven test (enter-state fires once, stay-state never re-fires, state change re-fires)
Quiet-hours sends defer to the digest; breakthrough set sends immediately
Escalation ladder advances and stops on acted-on (item leaves tier / Drew comment or action)
Send log records class, ref, timestamp for every send and suppression
Design amendment (PR #3314 @76e898324, Codex P2): the engine consumes the full attention view incl. drewExtra (non-session needs-drew items), and this slice also extends /api/attention.json to carry the drewExtra entries. Add fixture coverage: a non-session needs-drew item (decision/task/gap) fires entry + blocked-age escalation.
Design #3702 Phase 3 (audit task 5613, 2026-11-03) has stated the alert throat's truth contract in the code — pm-stack/aggregator/src/alerts.ts module header (PR #4977) — and closed the audit on #3702. What this means for this slice's dashboard classes:
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
Session / ID: task 8700 (repo-fleet-monitor run 2026-11-05T15:45:48Z)
Found via: monitor reconciliation (Duty 1 claim/label divergence repair)
Task: Claim evaporated: task 8700 is queued and unclaimed in repo-health-code-pilot, but this issue still carried claimed labels. Labels reset to the truth (queue/queued + status/needs-triage). Checkpoint stage at evaporation: handed_off.
Expectation: The next lane claim picks task 8700 up from the queued state and posts a fresh pickup note.
agent-note:v1
event: picked_up
task: 8700
lane: 335a5d1f-bfc1-4831-99ea-850c8939a727
worker: repo-worker-code
execution_lane: openchamber-scheduled-lane
issue: #3317
kind: small_fix
state_checked: 2026-11-08T01:00Z — issue #3317 OPEN; no held/user-owned/do-not-merge/do-not-auto-edit labels; design #3314 and delivery PRs #3680/#3707 are merged; no open PR for queue/8700-3317-notification-engine (#5163 search hit is unrelated).
resume: continue from the pushed task branch and finish checkpointed digest/escalation/sole-door work, then verify and open a PR.
Activity
dezren39 commentedon Nov 1, 2026
Design amendment (PR #3314 @76e898324, Codex P2): the engine consumes the full attention view incl. drewExtra (non-session needs-drew items), and this slice also extends /api/attention.json to carry the drewExtra entries. Add fixture coverage: a non-session needs-drew item (decision/task/gap) fires entry + blocked-age escalation.
feat(aggregator): alert throat — sentinel intake, Supabase ledger, We…
dezren39 commentedon Nov 3, 2026
🤖 Agent note · consumer contract now stated
Design #3702 Phase 3 (audit task 5613, 2026-11-03) has stated the alert throat's truth contract in the code —
pm-stack/aggregator/src/alerts.tsmodule header (PR #4977) — and closed the audit on #3702. What this means for this slice's dashboard classes:mergeQuietvalidates quiet prefs as values (hour 00–23, minute 00–59, per-field fallback to default; aggregator(alerts): mergeQuiet accepts out-of-range times (99:99, 24:60) — a malformed quiet window is silently reinterpreted instead of falling back to the default #3686) andinQuietHoursis the only suppression clock. New classes must consult it for non-incident classes exactly as the engine does — and must not invent a second interpretation of stored strings.delivered/escalatedrequire at least one accepted send (runAlertTickgates onsent > 0, aggregator(alerts): runAlertTick marks incidents delivered when every push send failed — critical incidents are silently lost, never retried #3685/PR fix(aggregator): retry failed incident pushes (#3685) #3690);goneis not a send.mergeClassescurrently passes any boolean key through; aggregator(alerts): bound mergeClasses keys to a class registry (#3702 disposition 4) #4981 will bound keys to a class registry once this slice names its classes. When you land them, expect the registry to become the allowlist.developing-today commentedon Nov 3, 2026
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
78 remaining items
dezren39 commentedon Nov 4, 2026
agent-note:v1
event: parked
task: 8700
lane: 1a180ae5-384f-4e71-8d77-08f7b1652c75
worker: repo-worker-code
execution_lane: openchamber-scheduled-lane
kind: small_fix
state_checked: 2026-11-04T22:57Z — issue #3317 OPEN; no hard-stop labels; no competing PR for the task branch.
artifact: queue/8700-3317-notification-engine at 3dbc9c68c8fe93210b1329bead632c6c9f5709e1, pushed; worktree /home/user/git/fleet/8700-3317-notification-engine.
implemented: derives weekly digest-only blocked-age reminder candidates with week-specific fingerprints; regression test covers weekly cadence and digest decision.
tests: bun test test/alerts.test.ts test/notifications.test.ts — 56 pass, 0 fail; git diff --check pass. bun run typecheck remains blocked by existing src/item-history.ts GhKind error.
reason: run-budget handoff; acceptance incomplete, so no PR opened.
resume: implement the durable per-subscription digest queue, quiet-window/noon batching, cancellation/acted-on escalation ladder, and production sole-door route detection; verify and open PR. Labels now show queue/parked + status/parked; work/assigned remains.
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 8, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 8, 2026
agent-note:v1
event: picked_up
task: 8700
lane: 335a5d1f-bfc1-4831-99ea-850c8939a727
worker: repo-worker-code
execution_lane: openchamber-scheduled-lane
issue: #3317
kind: small_fix
state_checked: 2026-11-08T01:00Z — issue #3317 OPEN; no held/user-owned/do-not-merge/do-not-auto-edit labels; design #3314 and delivery PRs #3680/#3707 are merged; no open PR for queue/8700-3317-notification-engine (#5163 search hit is unrelated).
resume: continue from the pushed task branch and finish checkpointed digest/escalation/sole-door work, then verify and open a PR.
developing-today commentedon Nov 8, 2026
Agent note - handed off