84e81371c1
Four documents asserted things the code contradicts. ARCHITECTURE's component diagram had the UI calling the autostart Manager directly. It does not, and must not: src/ui holds no reference to the package at all — Settings reads svc.AutostartStatus(), like everything else it reads. The edge is folded into the existing ui→Service one, so the diagram no longer draws the exception to the project's own rule. platform/desktop was described in both ARCHITECTURE and DEVELOPMENT as a "display-scale helper". It installs the .desktop entry and icon under XDG data home; there is no scale helper in it. The ~250-line file guideline was written as though the jobs_view and settings_view splits had settled it. Both files are over it again and history_view.go has never been split, so the guideline is now stated as the target it is, with the current state named rather than implied. STANDARDS pointed at a "CI coverage gate" item that ROADMAP does not have, while omitting the two it does. README's gosentry.json sample was three keys short of what the app writes on first run — default_timeout_seconds, theme and job_list_view — which made the one file the user is invited to hand-edit the least accurate thing in the document. The sample is now the real default (verified by marshalling DefaultConfig), with the keys explained, including why a zero timeout is written out and an unset one is not. The per-job overrides for overlap policy and timeout were undocumented despite being in the job dialog, and the feature list had not caught up with the timeout, the theme, or the compact job list. Version numbers in example output paths are now <version>, matching how the CI section already wrote them, so they cannot go stale again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
75 lines
4.3 KiB
Markdown
75 lines
4.3 KiB
Markdown
# GoSentry — Standards
|
|
|
|
Quality rules and intentional behavior for contributors. Package contracts live
|
|
in [ARCHITECTURE.md](ARCHITECTURE.md); test conventions in [TESTS.md](TESTS.md);
|
|
what a whole-project review looks at, in [REVIEW.md](REVIEW.md).
|
|
|
|
## Code quality
|
|
|
|
- Follow package contracts in [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
- User-facing errors → `dialog.ShowError` or a History event, never a silent `return`.
|
|
- Pure helpers → unit test in the same package.
|
|
- Fixes with severity ≥ medium → regression test.
|
|
- Documented intentional behavior → section below, not a backlog bug.
|
|
- UI view constructors accept `*app.Service`; call `app.Open()` only from `run.go`.
|
|
- A size that must follow the theme is **measured at build time, not written as
|
|
a pixel constant.** `theme.Padding()` and text metrics depend on the running
|
|
app's theme, text size, and DPI, so a hand-tuned number is only correct for
|
|
the one theme it was tuned against and clips under any other. Measure the real
|
|
widget, or derive the value from the theme, in a named helper: `rowOverlap`
|
|
(theme padding), `captionColumnWidth` and `textColumnWidth` (the widest of the
|
|
actual strings), `activityRowsHeight` (the list's own row template). The same
|
|
applies to a ratio computed from an absolute width — see `initialSplitOffset`.
|
|
A raw pixel literal is left only where nothing about it tracks the theme, and
|
|
says so in a comment.
|
|
|
|
## Config file compatibility
|
|
|
|
There is no migration step: `gosentry.json` and `jobs.json` are read as-is, are
|
|
meant to be hand-editable, and may have been written by an older version. A
|
|
change to their shape has to stay compatible on its own.
|
|
|
|
- A new `Config` field is tagged `omitempty`, and its zero value must mean the
|
|
behavior that existed before the field was added — a file written without it
|
|
keeps working unchanged. `DefaultConfig()` still sets the value explicitly.
|
|
- A zero that carries meaning is not a missing field and must not be backfilled
|
|
on load. See `DefaultTimeoutSeconds` in `storage.loadOrCreateConfig` and
|
|
`Job.TimeoutSeconds *int`, where unset and `0` are different answers.
|
|
- An unrecognised enum value reads as the default rather than an error, through
|
|
one helper that every consumer shares (`JobListView.IsCompact`, `ui.themeFor`),
|
|
and is normalized before being written back, so the file never gains a value
|
|
no reader understands.
|
|
- A renamed key keeps the old field on `Config` (tagged `omitempty`) purely so
|
|
it can still be read. `storage.loadOrCreateConfig` converts it to the new
|
|
field and clears it, so the retired key disappears on the next save. See
|
|
`Config.JobsDir` → `Config.JobsFile`. Where the new field has a non-empty
|
|
default, clear that default before unmarshalling, or "the file omits it" and
|
|
"the file sets it" become indistinguishable and the conversion never runs.
|
|
- Each of the three gets a test: the default in `storage`, the normalization in
|
|
`domain`, and a round-trip through the real config file in `app`.
|
|
|
|
## Intentional behavior (not bugs)
|
|
|
|
- `RunNow` is allowed during global pause and for disabled jobs.
|
|
- Selecting a jobs file that already exists **loads** it: its jobs replace the
|
|
in-memory list, which is the only way the user can switch between job lists. A
|
|
path with no file behind it receives the current jobs (rename/relocate). The
|
|
switch is refused while a job is running, because adoption drops every runtime
|
|
and a finishing run would then write its result onto whichever job inherited
|
|
its ID.
|
|
- Sequential mode runs jobs FIFO by order in `jobs.json`.
|
|
- Scheduler tick is 1s — sub-second `@every` intervals are not supported.
|
|
- Command timeout defaults to no timeout globally (`Config.DefaultTimeoutSeconds`
|
|
= 0) and is overridable per job (`Job.TimeoutSeconds *int`: unset = inherit the
|
|
global default, 0 = no timeout, positive = seconds). Neither zero may be
|
|
normalized away on load — 0 is a value, not a missing field.
|
|
- **History tab is session-only.** `JobRuntime.Logs` exists only in memory for the
|
|
current process. Log files on disk feed aggregate statistics via `SeedStats`
|
|
only. See [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
|
|
## Out of scope
|
|
|
|
Larger or blocked work is tracked in [ROADMAP.md](ROADMAP.md) (update check from
|
|
GitHub releases, cron-table import/export, window size persistence, History
|
|
column filters).
|