⚠️ FOLDED INTO FRAM. As of 2026-06-18 the canonical home of this engine isfram/chartroom(build target "beagle source code-intelligence, renting fram's public claim+Datalog API"). The fold was licensed by lockstep cadence + cross-repo friction relief (no version pin; beagle CI dropped a checkout), not by dependency-direction. The seam is guarded structurally in fram (core_code_blind_testkeeps the generic core blind to beagle-as-subject;chartroom_seam_testkeeps this module on fram's public surface). This repo is retained for history; do not edit here.
Code as claims, on Fram. Chartroom projects a beagle source tree into the same reified claim graph that Lodestar uses for life and work, then derives code intelligence — call graphs, scope-correct caller resolution, transitive leverage — as queries over that graph instead of as bespoke passes over text.
The bet is the same one Lodestar makes, pointed at source: a flat, text-and-grep view of a codebase rots and can't compute relational questions; the graph is always current and answers them for free. The question Chartroom exists to settle is whether that actually buys anything over the cold-parse, one-hop tools we already have — or not.
*.bjs ──beagle-claims──▶ CNF triples ──load──▶ Fram claim store ──Datalog──▶ leverage / callers
(AST as claims) [s "p" o] (interned graph) (transitive closure)
beagle-claims(in beagle,bin/beagle-claims) reflects a file's AST into newline-separated EDN claim triples[subj "pred" obj]—form-kind,name,calls, and a uniformchildcontainment edge. It's a cross-cutting analysis projection, not a compile target: it claims.bjs/.bclj/.bnixalike, ignoring each file's#lang.bin/emit-corpusruns that over a source tree →build/<name>.claims.src/chartroom.cljfolds the triples into a Fram store, derives the namespace-correct function call graph (a call binds the defn in its own module — the scope a bare-symbol match ignores), and runs the benchmarks.
Chartroom is the glue layer over three sibling projects; clone them next to this
repo (the ~/code/<name> layout the commands below assume) and have
Babashka (bb) on PATH:
- fram — the claim store + Datalog
engine. Build its classpath dir (
fram/out); the runner loads-cp ~/code/fram/out. - beagle — provides
bin/beagle-claimsandbin/beagle-roundtrip(the AST→claims projectors).bin/*here resolve it via$BEAGLE(default$HOME/code/beagle); override if you check it out elsewhere. - gjoa — the live corpus the benchmarks in RESULTS.md run against. Any beagle source tree works; gjoa is just the one measured.
bin/emit-corpus ~/code/gjoa/src ~/code/gjoa/tools ~/code/gjoa/tests build/gjoa.claims
bb -cp ~/code/fram/out:src src/chartroom.clj build/gjoa.claimsSee RESULTS.md for the measured verdict. In short: on the live gjoa corpus the graph answers two questions the incumbent cannot — scope-correct callers (perfect precision where bare-symbol match is 33–67% wrong) and transitive blast radius (the keystone a one-hop tool structurally can't surface) — and Fram's Datalog computes the real call-graph closure correctly.
Two projections, two jobs (both derived from the same source):
- Query projection (
beagle-claims) — compact AST claims with semantic overlays (calls/name/child). Great for leverage queries; lossy (drops types/params). ~18 triples/form. - Truth projection (
beagle-roundtrip) — verbose reader-datum claims that round-trip the program losslessly (types survive as tokens, comments as resolved references). The graph as a source of truth; text as a regenerable view. ~238 triples/form.
Built and validated in stages: projection → leverage benchmark → lossless round-trip → graph-native rename → a shadow-correct lexical resolver → rename-correct comments. Headline gates hold at 1100/1100 forms, 97/97 files. Measured results are in RESULTS.md; the stage-by-stage build log is in docs/build-log.md.