Documentation
¶
Overview ¶
Ergoaudit reports the API-surface measurements behind docs/specs/developer-ergonomics.md, so the spec's counts stay re-derivable as the code moves.
Usage:
go run ./tools/ergonomics-audit/ -mode focus [repo...] go run ./tools/ergonomics-audit/ -mode callbacks [repo...] go run ./tools/ergonomics-audit/ -mode ids [repo...] go run ./tools/ergonomics-audit/ -mode opt [repo...] go run ./tools/ergonomics-audit/ -mode literals [repo...] go run ./tools/ergonomics-audit/ -mode theme [repo...] go run ./tools/ergonomics-audit/ -mode a11y [repo...] go run ./tools/ergonomics-audit/ -mode visual [repo...]
With no repo arguments both modes audit the current directory.
Mode focus also rewrites. With -fix it inserts a generated ID into every literal it classifies as broken; -fix-dry-run reports those rewrites without performing them. -fix-only and -fix-exclude are regexps over repo-relative paths, applied in that order. Phase 1 of the spec runs it over this repo's tests and examples only, because go-gui's own widgets get hand-chosen IDs — a shipped widget's ID is public identity, not scaffolding:
go run ./tools/ergonomics-audit/ -mode focus -fix -fix-only '_test\.go$|^examples/' .
Mode focus answers: which focusable-by-default widget Cfgs leave ID unenforced, and how many call sites therefore render a control that is not keyboard-reachable. The unguarded Cfg set is derived from the go-gui source rather than hardcoded — a per-file scan for the ID tag picks the wrong struct in files declaring several Cfgs, which is how ListBoxCfg was once misreported as unguarded.
Mode callbacks answers: how many distinct On* callback shapes the public API exposes, split by whether they carry an EventCtx, a bare *Window, or a raw *Event. Counts are reported both deduplicated and raw, because the two differ (OnEvent alone is declared twice) and quoting one without saying which is how review disagreements start.
Mode ids answers: does anything still compose a widget ID by hand, rather than through gui.ScopeID? It exits non-zero on any finding, so it gates. See ids.go for what counts and how to mark an exception.
Mode opt answers: which *Cfg fields are plain — not Opt[T] — but sit in a zero-meaningful family (Padding, Radius, Spacing, Opacity, Size*, *Align enums), so a caller cannot distinguish "unset" from the zero value. It exits non-zero on any unmarked finding, so it gates like ids. See opt.go. Padding fields are exempt: Padding self-flags since #243.
Mode literals answers: does any code build a Padding or Color with a raw composite literal instead of a constructor, silently reading as unset? It exits non-zero on any finding, so it gates. See literals.go.
Mode a11y answers: does any code build a keyed A11YCfg literal that forwards the label but drops the description, so a description never reaches the accessibility tree? It exits non-zero on any finding, so it gates. See a11y.go.
Mode visual answers: does widget code still spell a dimming alpha or a type-size step as a literal, when the theme defines named roles for both (issue #335)? It scans gui/view_*.go and exits non-zero on any unmarked finding, so it gates. See visual.go for what counts and how to mark an exception.
All modes parse with go/ast: composite literals and func literals span lines, and regex cannot bracket-match them.