✓
Passing This code compiles and runs correctly.
Code
// Pins the named-gate surface end to end. The program itself is a decoy —
// post.sh drives `koruc input.k gate …` over the declarations this file
// carries:
// * `gate` lists the declared profiles and their membership
// * `gate dev` (advisory) runs the deterministic `check:` instrument and
// reports the judgment-class row — UNJUDGED when the profile declares
// no judge, with the cause named
// * odds-0 always misses, odds-100 always fires — the roll's verdict is
// independent of whatever happens to be staged in the enclosing repo
// * `gate broken` exits 1 on a failing instrument (check violations
// always block; advisory only softens judgment rows)
// * `gate strict --repo <scratch>` delegates the judgment row to the
// profile's judge binary — VIOLATION under enforcing → exit 1,
// --advisory → exit 0; `gate clean` pins the CLEAN verdict passing
// * `gate nosuch` refuses and names the declared set
import std/io
import std/invariants
import std/gate
std/gate:profile(dev) {
"block": false,
"description": "the dev commit gate — advisory"
}
std/gate:profile(broken) {
"block": true,
"description": "a profile whose instrument fails"
}
std/gate:profile(strict) {
"block": true,
"description": "enforcement over a judgment-class row — the judge decides",
"judge": "scratch/strict-judge"
}
std/gate:profile(clean) {
"block": true,
"description": "enforcement with a judge that returns CLEAN",
"judge": "scratch/clean-judge"
}
std/invariants:inferred {
"name": "shape-is-named",
"tags": ["dev"],
"rule": "every declared shape carries a name",
"check": "true"
}
std/invariants:inferred {
"name": "prose-rule",
"tags": ["dev"],
"rule": "a judgment-class row whose profile declares no judge"
}
std/invariants:inferred {
"name": "never-fires",
"tags": ["dev", "odds-0"],
"rule": "a row whose alarm can never roll low enough",
"check": "true"
}
std/invariants:inferred {
"name": "always-fires",
"tags": ["dev", "odds-100"],
"rule": "a row whose alarm always rolls low enough",
"check": "true"
}
std/invariants:inferred {
"name": "always-fails",
"tags": ["broken"],
"rule": "an instrument that always exits non-zero",
"check": "false"
}
std/invariants:inferred {
"name": "strict-rule",
"tags": ["strict"],
"rule": "a judgment-class row under an enforcing profile"
}
std/invariants:inferred {
"name": "clean-rule",
"tags": ["clean"],
"rule": "a judgment-class row whose judge returns CLEAN"
}
std/io:print.ln("gate-me")
Actual
gate-me
Expected output
gate-me
Flows
flow ~profile click a branch to expand · @labels scroll to their anchor
profile (expr: dev, source: "block": false,
"description": "the dev commit gate — advisory")
flow ~profile click a branch to expand · @labels scroll to their anchor
profile (expr: broken, source: "block": true,
"description": "a profile whose instrument fails")
flow ~profile click a branch to expand · @labels scroll to their anchor
profile (expr: strict, source: "block": true,
"description": "enforcement over a judgment-class row — the judge decides",
"judge": "scratch/strict-judge")
flow ~profile click a branch to expand · @labels scroll to their anchor
profile (expr: clean, source: "block": true,
"description": "enforcement with a judge that returns CLEAN",
"judge": "scratch/clean-judge")
flow ~inferred click a branch to expand · @labels scroll to their anchor
inferred (source: "name": "shape-is-named",
"tags": ["dev"],
"rule": "every declared shape carries a name",
"check": "true")
flow ~inferred click a branch to expand · @labels scroll to their anchor
inferred (source: "name": "prose-rule",
"tags": ["dev"],
"rule": "a judgment-class row whose profile declares no judge")
flow ~inferred click a branch to expand · @labels scroll to their anchor
inferred (source: "name": "never-fires",
"tags": ["dev", "odds-0"],
"rule": "a row whose alarm can never roll low enough",
"check": "true")
flow ~inferred click a branch to expand · @labels scroll to their anchor
inferred (source: "name": "always-fires",
"tags": ["dev", "odds-100"],
"rule": "a row whose alarm always rolls low enough",
"check": "true")
flow ~inferred click a branch to expand · @labels scroll to their anchor
inferred (source: "name": "always-fails",
"tags": ["broken"],
"rule": "an instrument that always exits non-zero",
"check": "false")
flow ~inferred click a branch to expand · @labels scroll to their anchor
inferred (source: "name": "strict-rule",
"tags": ["strict"],
"rule": "a judgment-class row under an enforcing profile")
flow ~inferred click a branch to expand · @labels scroll to their anchor
inferred (source: "name": "clean-rule",
"tags": ["clean"],
"rule": "a judgment-class row whose judge returns CLEAN")
flow ~print.ln click a branch to expand · @labels scroll to their anchor
print.ln (expr: "gate-me")
Test Configuration
MUST_RUN
Post-validation Script:
#!/bin/bash
# The named-gate matrix. Git-dependent verdicts are driven through
# --repo into scratch repositories the test creates, so the pin does not
# depend on whatever happens to be staged in the enclosing repo.
set -u
cd "$(dirname "$0")"
fail() { echo "FAIL: $1"; exit 1; }
# 1. Bare `gate` lists declared profiles and their membership.
LIST=$(koruc "$KORU_INPUT" gate 2>&1)
echo "$LIST"
echo "$LIST" | grep -qE "dev +advisory +4 rows" || fail "dev profile not listed with 4 rows"
echo "$LIST" | grep -qE "broken +blocking +1 row" || fail "broken profile not listed blocking"
echo "$LIST" | grep -qE "strict +blocking +1 row" || fail "strict profile not listed blocking"
echo "$LIST" | grep -qE "clean +blocking +1 row" || fail "clean profile not listed blocking"
# 2. `gate dev` — advisory profile: the instrument runs, the judged row is
# reported (skip without a staged diff, UNJUDGED with one — both honest),
# and the odds modifiers roll deterministically.
DEV=$(koruc "$KORU_INPUT" gate dev 2>&1)
echo "$DEV"
echo "$DEV" | grep -qE "shape-is-named +check ok" || fail "check row did not pass"
echo "$DEV" | grep -qE "prose-rule +(no staged changes|UNJUDGED)" || fail "judged row not reported"
echo "$DEV" | grep -qE "never-fires +rolled [0-9]+, needed < 0" || fail "odds-0 row fired"
echo "$DEV" | grep -qE "always-fires +check ok · rolled [0-9]+ < 100" || fail "odds-100 row missed"
# 3. json verdicts — the machine-readable block.
JSON=$(koruc "$KORU_INPUT" gate dev json 2>&1)
echo "$JSON"
echo "$JSON" | grep -q '"profile":"dev"' || fail "json: profile missing"
echo "$JSON" | grep -q '"mode":"advisory"' || fail "json: mode missing"
echo "$JSON" | grep -q '"name":"shape-is-named","verdict":"pass"' || fail "json: pass verdict missing"
# 4. `gate broken` — a failing instrument blocks regardless of stance.
if koruc "$KORU_INPUT" gate broken > broken.log 2>&1; then
cat broken.log; fail "gate broken exited 0 on a failing check"
fi
cat broken.log
grep -qE "✗ always-fails +check failed" broken.log || fail "check failure not reported"
grep -q "blocking violation" broken.log || fail "blocking summary missing"
# 5. `gate nosuch` refuses and names the declared set.
if koruc "$KORU_INPUT" gate nosuch > nosuch.log 2>&1; then
cat nosuch.log; fail "gate nosuch exited 0"
fi
cat nosuch.log
grep -q "no profile named 'nosuch'" nosuch.log || fail "unknown-profile refusal missing"
grep -q "declared:" nosuch.log || fail "declared set not named"
# 6. `gate strict` over a scratch repo — the judgment row delegates to the
# profile's judge. The judge is an executable contract: argv is
# (rule, staged-state), the verdict is the first stdout line —
# VIOLATION / CLEAN / anything else reads UNJUDGED. These stubs speak
# the protocol; koru/odds is the real judge.
rm -rf scratch
mkdir -p scratch
git -C scratch init -q .
git -C scratch config user.email gate@test
git -C scratch config user.name gate-test
git -C scratch commit -qm init --allow-empty
# empty repo: no staged diff → the judged row skips, gate is clean
CLEAN0=$(koruc "$KORU_INPUT" gate strict --repo "$PWD/scratch" 2>&1) || fail "empty staged diff did not skip"
echo "$CLEAN0"
echo "$CLEAN0" | grep -qE "strict-rule +no staged changes" || fail "judge-skip missing"
printf '#!/bin/sh\necho "VIOLATION p=0.87"\n' > scratch/strict-judge
printf '#!/bin/sh\necho "CLEAN p=0.91"\n' > scratch/clean-judge
chmod +x scratch/strict-judge scratch/clean-judge
echo x > scratch/f.txt
git -C scratch add f.txt
# enforcing profile + a VIOLATION verdict → exit 1
if koruc "$KORU_INPUT" gate strict --repo "$PWD/scratch" > strict.log 2>&1; then
cat strict.log; fail "enforcing profile exited 0 on a judge VIOLATION"
fi
cat strict.log
grep -qE "✗ strict-rule +VIOLATION p=0.87" strict.log || fail "judge VIOLATION missing"
grep -q "blocking violation" strict.log || fail "enforcement did not block"
# the same verdict, softened by --advisory → exit 0
SOFT=$(koruc "$KORU_INPUT" gate strict --repo "$PWD/scratch" --advisory 2>&1) || fail "--advisory still blocked"
echo "$SOFT"
echo "$SOFT" | grep -q "advisory" || fail "advisory mode not reported"
# a CLEAN verdict passes an enforcing profile
CLEAN=$(koruc "$KORU_INPUT" gate clean --repo "$PWD/scratch" 2>&1) || fail "clean profile exited nonzero on CLEAN"
echo "$CLEAN"
echo "$CLEAN" | grep -qE "✓ clean-rule +CLEAN p=0.91" || fail "judge CLEAN missing"
echo "$CLEAN" | grep -q "gate clean — clean" || fail "clean verdict summary missing"
# a profile with no judge declared is honest about it — UNJUDGED with the
# cause, never a silent pass; --judge-only skips check rows entirely
DEVJ=$(koruc "$KORU_INPUT" gate dev --repo "$PWD/scratch" --judge-only 2>&1)
echo "$DEVJ"
echo "$DEVJ" | grep -qE "prose-rule +UNJUDGED" || fail "no-judge UNJUDGED missing"
echo "$DEVJ" | grep -q 'declares no "judge"' || fail "no-judge cause not named"
echo "$DEVJ" | grep -q "check ok" && fail "--judge-only ran a check row"
rm -rf scratch broken.log nosuch.log strict.log
echo "=== PASS: named gates select rows, delegate judgment, and enforce ==="