fractal-engine is a small recursive compute engine with a canonical storage layer
around it. The compute kernel remains input -> processing -> output; storage records
what happened without adding model-facing concepts.
┌─────────────────────────────┐
│ CLI / API / codebrain │
│ agentcli · api · render │
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ read surface │
│ projection · inspect · trust │
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ canonical storage │
│ session-db · store.* │
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐ ┌──────────────────────┐
│ compute engine │ │ provider │
│ process · session-loop │◄──────►│ clojure-llm-sdk │
│ leaf · session-invocation │ │ │
│ runtime · rlm │ │ │
│ artifacts · snapshot · event │ └──────────────────────┘
└─────────────────────────────┘
process owns configuration and session execution assembly. It starts sessions,
installs the six REPL functions, selects the configured model for the current
invocation edge, and delegates the actual loop/call/invocation work to smaller
namespaces.session-loop owns one session input: provider message, Clojure eval,
observation, repeat, then commit a completed head when (FINAL value) appears. The
persisted row is still named turn for the read surface, but the semantic boundary is
"session input to immutable head."leaf owns lm / map-lm: bounded provider calls recorded as call rows and
payload refs only. Leaves never create sessions, heads, or invocation edges.session-invocation owns rlm / map-rlm / attach-rlm: normal session
creation/continuation plus invocation edges between caller and callee heads. It frames
child/attach instructions as the callee's user input for that edge; it does not install
a different behavior prompt into the callee session.provider-call owns provider request construction, cache descriptors, traced
provider completions, leaf parsing, and fanout bounds.rlm owns RLM invocation values: child result validation, stable handles,
envelopes, attach target resolution, and invocation fact recording.runtime owns namespace creation, model-facing function interning, fenced Clojure
extraction, eval, and observations.call is the traced-call skeleton: reserve id, record running call, run work,
record success/failure.event folds rich runtime event values into the in-memory view used while a
process is running. Persisted event history is compact SQLite rows plus row/payload
refs, not full event-body blobs.artifacts owns live session state and writes canonical facts/payloads through
storage. It does not maintain per-session filesystem homes.snapshot captures/restores EDN-safe vars through BlobStore payloads and
SQLite snapshot rows.The model-facing REPL surface is exactly:
FINAL lm map-lm rlm map-rlm attach-rlm
session-db owns the session-store facade: SQLite hot rows, head/current-ref
writes, handle/alias resolution, materialized state reads, and relationship reads.session-sqlite owns the local SQLite database, WAL setup, typed row writes,
and transaction-batch storage for the derived Datalog index.store.index owns Datahike projection catch-up/rebuild/query over SQLite
transaction batches.store.consistency owns quick/deep integrity checks over SQLite rows, BlobStore
bytes, and the derived Datahike index.store.io owns filesystem/EDN mechanics for local backends and product-side
exports.store.payload owns content-addressed payload refs and blob identity facts.store.schema owns the Datahike schema value.store.value owns pure lookup-ref/value-shaping helpers.blob-store owns content-addressed payload bytes. The local implementation writes
under the store root and verifies hash/size before SQLite rows point at blobs.session-model defines stable ids, head fingerprints, and invocation handles.SQLite is canonical for hot facts, identity, refs, time, and graph relationships. BlobStore is canonical for payloads. Datahike is a derived Datalog index rebuilt or lazily caught up from SQLite transaction batches. Filesystem paths are backend details for the local SQLite, Datahike, and BlobStore implementations; they are not session identity.
There is no filesystem session-home source of truth.
SQLite stores queryable hot rows: ids, refs, statuses, timestamps, kinds, labels, aliases, compact event records, head basis/current-head, derivation edges, invocation caller/callee/source relationships, model/provider ids, token/cost facts, cache ids, and blob hash/size/key/media-type facts. Datahike indexes the same facts for Datalog graph reads.
BlobStore stores replayable/restorable/renderable payloads: message content, root request descriptors, bounded leaf requests, provider responses, eval code/results/observations, final values, snapshots, vars, head state roots/components, raw errors, stack traces, and export bodies. It does not store a generic full event payload for every event; compact event records point at the typed payload refs that already own the bytes.
The boundary is semantic. Small final values and small snapshots are still blobs. Bounded summaries/previews may be SQLite rows and Datahike index facts; arbitrary generated content is not.
FINAL writes final/snapshot blobs, commits call/eval/message rows,
writes a compact immutable head-state root, creates an immutable head, and advances the
same session's current-head. FINAL does not terminate the session.rlm/map-rlm create child sessions and invocation facts; the model receives an
RLM envelope with :rlm/value, continuation handle, head handle, and deterministic
recognition metadata.attach-rlm continues a session ref or branches from a head ref. Session-ref attach
advances the callee session's current-head. Head-ref attach creates a new attached
child and records source -> attached-child derivation; the source head does not change.lm/map-lm create call facts and payload blobs only; no sessions or invocations.projection defaults to current/head state for addressable recursive node reads and
resolves blob refs as needed. It exposes event/history reads separately.inspect returns structured call/session/head/invocation detail for CLI/API JSON.render formats show, tree, cost, leaves, step, and trust output.provenance extracts and checks claim-vs-evidence structures.api exposes the supported Clojure facade.agentcli is the command-line use surface.Current reads dereference session/current-head -> head/state-ref, then materialize the
state root into the active session view; they do not mix abandoned branch events into
active output. History and progress reads use SQLite rows directly, so they remain useful
mid-run. No command requires Datahike or a generated projection file to exist.
The history/event stream is a compact audit surface: append order, event type, row
identity, status, source ids, and payload refs. It is not the current-state source and is
not a byte-for-byte replay of the rich in-memory event values. The derived event trace
adds summaries and causal refs over that compact stream for operators and product UIs;
it still does not participate in restore.
The runtime serializes in-session event/call/invocation id allocation through the
session state's emit lock. SQLite commits are serialized per store root and use WAL mode
so parallel map-lm/map-rlm branches do not race current-head or row writes. Child work
can still run concurrently; only the canonical hot-store commits are serialized.
This pass implements local SQLite, filesystem-backed Datahike projection, and local filesystem-backed BlobStore. The protocols and config keep backend choices isolated, but there is no S3/AWS implementation or live S3 validation.
Can you improve this documentation? These fine people already did:
DeadMeme5441 & DeadMemeEdit 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 |