DefaultTimeoutSeconds now means "no timeout" when 0/empty, and that is
the new default, rather than an invalid config forcing a positive
value. runner.RunJob avoids context.WithTimeout with a zero duration
(which would expire immediately) and instead runs on a plain
cancelable context when no timeout is configured. Per-job
TimeoutSeconds inherit semantics are unchanged.
Add an optional per-job run timeout following the overlap_policy inherit
pattern: Job.TimeoutSeconds (0 = inherit) resolves against a new
Config.DefaultTimeoutSeconds (default 30s), replacing the hard-coded 30s
guard in runner.RunJob.
- domain/storage: new fields, default 30, load-time normalization
- runner: RunJob takes an explicit timeout; StartOnly stays untimed so it
keeps measuring launch latency only
- app: effectiveTimeout resolves under mu into runEnv, threaded to runJob;
seam signature and validation updated; DisplayTimeout helper
- ui: Timeout entry in the job dialog, Default timeout in Settings, and a
Timeout row in the details panel
- tests + docs (ARCHITECTURE, STANDARDS, ROADMAP, CHANGELOG) updated;
version bumped to 0.12.0
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace overlap Pending flag with PendingRuns counter, match seed stats
by job_id, align average duration with TimedRunCount, and tidy docs.
Co-authored-by: Cursor <cursoragent@cursor.com>
Snapshot store paths under lock before async runs, roll back failed
start/save state, emit UI events only after successful persistence,
surface log write failures, and sync stale YAML docs to JSON.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Allow manual "Run now" while the scheduler is paused: pause now stops only
automatic scheduled runs (RunDue), not the user's explicit action. Drop the
paused guard in Service.RunNow and the UI pause dialog; update tests.
- Cap the details metadata caption width via a new captionValueLayout so a wider
window feeds extra space to the value column instead of the short caption.
- Reorganize the Settings tab into two columns (Application+Queue / Storage+About)
with Save spanning the full width; move the Autostart status onto its own line.
- Condense the Jobs list rows with compactVBoxLayout to fit more jobs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RunDue now resolves each job's effective overlap policy via
effectiveOverlapPolicy (job value when set, else Config.OverlapPolicy)
instead of reading the global policy once per tick. An empty
Job.OverlapPolicy inherits the global default, so normalizeJobs continues
to leave the field untouched rather than backfilling it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add RunCount, FailCount, LastDurationMS, AvgDurationMS, MaxDurationMS
to JobRuntime and fold each completed RunRecord into them via updateStats
called from executeRun.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rework RunDue/startRunLocked/executeRun so the ExecutionMode and
OverlapPolicy config knobs take effect:
- startRunLocked advances NextDue to the next occurrence instead of
zeroing it, keeping the schedule marching during an in-flight run.
- RunDue scans all due jobs: parallel starts every due, non-running job;
sequential defers a due job while any other job runs. When a job comes
due again mid-run, skip drops it and queue marks it Pending; either way
NextDue is advanced past the fired occurrence.
- executeRun re-runs a Pending job once the current run finishes.
- RunNow gains a sequential-mode guard refusing a manual run while
another job is running.
- Add anyRunningLocked and advanceNextDueLocked helpers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extracts the four dispatch functions and their private helper
runningOutput into a dedicated file so operations.go stays focused on
CRUD and settings. No behaviour change; shared helpers (prependLog,
refreshNextRunLocked, etc.) remain in operations.go where other
operations already call them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>