1# The local gate
2
3A solo repo with no CI still needs one command that decides whether a revision
4may land. Write it in the repo's own scripting language, and keep it small.
5Snowbound's working example is
6[`tools/ci.py`](https://shale.paperclover.net/snowbound/tree/-/tools/ci.py).
7
8## What it does
9
10- **Gates a revision, not the working copy.** It defaults to main and takes a
11 revision as an argument. It checks that revision out into its own
12 workspace, with its own build cache, so agents' half-finished edits can't
13 leak in. A working-copy mode freezes the tree as it was when the run
14 started.
15- **Holds a lock**, so two runs never share a build directory. The second run
16 says it is waiting.
17- **Runs lanes:** format, lint with warnings as errors, tests, and a build for
18 each other platform the project ships. Each lane has its own time limit.
19- **Skips a lane whose toolchain is missing, and says why** ("needs zig"). It
20 never passes that lane silently.
21- **Is fast by default.** The default run finishes in minutes. Exhaustive or
22 fuzz-like sweeps sit behind an opt-in flag or env var. Snowbound's tests went
23 from about half an hour to under three minutes once its sweeps moved out.
24- **Can run only what changed.** A changed-files mode runs just the lanes and
25 test packages that the diff from main reaches.
26- **Reports failures by owner.** The output is a table of failures, each with
27 its first errors at file and line, so the agent whose edit broke it is
28 obvious.
29- **Keeps logs.** Each run writes its lane logs and a machine-readable summary
30 into a folder, and the last twenty folders are kept.
31- **Keeps the build cache under a size budget** after each run. A cache of a
32 million files once slowed font tests by minutes.
33- **Clears env vars that tests read** before running, so the agent's own
34 environment doesn't change results.
35- **Exits with the result.**
36
37## Rules around it
38
39- **Gate the exact revision you are about to land**, after rebasing onto main.
40 A green working copy proves nothing about the commit.
41- **Never pipe the gate through `grep`, `awk` or `tail` to judge it.** Read its
42 exit status. A filtered "clean" once hid a check that had never run.
43- **The release script runs the gate on the commit it is about to publish.**
44- **After a usage limit or a crash, gate the cut-off agents' work before landing
45 any of it.**