chore(lint): enforce the no-sleep discipline in CI (RIG-3013) - #748
Merged
Conversation
|
Compass engineering docs preview: https://compass-repo-rig-3013-no-sle.compass-eng-docs.pages.dev Deployed from |
The no-fixed-sleep discipline was agent guidance only: `rule://go-no-sleep-in-test` (Go) and `rule://ts-no-test-timers` (TS) nudge an agent mid-write, but nothing in CI failed the build on a blind sleep. A prior cleanup removed the flaky sleeps, so the tree is clean today — this gives the conventions CI teeth so a future one can't land unchallenged. Reuses linters already on PATH; no new gate, no new tool: - **Go** — `forbidigo` (already active under golangci's `default: all`) bans `time.Sleep` via a `settings.forbidigo.forbid` entry in `go/.golangci.yml`. The default `fmt.Print*`/`print(ln)` identifiers are restated (a `forbid` list replaces them). Escape is `//nolint:forbidigo // <reason>`, reusing the existing `nolintlint` reason-required + stale-flagging machinery. - **TS/Bun** — biome `noRestrictedGlobals` (stable `style` rule) bans `setTimeout`/`setInterval` in the single root `biome.json`. Escape is `// biome-ignore lint/style/noRestrictedGlobals: <reason>`. `Effect.sleep` is exempt — it is fiber-scheduled and TestClock-testable, the correct primitive. Every current call site is genuinely legit and carries a justified escape naming its reason: poll-until-ready loops with a deadline, `testing/synctest` virtual-clock advances, timeout-as-assertion guards, library macrotask yields, and abort-aware production backoff. Verified: `golangci-lint run` exit 0, `biome check .` exit 0, and a fresh unjustified sleep fails each gate with the intended message. Follow-up (not here): two real timed waits in `apps/ui/src/components/MarkdownText.test.tsx` wait out the component's real debounce; converting them to fake timers is component-test surgery (Solid + async Shiki, no fake timers in the suite today) and is flagged inline for a dedicated PR. Spec-impact: none. Refs RIG-3013 Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
force-pushed
the
compass-repo/rig-3013-no-sleep-ci-gate
branch
from
August 30, 2026 19:53
92548ae to
df388fb
Compare
mattwilkinsonn
approved these changes
Aug 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The no-fixed-sleep discipline was agent guidance only:
rule://go-no-sleep-in-test(Go) andrule://ts-no-test-timers(TS) nudge an agent mid-write, but nothing in CI failed the build on a blind sleep. A prior cleanup removed the flaky sleeps, so the tree is clean today — this gives the conventions CI teeth so a future one can't land unchallenged.Reuses linters already on PATH; no new gate, no new tool:
forbidigo(already active under golangci'sdefault: all) banstime.Sleepvia asettings.forbidigo.forbidentry ingo/.golangci.yml. The defaultfmt.Print*/print(ln)identifiers are restated (aforbidlist replaces them). Escape is//nolint:forbidigo // <reason>, reusing the existingnolintlintreason-required + stale-flagging machinery.noRestrictedGlobals(stablestylerule) banssetTimeout/setIntervalin the single rootbiome.json. Escape is// biome-ignore lint/style/noRestrictedGlobals: <reason>.Effect.sleepis exempt — it is fiber-scheduled and TestClock-testable, the correct primitive.Every current call site is genuinely legit and carries a justified escape naming its reason: poll-until-ready loops with a deadline,
testing/synctestvirtual-clock advances, timeout-as-assertion guards, library macrotask yields, and abort-aware production backoff.Verified:
golangci-lint runexit 0,biome check .exit 0, and a fresh unjustified sleep fails each gate with the intended message.Follow-up (not here): two real timed waits in
apps/ui/src/components/MarkdownText.test.tsxwait out the component's real debounce; converting them to fake timers is component-test surgery (Solid + async Shiki, no fake timers in the suite today) and is flagged inline for a dedicated PR.Spec-impact: none. Refs RIG-3013
Co-authored-by: Matt Wilkinson matt@rigel.build