Skip to content

R2 — a complete Rete fell out in a day, because it was assembly, not invention

The north star went green and the builder said it plain:

“we built a complete rete in under a day — that’s…. insane.”

It is worth being precise about what, so “insane” reads as method and not luck. What shipped, end to end, in a day: alpha matching; equality joins with real cross-condition unification (the HashJoinNode — the part every toy evaluator hand-waves); production firing; cascade to a monotone fixpoint; truth maintenance with transitive retraction (retract a supporting fact, its whole derived chain vanishes); and a homoiconic defrule / query surface — in a language that did not exist as a general substrate a year ago. Not a naive stand-in. The thing Forgy’s 1974 thesis is about, with the parts CLIPS / Drools / Clara add bolted on, green against an acceptance test (cold-and-windy) that was written on day one and never moved.

Why it was possible — the grounded version:

  • It was assembly, not invention. The hard parts were already on the shelf: persistent collections (0a–0d), the total-pure macro-eval engine (arc 249), types-as-forms (arc 251), records, the WatAST bridge, symbol-table reflection. Rete was orchestration of Rust with clean syntax — exactly what wat is for ([[project_wat_is_spec_rust_is_impl]]). The day was wiring capability that already existed; every prior arc was a stone in this foundation without knowing it.
  • The north star was the contract from minute one. One green test fixed the target; every stone aimed at it. No drift, no scope-debate mid-build.
  • The strike discipline did the compounding. Each stone: draw (DESIGN + a RED probe that fails on exactly the gap) → fire one sonnet → weigh against an independent re-run + the diff → ship green. Slow is smooth; we never fought the same boss twice.
  • The inserts-only thesis paid triple ([[project_rete_inserts_only_replay]]): it kept the engine simple (pure value-semantics, no mutation), it made TM fall out of replay instead of needing a justification graph, and it handed us a known-correct oracle for free (R1).
  • Grounding caught the rabbit holes before they cost a day each: the defrule macro loop, the query Bundle-archaeology smell (→ the return-type-of intrinsic), the 4b input/derived TM bug, the keyword-resolves-to-its-constructor “is-it-a-defect” question (it isn’t — names resolve to bindings). Each a fifteen-minute probe, not a five-hour wrong turn.

The honest asterisk: this is the correct-but-slow Rete (~130–820 facts/s, O(N²) — the re-run-from-scratch oracle). The day did not produce the fast engine. It produced the spec the fast engine will be held to — which is the more valuable artifact, and the reason the speed is repeatable rather than a one-off.

This is the bar, and it is the close. The builder set both the target and the scope:

“we exceed clara/java — at minimum not having a gc means we are theoretically faster already?” “i don’t think this is a new arc — i think this is the closing condition for the rete arc as a whole.”

So arc 278 does not close at the green north star. It closes when the Rust fire kernel — delta propagation, join-bindings-keyed joins, native mutable memories behind the transient/freeze boundary — is differential- tested bit-for-bit against this oracle and benched at or past Clara. And the GC point is real, not a boast: Clara runs on the JVM, where a stop-the-world pause is a tail-latency spike at exactly the wrong moment for line-rate packet processing. Rust has no GC — ownership + Arc refcounting, no pauses, cache-dense native structures. At the line, predictable latency (no GC jitter) may matter as much as raw throughput, and we get it by construction. Theoretically ahead before we optimize a thing; the arc closes when we prove it on the bench.