typescript · deterministic · auditable · ai-native · mit

Business logic that explains itself.

Payroll, pricing, tax, financial models — Balkis turns them from code scattered across your app into typed, versioned data with deterministic execution, a full audit trail for every number, and native access for AI agents.

193tests passing
12packages
~1 µsper calculation*
56.8×parallel async†

* measured live on this page below  ·  † published benchmark

the problem

Your most important numbers live in your least inspectable code

Every calculation-heavy system rots the same way: formulas buried in route handlers, implicit ordering, no validation, and no answer to the only question that matters — “why did this number come out this way?”

😵 Before — logic buried in code

A tax rule, a discount, a rounding decision… somewhere in 400 lines of handler.

// somewhere in routes/checkout.ts … app.post("/quote", async (req, res) => { // …90 lines of parsing… let total = items.reduce((s,i)=>s+i.p*i.q,0); if (user.tier=="vip") total *= 0.8; // why 0.8? since when? total = total * 1.11; // VAT? hardcoded total = Math.round(total*100)/100; // float drift ✓ // …no trace, no versions, no tests… res.json({ total }); // good luck, auditor });

✨ After — logic as data

Each calculation declares its inputs, outputs, dependencies, and version. The framework derives execution order, validation, audit trails, docs — and the graph below is real.

// calculations are frozen, self-describing values defineCalculation({ id: "pricing.discount", version: "2.1.0", summary: "VIP tier gets 20%.", input: z.object({ tier: z.string() }), output: z.object({ pct: z.number() }), dependencies: [orderTotal], // typed, cycle-free calculate: ({ deps }) => ({ … }), }); // every run: validated in, validated out, // full audit trace, reproducible, explainable.
no mockups — this is the real engine

Watch Balkis run, right now, in this tab

The actual engine is loaded on this page. Below it computes a payroll — rule-driven bonus included — and you watch the dependency graph execute, the audit trace assemble, and the run explain itself. Numbers are measured, not scripted.

payroll.total = gross × (1 + bonus%)
inputssalary · score payroll.gross payroll.bonus ⚖ payroll.total result

⚖ = a rule group: the bonus policy is JSON conditions with priorities, not code.

AUDIT TRACE
don’t trust us — measure it

The proof lab: every claim runs on your machine

Marketing pages say “blazing fast” and “rock solid”. This one hands you the lab. Each experiment below executes the real engine in your browser and prints what it measured.

⚡ Speed: a 1,000-calculation graph

Builds a 1,000-node dependency chain — validation, tracing, everything on — and times one full run. Then re-runs it through the incremental cache.

🏁 Parallel vs sequential — live race

Three independent async calculations (~250 ms each, think API calls). Sequential pays the sum; parallel overlaps them. Watch the bars — they move in real time.

sequential
parallel

🛡️ Reliability: determinism & validation

Runs the same calculation three times and compares results byte-for-byte, then feeds it garbage and shows the structured rejection.

Lab-recorded numbers (Node 24, Apple Silicon) from the published benchmark suite — the same shape you just measured:

scenariosequentialparallelspeedup
async fan-in, width 4 (5 ms/leaf)22.7 ms5.8 ms3.9×
async fan-in, width 1691.0 ms6.0 ms15.3×
async fan-in, width 64363.2 ms6.4 ms56.8×
sync chain, 1,000 nodes (engine overhead)0.55 ms~0.6 µs/node

Honesty clause: parallel mode helps async work. On pure synchronous math it’s ~0.8× (single-threaded JS), so sequential stays the default. That trade-off is written down (D14), like the other 21 design decisions.

the hub

One catalog. Every surface.

Define your logic once as data. Balkis derives everything else — for developers, for auditors, for finance teams, and for AI agents.

Your numbers deserve an audit trail.