Commit Graph

108 Commits

Author SHA1 Message Date
mixeme b45ab654c2 app/version, docs/CHANGELOG: bump to 0.10.0 (T8.1)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:26:03 +03:00
mixeme 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
mixeme 6c69f323bd runner/seed, app/service: seed run-time stats from log files (T2.5)
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>
2026-06-24 08:16:47 +03:00
mixeme 7dafa82b21 domain/runtime, app/run: add execution-time statistics aggregate (T2.4)
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>
2026-06-24 08:13:02 +03:00
mixeme 2b0cdb57f4 runner/logfile: write duration line to log header (T2.3)
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>
2026-06-24 08:11:05 +03:00
mixeme 42d73b9eb0 domain/record, runner: add DurationMS to RunRecord (T2.1, T2.2)
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>
2026-06-24 08:09:59 +03:00
mixeme 61ea3ce2af app/format_test: add EventLine test cases (T1.4)
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>
2026-06-24 07:52:53 +03:00
mixeme 0f27d75359 ui/jobs_view: render job logs as compact one-line entries (T1.2)
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>
2026-06-24 07:50:03 +03:00
mixeme 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
mixeme 3907ab3c18 P7.1: move Windows-only runner tests into runner_windows_test.go
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>
2026-06-24 00:23:25 +03:00
mixeme 0b8c340f6e Bump version to 0.9.0; update changelog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 22:46:57 +03:00
mixeme 26f58abda6 P6.2: left-click tray icon shows window via SetSystemTrayWindow
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>
2026-06-23 22:27:37 +03:00
mixeme f533739d6e P5: per-platform transparent, size-appropriate window/tray icons
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>
2026-06-23 22:09:04 +03:00
mixeme 6136bb645b Bump version to 0.8.0; update changelog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 08:20:29 +03:00
mixeme 73dae9e64c P4.2: Add Browse button for Command field in job dialog
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>
2026-06-23 08:19:40 +03:00
mixeme 564609d8fb P4.1: Wire desktop notifications for failed job runs
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>
2026-06-23 08:18:12 +03:00
mixeme fb9d0650a6 Bump version to 0.7.0; update changelog
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>
2026-06-23 08:05:03 +03:00
mixeme 6b8f9a4ccf P3.5: Add queue dispatch tests
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>
2026-06-23 08:02:20 +03:00
mixeme 94a8dcc62a P3.4: Add Queue group to settings view
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>
2026-06-23 07:57:51 +03:00
mixeme b3e699792a P3.3: Apply execution mode + overlap policy in dispatch
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>
2026-06-23 07:54:12 +03:00
mixeme d381a22034 P3.2: Move RunDue/RunNow/startRunLocked/executeRun into app/run.go
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>
2026-06-23 07:39:54 +03:00
mixeme 9b4e9ee311 P3.1: Add ExecutionMode/OverlapPolicy to Config; add Pending to JobRuntime
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>
2026-06-23 07:32:19 +03:00
mixeme 6fcaa46f7a Bump version to 0.6.0; update changelog
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>
2026-06-22 22:24:52 +03:00
mixeme db9d5adb06 P2.2: remove PySentry legacy systemd + desktop autostart from Linux
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>
2026-06-22 22:10:11 +03:00
mixeme a7faccef8a P2.1: remove PySentry legacy registry autostart from Windows
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>
2026-06-22 22:06:28 +03:00
mixeme 11b7012cf2 Bump version to 0.5.0; update changelog
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>
2026-06-22 21:58:57 +03:00
mixeme 9af279e28f P1.6: update tests and docs for JSON storage + exit-code removal
- storage/store_test.go: switch TestJobsYAMLDoesNotPersistRuntimeNoise to
  json.Marshal (renamed to TestJobsJSONDoesNotPersistRuntimeNoise); add
  TestLoadOrCreateJobsMigratesFromLegacy to cover the jobs YAML import path
- app/operations_test.go: update newTempService paths to .json filenames
- docs/TESTS.md: reflect JSON round-trip, drop SuccessExitCodes tests, remove
  Exit Code Flexibility design-principle entry
