Skip to content

[task-timer-expiry]: Task timer expiry workflow - #61

Merged
archae0pteryx merged 2 commits into
mainfrom
feat/task-timer-expiry
May 18, 2026
Merged

[task-timer-expiry]: Task timer expiry workflow#61
archae0pteryx merged 2 commits into
mainfrom
feat/task-timer-expiry

Conversation

@archae0pteryx

@archae0pteryx archae0pteryx commented May 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Persist task timers as Expired from the background expiry workflow.
  • Add a platform-neutral notification sink path and task_timer_expired notification source.
  • Keep task timer expiry scoped to AnimalDetail/notifications, without changing animal or tray expired state.

Local issue

  • Completed: issues/done/053-task-timer-expiry-workflow.md

Completion promise

Task timers have a defined expiry behavior that is persisted, tested, and reflected consistently in AnimalDetail without confusing Focus-level expired animal behavior.

Validation

  • task check

Summary by CodeRabbit

  • New Features
    • Task timers now expire and persist their "Expired" status across app restarts
    • Optional notifications alert you when task timers expire (configurable in settings)
    • Expired task timers display in task controls without affecting animal appearance or Focus timer behavior

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@archae0pteryx has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 56 minutes and 3 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7ffc14bd-bd4e-4997-a218-eb66a72c0810

📥 Commits

Reviewing files that changed from the base of the PR and between 0575184 and 15d78b1.

📒 Files selected for processing (2)
  • CONTEXT.md
  • PRD.md
📝 Walkthrough

Walkthrough

This PR implements task timer expiry detection, persistence, and notifications for the ADHD Ranch app. It adds domain models to distinguish focus and task timer expirations, a command-layer workflow that orchestrates expiry updates and notification emission, Tauri integration to emit task-expired events, and frontend UI controls and rendering for expired task timers.

Changes

Task Timer Expiry Workflow

Layer / File(s) Summary
Domain: Timer transition detection and notification source
crates/domain/src/timer_ticker.rs, crates/domain/src/notification.rs, crates/domain/src/lib.rs
TimerTransitionTarget enum distinguishes focus vs task expirations in TimerTransition. tick() is rewritten to iterate focuses and tasks, emitting transitions for expired running timers with task index and text. TaskTimerExpiredSource notification source is introduced with key "task_timer_expired" and included in all_sources(). Tests validate transition detection and notification source defaults.
Workflow: Timer expiry orchestration
crates/commands/src/timer_expiry.rs, crates/commands/src/lib.rs
NotificationRequest, NotificationSink trait, and TimerExpiryEvent enum model expiry payloads. TimerExpiryWorkflow accepts injected storage, settings, and notification sink, with run_once() iterating transitions from tick(), resolving focus/task targets, persisting timer state via FocusStore, conditionally notifying based on NotificationSource enablement, and returning TimerExpiryEvents. RecordingSink and StubStore test helpers validate persistence and notification emission/suppression.
Tauri: Platform integration and event emission
src-tauri/src/app/timer_expiry.rs
TauriNotificationSink implements NotificationSink by dispatching system notifications. Owned payload structs TimerExpiredPayload and TaskTimerExpiredPayload are defined. Scheduler loop runs workflow.run_once() in blocking task with runtime Settings from SettingsState, mapping TimerExpiryEvent variants into focus-expired or task-expired Tauri IPC events. New TASK_TIMER_EXPIRED_EVENT constant exported.
Storage: Task timer persistence validation
crates/storage/src/focus_store.rs
Tests verify MarkdownFocusStore::update_task_timer() persists Expired status correctly indexed by task position, and that out-of-range indices return FocusStoreError::TaskIndexOutOfRange.
Frontend: Settings toggle and UI rendering
src/components/SettingsWindow.tsx, src/components/AnimalDetail.test.tsx, src/components/App.test.tsx
NOTIFICATION_SOURCES includes new task_timer_expired toggle. AnimalDetail test asserts task with Expired status displays "Expired" text. App test verifies expired task timer does not add "pig-sprite--expired" class to focus pig.
Documentation and issue tracking
CHANGELOG.md, CONTEXT.md, PRD.md, issues/README.md, issues/done/053-task-timer-expiry-workflow.md
Changelog documents "053" task expiry workflow, persistence, and notification plumbing. Context and PRD clarify task timer semantics, persistence as indexed sidecar, and exclusion from animal/tray rendering. Issue moved from open to done queue.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • killallgit/adhd-ranch#51: Extends crates/domain/src/timer_ticker.rs timer-tick machinery by evolving TimerTransition to target both focus and task timers, building directly on the retrieved PR's introduction of timer_ticker::tick and TimerTransition.
  • killallgit/adhd-ranch#34: Both PRs extend the React SettingsWindow notification UI surface—[032] Preferences window #34 introduces the base Notifications settings component, while this PR adds a new task_timer_expired notification toggle to the same NOTIFICATION_SOURCES list.
  • killallgit/adhd-ranch#60: Extends per-task timer UI and persistence introduced in #60 by adding background task-timer expiry (persisting status: Expired), task-expired notifications, and AnimalDetail rendering tests, building directly on the same task-timer and sidecar groundwork.

