Skip to content

[DEV-93] Add quiet hours / scheduled drain to the worker so users can limit unattended work to chosen times (e.g. nights only) - #87

Open
danii1 wants to merge 5 commits into
mainfrom
feature/dev-93-attempt-14
Open

[DEV-93] Add quiet hours / scheduled drain to the worker so users can limit unattended work to chosen times (e.g. nights only)#87
danii1 wants to merge 5 commits into
mainfrom
feature/dev-93-attempt-14

Conversation

@danii1

@danii1 danii1 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Task: DEV-93

Summary: Add quiet hours / scheduled drain to the worker so users can limit unattended work to chosen times (e.g. nights only)

Implementation Details

I'll start by reviewing the details, then set up a structured plan to tackle this task efficiently.
I have the full picture. Now implementing — starting with the core schedule library.
Now fixing two flaws I spotted while re-reviewing: the broken formatTimeWindow, the messy gap-snap loop, and the throwing OpenPickupGate.snapshot().
Now the WorkerState metadata KV (for drain timestamps):
Now the acquirer gating:
Now extending workspace config parsing:
Wiring the gate into workspace-worker.ts:
Now the dashboard API + server plumbing:
Now the run-now CLI command:
Top-level imports already cover existsSync/writeFileSync/dirname/resolve — simplifying:
Also update the worker --help to mention the new subcommand:
Now the dashboard UI — API types and StatusStrip:
Early typecheck before writing tests:
Now writing the schedule test suite:
API semantics confirmed: instantAt anchors on the local calendar day of the passed instant. The design is sound (per-zone day model); my test anchors were wrong. Fixing docs + tests:
instantAt currently lands on the EDT (first) duplicate; documented policy says standard-time (second). Adding explicit ambiguity resolution:
Schedule lib fully green. Now extending the existing test suites:
Now appending the gating tests at the end of the TaskPollingAcquirer describe block:
Full package suite:
UI builds. Now the docs — first check inbound anchor links to the section I'm replacing:
rg -r mangled the display (replacement flag) — verifying actual file contents are untouched:
Now checking cli.test.ts help-text assertions before finalizing docs:
Now the main docs rewrite — replacing the cron night recipe with the native feature:
Update the intro sentence of that doc, and the license section's cron mentions:
Now worker.md — new section plus updated cross-link:
workspaces.md — sample config, key explanations, and run-now:
Now USAGE.md:
Bump dateModified on the touched docs:
Full verification round — format, lint, typecheck, tests, build:
End-to-end smoke test of the new CLI against the built bundle:
Manual-run lifecycle confirmed. Final review of the core diff:
DEV-93 is implemented. All acceptance criteria are met, verified with 980 passing tests, clean lint/typecheck/format, and a green build across the monorepo.

What was built

Quiet hours / working windows for the worker's ready-task drain — gated at the TaskPollingAcquirer.tick() level (the "window applied to the ready-task query" shape from the task notes; the automations pattern was rejected since drain ticks are already the correct seam and in-flight tasks finish naturally via sequential execution).

Config (workspace.toml)

[worker.schedule]
active = ["22:00-06:00"]   # pick up new tracker tasks only then (local time)
blocked = []               # stay quiet even inside active windows
timezone = ""              # optional IANA name; blank = machine local time
catch_up_missed = true     # one catch-up drain after a fully missed window

New files

  • packages/code/src/lib/schedule.ts — window parsing/validation (union of actives, blocked wins on overlap, midnight wrap, equal start/end rejected), WallClock built on Intl (local time by default or named IANA zone), DST handling (spring-forward gap snaps forward ~within the lost hour; fall-back duplicates resolve to the standard-time pass), next-transition resolution that ignores no-op overlaps, missed-window/catch-up logic, the PickupGate (incl. run-now sentinel consumption and open/close flip events).
  • packages/code/tests/schedule.test.ts — 34 tests incl. real US DST dates for both transitions.

Changed behavior

  • Gating (task-polling-acquirer.ts:152): closed gate → no detect/evaluate/execute, cursors untouched; in-flight task finishes; manual/catch-up bypass one tick; schedule errors degrade to a warn-once fail-open.
  • Wiring (workspace/workspace-worker.ts): gate creation from config, startup banner (🕒 Working windows…, next flip), exactly-once-per-flip logs (🌙/[schedule]☀️), catch-up decision fed by persisted last-drain timestamp.
  • Catch-up persistence: worker_meta KV table in WorkerState (TASK_POLL_LAST_DRAIN_KEY).
  • Manual trigger: devintern worker run-now [--workspace path] writes <home>/.run-now; worker consumes it within one poll interval, drains ignoring windows.
  • Status surfaces: /api/worker now returns a schedule snapshot (embedded dashboard only) and the dashboard header strip shows inside/outside window + next open/close time.

Docs

  • automated-task-processing.md: the cron-of-the-CLI "Night-only CLI runs" recipe replaced by native quiet hours (timezone/DST/catch-up/run-now); retained scheduler-agnostic guidance (PATH pinning, user services, SSH push, process cleanup, failure feedback), leaving only estimation on timers.
  • workspaces.md + worker.md: schema, semantics, cross-links (dead #night-only-cli-runs anchors updated). USAGE.md cron snippet replaced.

Not committed — say the word if you'd like a commit/PR.


This PR was automatically created by @devintern/code

danii1 added 2 commits August 27, 2026 16:54
…ker so users can limit unattended work to chosen times (e.g. nights only)
…t-14

# Conflicts:
#	packages/code/src/lib/workspace/workspace-worker.ts
@danii1

danii1 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

🔀 This branch had merge conflicts with main; devintern resolved them and pushed the merge. Please double-check the resolution.

@danii1

danii1 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

🔀 This branch had merge conflicts with main; devintern resolved them and pushed the merge. Please double-check the resolution.

…t-14

# Conflicts:
#	packages/code/src/dashboard-server.ts
#	packages/code/src/lib/dashboard-api.ts
@danii1

danii1 commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

🔀 This branch had merge conflicts with main; devintern resolved them and pushed the merge. Please double-check the resolution.

@danii1 danii1 added the devintern-authored Pull request written by DevIntern working its own backlog label Aug 29, 2026
…t-14

# Conflicts:
#	packages/code/src/dashboard-server.ts
#	packages/code/src/lib/dashboard-api.ts
#	packages/code/src/lib/workspace/config.ts
#	packages/code/src/lib/workspace/workspace-worker.ts
#	packages/code/tests/dashboard-api.test.ts
@danii1

danii1 commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

🔀 This branch had merge conflicts with main; devintern resolved them and pushed the merge. Please double-check the resolution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devintern-authored Pull request written by DevIntern working its own backlog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants