Code as facts, on Fram. Codegraph projects a beagle source tree into the same reified fact graph that North 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 North 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 Codegraph exists to settle is whether that actually buys anything over the cold-parse, one-hop tools we already have — or not.
*.bjs ──beagle-facts───▶ CNF triples ──load──▶ Fram fact store ──Datalog──▶ leverage / callers
(AST as facts) [s "p" o] (interned graph) (transitive closure)
beagle-facts(in beagle,bin/beagle-facts) reflects a file's AST into newline-separated EDN fact triples[subj "pred" obj]—form-kind,name,calls, and a uniformchildcontainment edge. It's a cross-cutting analysis projection, not a compile target: it projects.bjs/.bclj/.bnixalike, ignoring each file's#lang.bin/emit-corpusruns that over a source tree →build/<name>.facts.src/codegraph.bcljfolds 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.
Codegraph 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 fact store + Datalog
engine. Build its classpath dir (
fram/out); the runner loads-cp ~/code/fram/out. - beagle — provides
bin/beagle-factsandbin/beagle-roundtrip(the AST→facts 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.facts
bb -cp ~/code/fram/out:src:~/code/fram -m codegraph build/gjoa.factsSee 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-facts) — compact AST facts with semantic overlays (calls/name/child). Great for leverage queries; lossy (drops types/params). ~18 triples/form. - Truth projection (
beagle-roundtrip) — verbose reader-datum facts 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.
Codegraph is dual-licensed under your choice of the MIT License
or the Apache License, Version 2.0
(MIT OR Apache-2.0).