Files
gosentry/docs/STANDARDS.md
T
mixeme 4d014e2f45 docs: add a review agenda and config compatibility rules
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>
2026-07-26 22:44:30 +03:00

2.6 KiB

GoSentry — Standards

Quality rules and intentional behavior for contributors. Package contracts live in ARCHITECTURE.md; test conventions in TESTS.md; what a whole-project review looks at, in REVIEW.md.

Code quality

  • Follow package contracts in 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.

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.
  • 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.
  • 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.

Out of scope

Larger or blocked work is tracked in ROADMAP.md (window size persistence, History column filters, CI coverage gate).