A programming language where decisions are the branches. Declare a decision, match on its answers, and the checker makes sure every answer and “not sure” is handled before anything runs.
You write ordinary logic: functions, loops, lists and strings. Wherever the program needs judgment, you declare a decision with its question and labeled answers, then match on it. Every match needs an arm for each label and an uncertain arm, so a model that isn't sure takes a path you wrote rather than a guess.
decision moderate: choice "Is this comment ok to publish?" {
ok: "harmless comment"
spam: "ads, links, scams"
toxic: "insults, harassment"
examples from "comments.csv"
tiers builtin -> jet
threshold 0.85
}
fn action(comment: text) -> text {
match moderate(comment) {
ok => "publish"
spam => "quarantine"
toxic @ 0.9 => "hide" // only when p(toxic) ≥ 0.9
uncertain => "review" // required: leaving it out is a compile error
}
}At runtime each decision climbs its chain of tiers until one is confident. The first is a small model trained from the decision's own examples; above it sit Nodd and Jet. Several decisions on the same input go to Jet in one request, so it reads the input once.
| Tier | Runs | What it is |
|---|---|---|
builtin | Anywhere, no dependencies, under 1 ms | Hashed n-gram logistic regression with temperature calibration, trained from the decision's examples |
nodd | Node or the browser | A Nodd classifier exported for the decision, with its calibrated threshold |
jet | HTTP /v1/decide | Jet, a typed decision model: choices, scores and yes/no probabilities |
fn | Anywhere | Any function: rules, an LLM call or a human queue |
A tier that fails, like Jet being down, is recorded and skipped. If every tier is unsure, the answer goes to the uncertain arm. Design
| Mistake | Result |
|---|---|
No uncertain arm | Compile error |
| A label without an arm | Compile error |
| An arm for a label that doesn't exist | Compile error |
| An example labeled with a label that doesn't exist | Compile error |
| Arms returning different types | Compile error |
The same checks hold in TypeScript. The runtime is also a library, and its match type rejects the same mistakes at compile time.
import { at, choice, decide, jet, match } from "@quaedra/verdict";
import { builtinFromDisk } from "@quaedra/verdict/node";
const o = await decide(Moderate, comment);
match(o, {
ok: () => publish(),
spam: () => quarantine(),
toxic: at(0.9, () => hide()),
uncertain: () => review(), // required: forgetting it won't compile
});Needs Node 22 or later. Programs that use Jet read its address from JET_URL.
npm install @quaedra/verdict npx verdict check program.vd # every error, with line, column and a caret npx verdict run program.vd # check, then run npx verdict build program.vd # train the builtin tier → .verdict/
Read the docs for decision types, tiers and the CLI, or the language reference.