feat(core): schedule windows (time-of-day backup gating) - #12
Merged
Merged
Conversation
Add an optional schedule window that pauses backups outside a user-configured local-time range and resumes automatically once the clock re-enters it (DESIGN s17, "only sync 23:00-06:00"). Core: a new `ScheduleConfig` with a pure, FakeClock-deterministic `allows()` predicate and a `PauseReason::Schedule` gate in the orchestrator, placed after the battery gate. Like the pacer's "midnight Pacific" boundary, driven-core stays free of a timezone database: local time is derived from a fixed `utc_offset_minutes` the app captures from the OS, with the same bounded-DST caveat. Same-day, midnight-wrapping, whole-day, day-of-week, and UTC-offset cases are all unit-tested, plus two orchestrator gate tests. Backend: thread the schedule through the SPEC s22 `global` settings group (DTO, patch, snake_case storage with serde(default) so pre-V2 blobs still load) into `OrchestratorConfig`, clamping defensively. Tray gains a paused-on-schedule tooltip + classification. UI: a new Settings "schedule window" section (enable, from/to times, day-of-week toggles) wired through the settings store, with TS types, i18n, and a component test. The UTC offset is captured fresh from the browser on each save. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WvXMHHbYGddVPpmQR2XmK1
pmaxhogan
force-pushed
the
claude/feat-schedule-windows
branch
from
June 25, 2026 16:07
b2b02e0 to
89afd39
Compare
Contributor
Coverage
Gate: informational - no |
pmaxhogan
added a commit
that referenced
this pull request
Jun 26, 2026
… V2+" list (C4) DESIGN s17 still listed schedule windows, pre/post shell hooks, and metered-network throttle as deferred, and the schedule-windows entry asserted "V1 does NOT ship this" - all three shipped in 0.2.0 (#12/#16/#17), plus CLI local-state inspection (#13). Annotate each "(SHIPPED 0.2.0)" + add a header note; keep the historical design text. Also note metered detection is Windows-only (conservative default on macOS/Linux). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m
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.
What
Implements schedule windows from the V2 backlog (DESIGN s17, "only sync 23:00-06:00"): an optional local-time window outside which backups pause and then resume automatically.
Design
driven-corestays free of a timezone database, exactly like the pacer's "midnight Pacific" quota boundary: local time is derived from a fixedutc_offset_minutesthe app captures from the OS/browser on each save, with the same bounded-DST caveat (documented). The gate predicate is a pure function of the injectedClock, so it's deterministic underFakeClock.Changes
Core (
driven-core)ScheduleConfig+ pureallows(now_ms)— handles same-day, midnight-wrapping (23:00-06:00), whole-day (start == end), day-of-week, and UTC-offset cases. Uses Euclidean math so a backwards/pre-epoch clock can't panic (DESIGN s18.7).PauseReason::Schedule; gate added toevaluate_gatesafter the battery gate. Resumes on a later cycle once the window re-opens (consistent with how battery/metered resume).allows()unit tests + 2 orchestrator gate tests.Backend (
src-tauri)globalsettings group: DTO, patch, snake_case storage with#[serde(default)](pre-V2globalblobs still deserialise), and intoOrchestratorConfigwith defensive clamping.UI (
ui)timeinputs, day-of-week buttons. Wired through the settings store; TS types + i18n added; component test covering enable / time-edit / day-toggle.Tests / gates (all green locally)
driven-core: schedule unit + gate tests pass; clippy clean.driven-app: 201 tests pass (incl. tray).Behaviour notes
enabled: false) — pure V1 behaviour, the gate is inert.🤖 Generated with Claude Code
Generated by Claude Code