Conversation
A one-time 'at' schedule with a timestamp already in the past is accepted, fires on the next scheduler tick, and the one-shot job is then deleted — so the payload runs immediately with no future occurrence and disappears. That is almost never what a caller scheduling a one-time reminder intends. Validate the 'at' timestamp against the current time in SchedulerOps.add and SchedulerOps.update (the two structured-schedule entry points) and raise a field-named ValueError before persisting, matching the existing timezone and interval validation style. Recurring cron/every schedules are unaffected. Fixes TokenRhythm#1516
|
Refreshed this PR onto the latest Verification on the refreshed head:
GitHub reports the branch as mergeable; the newly triggered CI jobs are still running. |
|
Task A refresh (2026-09-05): fetched latest Verification on the refreshed head:
No new comments/reviews or unresolved review threads. |
|
Refreshed this branch onto latest upstream/main (1663b1a); new head is 37231ee. The one-commit base update merged without conflicts, and the strict one-time schedule diff remains limited to scheduler ops plus its regression tests. Verification: 17 strict-schedule tests passed, focused Ruff passed, and git diff --check passed. |
|
Task A refresh: merged latest |
|
Task A refresh: merged latest |
|
Refreshed onto current upstream/main (cfa8e4b); merge completed without conflicts and preserved the scheduler change. New head: 172d5c4. Verification: .venv/bin/pytest -q tests/test_scheduler/test_ops_strict_schedule.py (17 passed); git diff --check refs/task-a/upstream/main...HEAD (clean). Fresh CI is running. |
|
Task A refresh: merged latest |
|
Task A refresh: merged latest Verification: |
|
Task A refresh: merged latest |
|
Task A base refresh: merged current upstream/main (a25b696) without conflicts and pushed ec50f84. The incoming base change only updates the Windows desktop icon/verification script and does not overlap this scheduler fix. Verification: PYENV_VERSION=3.11.11 uv run pytest -q tests/test_scheduler/test_ops_strict_schedule.py -> 17 passed; focused Ruff check/format and git diff --check passed. |
|
Task A base refresh: fast-forwarded to the maintainer follow-up commit ( |
|
Task A update: fast-forwarded the local branch to include the maintainer commits through Fresh verification on the updated head:
The previous CI run had two failures while still running; the new head has started a fresh CI evaluation. |
|
Refreshed this branch onto the latest |
|
Task A base refresh: merged current |
|
Task A base refresh: merged latest upstream/main (7ac8b37) without conflicts and pushed 49cda42 (0 behind / 73 ahead). The incoming skill-install work touched scheduler files, but Git reconciled it cleanly while preserving this PR’s past one-time schedule rejection. Verification: |
Scope
Integrated into main through #1684, retaining the original contribution and maintainer follow-up commits. This PR is closed as superseded by that merged integration.
Past one-time schedules previously executed immediately and disappeared after their run. New or rescheduled
atjobs now reject past timestamps before persistence, with an actionable field-named error.Scope boundary: scheduler creation/update validation, idempotent creation, the cron update RPC, and regression tests. An update containing both an enabled toggle and an invalid schedule leaves the entire stored job unchanged. Valid combined updates persist once. Idempotent retries return an existing job even after its scheduled time; only a genuinely new job is checked for expiry, after acquiring the creation lock with a fresh clock.
Recurring schedules and metadata-only changes to existing overdue jobs retain their behavior.
Branch
Base branch: main.
Target exception: none.
Integrated mainline fixes: #1674 (SQLite fallback connection compatibility) and #1677 (atomic initial generated publication receipts) resolve existing main-branch failures exposed by CI. Both fixes are included and tested with this change. #1674 and #1677 both merged separately after their own review and required CI checks.
Issue
Linked issue: Refs #1516. The closing reference is carried by the stable integration in #1684.
Release Note
Release note: Reject expired one-time reminders without partially updating tasks or breaking idempotent creation retries. No standalone changelog entry added.
Tests
git diff --checkpassed.Maintainer Live Check
Maintainer live check: no.
Surface: gateway.
Safety
Offline, deterministic, credential-free tests use synthetic jobs and isolated temporary databases. No secrets, runtime transcripts, or local artifacts are included.
Third-Party Origin
Third-party origin: original OpenSquilla contribution by @lifelmy, retained with its commit history in #1684. Maintainer follow-ups make updates atomic and preserve idempotent retries. No external vendored implementation.