These libraries are experimental. APIs may change without notice. Generated from source with koruc 0.1.7 on 9/16/2026.
Regressions
@korulang/regressionsv3 — SELF-DESCRIBING TESTS (inline `//~` annotations). A case is declared as:
regressions/index.kz · 9 tors· 1 internal
@korulang/regressions — a programmable, koru-native test/verification runner. · 54 more lines
@korulang/regressions — a programmable, koru-native test/verification runner.
v3 — SELF-DESCRIBING TESTS (inline `//~` annotations). A case is declared as:
koru/regressions:case(gzip round-trip) {
"file": "gzip/tests/roundtrip.kz"
}
where the label is an `expr: Expression` and the body is a `source: Source`
carrying a JSON object (the same idiom koru itself uses for `flag.declare` /
`command.declare` / `deps.requires`). The `test` command collects these at
COMPILE TIME (same [comptime|command] mechanism as koru/docker), runs each
case through a `koruc` subprocess, and scores it. Zero koru-toolchain
changes — pure external orchestration.
EXPECTATIONS come in TWO ADJACENT SPELLINGS, one vocabulary, one wall:
the declared norun markers below (like `case`, collected from the test's
own AST — the compiler parses, resolves, and validates them) and the //~
comment directives (ruled Lars 2026-07-17). Both feed the same validation
and scoring; a file uses one spelling, never both. The comment form is
also the only one that can score a frontend negative — a file that fails
at the frontend never materializes its AST, so it cannot declare itself:
~koru/regressions:run() compile + run + exit 0 + no leaks
~koru/regressions:compile-fail(stage: backend) must fail, pinned to stage
~koru/regressions:error(id: "KORU030", msg: "…") pinned diagnostic (ID + substring)
~koru/regressions:expect(text: "…") produced-program output must contain it
~koru/regressions:expect-not(text: "…") produced-program output must NOT contain it
~koru/regressions:leaks-allow(reason: "…") opt out of the leak gate (reasoned)
//~ run the same vocabulary, as comments
//~ compile_fail(frontend|backend)
//~ error[KORU030]: msg
//~ expect: text / //~ expect-not: text
//~ leaks: allow <reason>
The suite stays pure composition (a case = a label + a file). A JSON "kind"
is retired and rejected with teaching. An unpinned compile-fail is itself a
failure. Leak gate is default-ON and overrides pass (same detection as
koru's run_regression.sh: the Zig GPA "memory address … leaked" report).
HISTORY — a ledger (.koru-regressions/latest.json, gitignored) records the
last COMPLETE run's verdicts; the board diffs against it (NEW / FIXED /
REGRESSION) and a green→red flip — or any red — exits 1, so
`koruc suite.k test` is an honest CI gate.
SELECTION — case blocks may declare "category" and "tags" arrays; the
invocation selects with --category/-c, --tag/-t, --smoke. Filtered runs
never write the ledger (a partial board must not clobber history), and a
filter matching nothing is refused, not silently green.
Next: named line markers (@marker — blocked on backend diagnostics carrying
real file:line), cross-backend parity (backends: zig js), result cache +
parallelism, general run-recipe (pytest/cargo).
~[comptime|command] pub tor test {
program: *const Program,
allocator: __koru_std.mem.Allocator,
argv: []string
}// `score` — the OVERRIDABLE runner seam (abstract event, same pattern as
// compiler:coordinate). The default below scores a case by driving `koruc` as a
// subprocess; a user swaps the entire behavior with `~koru/regressions:score = …`
// (e.g. to run pytest/cargo, or to traverse a dependency graph). "Traverses
// stuff" today = one case; the seam is what a future graph-runner plugs into.
//
// Named `score`, not `run` — the expectation marker below owns `run()`, and a
// tor name is unique per module (measured: two `run` tors emitted a duplicate
// `run_event` struct in the backend).
~[comptime|abstract] pub tor score {
dir: string,
base: string,
allocator: __koru_std.mem.Allocator
}
| passed
| failed string// The `case` marker: a declared test case, collected from the AST by `test`.
// `expr` = the human label; `source` = a JSON object block. Void at runtime.
~[comptime|norun] pub tor case { expr: Expression, source: Source }// The EXPECTATION markers — a test file's self-description as declared program
// surface, ADJACENT to the //~ comment directives (ruled Lars 2026-07-17).
// Each is collected from the test program's AST — via its program.ast.json —
// by `run-exec`, the same walk that collects `case` from suite.k. The
// compiler parses, resolves, and validates them: a typo is a compile error
// with a location, an unknown marker is impossible, and "can't drift" lives
// in the type system. Both spellings map onto the same vocabulary:
//
// //~ run <-> koru/regressions:run()
// //~ compile_fail(stage) <-> koru/regressions:compile-fail(stage: …)
// //~ error[ID]: msg <-> koru/regressions:error(id: "ID", msg: "…")
// //~ expect: text <-> koru/regressions:expect(text: "…")
// //~ expect-not: text <-> koru/regressions:expect-not(text: "…")
// //~ leaks: allow reason <-> koru/regressions:leaks-allow(reason: "…")
//
// One vocabulary, one spelling per test — mixing them is rejected. A
// `compile-fail(stage: frontend)` DECLARED marker is contradictory (a file
// that fails at the frontend never materializes its AST, so it cannot declare
// itself); the frontend-negative kind is spelled with the adjacent //~ form,
// which the runner reads from the file text before compiling.
//
// Positive: compiles, runs, exits 0, no leaks.
~[comptime|norun] pub tor run {}// Negative, pinned to a stage. `frontend` is unscoreable (see above).
~[comptime|norun] pub tor compile-fail { stage: Expression }// Diagnostic pin: diagnostic ID + message substring.
~[comptime|norun] pub tor error { id: Expression, msg: Expression }// Produced-program output must contain this substring.
~[comptime|norun] pub tor expect { text: Expression }// Produced-program output must NOT contain this substring.
~[comptime|norun] pub tor expect-not { text: Expression }// Reasoned opt-out of the leak gate — a reason is required.
~[comptime|norun] pub tor leaks-allow { reason: Expression }