- docs/PRE-RELEASE-TASKS.md: mark P1.6 complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 21:57:39 +03:00
mixeme 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
mixeme d5418efe37 P1.4: one-time YAML import in storage
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>
2026-06-22 21:40:00 +03:00
mixeme 8df248a1b2 P1.3: rename storage files to gosentry.json / jobs.json
- 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>
2026-06-22 21:33:02 +03:00
mixeme 7ec5521309 Switch storage serialization from YAML to JSON (P1.2)
Replace writeYAML with writeJSON (json.MarshalIndent, 2-space indent,
trailing newline) and switch the config and jobs Unmarshal calls to
encoding/json. Mark P1.2 done in the pre-release task list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:24:28 +03:00
mixeme b7bbb41845 P1.1: swap yaml struct tags for json in domain types
Replace yaml:"…" tags with json:"…" on Job, Config, and JobsFile.
Add omitempty to bool fields in Config that previously lacked it.
Update comments to reference .json filenames.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 21:21:56 +03:00
mix 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
mixeme d24211cab2 Fix autostart status for paths with non-ASCII chars and spaces
readShortcut read the shortcut TargetPath via [Console]::Out.Write, which
uses the system OEM code page by default. On Russian Windows (CP866) this
encoded Cyrillic characters differently from UTF-8, so Go's string(output)
produced a garbled path that never matched os.Executable, causing
AutostartStatus to always report "shortcut points to another executable"
for any install directory that contained non-ASCII characters.

