fix(lint): ST1021 — lead JitteredTicker docstring with the type name

CI run #25838658130 against the Phase 6 commit (8191b1ee) failed
the golangci-lint step:

  internal/scheduler/jitter.go:11:1: ST1021: comment on exported
  type JitteredTicker should be of the form "JitteredTicker ..."
  (with optional leading article) (staticcheck)

The Phase 6 SCALE-M5 commit led the doc block with the Phase 6
backstory ("Phase 6 SCALE-M5 closure (2026-05-14): bounded-jitter
wrapper ...") rather than the type name. Pre-commit verification
ran `go test` + `go vet` but not staticcheck — same gap CLAUDE.md
already calls out in the "make verify" rule. The lint set in
.golangci.yml enables `staticcheck` with `checks: ["all", ...]`
which includes ST1021; the project's `gofmt + go vet + go test`
trio does NOT include it.

Restructured the comment so the first line leads with
`JitteredTicker is ...` (godoc-canonical form) and demoted the
Phase 6 backstory to a trailing paragraph. Same content, same
SLO-preservation explanation, same pre-Phase-6 contrast — just
reordered so godoc renders the documentation correctly and
staticcheck stays clean.

The local-staticcheck-binding-rule from the lockfile-regen and
fail-closed-pairing hotfixes applies here too: any future commit
that introduces an exported Go symbol must include the symbol
name in the first word of its doc block. Adding this to the
"pre-commit pattern lessons" list in the audit's Tasks-Deferred
table along with the Phase 7 update.

Verification:
  staticcheck -checks all,-<project-exclusions> \
    ./internal/scheduler/... → clean
  go test ./internal/scheduler/... -count=1 → ok (9.6s)
  gofmt -l internal/scheduler/jitter.go → clean

Closes: CI run 25838658130 lint failure on master@8191b1ee
This commit is contained in:
shankar0123
2026-05-14 03:00:16 +00:00
parent ba66748b5b
commit ed60059e80
+18 -20
View File
@@ -8,28 +8,26 @@ import (
"time" "time"
) )
// Phase 6 SCALE-M5 closure (2026-05-14): bounded-jitter wrapper // JitteredTicker is a bounded-jitter wrapper around time.Timer that
// around time.Timer to spread scheduler-loop tick co-fires. // fires on C once per interval ± jitterPct, with the jitter drawn
// fresh on every tick. The base interval is the same as a bare
// time.NewTicker; only the per-tick envelope changes. This preserves
// every loop's expected SLO (a renewal scan still runs ~once per
// hour) while breaking up the co-fire pattern that bare tickers
// produce when multiple loops share a nominal cadence.
// //
// Pre-Phase-6 the 15 scheduler loops in scheduler.go each used a // Stop must be called by the caller (typically via defer) to release
// bare time.NewTicker(interval). When multiple loops share a // the goroutine. After Stop, the C channel is closed.
// nominal cadence (e.g. several loops on a 1h interval), they
// co-fire at the same wall-clock boundary post-server-start,
// producing visible CPU + DB spikes at every hour boundary. The
// renewal scan + the agent health check + the digest preview all
// firing within milliseconds of each other on a freshly-booted
// server can saturate the connection pool until they complete.
// //
// JitteredTicker replaces the bare time.NewTicker with a goroutine // Phase 6 SCALE-M5 (2026-05-14) introduced this wrapper. Pre-Phase-6
// that fires C once per interval ± jitterPct, drawn fresh on every // the 15 scheduler loops in scheduler.go each used a bare
// tick. The base interval is the same as before; only the per-tick // time.NewTicker(interval); when multiple loops shared a nominal
// envelope changes. This preserves every loop's expected SLO (a // cadence (e.g. several loops on a 1h interval), they co-fired at
// renewal scan still runs ~once per hour) while breaking up the // the same wall-clock boundary post-server-start, producing visible
// co-fire pattern. // CPU + DB spikes at every hour boundary. The renewal scan + the
// // agent health check + the digest preview all firing within
// JitteredTicker.Stop() must be called by the caller (typically via // milliseconds of each other on a freshly-booted server could
// defer) to release the goroutine. After Stop, the C channel is // saturate the connection pool until they completed.
// closed.
type JitteredTicker struct { type JitteredTicker struct {
// C is the channel a tick fires on. Read this in the loop's // C is the channel a tick fires on. Read this in the loop's
// select{} the same way you'd read time.Ticker.C. // select{} the same way you'd read time.Ticker.C.