Skip to content

feat(core): schedule windows (time-of-day backup gating) - #12

Merged
pmaxhogan merged 1 commit into
mainfrom
claude/feat-schedule-windows
Jun 25, 2026
Merged

pmaxhogan merged 1 commit into
mainfrom
claude/feat-schedule-windows

Conversation

@pmaxhogan

Copy link
Copy Markdown
Owner

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.

Stacked on #11 (coverage gate + CONTRIBUTING). Until #11 merges, this PR's diff also shows #11's files — review the schedule-window files below. I'll rebase onto main once #11 lands to clean the diff. Targeting main so the coverage gate runs here.

Design

driven-core stays free of a timezone database, exactly like the pacer's "midnight Pacific" quota boundary: local time is derived from a fixed utc_offset_minutes the 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 injected Clock, so it's deterministic under FakeClock.

Changes

Core (driven-core)

  • ScheduleConfig + pure allows(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).
  • New PauseReason::Schedule; gate added to evaluate_gates after the battery gate. Resumes on a later cycle once the window re-opens (consistent with how battery/metered resume).
  • 6 allows() unit tests + 2 orchestrator gate tests.

Backend (src-tauri)

  • Schedule threaded through the SPEC s22 global settings group: DTO, patch, snake_case storage with #[serde(default)] (pre-V2 global blobs still deserialise), and into OrchestratorConfig with defensive clamping.
  • Tray: paused-on-schedule tooltip + non-network classification + i18n + test.

UI (ui)

  • New Settings "schedule window" section: enable toggle, from/to time inputs, 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).
  • UI: build (vue-tsc) + 165 unit tests + lint + prettier; coverage up to 81.91%.

Behaviour notes

  • Default is disabled (enabled: false) — pure V1 behaviour, the gate is inert.
  • A window that wraps past midnight (e.g. 23:00-06:00) is evaluated against the current local day, so enable both the evening day and the following morning's day for full coverage (documented on the type).

🤖 Generated with Claude Code


Generated by Claude Code

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
pmaxhogan force-pushed the claude/feat-schedule-windows branch from b2b02e0 to 89afd39 Compare June 25, 2026 16:07
@github-actions

Copy link
Copy Markdown
Contributor

Coverage

Area main this PR delta
Rust (lib crates) n/a 75.71% n/a
UI (vue/ts) n/a 81.92% n/a

Gate: informational - no main baseline cached yet; will enforce from the next PR.

@pmaxhogan
pmaxhogan merged commit 3de2cf7 into main Jun 25, 2026
15 of 16 checks passed
@pmaxhogan
pmaxhogan deleted the claude/feat-schedule-windows branch June 25, 2026 16:22
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
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.

2 participants