Add SeedStats, which reconstructs per-job execution-time aggregates from
existing log files: suffix-matched by sanitized job name, bounded by
MaxLogFiles, and tolerant of duration-less legacy logs (counted in
run/fail totals but excluded from last/avg/max). NewService folds the
seed into each JobRuntime at build time so stats survive a restart.
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>
Pass durationMS to writeRunLog and include it as 'duration' in the
log header for persistence.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add DurationMS int64 field to RunRecord and measure wall-clock
start→finish in RunJob; StartOnly jobs record 0.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cover the compact formatter with three scenarios:
- Log file present: shows base name only (not full path)
- Log file absent: formats without a log column
- Empty trigger: defaults to "Unknown"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch the jobLogs list template to TextTruncate wrapping and use
EventLine (base log filename only) instead of EventText so each
activity row stays on a single line in the jobs panel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
New feature section: store the global pause in Config so "Pause all"
survives restarts (config field, persist in SetGlobalPause, init service
and UI from it). Renumber the later plan sections and task phases to fit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Execution checklist for RELEASE-0.10-PLAN.md: 7 phases of tasks each
tagged with recommended model and thinking depth, plus a completion
checklist and definition of done.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Section 6 now includes dropping the one-time YAML import that shipped in
0.9.0: the shadow structs and import path in storage, the legacy path
names, the go.yaml.in/yaml/v4 dependency, the import tests, and the
*.yaml ignore rules.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Section 6 now preserves the startup-timing instrumentation through the
post-field-test cleanup and adds a task to refresh docs/ARCHITECTURE.md
for the per-job overlap policy, run-time statistics, and jobs_view split.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add docs/RELEASE-0.10-PLAN.md covering the open roadmap follow-ups plus
per-job overlap policy, run-time statistics, one-line activity entries,
log-name fix, and 720p window sizing. Drop the non-portable delivery
formats (.deb, installer, AppImage, Flatpak, winget) from ROADMAP.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the resolved Tray Interaction section (0.9.0) and the completed
run.go split note; keep pending follow-ups, cleanup, and packaging.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
All 8 phases of the pre-release milestone are done and committed; the
plan and task checklist are no longer needed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move Requirements, Build, Run From Source, Project Layout, and
Dependencies/mirroring out of README into docs/DEVELOPMENT.md. Update
version references to 0.9.0 and correct the storage description to JSON.
README retains user-facing sections and gains a Development link.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tests touching SysProcAttr.HideWindow/CmdLine and windowsShellCommandLine
are guarded by //go:build windows; runner_test.go drops the winproc import.
Linux cross-compile and Windows test run both clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Warm-run average (runs 2-5 of 5) via env-gated phase timers in run.go:
after Fyne app + window + tray 193 ms (was 285 ms on Fyne 2.6.3)
after newMainView 249 ms
after SetContent 252 ms
after w.Show() [TOTAL] ~414 ms (was ~644 ms, -230 ms / -36%)
Instrumentation reverted before this commit; source is clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previous commit used PowerShell process-launch timing instead of the
History tab metric. Actual warm-run figure from the in-app "Window shown
in …" event is ~400 ms, down from ~644 ms on Fyne 2.6.3 (~37% recovery).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Measured warm-run startup (launch to window creation) via PowerShell Stopwatch
across 3 runs: ~1215 ms average. Added finding for 2026-06-23 noting the
measurement method and that Fyne 2.7.4 builds cleanly with no breaking changes.
For higher-precision measurement, the GOSENTRY_TIMING instrumentation pattern
from the previous finding can be reused.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Calls desk.SetSystemTrayWindow(w) after SetSystemTrayMenu so a left-click
on the tray icon shows/focuses the window without opening the menu. The
explicit "Show" menu item is kept for right-click access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
go.mod already pins fyne.io/fyne/v2 v2.7.4 (latest 2.7.x). Verified
go mod tidy is a no-op and rebuilt under MSYS2 UCRT64/CGO: build, vet,
and go test -race ./... all green with no code changes. 2.7 changelog
review found no breaking changes affecting GoSentry.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tick P5.1 and P5.2 in the completion checklist and reword the P5.2 task line
to match what shipped in f533739: size-appropriate, transparent per-platform
icons (tray uses the small icon; Windows window/taskbar draws from the
multi-size gosentry.ico via the GLFW_ICON resource; Linux titlebar uses
IconSmall) rather than "window icon stays large".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Give the window titlebar, taskbar, and tray a size-appropriate icon with a
transparent boundary on both Windows and Linux, instead of scaling one PNG to
every size.
Assets:
- Regenerate the PNGs and gosentry.ico with feathered color-to-alpha so the
rounded-tile boundary is transparent; a binary white-key had left an opaque
halo that read as a border on dark taskbars/trays.
- Rebuild gosentry.ico as multi-size (16 hand-tuned + 32/48/256 from big) and
add a single-frame 16x16 gosentry-icon-16x16.ico for the Windows tray.
- assets.go: add IconSmall() and IconSmallICO().
Wiring:
- Windows window/taskbar: embed gosentry.ico under the GLFW_ICON resource and
skip a.SetIcon so GLFW selects the right frame per size (hand-tuned 16 for the
titlebar, a larger frame for the taskbar).
- Windows tray: SetSystemTrayIcon(IconSmallICO()), a 16x16 ICO frame.
- Linux window titlebar: a.SetIcon(IconSmall()) for a crisp ~16px _NET_WM_ICON;
tray uses the big PNG since StatusNotifierItem renders larger.
Also bump Fyne 2.6.3 -> 2.7.4 (systray 1.11.0 -> 1.12.1) and document the full
cross-platform icon strategy in assets.go, gosentry.rc, run.go, and tray.go.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add chooseFile helper (dialog.NewFileOpen) in settings_view.go and wrap
the Command entry in job_dialog.go with a Browse button so users can
pick an executable from a file picker instead of typing the path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Service.ShouldNotifyOnFailure() (reads config under mu) and call
fyne.CurrentApp().SendNotification in the mainwindow subscriber when a
Manual/Schedule run completes with State == "Failed" and the setting is on.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 3 complete: execution modes and overlap policies for job dispatch.
- Bumped version from 0.6.0 to 0.7.0 in src/app/version.go
- Added 0.7.0 entry to docs/CHANGELOG.md documenting parallel/sequential
execution modes and skip/queue overlap policies, and their interaction
with the Settings UI and manual runs.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
New src/app/run_test.go exercises the execution mode + overlap policy
dispatch paths added in P3.3, reusing the fake runJob seam:
- parallel mode starts all due jobs concurrently
- sequential mode serializes due jobs one at a time
- skip overlap policy drops a re-fire while running (no Pending)
- queue overlap policy marks Pending and re-runs after the run finishes
- RunNow refuses a manual run while another job runs in sequential mode
Helpers prime NextDue to the past and tick at the wall clock so a started
job (advanced an hour out) does not spuriously re-fire.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add Execution mode and Overlap policy widget.Select controls in
ui/settings_view.go under a new Queue section group, between the
Application and Storage sections. Both selects are primed from the
current config on open and their selected values are written back into
the config struct on save, passing through the existing UpdateSettings
validation path.
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>
Introduces ExecutionMode (parallel/sequential) and OverlapPolicy
(skip/queue) types and constants in domain/config.go, wires defaults
(parallel/skip) into loadOrCreateConfig and the normalization pass, and
adds validation in validateConfig. Adds Pending bool to JobRuntime as
the flag P3.3 will use to re-run a queued overlap. Marks P3.1 done.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Linux build host reads these scripts from a shared mount of the
Windows working tree, where autocrlf produces CRLF line endings. bash
then failed on `set -o pipefail` (trailing CR in the option name), and
the version parsed from version.go carried a trailing CR into the Docker
tag ("...:0.6.0\r": invalid reference format).
- Add .gitattributes forcing LF on *.sh so Windows checkouts stay LF.
- Strip CR from the version extraction in all three Linux build scripts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 2 (PySentry legacy removal) complete: removed legacy autostart code
for Windows and Linux, updated ignore files for JSON storage.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Drop pysentry.yaml references; add gosentry.json and jobs.json.
Keep *.yaml wildcard to ignore legacy files during import window.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The legacy tests TestParseRegistryRunValue (Windows registry-based
autostart) and TestLinuxAutostartRemovesLegacyDesktopEntry (Linux systemd
cleanup) were already removed in P2.1 and P2.2. All remaining tests in
autostart_windows_test.go and autostart_linux_test.go test the current,
non-legacy implementation (Startup folder shortcuts and desktop files).
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Drop cleanupLegacySystemdAutostart, cleanupLegacyDesktopAutostart,
legacySystemdAutostartExists, legacyDesktopAutostartExists, and their
path helpers; remove calls from SetAutostart and AutostartStatus; drop
the os/exec import. Remove TestLinuxAutostartRemovesLegacyDesktopEntry
which referenced the deleted legacyAutostartDesktopPath function.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Drop legacyAutostartName, cleanupLegacyRegistryAutostart,
legacyRegistryAutostartExists, parseRegistryRunValue, and readShortcutTarget
from autostart_windows.go; remove the corresponding legacy registry checks
from SetAutostart and AutostartStatus; delete TestParseRegistryRunValue.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 1 complete: JSON storage + exit-code removal (P1.1-P1.6).
Settings and jobs now persist as gosentry.json / jobs.json with
one-time YAML import for existing installs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
When gosentry.json / jobs.json are absent, read a pre-migration
gosentry.yaml / jobs.yaml via private yaml-tagged shadow structs and
return the data unsaved; the existing SaveConfig/SaveJobs in OpenStore
then rewrite it as JSON. Replaces the placeholder that pointed configPath
at the legacy YAML file and tried to json.Unmarshal it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ConfigFileName → "gosentry.json", JobsFileName → "jobs.json"
- Remove exported LegacyConfigFileName ("pysentry.yaml")
- Add unexported legacyYAMLConfigFileName / legacyYAMLJobsFileName for
the upcoming one-time YAML import (P1.4)
- Update store.go fallback path and comments to describe YAML→JSON
migration rather than the old PySentry→GoSentry rename
- Align store_test.go references and test comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>