This document inventories the high-level changes in the gateless/clara-rules fork
since it diverged from upstream cerner/clara-rules, as of 2026-05-01.
fire-rules-async API, :parallel-batch-size
for parallel RHS execution, and interruptible sessions, all built on
gateless/futurama instead of core.async.core.cache CacheProtocol instances and can be swapped or cleared.ham-fisted performance rewrite. Working memory, beta graph, update caches,
and Fressian durability use ham-fisted mutable collections.defhierarchy macro, namespace-level rule properties,
IClaraSource protocol replacing IRuleSource, function-as-rule-source support,
and &env capture in rule/query macros.inspect-facts, and
:fact->explanations in the inspect output.sorting-by, sorted-grouping-by, and a safe-default
acc/sum.deps.edn + tools.build,
Kaocha for tests, GraalVM native-image smoke build, and republished as
com.github.gateless/clara-rules on Clojars.fire-rules-async added as a first-class API (clara.rules.clj,
engine.clj). Returns a CompletableFuture and supports awaiting RHS that
return futures/channels/deferreds. New :parallel-batch-size option pops N
activations at once.fire-activation! / fire-activation-async!, fire-activations! /
fire-activations-async!, process-activations!, do-fire-rules macro.core.async with gateless/futurama (own library) as the
async primitive; pinned to 1.4.2.pop-activation! → pop-activations! [memory count] in IMemoryReader
(breaking change for custom memories) to support batch pops.futurama/async-cancelled? checks inside the
activation loop — runaway/infinite loops can be cancelled. Tests in
test_infinite_loops.clj.ReadOnlyLocalSession deftype that throws on insert/retract/fire-rules.assemble-read-only, as-read-only,
assemble-query-only, as-query-only, rulebase->query-only-rulebase,
memory->query-only-beta-memory.:read-only? and :query-only? on
serialize-session-state / deserialize-session-state. Read-only sessions
skip RHS/alpha/test/join-filter/accum compilation (uses com/read-only-expr
stub).rem-rhs-fn, rem-alpha-fn,
rem-join-filter-fn, rem-test-fn, rem-accumulator,
reconstruct-node-expr-fn-lookup.IMemoryReader/get-tokens-map protocol method to fetch full beta-memory
state.:cache on mk-session now accepts
true/false/any core.cache CacheProtocol. Default is an LRU cache.:compiler-cache option on mk-session for memoizing expression
compilation; default is a soft-reference cache.clear-session-cache! and clear-compiler-cache!.:hash-expr-fn option for deterministic, MD5-based cache keying.ham-fisted introduced as a core dep (currently 3.006). Used pervasively in:
forward-edges/backward-edges/
id-to-condition-node/id-to-production-node/id-to-new-bindings) is now
a MutableLongHashMap instead of a sorted Clojure map. Schema in
schema.clj was updated accordingly.memory.clj was rewritten — 533-line diff): TransientLocalMemory
uses ham-fisted mutable maps (MutableMap) for alpha/beta/accum/production
memory and replaces compute!-based ops everywhere; LinkedList helpers
retained for hot paths.OrderedUpdateCache rebuilt around IMutList;
CancellingUpdateCache simplified to use ham-fisted's
compute-if-absent!/apply-concat.hamf/set and hamf/map Fressian handlers so
deserialized sessions retain ham-fisted collection types.compute, simplified equality wrappers, etc.IRuleSource/load-rules → IClaraSource/load-source.clear-ns-productions! → clear-ns-vars!.defhierarchy macro added — defines a make-hierarchy derive chain in a
var; integrates with mk-session's new :hierarchy option and
create-ancestors-fn.defrule rewritten: now expands to a defn with three arities (no-args
returns rule map; full args is the compiled RHS handler). Rule's :handler
field stores a symbol pointing at the compiled function. Var serialization
support added (clojure.lang/var Fressian handler) so handlers serialize via
symbol.clojure.lang.Fn now implements IClaraSource (you can pass functions as
rule sources and they're invoked to produce rules).=> separator is now optional when there's no LHS.defrule/defquery/parse-rule/parse-query now capture &env (local
lexical env) and &form metadata. Fixes env not being available in
expression/accumulator join nodes.dsl/get-ns-props,
dsl/add-allowed-ns-props!, dsl/set-allowed-ns-props!. Defaults to
:author :no-loop :salience — set ns metadata ^{:salience 100} and rules
in that namespace inherit it.acc/sum: :default-value kw-arg (defaults to 0) so nil fields no longer NPE.sorting-by accumulator (sort-by with optional comparator and
convert-return-fn).sorted-grouping-by accumulator (groups + sorts both groups and
within-group; result is an array-map for ordering preservation).grouping-by private helper extracted.InspectionSchema renamed → RulesInspectionSchema; new
FactsInspectionSchema.inspect: :root-facts and
:fact->explanations.get-root-facts and inspect-facts functions; root facts are
now memorized in working memory (new ROOT_NODE, ROOT_NODE_ID,
->RootElement).get-condition-matches, to-explanations, gen-all-rule-matches,
gen-fact->explanations, explain-activation made public.?__gen__) removal from inspect bindings results.PendingUpdate operation types renamed: :insertion → :insert,
:retraction → :retract.CyclicalRuleListener.to-persistent! now returns the cycles count instead
of nil — useful for telemetry on hit limits.ThreadLocals to dynamic vars
(*node-id->node-cache*, *node-fn-cache*, *clj-struct-holder*,
*mem-facts*, *mem-internal*) — done so async/virtual threads work safely.with-thread-local-binding macro replaced with binding.clojure.lang.Var.JavaEqualityWrapper got an identity-first short-circuit and (==hash)
short-circuit. New helpers jeq-wrap/jeq-unwrap. New FactIdentityWrapper
deftype with fact-id-wrap/fact-id-unwrap (used by inspection root-fact
diffing).compute-for macro added in platform.clj.null-listener? now treats nil as null (defensive against missing
listener).combine-listeners helper that returns the default null listener for
empty collections vs. a delegating listener otherwise.app/clara/main.clj and Makefile
build-native target verifying that a clara-rules app compiles to a native binary.cerner/clara-rules to com.github.gateless/clara-rules
on Clojars; pom, README badge, namespace updated.project.clj patterns to deps.edn + tools.build
(tool/build.clj); Makefile drives all flows; Kaocha test runner replaces
lein-test (bin/kaocha, tests.edn, junit-xml/cloverage support).dev/user.clj significantly expanded with REPL scaffolding (added Portal
viewer support, slf4j logging deps).defhierarchy, clear-ns-vars!, etc.).test_engine.clj, coverage_ruleset.clj/test_coverage.clj
(validates instrumentation works), long_running_tests.clj parallel options.testing-utils: added test-compile-async-action and
test-fire-rules-async helpers.read-only-expr, mk-node-fn-name,
compile-action-handler (separated from compile-action), build-rule-node,
create-get-alphas-fn (was private), create-ancestors-fn,
alpha-roots-wrap, load-source*.effective-type and get-fields now memoized.AlphaRootsWrapper deftype simplified (now wraps JavaEqualityWrapper
directly instead of carrying its own hash).:omit-compile-ctx plumbing for serialization.Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |