Skip to content

feat(reminders): lifecycle-aware source task check#58

Merged
madtank merged 1 commit intomainfrom
orion/reminder-lifecycle
Apr 16, 2026
Merged

feat(reminders): lifecycle-aware source task check#58
madtank merged 1 commit intomainfrom
orion/reminder-lifecycle

Conversation

@madtank
Copy link
Copy Markdown
Member

@madtank madtank commented Apr 16, 2026

Summary

Closes the reminder-runner gap surfaced by tasks e032bc49 (urgent) and f00e36ac (high).

  • Terminal → stop. Before firing, fetch the source task; if it's completed/closed/done/cancelled/archived/resolved (or completed_at is set), disable the policy and skip the send. No more stale reminder floods after a task closes.
  • Pending review → reroute. If the task is flagged pending_review (status, tag, requirements.pending_review, or requirements.review_owner*), reroute the alert to review_ownercreator_fallback, prefixed with [pending review]. Stops pinging the worker about a task that isn't theirs to move.
  • Active → unchanged.
  • Skipped results do NOT advance fired_count or reschedule next_fire_at.

Files

  • ax_cli/commands/alerts.py — new _task_lifecycle() helper + _TERMINAL_TASK_STATUSES constant.
  • ax_cli/commands/reminders.py_fire_policy uses the helper; run loop short-circuits on skipped.
  • docs/reminder-lifecycle.md — full contract doc with state table, routing priority, envelope changes, backward-compat notes, test coverage.
  • tests/test_reminders_commands.py — 3 new tests (terminal skip+disable, pending_review → review_owner, pending_review fallback → creator). 220 total pass.

Test plan

  • pytest tests/test_reminders_commands.py — 8 pass (5 existing + 3 new)
  • pytest -q full suite — 220 pass
  • ruff format --check + ruff check clean
  • Post-merge: bounce dogfood reminder scheduler at /home/ax-agent/shared/worktrees/ax-cli-alerts-dogfood to pick up the new logic (separate follow-up under task 3948361d scheduler hygiene)

🤖 Generated with Claude Code

Tasks: e032bc49 (urgent) + f00e36ac (high).

Before firing a task-backed reminder policy, fetch the source task and
classify its lifecycle:

- Terminal (completed/closed/done/cancelled/canceled/archived/resolved,
  or completed_at set) → disable the policy + emit a skipped-result.
  No message is sent, fired_count does NOT advance.
- Pending review (status=pending_review, tags contains pending_review,
  requirements.pending_review truthy, or requirements.review_owner*
  set) → reroute to review_owner → creator_fallback, prefix the reason
  with [pending review]. Do not wake the assignee.
- Active → unchanged default (assignee / creator fallback).

Adds _task_lifecycle() in alerts.py; reminders.py wires it through
_fire_policy and the run loop (skipped results do not advance).

Docs: docs/reminder-lifecycle.md with the full state table, routing
priority, envelope changes, and backward-compat notes.

Tests: 3 new — terminal skip+disable, pending_review → review_owner,
pending_review fallback → creator. 220 total pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@madtank madtank merged commit 3dcc07a into main Apr 16, 2026
6 checks passed
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