Add scheduled reminders with one-shot, interval, and cron support#144
Merged
Conversation
Implement the reminders subsystem (PRD-008) using Aaron.Akka.Reminders for durable scheduling with Cronos for cron expression parsing. Two reminder modes: - Self-targeting: re-injects prompt into originating Slack thread - Autonomous: creates fresh session, posts to configured channel Core components: - ReminderManagerActor: singleton actor handling schedule/cancel/list with concurrency limits, failure tracking, and auto-cancel threshold - ReminderExecutionActor: short-lived child per execution, creates MaterializedSession via SessionPipeline - CronScheduleHelper: Cronos wrapper for next-fire computation - LLM tools: set_reminder, cancel_reminder, list_reminders - REST API: GET/POST/DELETE /api/reminders endpoints - CLI: netclaw reminder list|create|cancel|show subcommands Uses in-memory storage for MVP (reminders do not survive restarts).
…ering - Add protobuf serialization attributes to ReminderPayload, ReminderSchedule, ReminderId, and ReminderScheduleType to prevent silent empty bytes on durable storage. Convert record types to sealed classes with proper timestamp storage (long ms/ticks) and computed properties. - Wire TimeProvider through ReminderExecutionActor, replacing two DateTimeOffset.UtcNow violations. - Add try-catch to ReminderExecutionActor.PostStop to prevent disposal exceptions from propagating to the guardian. - Inject ReminderConfig into SetReminderTool, replacing hardcoded 60s minimum interval with config-driven MinIntervalSeconds. - Add GetReminderCommand/GetReminderResponse to move single-reminder filtering from REST layer to domain layer. - Move CreateReminderRequest DTO from domain protocol to Program.cs where it belongs (only used by one REST endpoint). - Delete anemic List_empty_returns_empty test that only asserted NotNull on a property that can never be null. - Replace DateTimeOffset.UtcNow with TimeProvider.System.GetUtcNow() in test helper. Remove unused variable in REST POST endpoint.
This was referenced Mar 5, 2026
Move reminder execution to file-backed definitions with pointer payloads, durable SQLite scheduling, and CLI/daemon lifecycle operations so reminders survive restarts and can be safely validated, imported, enabled, disabled, or deleted.
Introduce a six-step reminder builder with textarea-based instruction fields and wire bare reminder CLI invocation to the new Termina page. Extend daemon reminder create requests to accept explicit notify instructions from the UI flow.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
netclaw reminder list/cancel), REST API endpoints, and LLM tools (set_reminder,cancel_reminder,list_reminders)Test plan
dotnet build— 0 errors, 0 warningsdotnet test --filter Reminders— 21 tests pass (3 manager actor + 7 tool + 11 cron helper)dotnet test— full suite passes (710 tests)dotnet slopwatch analyze— 0 issues