Close the Unreleased section as 0.14.0 and fill the gaps in it: the Folder
caption moving onto the filter row, the padding around the Settings button
row, the Truncation-field refactor, the Docker build cache mount, and the
review/standards documents added since 0.13.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reading a log file meant copying the configured path out of Settings and
pasting it into a file manager. The Logs directory row now carries an Open
button beside Browse that reveals the folder directly.
The new src/platform/filemanager package holds the platform split — explorer
on Windows, xdg-open on Linux, an "unsupported" error elsewhere — and starts
the handler without waiting on it, since Explorer exits non-zero even after it
opens the window and blocking would stall the UI thread. A missing path, a
path that is a file, and a handler that will not start are all reported to the
user; the logs directory does not exist until the first run, so that case is
reachable.
The button opens whatever the field currently holds rather than the saved
config, so an edit can be checked before Save. Resolving a relative directory
against the application folder is the store's rule, so resolveConfiguredDir is
now exported as storage.ResolveConfiguredDir instead of being duplicated in
the UI.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The hint was a lone example path, which left the one-argument-per-line
convention to guesswork. It now names the rule and shows a flag plus a
path containing a space, so the absence of quoting is visible too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The caption sat on its own line above the select, costing the sidebar a full
label of height before the job list started. It now occupies the border
layout's left slot, next to the select and the view toggle, so the whole filter
is one row and the list begins a line higher.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reviewing the project used to mean re-stating what to look at every time.
docs/REVIEW.md now holds that agenda once — nine areas, each anchored to this
codebase — and both entry points point at it rather than copying it: the
/review-project command in .claude/commands, and a section in CLAUDE.md so a
plain-language review request lands in the same place.
STANDARDS.md gains a "Config file compatibility" section. The project has
applied the same rule three times (Theme, JobListView, TimeoutSeconds) without
ever writing it down: a new Config field is omitempty and its zero value means
the previous behavior, a meaningful zero is never backfilled on load, and an
unrecognised enum value reads as the default through one shared helper. With no
migration step and hand-editable files, that is what keeps older configs working.
Also removes docs/PLAN-compact-job-list.md, implemented in edabc57 — everything
but the version bump, which now waits for the release along with the rest of
the Unreleased section. .claude/settings.local.json is ignored so the shared
command can be tracked without per-developer permissions.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fyne.TextTruncate is deprecated in Fyne 2.7.4 in favour of the widget's
Truncation field. Behaviour is unchanged: a long job name is clipped rather
than widening the row, which is what keeps the compact row's status pinned to
the right-hand edge.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Agent sessions did not pick up docs/STANDARDS.md automatically. CLAUDE.md is
loaded every session, so it links the standards, architecture, and test docs,
repeats the few rules most often broken, and records the CGO/MSYS2 build
prerequisite and the commit-to-main convention.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each job can now render as a single line — name on the left, status on the
right — instead of the three-line block, so many more jobs fit without
scrolling. A toggle button beside the Folder filter switches between the two
modes and is labelled with the action it performs, matching the existing
"Disable auto" convention.
The choice is persisted as Config.JobListView ("detailed" / "compact", stored
as job_list_view in gosentry.json). Empty, legacy, and unrecognised values all
normalize to detailed, so existing installs keep the current look and the file
never gains a value no reader understands.
Selection, the details panel, the folder filter, and live status updates work
unchanged in both modes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
The plan now uses a button that flips its own text and icon (Compact +
ListIcon / Detailed + ViewFullScreenIcon), mirroring the existing
stopAllButton idiom, instead of a "View" dropdown. It sits beside the folder
filter on the same row via a border layout, so the sidebar header keeps its
current height and the toolbar row is untouched.
The label helpers become nextJobListView and viewToggleText, with tests and
the verification steps updated to match.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Plans an opt-in one-line rendering of the Jobs tab list (name left, status
right) alongside the current three-line detailed rows, switched from a "View"
dropdown beside the Folder filter and persisted as a new Config.JobListView
field.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Save/Cancel/Defaults row sat flush against the separator above it
and the tab's left edge, tighter than the other vertical gaps in the
tab. Add matching padding spacers to bring it in line.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Give the light variant a soft teal window canvas with white inputs,
menus, dialogs, and buttons on top, plus teal-tinted separators, input
borders, and table headers. Cards and fields now lift off a branded
background instead of reading as a plain accent swap on gray. Text stays
dark (delegated to the base foreground) for high contrast on both the
teal canvas and the white surfaces.
Lock the teal canvas and white input background into the theme tests so
the light look cannot silently regress.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cancel discards unsaved edits by reloading the saved config; Defaults
loads built-in default values into the form for review before saving.
Extracts the default config into domain.DefaultConfig() so the store
and settings UI share one source of truth.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add a custom Fyne theme derived from the logo and app icon (deep teal
primary, amber accent, branded job-status colors) with light and dark
variants, and let the user choose between it and Fyne's default theme
from Settings. The dark variant uses deep-teal surfaces to echo the app
icon.
The choice is persisted as a new Config.Theme field ("default" /
"gosentry"), applied at startup before the first frame and live-previewed
when picked in Settings. Empty/legacy configs normalize to the default
theme so existing installs keep the original look.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the <owner>/<repo> placeholders with the actual GitHub release repo
now that it's known.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Plan a best-effort, opt-in check that compares app.Version against the
latest published GitHub Release and surfaces an "Update available" hint in
Settings — detection and notification only, no auto-download.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The per-job command timeout is now shipped (0.12.0); its ROADMAP entry is
gone, so the implementation plan is no longer needed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
Add a Platforms section to the README stating that autostart and desktop
integration are implemented only on Windows and Linux; macOS may build the
GUI but those features are stubbed. Avoids over-promising ahead of 1.0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Theme-aware <picture> swaps the dark wordmark variant under
prefers-color-scheme: dark so it stays legible on GitHub's dark theme.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Recommended variant from gosentry-logo.html: Space Grotesk SemiBold with
an amber "G", a clock-dial "o" (ring + hands), and petrol "Sentry". Ships
self-contained SVGs (glyphs outlined to paths, no font dependency) in
light/dark/mono plus transparent PNGs at 256-2048px, with a README and the
gen_logo.py/raster.py generators for reproducibility.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both workflows now run on `release: published` and attach the built
archives to the release the user creates, rather than pushing a tag and
having the workflow create the release. Tag comes from the release event;
GitHub no longer regenerates release notes. Docs updated accordingly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The golang:1.22-bookworm container has no node binary and Codeberg's
runner does not inject one, so checkout/forgejo-release failed with
'node: not found'. Add a pre-checkout run step (which executes via the
container shell and needs no node itself) to apt-install nodejs before
the JS-based actions run.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codeberg's hosted runners are tagged codeberg-tiny/small/medium (+ -lazy),
not 'docker', so the job was never picked up ('No active runner with tag
docker'). The three CGO cross-compiles exceed the non-lazy 10 min cap, so
use the medium -lazy runner, which relaxes the wall-clock limit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add tag-triggered CI that builds and publishes the linux/amd64,
linux/arm64, and windows/amd64 release binaries on both forges.
- scripts/ci-build-release.sh: shared, Docker-free build+package for all
three targets (Windows cross-compiled via MinGW), reused by both
workflows so the build logic lives in one place.
- .github/workflows/release.yml: GitHub Actions, publishes via
softprops/action-gh-release using the built-in token.
- .forgejo/workflows/release.yml: Forgejo Actions for Codeberg, publishes
via forgejo-release using a RELEASE_TOKEN secret.
- .gitattributes: force LF on workflow YAML so bash run: blocks don't
break on Linux runners.
- docs/DEVELOPMENT.md: document the tag -> release flow and token setup.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The prior fix switched \n to <br/> in node labels, but Gitea's mermaid
renderer still emits unclosed <br> tags in the generated SVG regardless
of source syntax. Use single-line labels instead to avoid <br> entirely.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replace CODE_REVIEW.md with a living maturity checklist, document
session-only History, inject Service into newMainView for testability,
add UI and scheduler regression tests, and fix RunNow error surfacing
plus empty jobs view handling.
Co-authored-by: Cursor <cursoragent@cursor.com>
StartOnly jobs previously forced DurationMS to 0 because GoSentry does
not wait for the process to exit, leaving the Statistics line stuck at
"last 0 ms, avg 0 ms". The runner already measures launch latency (time
to spawn the process) for the History detail; this now returns that
value as the run duration so the existing duration-driven stats pipeline
folds it into last/avg/max.
Sub-millisecond launches still round to 0 and are excluded from the
average, matching prior behavior.
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>
Saving w.Canvas().Size() when the window is maximized persists the maximized
dimensions, corrupting the stored size for the next launch. Commented out the
save calls until per-OS maximized detection (IsZoomed / _NET_WM_STATE /
NSWindow.isZoomed) is implemented. Roadmap entry updated to reflect frozen
status.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Persist window size on quit/close and restore it on next launch
- Update appID from ru.mixdep.gosentry.desktop to ru.mixeme.gosentry.desktop
- Use markdown headers for Build sections in DEVELOPMENT.md
- Remove stale go.yaml.in/yaml/v4 dependency from DEVELOPMENT.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fyne 2.7.4 made Table.Select() reject cells with Row < 0, so OnSelected
was never fired for header clicks and the Time sort toggle stopped working.
Replace the plain Label header with a custom historyHeader widget that
implements fyne.Tappable; UpdateHeader wires OnTapped for col 0 directly.
Also swap "asc"/"desc" text for ▲/▼ glyphs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Give the Queue selects the same default spacing as the Storage fields
- Widen the settings caption column so "Default overlap policy" fits
- Disable Save until a field differs from the saved config, re-enabling on
change and re-disabling after a successful save
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.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>
The "Selected job activity" list kept showing the previous job's entries
when a different job was selected. dp.update() reassigned the backing
slice but never refreshed the widget.List, and only the refreshView path
appended an explicit refresh. Move d.logs.Refresh() into update()/clear()
so every caller redraws the panel.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bump version to 0.10.2 and document the UI density/resizing work in the
changelog. Also restructure the settings form into sections so separators
and the editable Storage fields keep normal spacing (dividers no longer
crowd the row above, entry boxes stay visibly separated) while the
label-only sections remain condensed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the job details and settings views more compact and remove the tall
minimum that prevented resizing the window shorter:
- Lay job metadata out in two columns and stack rows with a negative-gap
compactVBoxLayout, roughly halving the block height.
- Wrap the settings form in a vertical scroll so it no longer dictates
the window minimum (AppTabs sizes to the tallest tab), and tighten its
rows with the same compact layout.
- Shrink the command-output scroll minimum height so the details pane can
get shorter; long output still scrolls.
- Size the "Selected job activity" panel to exactly maxJobActivityRows
using widget.List's own content-height formula, so all three rows show
without a scrollbar regardless of theme or DPI.
Together these drop the minimum window height from ~891px to ~570px.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add echo statements at key build steps to indicate progress:
- Build start and version info
- Output path
- Environment setup
- Icon resource embedding (or warning if windres not found)
- Go compilation
- Success completion message
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Rename icon files from mixed naming (big/16x16) to consistent size-based
names (large/small) for clarity. Update Go functions and variables to
reference the new asset names. This makes the icon pipeline easier to
understand and maintain.
File changes:
- gosentry-icon-big.png → gosentry-icon-large.png
- gosentry-icon-16x16.png → gosentry-icon-small.png
- gosentry-icon-16x16.ico → gosentry-icon-small.ico
- Embedded variable: iconBytes → iconLargeBytes for clarity
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Document the shipped work missing from the entry: per-job overlap
policy, persisted global pause, 720p-safe window sizing, portable
packaging helpers, and the internal cleanup (jobs_view split, dropped
YAML migration, planning-doc removal).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remove RELEASE-0.10-PLAN.md and RELEASE-0.10-TASKS.md now that the
0.10.0 milestone work is finished (history preserved in git). Trim
ROADMAP.md to open items only; completed work lives in CHANGELOG.md.
Version stays 0.10.0 — this release is not yet tagged/shipped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ROADMAP.md now documents that T6.1 (jobs_view split), T6.2 (cleanup),
and T7.1–T7.2 (Windows zip + Linux tar.gz packaging) are complete.
Version 0.10.0 and CHANGELOG.md were already finalized.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
package-windows.bat builds gosentry.exe then bundles it with README and
CHANGELOG into a versioned .zip via PowerShell Compress-Archive.
package-linux.sh does the same for linux-amd64 and linux-arm64 (arm64
cross-compiles via aarch64-linux-gnu-gcc; skips gracefully if absent),
producing .tar.gz archives with files at the archive root.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
T6.1: split jobs_view.go into three files — jobs_view_helpers.go (pure
helpers) and jobs_view_details.go (detailsPanel struct with widget
creation, update, clear, and container methods) — bringing jobs_view.go
from 459 to ~200 lines.
T6.2: remove stale YAML upgrade note from README; drop *.yaml from
.dockerignore.
T6.3: delete YAML shadow structs (yamlConfig/yamlJob/yamlJobsFile),
importYAMLConfig/importYAMLJobs, legacy path constants, and all
YAML-import tests; run go mod tidy to remove go.yaml.in/yaml/v4.
T6.4: refresh ARCHITECTURE.md — JSON storage references, new Key Domain
Concepts section (per-job overlap policy, run-time statistics + log
seeding, persisted pause flag, jobs_view split).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Lower default from 1120×720 to 1024×660 so the window opens fully
visible on 1366×768 / 720p screens. Reduce minJobsSidebarWidth (480→400)
and commandOutputScroll min size (520×160→460×120) to match; the layout
engine enforces these as the natural minimum, keeping the UI usable at
the smaller default.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TestSetGlobalPausePersistsToConfigFile reads gosentry.json back from disk
after each SetGlobalPause call and asserts the Paused flag is correctly
written and cleared. TestServiceRebuiltFromPausedStoreStartsPaused builds
a second Service from the already-updated store and confirms both RunDue
and RunNow are refused while the service is paused.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
schedulerPaused, the scheduler-state label, and the Pause-all/Resume-all
button now read Config.Paused at construction time so they correctly reflect
a paused install on restart instead of always starting in the running state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Config.Paused bool so the scheduler's paused flag survives a restart.
SetGlobalPause now writes the flag into store.Config and calls SaveConfig;
NewService seeds s.paused from Config.Paused before computing first next-run
times, so jobs show "Scheduler paused" immediately at startup when paused.
Also add Paused to the yamlConfig shadow struct to keep the direct conversion
from domain.Config valid until the YAML import path is dropped in T6.3.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds three tests for the effective-policy resolution:
- per-job "queue" overrides global "skip" (job marked Pending, re-runs)
- per-job "skip" overrides global "queue" (overlap dropped, no re-run)
- empty Job.OverlapPolicy inherits the global default
Also ticks Phase 3 complete in docs/RELEASE-0.10-TASKS.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 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>
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>
Adds OverlapPolicy field to Job struct with json:"overlap_policy,omitempty"
tag. When empty, the field signals that the job should inherit the global
overlap policy setting from Config. Also updates yamlJob shadow struct to
maintain field-layout equivalence for YAML→JSON import compatibility.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The Log column was fixed at 240px with TextTruncate, clipping log file
names like 20260601-100000_<JobName>.log. Measure the widest value and
size the column to fit (bounded 240–520px), recomputing on refresh so
newly recorded events widen the column instead of being cut off.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Show only the latest 3 activity entries for the selected job instead of the
full in-memory list, and pin the panel to the bottom of the details pane via a
Border so the command output absorbs the remaining vertical space.
Adds fixedHeightLayout (mirroring minWidthLayout) to reserve a stable height
for the activity list. The full per-job history (maxJobLogs) is untouched and
still available in the History view.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
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>