Poem

🐰 A timer ticks for every task,
Now expired ones wear the mask,
The workflow knows just what to do—
Persist and notify, tried and true!
No pig sprite changes, fears allayed,
Just task timers, softly displayed. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly reflects the primary change: implementing a task timer expiry workflow, which is the main objective across all modified files (domain logic, storage, commands, and UI).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/task-timer-expiry

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CONTEXT.md`:
- Around line 35-36: The phrase "pinned/frozen state" in the sentence starting
"Ephemeral in the sense that pinned/frozen state is not persisted, but timers
themselves survive restarts" is undefined and confusing; update that sentence to
either define what "pinned/frozen state" means or remove it and replace with a
clear statement such as "Timers persist across restarts" (or "Timers persist
across restarts; pinned/frozen UI state is not persisted" if you intend to keep
the distinction), and ensure the wording around "ephemeral" is removed or
revised so it no longer contradicts "survive restarts."
- Around line 35-36: Split the long FocusTimer paragraph into multiple shorter
sentences or bullet points to improve readability: separate the data model
(fields: duration_secs, started_at, status) from behavior differences
(Focus-level timers driving pig scale growth and expired-focus alerts vs
Task-level timers expiring independently), persistence/ephemeral notes (timers
survive restarts but pinned/frozen state is not persisted), and UI/notification
effects (AnimalDetail shows Task timer as Expired, tray/animal rendering
unaffected by Task expiry, and the task_timer_expired notification source emits
to the platform sink). Keep references to FocusTimer, Task timer, AnimalDetail,
task_timer_expired, and pig scale growth so readers can quickly scan each
concern.

In `@PRD.md`:
- Around line 80-81: The long "Timer growth" paragraph mixes Focus timer
behavior, Task timer behavior, and implementation notes—split it into three
clear subsections or bullet groups: (1) "Focus timer" describing FocusTimer
growth from 1× to 3×, ghostly/expired rendering, tray Expired behavior, and how
adding a task revives an expired Focus; (2) "Task timers" describing per-Task
independence, persistence of status: Expired, AnimalDetail rendering of Task
timers as Expired, and the notification source task_timer_expired emitting to
the platform sink; and (3) "Implementation status" noting the pig sprite and
animal-neutral AnimalDetail; keep references to Focus, FocusTimer, Task,
AnimalDetail, and task_timer_expired so readers can map behaviors to code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: dc7cc493-2828-4a73-afbb-e42c64162bec

📥 Commits

Reviewing files that changed from the base of the PR and between f9d3b6d and 0575184.

📒 Files selected for processing (16)
  • CHANGELOG.md
  • CONTEXT.md
  • PRD.md
  • crates/commands/src/lib.rs
  • crates/commands/src/timer_expiry.rs
  • crates/domain/src/lib.rs
  • crates/domain/src/notification.rs
  • crates/domain/src/timer_ticker.rs
  • crates/storage/src/focus_store.rs
  • issues/053-task-timer-expiry-workflow.md
  • issues/README.md
  • issues/done/053-task-timer-expiry-workflow.md
  • src-tauri/src/app/timer_expiry.rs
  • src/components/AnimalDetail.test.tsx
  • src/components/App.test.tsx
  • src/components/SettingsWindow.tsx
💤 Files with no reviewable changes (2)
  • issues/053-task-timer-expiry-workflow.md
  • issues/README.md

Comment thread CONTEXT.md Outdated
Comment thread PRD.md Outdated
@archae0pteryx
archae0pteryx merged commit f654bf8 into main May 18, 2026
2 checks passed
@archae0pteryx
archae0pteryx deleted the feat/task-timer-expiry branch May 18, 2026 22:19
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