This library is in flux. APIs may change without notice. Generated from source with koruc 0.1.7 on 10/5/2026.
Gate
~import std/gateGATE — named enforcement profiles over declared rules
gate.kz · 2 tors
GATE — named enforcement profiles over declared rules · 63 more lines
GATE — named enforcement profiles over declared rules
An invariant row (std/invariants) declares a rule in source, next to the
code it constrains. A gate PROFILE names when and how a set of those
rules is enforced — and the same program answers differently under
different profiles, because the profile is a selection over the declared
surface, not a property of it. `dev` for a workstation commit, `aerospace`
for a sanctioned pipeline: the rules do not change; the profile chooses
which of them are asked and how hard a "no" lands.
SURFACE:
std/gate:profile(dev) {
"block": true,
"description": "the local commit gate",
"judge": "invariants/gate", // optional — verdict delegator
"judge_src": "invariants/gate.k" // optional — staleness oracle
}
The name is positional — `expr` is made for this: a profile's whole job is
being a name, so the name rides the call and the block carries only the
policy fields (`block`, `description`, `judge`, `judge_src`). A `"name"`
key in the block is a refusal — it would let the name and the field
disagree.
A rule joins a profile by tag: `tags: ["dev"]` on the invariant row makes
it a member of `gate dev`. `"dev-local"` marks the row file-scoped — it
fires only when its own declaring file is in the staged diff. `odds-N` is
a deterministic alarm: the row fires when sha256(name ++ "\0" ++ staged
diff) mod 100 lands below N — same staged state, same roll, so re-running
the gate answers identically and the alarm is driven by commit activity,
not a schedule. `repo-X` scopes a check: row to a consumer repo (matched
on the repo directory's basename).
koruc <file> gate — list the profiles this program declares
koruc <file> gate dev — run the `dev` profile
koruc <file> gate dev json — machine-readable verdicts
koruc <file> gate dev --advisory — soften a blocking profile locally
koruc <file> gate dev --checks-only — instruments only, no judged rows
koruc <file> gate dev --judge-only — judged rows only, no instruments
koruc <file> gate dev --repo PATH — gate another repo's staged diff
EXECUTION. The row's `check:` field decides its strategy, as it always
has: a `check:` command is a deterministic instrument — exec'd in the
directory of the file that declared the profile, non-zero is a
VIOLATION. A row without `check:` is judgment-class: the profile's
`judge` names the binary the verdict delegates to (argv: rule, staged
state; first stdout line is the verdict — VIOLATION / CLEAN / anything
else reads UNJUDGED). A stale or missing binary rebuilds through
`koruc build <judge_src>` when the profile names one. Judgment has a
measured input window (~96KB of staged state — gate.py's bound, kept);
beyond it the row is UNJUDGED, and a profile with no `judge` UNJUDGEs
every judged row with the cause named. Deterministic check failures
always block; judgment verdicts block only when the profile's `block`
stands — the profile declares the default and `--advisory` is the only
tightening direction.
Two honesty rules ported from gate.py: a profile name that matches no
declaration is a refusal, not an empty run — `gate typoname` exits 1 and
names the declared set. And UNJUDGED is never a silent pass.
[norun] for the same reason as flag.declare: the profile declaration is
data in the AST, harvested after the parse — a consumer discovers gates
by parsing the program, never from a hardcoded list.
~[comptime|norun] pub tor profile { expr: Expression, source: Source }~[comptime|command] pub tor gate {
program: std/compiler:*const Program,
allocator: __koru_std.mem.Allocator,
argv: []string
}