Fix: prepend [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
to the readShortcut PowerShell script so the output is always UTF-8.

Also harden sameWindowsPath against NTFS 8.3 short names: when a directory
name contains spaces Windows assigns a short name (e.g. LOCALG~1 for
"Local Git"), and the OS may use that form when launching from a
Startup-folder shortcut. Add an os.SameFile fallback that compares paths
by volume serial number and file index, which is immune to 8.3 vs long
name differences as well as directory junction points.

Add normalizeWindowsPath helper that strips quotes and the \?\ extended-
length prefix before filepath.Clean so those variants compare equal to
the plain path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 07:38:18 +03:00
mixeme 975829ed70 Improve command execution modes 2026-06-18 00:13:12 +03:00
mixeme eb6a1907e6 Document tricky design decisions
Add explanatory comments around startup timing, single-instance focus handoff, config migration, and Windows/Linux autostart choices.

The new comments capture why these implementations were chosen, what alternatives were intentionally avoided, and which user-facing problems those tradeoffs solve.
2026-06-17 23:01:05 +03:00
mixeme 2f7bbe4fca Fix startup timing measurement
Bump the version to 0.3.1 and record startup timing after the main window is actually shown.

Keep autostart launches distinct in History by recording a separate tray-start message when the UI intentionally starts hidden.
2026-06-17 22:57:23 +03:00
mixeme 94033e794f Rename project to GoSentry
Rename the application, Go module path, command package, build artifacts, resource script, and embedded icon assets from PySentry/pysentry to GoSentry/gosentry.

Move portable settings to gosentry.yaml while reading legacy pysentry.yaml during the transition, then rewrite settings under the new name.

Update Windows and Linux autostart integration to use GoSentry names while cleaning up legacy PySentry registry, desktop-entry, and systemd artifacts.

Refresh README, architecture notes, roadmap, changelog, and release examples for version 0.3.0.
2026-06-17 07:29:58 +03:00
mixeme 872cc82c5c Release version 0.2.5
Bump the application version to 0.2.5 and update documented artifact names.

Document the Windows VirtualBox/RDP OpenGL startup failure and the Mesa software OpenGL workaround.

Record the tray-icon double-click limitation in the roadmap for future Fyne or platform-specific tray work.
2026-06-16 22:08:20 +03:00
mixeme b1fe8bd675 Start autostart launches in tray
Add a shared --start-in-tray argument that lets autostart start the scheduler and tray integration without opening the main window.

Write the argument into Windows Startup shortcuts and Linux XDG Autostart desktop entries, and verify existing autostart entries include it.

Keep manual launches unchanged and let a manual second launch reveal an already-running instance while duplicate autostart launches stay hidden.
2026-06-16 21:52:00 +03:00
mixeme 44f24ab3d8 Use Startup shortcut for Windows autostart
Replace the HKCU Run autostart entry with a per-user Startup folder shortcut. A .lnk stores TargetPath separately, which avoids fragile quoting when the executable path contains spaces.

Remove legacy PySentry and GoSentry Run entries when saving autostart settings, and report shortcut status from the actual shortcut target.

Add Windows tests that create and read a temporary shortcut with spaces in the path so the PowerShell/COM invocation remains covered.
2026-06-16 21:40:48 +03:00
mixeme 0bc9e91d1e Stabilize Jobs details panel width
Wrap dynamic job detail labels so long names, schedules, commands, and status values no longer change the right panel minimum width when the selected job changes.

Point embedded and Windows resource icons at the current asset filenames so tests and Windows builds continue to work after the asset cleanup.
2026-06-16 21:24:03 +03:00
mixeme d202f8a94c Replace archived YAML dependency
Switch direct YAML usage from gopkg.in/yaml.v3 to go.yaml.in/yaml/v4, the maintained YAML org fork of the archived go-yaml repository.

Update README dependency and mirroring links so the documented source repository matches the module used by the application.
2026-06-16 08:12:14 +03:00
mixeme c1bd8c952c Release version 0.2.4
Prevent repeated application launches by using a local single-instance control channel. A second process forwards a show command to the already running instance and exits.

Bump the application version to 0.2.4 and update README artifact examples plus docs/CHANGELOG.md.
2026-06-16 08:01:42 +03:00
mixeme e8e0060063 Align Settings sections into compact rows
Add a Settings-specific row layout with a narrower label column so Storage and About no longer waste half the width on captions.

Format the Application section with the same row layout and reserve a third column for the autostart status. The checkbox column is sized to fit the longest Application checkbox so the section reads like a table.
2026-06-16 07:57:32 +03:00
mixeme 7252d3683c Clean up Settings application block
Remove the duplicated application version row from the Settings Application block now that version details live in About.

Keep the autostart control inline and shorten its checkbox text to Start on login.
2026-06-16 07:45:17 +03:00
mixeme 088f6e77b0 Add versioned Docker builder tags and Settings about block
Tag Docker builder images with the current application version in both Linux Docker build scripts so different release environments do not overwrite each other with one floating builder tag.

Replace the Settings Scheduler note with an About block that shows the GoSentry version, Go runtime version, Fyne module version, and the project repository link.
2026-06-16 07:36:00 +03:00
mixeme 4a8feb351e Release version 0.2.3
Improve the History tab by keeping records in chronological order, rendering them as a compact table, and allowing the Time column to toggle ascending or descending order.

Use the native Fyne table header so users can resize columns, including Detail and Log, and show only the log file name instead of the full log path.

Bump the application version to 0.2.3 and update README artifact examples plus docs/CHANGELOG.md.
2026-06-15 21:16:57 +03:00
mixeme e016da5277 Make History chronological and compact
Append new History events at the end instead of prepending them so the tab reads from oldest to newest.

Replace the loose widget.List rendering with a table that exposes Time, Trigger, Job, State, Detail, and Log columns. This removes the large visual gaps between rows and makes the activity log easier to scan.

Use full timestamps for UI-generated events so startup, UI actions, manual runs, and scheduled runs share the same time format.
2026-06-15 21:07:06 +03:00
mixeme c644636e57 Release version 0.2.2
Add Linux desktop integration that installs a user-level .desktop file and icon under XDG data directories so taskbars can match the PySentry window to the application icon.

Pass the installed icon path into Linux autostart desktop entries when available, while keeping the Windows and fallback autostart APIs compatible.

Bump the application version to 0.2.2, update README artifact examples, and record the release notes in docs/CHANGELOG.md. Also adjust the Mermaid architecture diagram so Gitea can render it without invalid SVG line-break tags.
2026-06-15 20:57:16 +03:00