Checks & gates
Transitions in cairn are free (any state to any state) except for two gates. Everything else about moving a task through its states is unconstrained.
The two gates
- Deps gate: a task can't leave the
initialstate until every id in itsdepsis in aclosedstate. Deps do not gate closing, only starting. Thereadyflag reflects this and is derived on read, never stored. - Checks gate: a task can't enter a
closedstate unless all itscheckspass.- Zero checks ⇒ passes vacuously.
- On closing, if checks aren't already all
pass, the engine auto-runs thecmdchecks, then closes on all-pass or refuses on any fail.
WARNING
Reopening a closed task is allowed, but check results are not reset on reopen; they keep their last value, so a re-close reuses them. Closing re-runs cmd checks fresh, so a stale pass from an earlier attempt still can't slip a broken close through.
See Task files & config → Gates for where checks live in the task file.
cmd vs manual checks
| Kind | Has cmd? | How result is set |
|---|---|---|
cmd | yes | executed; exit code decides pass/fail |
manual | no | set by attestation, not execution |
- A check with a
cmdis executed viash -c "<cmd>"; any shell line works (go test ./...,pytest -q && ruff check .,./scripts/verify.sh). - A check without a
cmdis manual: itsresultis set by attestation, not execution. A pending manual check blocks closing until it's resolved.
The shell
Command checks run in a POSIX shell so a task's cmd behaves identically on every machine. By default cairn uses sh, which must be on your PATH:
- macOS / Linux: works without extra setup.
- Windows: install Git Bash or WSL (which provide
sh). A barecmd/PowerShell install has nosh. - Override the shell with the
CAIRN_SHELLenvironment variable. Set it to a shell on yourPATH(e.g. an absolute path tosh, orbash).
If the shell can't be found, cairn fails the run with a clear message rather than a cryptic per-check error:
check: shell "sh" not found on PATH. Install a POSIX shell (Git Bash or WSL on Windows),
or set CAIRN_SHELL to oneWrite portable check commands
Because checks run through sh, keep cmd lines POSIX (&&, ./script.sh, standard quoting) so they pass identically for a teammate on another OS and in CI.
Exit codes, timeout, and output
- Exit code
0=pass, non-zero =fail. - A check may set an optional
timeout(seconds); otherwisecheck_timeout_defaultfromconfig.yamlapplies. On timeout the process (and its process group) is killed and the result isfail. - An optional
cwd(relative to the repo root) sets the working directory for the command. - Output (stdout+stderr, ~8KB tail) goes to
.cairn/runs/<id>-<timestamp>.log. The task file stores onlyresult:so diffs stay clean. Theruns/directory is gitignored.