A local-first, hyper-relational knowledge base with content-addressable storage (CAS). Built as a Master's thesis prototype.
- Hyper-relational graph: Knowledge is stored as
statement(Subject, Predicate, Object, Properties). Subjects and objects can themselves be statements (reification), enabling claims about claims. - Content-addressable storage: Files are staged, SHA-256 hashed, and committed atomically alongside their graph metadata. Deduplication is automatic.
- Time-travel: Updates create new statement versions linked via
replaces_id.pl historywalks the version chain. - Prolog-first: Trealla Prolog is the main runtime. SQLite and Raylib are accessed via C shared libraries loaded through FFI.
- Interactive GUI: A Raylib-based graph viewer with image previews, a query bar, and node search.
Dependencies: Clang, X11 (Linux) or Xcode CLT (macOS). Trealla Prolog, Raylib, raygui, and SQLite are included as submodules.
git clone --recurse-submodules <repo-url>
cd kb
makeThis builds libcas.so, libgui.so, and libsqlite3.so in the project root. Raylib is compiled from source during make.
To build Trealla from source:
cd vendor/trealla && makeThen ensure tpl is on your $PATH.
# Load a context into memory and open a REPL
tpl -l main.pl -- pl load concept(mathematics)
# Assert a new statement
tpl -l main.pl -- pl assert \
"statement(concept(mathematics), foundation_of, concept(logic), [])"
# Full-text search
tpl -l main.pl -- pl search mathematics
# View version history of a term
tpl -l main.pl -- pl history concept(mathematics)
# Ingest a file into CAS
tpl -l main.pl -- cas add document.pdf
# List CAS objects
tpl -l main.pl -- cas list
# Launch the GUI
tpl -l main.pl -- gui
# Check database consistency
tpl -l main.pl -- pl verify
# Run garbage collection
tpl -l main.pl -- pl gcmain.pl CLI router and REPL
prolog/
sync.pl 2-phase commit: marshal Prolog terms ↔ SQLite
cas.pl FFI bindings to libcas.so
db.pl SQLite queries
gui.pl Raylib frontend (yield-loop pattern)
ontology.pl In-memory knowledge graph
src/
cas.c / cas.h CAS: stage, SHA-256 hash, commit atomically, verify
gui.c / gui.h Raylib renderer and input handler
graph.c / graph.h Graph layout
util.c / util.h SHA-256, MD5
sql/
schema.sql SQLite schema (WAL mode, FTS5, reification)
vendor/ Trealla, Raylib, raygui, SQLite (submodules)
Every piece of knowledge is a statement/4 term:
statement(Subject, Predicate, Object, Properties)Subject and Object are Prolog terms or integer IDs pointing to other rows in the statement table, enabling arbitrary nesting. The SQLite schema mirrors this with ANY-typed columns and a replaces_id foreign key for versioning.
Example:
% Alice claims (with certainty 0.9) that Bob likes pizza
statement(
person(alice),
claims,
statement(person(bob), likes, food(pizza), []),
[certainty(0.9)]
)Context loading uses bidirectional recursive CTEs to pull only the subgraph reachable from a seed term into Prolog's in-memory working set.
A kb.nix shell is provided for reproducible builds:
GPL-3.0 — see LICENSE.md.
