Skip to content

feat(alerts): embed task snapshot in reminder alert metadata#56

Closed
madtank wants to merge 17 commits intomainfrom
feat/alerts-cli-mvp
Closed

feat(alerts): embed task snapshot in reminder alert metadata#56
madtank wants to merge 17 commits intomainfrom
feat/alerts-cli-mvp

Conversation

@madtank
Copy link
Copy Markdown
Member

@madtank madtank commented Apr 16, 2026

Lands PR #54 onto main. Earlier merge collapsed the task snapshot into feat/alerts-cli-mvp; this promotes it. 21 tests pass. Task e55be7c8.

anvil and others added 17 commits April 15, 2026 05:10
… MVP

First-slice MVP for task dfef4c92 (Activity Stream alerts and reminders).
Thin wrapper over POST /api/v1/messages using the existing metadata.alert
path — zero backend schema changes, no scheduler dependency.

Commands:
- ax alerts send — fire an alert/reminder with severity, target, source_task,
  due_at, remind_at, evidence. Emits metadata.ui.cards[0].type="alert" so
  the frontend's AlertCardBody renders it (verified against AxMessageWidgets).
- ax alerts reminder — shortcut for --kind reminder (source_task required).
- ax alerts ack/resolve/state — post a state-change REPLY (backend PATCH
  only accepts content, not metadata, so state transitions become first-class
  stream events referencing the parent alert via parent_message_id).

Reminder cards stay compact: no mcp_app widget, no task-board initial_data.
The card's resource_uri points at the linked task so it's clickable.

Dogfooded against next.paxai.app:
- msg 233089a7 — alert send, card type=alert, target+source_task set.
- msg 23c50444 — reminder send, kind=task_reminder, resource_uri set.

Related: 65c76d9b (CLI alert metadata), 0dacbc1e (task reminders), ebd63283
(activity stream taxonomy). Scheduler (68656c16) deferred to slice 2.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Help text for ack/resolve/state now documents:
- the "recipient acks, not firer" boundary (backend refuses self-replies)
- task 247f7bf0 as the follow-up that enables in-place state transitions

Per aX feedback on ax-cli#53.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…th design

Refinement per ChatGPT 2026-04-15 on dfef4c92 / 0dacbc1e:
tasks are canonical reminder/workflow objects; alerts are Activity Stream
events generated from (or linked to) tasks.

Changes:
- Add `snoozed` to allowed states + `ax alerts snooze <id>` command.
  Scheduler (68656c16) will re-fire at remind_at / next cadence.
- When `--source-task` is set and `--target` is omitted, auto-resolve
  target from task.assignee_id → task.creator_id. Explicit --target still
  wins for escalation. Displays "target: orion (from task assignee)" so
  users see when auto-resolution fired.
- Module docstring now states the "task = source of truth" design rule
  and points at 0dacbc1e / 68656c16 / 34bfbf6b for the scheduler-driven
  follow-up (recurring / SLA / stale-task nudges).

4 new tests (13 total for alerts, 199 full suite). Dogfooded on prod:
msg 18bb003a — reminder auto-targeted orion from task dfef4c92 assignee.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…reminders

Per ChatGPT coordination update on ax-cli#53 / b911ea19:

- Reject any --remind-at / --due-at before 2020 with a clear error that
  names the likely root cause (runner with broken/frozen clock). Real
  case caught in msg b9fb15b6 where a remind_at landed as 2000-01-01.
- Reject malformed ISO-8601 with a typed message instead of letting
  garbage flow into the alert metadata.
- Default response_required=true for --kind reminder (they're work
  nudges — recipient is expected to ack/snooze). --kind alert stays
  opt-in via --response-required.

3 new tests (16 total alerts, 202 full suite). ruff format + check clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Task e55be7c8: task reminder alert cards today truncate and surface raw
implementation fields, with no Open Task action even though the payload
includes source_task_id. This commit does the CLI-side half — enrich the
reminder envelope with a compact task snapshot (id, title, priority,
status, assignee_id, assignee_name, creator_id, deadline) so the frontend
can render task context inline without a second round-trip.

Changes
- alerts.py: extract _agent_name_for + _fetch_task_snapshot helpers
  (shared by _resolve_target_from_task).
- alerts.py: _build_alert_metadata grows a task_snapshot kwarg; when
  present, embeds at alert.task and card_payload.task.
- reminders.py: _fire_policy fetches the snapshot once per fire and passes
  it to _build_alert_metadata.
- tests: positive case (snapshot embedded with all fields) + negative case
  (fetch failure still fires reminder with source_task_id fallback).

Frontend half (task e55be7c8 assignee frontend_sentinel) renders the task
block on the alert card + wires an Open Task button to resource_uri
ui://tasks/{source_task_id}. The MCP widget ui://tasks/detail already
exists; the button is a simple MCP app link.

Validation
- PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest tests/test_alerts_commands.py tests/test_reminders_commands.py
- Result: 21 passed (19 existing + 2 new)

Task: e55be7c8-4758-434c-bea9-1a35b27a769a

Co-authored-by: anvil <anvil@ax-platform.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@madtank
Copy link
Copy Markdown
Member Author

madtank commented Apr 16, 2026

Superseded by new PR — cherry-picked #54 directly onto main (avoids squash-merge conflict from base branch).

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.

1 participant