Commit Graph
9 Commits
Author SHA1 Message Date
mixandClaude Sonnet 5 263717874c fix: remove no-op SaveJobs calls, fix PendingRuns lifecycle and cap
Implements items 4-5 of the whole-project review's suggested order
(docs/PROJECT_REVIEW_PLAN.md):

- Drop the three SaveJobs calls in the run lifecycle (startRunLocked,
  executeRun, SetGlobalPause): none of them change a durable Job field,
  everything they touch lives on JobRuntime, which is never persisted.
  Retire TestStartRunLockedRollbackOnSaveFailure with the rollback it
  guarded, since a run can no longer fail to start this way.
- Clear PendingRuns (the "queue" overlap policy's backlog) when a job is
  disabled or the scheduler is globally paused, so resuming or
  re-enabling a job no longer replays a deferred run left over from
  before the pause/disable. Cap it at maxPendingRuns (10) so a job whose
  runs take longer than its own interval stops accumulating an unbounded
  backlog. Surface the queued count in the details pane via DisplayStats.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 17:06:55 +03:00
mixemeandClaude Opus 5 e85cbc4eb1 feat: make per-job timeout 0 mean "no timeout" instead of inherit
A per-job timeout now has three distinct states: unset inherits the global
default, an explicit 0 means no timeout and does not inherit, and a positive
value is the per-job limit. Job.TimeoutSeconds became *int so unset and 0 stay
distinguishable in jobs.json.

Also fixes the global default, which could not persist a 0. loadOrCreateConfig
normalized DefaultTimeoutSeconds <= 0 back to 30 on every read of an existing
gosentry.json, so "no timeout" only held until the next restart. The field is
now written unconditionally (no omitempty) and read back as-is.

Existing jobs and configs are unaffected: a job with no timeout_seconds still
inherits, and a saved global default of 30 stays 30.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 22:44:30 +03:00
mixeme 33a246cd13 feat: make global default timeout 0 (infinite) instead of required 30s
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.
2026-07-26 13:57:03 +03:00
mixemeandClaude Opus 4.8 48faddb3bd feat: per-job command timeout with global default
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>
2026-07-25 23:24:50 +03:00
mixemeandClaude Sonnet 4.6 554ce2b93a ui/app: per-job overlap policy in job dialog and details panel
- job_dialog.go: add overlap-policy widget.Select with "(Use global
  default)" → empty, "skip", and "queue" options; pre-selects the job's
  current value; on save maps the inherit label back to empty string.
- app/format.go: add DisplayOverlapPolicy(job, globalPolicy) — returns
  the policy name when overridden, else "skip/queue (global default)".
- ui/jobs_view.go: add "Overlap policy" detail row updated in
  updateDetails using DisplayOverlapPolicy.
- settings_view.go: rename "Overlap policy" label to "Default overlap
  policy" to clarify it is the global default jobs can override.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 21:05:50 +03:00
mixemeandClaude Sonnet 4.6 886d0d9caa app/format, ui/jobs_view: DisplayStats summary + Statistics detail row (T2.6, T2.7)
Add DisplayStats to format.go: returns "No runs recorded" when RunCount is
zero, otherwise a one-line "N runs, M failed, last X ms, avg Y ms, max Z ms"
summary.  Wire a Statistics detail row into the jobs panel that refreshes via
updateDetails alongside the other runtime fields.

Tests: TestDisplayStats (nil/zero/normal/no-fail), TestUpdateStats (three
sequential fake runs through updateStats verifying all aggregate fields), and
five seed tests in runner/seed_test.go covering basic aggregation,
duration-less legacy logs, maxFiles capping, missing directory, and
unmatched log files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:24:48 +03:00
mixemeandClaude Sonnet 4.6 8fc28f592d app/format: add EventLine compact formatter (T1.1)
Uses filepath.Base for the log file so the jobs log view can show
one-line entries without the full directory path cluttering the row.
EventText is kept intact for the History table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 07:49:26 +03:00
mixemeandClaude Sonnet 4.6 fb149899e2 P1.5: drop SuccessExitCodes field and exit-code flexibility
Remove the SuccessExitCodes field from domain.Job and every layer that
read or wrote it: runner/exitcodes.go (deleted), runner.go runStateDetail
simplified to 0=OK / non-zero=Failed, logfile.go, format.go, operations.go,
store.go, job_dialog.go, and jobs_view.go. Tests updated accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 21:52:15 +03:00
mixandmixeme 01fd572a89 Refactoring complete: v0.4.0 architectural milestone (#1)
## Summary

Completed Phase 5 refactoring and reached the target architecture.

**Architectural milestone achieved:**
- Service layer owns all state and is the sole writer
- UI is a thin Fyne view, all widget updates marshaled via `fyne.Do`
- Core engines are stateless and injectable
- Domain types are pure (no `yaml:"-"` fields)
- Full module builds and `go vet ./...` clean

## Changes

- Bump version: 0.3.6 → 0.4.0
- Update CHANGELOG with Phase 5 summary
- Add ROADMAP "Refactoring Follow-Ups" section

## Known follow-up work

1. **Linux test build broken** — `runner_test.go` needs `//go:build windows` tag
2. **File-size limits exceeded** — `operations.go` (486 lines), `jobs_view.go` (415 lines)

See ROADMAP.md for details.

---------

Co-authored-by: mixeme <mix.public@ya.ru>
Reviewed-on: #1
2026-06-22 08:05:10 +03:00