New: Fixed Bid Applications. See the packages

EffortlessAPI
FAQ / Expressivity & Theory / Transitive Closure / Can a rulebook express transitive closure?

Can a rulebook express transitive closure?

Thumbnail from the film 'Transitive Closure, Made Obvious' — a workflow diagram whose inferred precedence pairs fill in on their own
From the film "Transitive Closure, Made Obvious": four typed facts become ten, on their own.
The short answer

Yes — closure is a first-class field type in the rulebook. You declare "type": "closure" over a relationship, optionally with an edge filter, and every substrate emits it: WITH RECURSIVE in Postgres, owl:TransitiveProperty in OWL, an explicit traversal in Python, Go, and TypeScript.

Yes. This is the most-asked question in the project's history — and the one most often answered wrongly about us, occasionally even by old copies of our own docs — so here is the precise answer.

The theorem (which is real)

Transitive closure is provably not expressible in first-order logic with aggregates (Hella, Libkin, Nurmonen & Wong, "Logics with Aggregate Operators", J. ACM 2001; Libkin, "Expressive Power of SQL", 2003; extending Aho & Ullman, 1979). The rulebook's formula/lookup/aggregation fragment sits exactly in that class. So no formula field, however large, computes unbounded reachability. That part is settled mathematics.

The conclusion (which does NOT follow)

The wrong conclusion is "...therefore the rulebook can't do closure." The theorem is the reason closure is its own declared primitive — not a wall the rulebook stops at. A closure field is one line in the model — { "name": "PrecedesStepClosure", "type": "closure" } — declared over a relationship, optionally with an edge filter. Every substrate emits that one declared field: a WITH RECURSIVE view in Postgres, an owl:TransitiveProperty in OWL, an explicit graph traversal in Python, Go, and TypeScript. These are emissions of a declared field, no different from a COUNTIFS becoming a SQL aggregate. Downstream calculated fields consume the closure like any other field — and the conformance harness grades every closure cell across substrates rather than assuming agreement.

It runs, today, including the hard cases

  • talismans-special-solutions declares PrecedesStepClosure, DelegationClosure, and DerivationClosure; conformance tests assert the inferred pairs, and ordinary aggregation fields count them (6 inferred precedence pairs; 10 total closure pairs).

  • procedural-knowledge-ontology runs closure over a cyclic step graph with rework loops (LeadsToClosure — steps on a cycle correctly reach themselves), plus a filtered-edge closure (LeadsWithoutHumanGateClosure) that detects publications which bypassed every human approval gate.

  • The latest conformance run graded 473,312 cells, and every substrate with a closure engine agreed on every closure cell.

Exactly like OCL adding closure(), SQL adding WITH RECURSIVE, and OWL having transitive properties: every serious framework grows a closure primitive, because the boundary is a theorem. The rulebook simply declares its primitive in the model itself, where it belongs.

The back story

Every answer here has a story behind it — and each story is (or becomes) a film.

The day our own docs argued against us

film not yet published

In October 2026 an AI code reviewer read this project's README and constructed a confident argument that the rulebook could not express transitive closure — citing, as its evidence, our own README. An older paragraph still described closure as something "handed to substrate-native mechanisms," a boundary the rulebook "cannot cross on its own." The rulebooks themselves disagreed: "type": "closure" was declared seven times across three projects, every substrate emitted it, and the harness had graded hundreds of thousands of closure-derived cells. The reviewer was reasoning correctly from stale text — which is exactly how misinformation about your own system propagates once AIs read docs as ground truth. We purged the hedge from every doc, every skill, and every data row the same day, and this FAQ entry exists so there is one canonical page to point at, forever, instead of re-litigating it thread by thread.