release: v1.0.3

Bump version, update CHANGELOG, and retake README screenshots
(Jobs, History, Settings) to match the current GUI.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 04:14:10 +03:00
parent 4fb9bf6ff3
commit 89f119ab3e
8 changed files with 116 additions and 40 deletions
+5 -2
View File
@@ -14,8 +14,11 @@ creating, grouping, pausing, running, and monitoring scheduled shell commands.
<table> <table>
<tr> <tr>
<td align="center"><img src="images/screenshot_jobs.PNG" alt="Jobs tab"><br><em>Jobs tab — job list with details panel and run statistics.</em></td> <td align="center"><img src="docs/screenshots/screenshot_jobs.PNG" alt="Jobs tab"><br><em>Jobs tab — job list with details panel and run statistics.</em></td>
<td align="center"><img src="images/screenshot_settings.PNG" alt="Settings tab"><br><em>Settings tab — application, queue, storage, and version info.</em></td> <td align="center"><img src="docs/screenshots/screenshot_history.PNG" alt="History tab"><br><em>History tab — past runs with trigger, state, and log file.</em></td>
</tr>
<tr>
<td align="center" colspan="2"><img src="docs/screenshots/screenshot_settings.PNG" alt="Settings tab"><br><em>Settings tab — application, queue, storage, and version info.</em></td>
</tr> </tr>
</table> </table>
+106 -34
View File
@@ -2,25 +2,13 @@
All notable GoSentry changes are recorded in this file. All notable GoSentry changes are recorded in this file.
## 1.0.2 - 2026-08-05 ## 1.0.3 - 2026-08-07
**KeepRunningInTray is wired to runtime; Windows failure notifications can show **The findings of a whole-project review: durable JSON and log writes, bounded
the app icon (experimental).** History and overlap queues, and a Jobs selection that follows the job.**
**Application:** **Application:**
- **Keep running in the system tray** now controls behaviour: with the tray on
(default), closing the window hides it and autostart uses `--start-in-tray`;
with the tray off, closing quits the app and autostart opens the main window.
- Saving a tray change updates close behaviour and the autostart entry
immediately. The notification-area icon follows the saved value after a
restart; Settings shows a hint when a restart is needed (Fyne cannot add or
remove the icon mid-session).
- A stale autostart shortcut that still passes `--start-in-tray` no longer hides
the window when the tray setting is off — saved config wins over the CLI flag.
- On Windows, failure toasts can show the app icon: after `NewWindow`,
`AppMetadata.Icon` is registered so Fyne picks up artwork without calling
`SetIcon`, which would override the PE multi-size window/taskbar icon.
- Fixed a Windows quoting bug where a job whose **Command** field held a whole - Fixed a Windows quoting bug where a job whose **Command** field held a whole
command line (a `.bat`/`.cmd` wrapper followed by an argument that itself command line (a `.bat`/`.cmd` wrapper followed by an argument that itself
ended in `.exe`) had its entire command line mistaken for the program path, ended in `.exe`) had its entire command line mistaken for the program path,
@@ -51,29 +39,51 @@ the app icon (experimental).**
gets slower the longer the app has been running. Measured on 5000 accumulated gets slower the longer the app has been running. Measured on 5000 accumulated
records, one History redraw went from **15.8 ms to 0.9 ms**; at the new cap records, one History redraw went from **15.8 ms to 0.9 ms**; at the new cap
the width rescan alone accounted for 1.5 ms of every redraw. the width rescan alone accounted for 1.5 ms of every redraw.
- Two runs of the same job that start within the same second no longer share a
log file name. The later one gets a `-2`, `-3`, … suffix instead of silently
overwriting the earlier one's log — reachable with a fast manual re-run or a
sub-second queue drain.
- A hand-edited `jobs.json` in which two entries carry the same `id` no longer
leaves them sharing one runtime, one parsed schedule, and one statistics
bucket; the duplicate is reassigned a free ID on load, as an absent ID always
was.
- The **average run duration** shown in Statistics is now the exact sum divided
by the timed-run count rather than an incrementally folded integer mean. The
old form truncated on every run and the error compounded over a job's life,
so the live figure drifted away from the one rebuilt from log files after a
restart.
- On Linux, a failure to install the `.desktop` file or icon is now reported in
History instead of being discarded, so the visible symptom — a generic dock
icon — has an explanation.
**Jobs:**
- **The Jobs tab keeps its selection on the job, not on the row.** Selecting a - **The Jobs tab keeps its selection on the job, not on the row.** Selecting a
different jobs file in Settings replaces the whole job list; the details pane different jobs file in Settings replaces the whole job list; the details pane
then described whichever job happened to land on the previously selected row — then described whichever job happened to land on the previously selected row —
or went blank if the new list was shorter — while the highlight in the list or went blank if the new list was shorter — while the highlight in the list
stayed where it was. The selection now follows the job itself, and the stayed where it was. The selection now follows the job itself, and the
highlight and the details pane always describe the same one. highlight and the details pane always describe the same one.
- Switching the **Folder** filter now keeps the current selection when the new
filter still shows that job, instead of always jumping to the folder's first
job.
**Settings:**
- **Max log files and max log age days now accept 0, meaning "keep - **Max log files and max log age days now accept 0, meaning "keep
everything."** Log cleanup already supported disabling either policy; the everything."** Log cleanup already supported disabling either policy; the
Settings form and the Service validator rejected the value that would have Settings form and the Service validator rejected the value that would have
turned it on. A config that already set either to 0 is no longer silently turned it on. A config that already set either to 0 is no longer silently
rewritten back to the 100/30 defaults on load. rewritten back to the 100/30 defaults on load.
- Opening the tab and saving no longer block the window while the autostart
**Jobs:** status is read — on Windows that check shells out to PowerShell, and it now
runs off the UI thread.
- New disabled example *Failure notification test* (folder Examples). Run it - Two spellings of the same absolute **Jobs file** path (mixed separators, a
manually to trigger a failed run and verify Settings → Notifications without trailing separator) no longer read as a change of file, so saving no longer
waiting on the scheduler. triggers a spurious reload of the file already in use.
**Documentation:** **Documentation:**
- **`docs/ARCHITECTURE.md`** — new §Platform layer: why autostart, file manager,
shell, and winproc are OS-specific; compile-time vs runtime branching; rules
for adding platform code.
- Documentation audited against the code. `ARCHITECTURE.md` — the `jobs_view.go` - Documentation audited against the code. `ARCHITECTURE.md` — the `jobs_view.go`
split is six files, not five (the state extraction was never counted), the split is six files, not five (the state extraction was never counted), the
statistics table lists `TimedRunCount`, the store edge of the diagram names statistics table lists `TimedRunCount`, the store edge of the diagram names
@@ -85,15 +95,24 @@ the app icon (experimental).**
deliberately-uncovered list covers everything the profile reports at 0%, and deliberately-uncovered list covers everything the profile reports at 0%, and
the coverage figure records how to read the total rather than the per-package the coverage figure records how to read the total rather than the per-package
lines. `ROADMAP.md` — the over-the-guideline table was re-measured. lines. `ROADMAP.md` — the over-the-guideline table was re-measured.
- README's scheduler wording caught up with the 0.11.2 rename of "Pause all" to
**Disable auto**, and its notification description matches what the app sends.
- `STANDARDS.md` records the rules the review settled: no file I/O under
`Service.mu`, the History and pending-run caps, the zero-retention meaning,
that a start-only process outlives GoSentry, the single-instance fallback's
consequence, and the unauthenticated instance-channel port.
- `docs/REVIEW.md` (the whole-project review agenda) and the working plan it
produced are retired now that every item is either landed here or recorded in
`ROADMAP.md`, the way the test review plan was in 1.0.1. `STANDARDS.md` is the
surviving reference.
- The screenshots moved to `docs/screenshots/`.
**Internal:** **Internal:**
- App-side failure-notification timing is appended to `logs/notify-timing.tsv` - The failure-notification timing diagnostic added in 1.0.2 is now written to
for diagnosing toast delay (OS latency excluded). The `.tsv` extension keeps `logs/notify-timing.tsv`. The `.tsv` extension keeps it out of `CleanupLogs`,
the diagnostic file out of `CleanupLogs`, which manages only `.log` files, so which manages only `.log` files, so it is neither deleted by age nor counted
it is neither deleted by age nor counted against **Max log files**. The append against **Max log files**, and the append now runs off the UI thread.
runs off the UI thread. `scripts/measure-windows-toast.ps1` measures the
PowerShell baseline on Windows.
- `jobs.json` is no longer rewritten twice per run. Starting and finishing a run - `jobs.json` is no longer rewritten twice per run. Starting and finishing a run
touch only `JobRuntime`, which is never persisted, so both saves re-serialised touch only `JobRuntime`, which is never persisted, so both saves re-serialised
identical bytes; `SetGlobalPause` did the same alongside its real `SaveConfig`. identical bytes; `SetGlobalPause` did the same alongside its real `SaveConfig`.
@@ -108,10 +127,63 @@ the app icon (experimental).**
instead of twice. instead of twice.
- The Jobs tab was split into `jobs_view.go` (construction, refresh, layout), - The Jobs tab was split into `jobs_view.go` (construction, refresh, layout),
`jobs_view_state.go` (the job/runtime snapshot, folder filter, and selection), `jobs_view_state.go` (the job/runtime snapshot, folder filter, and selection),
`jobs_view_list.go`, and `jobs_view_toolbar.go`. What used to be one 330-line `jobs_view_list.go`, and `jobs_view_toolbar.go`, joining the existing
constructor whose dozen closures shared seven mutable locals is now widgets `jobs_view_details.go` and `jobs_view_helpers.go`. What used to be one
reading one named state object — which is what made the selection fix above a 330-line constructor whose dozen closures shared seven mutable locals is now
change in one place instead of five. widgets reading one named state object — which is what made the selection fix
above a change in one place instead of five.
- `Service.Store()` is replaced by typed `Service.Config()` and `Service.Paths()`
accessors that copy under the lock, so the UI no longer reaches into a shared
`*storage.Store`. The Jobs pause control is now driven by `refreshView`
reading `svc.Config().Paused` on every event, making it a real consumer of
`SchedulerStateChanged`, and the main window's event listener is a type switch.
- Dead code removed: `collectActivity`, the `yaml` tags on `RunRecord`, the
`logArguments`/`LogArguments` alias, the redundant package-level
`SetAutostart`/`AutostartStatus` functions, and the Settings Save handler's
second copy of the Service's validation rules. The
`systemTrayRegistered`/`mainWindowHidden` globals are one `trayState` value
that `Run` owns and threads through.
- `scripts/test.bat` no longer prints mojibake for its checkmarks under a
non-UTF-8 code page.
## 1.0.2 - 2026-08-05
**KeepRunningInTray is wired to runtime; Windows failure notifications can show
the app icon (experimental).**
**Application:**
- **Keep running in the system tray** now controls behaviour: with the tray on
(default), closing the window hides it and autostart uses `--start-in-tray`;
with the tray off, closing quits the app and autostart opens the main window.
- Saving a tray change updates close behaviour and the autostart entry
immediately. The notification-area icon follows the saved value after a
restart; Settings shows a hint when a restart is needed (Fyne cannot add or
remove the icon mid-session).
- A stale autostart shortcut that still passes `--start-in-tray` no longer hides
the window when the tray setting is off — saved config wins over the CLI flag.
- On Windows, failure toasts can show the app icon: after `NewWindow`,
`AppMetadata.Icon` is registered so Fyne picks up artwork without calling
`SetIcon`, which would override the PE multi-size window/taskbar icon.
**Jobs:**
- New disabled example *Failure notification test* (folder Examples). Run it
manually to trigger a failed run and verify Settings → Notifications without
waiting on the scheduler.
**Documentation:**
- **`docs/ARCHITECTURE.md`** — new §Platform layer: why autostart, file manager,
shell, and winproc are OS-specific; compile-time vs runtime branching; rules
for adding platform code.
**Internal:**
- App-side failure-notification timing is appended to `logs/notify-timing.log`
for diagnosing toast delay (OS latency excluded).
`scripts/measure-windows-toast.ps1` measures the PowerShell baseline on
Windows.
## 1.0.1 - 2026-08-04 ## 1.0.1 - 2026-08-04
+3 -2
View File
@@ -280,8 +280,9 @@ Before tagging:
1. Bump `src/app/version.go`. The tag must match it exactly. 1. Bump `src/app/version.go`. The tag must match it exactly.
2. Add the version's [CHANGELOG.md](CHANGELOG.md) section. 2. Add the version's [CHANGELOG.md](CHANGELOG.md) section.
3. Retake the README screenshots (`images/screenshot_jobs.PNG`, 3. Retake the README screenshots (`docs/screenshots/screenshot_jobs.PNG`,
`images/screenshot_settings.PNG`) if the GUI changed its appearance. This is `docs/screenshots/screenshot_settings.PNG`,
`docs/screenshots/screenshot_history.PNG`) if the GUI changed its appearance. This is
easy to forget because nothing fails without it: `README.md` is packaged easy to forget because nothing fails without it: `README.md` is packaged
inside every release archive and is what the forge shows on the project page, inside every release archive and is what the forge shows on the project page,
so a stale shot advertises an application that no longer exists. Take them so a stale shot advertises an application that no longer exists. Take them
+1 -1
View File
@@ -143,7 +143,7 @@ Design notes / open questions:
[ARCHITECTURE.md](ARCHITECTURE.md) sets a ~250-line guideline per source file [ARCHITECTURE.md](ARCHITECTURE.md) sets a ~250-line guideline per source file
and records the `jobs_view.go` and `settings_view.go` splits as the worked and records the `jobs_view.go` and `settings_view.go` splits as the worked
examples. `jobs_view.go` was split again in 1.0.2 — into view, state, list, and examples. `jobs_view.go` was split again in 1.0.3 — into view, state, list, and
toolbar — because the selection defect it carried was a symptom of the size toolbar — because the selection defect it carried was a symptom of the size
(one 330-line constructor over seven shared locals). Six non-test files are (one 330-line constructor over seven shared locals). Six non-test files are
over the guideline: over the guideline:
Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 100 KiB

+1 -1
View File
@@ -3,4 +3,4 @@ package app
// Version is the application version shown in the GUI and used by build // Version is the application version shown in the GUI and used by build
// scripts in artifact names. It is a var rather than a const so release builds // scripts in artifact names. It is a var rather than a const so release builds
// can override it with Go ldflags when CI tags a build. // can override it with Go ldflags when CI tags a build.
var Version = "1.0.2" var Version = "1.0.3"