Hermes Atlas v0.1: A Local-First, Incrementally-Compiled, Falsifiable Knowledge System

Hermes Atlas v0.1: A Local-First, Incrementally-Compiled, Falsifiable Knowledge System
August 9, 2026 · Daniel Kliewer
Most "agentic knowledge" tooling is query-time retrieval with a graph bolted on. Microsoft's GraphRAG is the reference case, and it has two documented weaknesses that a compile-time design fixes:
- No native incremental update. New information forces a full graph rebuild.
- Community summaries at query time. Adds 2–3× latency to every query, repeated forever.
- Conflicts are handled by majority vote + minority caveat — a good instinct left unformalized.
Hermes Atlas v0.1 takes the opposite stance: extract once, at compile time, into a versioned static artifact; keep contradictions as first-class nodes; and prove the graph is doing work a keyword search cannot with a Popper-style canary.
This post is a replication guide. Every command below was run for real, on a Mac, on Python 3.14. The numbers are from the actual runs, not illustrations. The source, README, and the longer replication guide live at kliewerdaniel/hermes-atlas.
0. Environment
# Python 3.14
/opt/homebrew/bin/python3.14 --version # => Python 3.14.6
mkdir -p ~/Documents/Projects/hermes-atlas
cd ~/Documents/Projects/hermes-atlas
python3.14 -m venv .venv
# stdlib-only at runtime; only dev dep is pytest
env -u PYTHONPATH -u PYTHONHOME ./.venv/bin/python -m pip install -q pytest
Note on the
env -u …prefix. Under the Hermes shell the active venv leaksPYTHONPATH/PYTHONHOMEfrom a different interpreter, which breaks imports (ModuleNotFoundError: pydantic_core). Stripping both before invoking the project interpreter is the fix. On a clean shell you don't need it. This cost me real debugging time; record it so you don't lose the same hour.
The package is hermes_atlas/ with modules store, extract, confidence, contradictions, graph, gaps, personas, canary, compiler, loop, cli, ingest, inference. 53 tests. All green.
env -u PYTHONPATH -u PYTHONHOME ./.venv/bin/python -m pytest -q -p no:cacheprovider
# 53 passed in 0.65s
1. The changelog is built first, on purpose
GraphRAG lacks a durable mutation log, so it cannot know what a delta recompile is allowed to leave alone — every ingest degenerates into a full rebuild. Atlas inverts that: the append-only changelog is the source of truth, and the store is silent on unchanged content.
# store.py — the no-op that makes delta provable
def write(self, collection, record, cycle=0, pass_id=""):
chash = content_hash(record)
existing = self.read(collection, record["id"])
if existing is not None and prev_hash == chash:
return False # silence: nothing written to the changelog
...
A changelog that stays silent when inputs are identical is what lets you prove a delta recompile touched nothing it shouldn't.
2. Compile-time extraction (reuse, don't rebuild)
The extraction module is ported, not rewritten, from the Sovereign Knowledge
Compiler: split into sentences, tag each with a controlled-vocabulary stance
(support / contradict), extract co-mentioned entities as relationships. It is
deterministic — no model — so it runs once per source, keyed on checksum.
Extraction provenance is tracked separately from the source checksum:
# compiler.py
def _needs_extraction(self, source):
prev = self.store.read("sources", source["id"])
if prev is None:
return True
return prev.get("extracted_checksum") != source.get("checksum")
Bug we hit (and you will too). The first version compared the source checksum to decide extraction. But
ingestwrites the source without extracting — so the compiler sawchecksum == checksumand skipped extraction, producing a 0-claim graph silently. The fix: trackextracted_checksumindependently, and preserve it across recompiles so a second identical compile is a true no-op. There is a regression test:test_ingest_does_not_pre_extract.
3. Confidence that never silently overwrites
A claim with no supporting evidence scores exactly 0.0 — not a small
positive from a recency prior. That load-bearing line is what guarantees "never
silently overwrite":
# confidence.py
if not evidence:
return ConfidenceResult(score=0.0,
note="no supporting evidence: claim is asserted, not evidenced")
Independence is counted by domain/author, not source count — ten posts from
one blog are one independent source, and a claim repeated across syndicated copies
is penalised, not boosted (corroboration only counts distinct independent
domains). Conflicting evidence lowers confidence but both sides survive.
4. Contradictions are first-class nodes
When two claims oppose each other, Atlas creates a contradiction record with its own id. Both claims keep their own record and confidence. Resolution is an explicit, logged act — never a side effect of the newest source winning.
# contradictions.py
def mine_contradictions(claims, min_overlap=0.30):
# pair on shared NON-generic content words, opposite polarity
# anchored on >=1 non-generic word (trims "AI is X / AI is not X" noise)
# NO upper-overlap bound: a direct negation shares 100% of its words
# and IS the contradiction we want, not a duplicate
Two bugs surfaced here, both real:
- The miner originally anchored only on proper nouns, so thesis-level contradictions ("the model is local-first" vs "…is not local-first") were missed. Fixed by anchoring on shared non-generic content words.
- The pair's
claim_a/claim_bwere ordered by dict iteration, which shifts when new sources are added — so the contradiction record's content hash changed on every delta recompile, looking like corruption. Fixed by canonicalisinga = min(claim_a.id, claim_b.id). Regression test:test_delta_recompile_keeps_internal_contradictions_stable.
5. Incremental communities + cached summaries
Community detection is a label-propagation append: existing labels are the
seed, only new/adjacent nodes may move (stability() reports the drift vs a full
recompute). Summaries are compiled once and cached against a membership hash.
# Track A: full compile vs delta recompile
compile #0 (full) in 10.55s changelog entries added 3471
compile #1 (incremental) in 0.34s changelog entries added 11
community stability vs full rebuild: 1.000
The delta added 11 entries (vs 3471 for full) and prior-record violations: 0 — the delta path provably touched only the 3 new sources plus their 2 new claims. That is the whole point of building the changelog first.
Another determinism bug:
Graphnode order followeddictinsertion order, which depends ong.nodesiteration — non-reproducible across runs. Fixed by keeping an explicit_orderlist and sorting the propagation order. Andsummary_cached(a diagnostic flag) was being persisted on the community record, flippingFalse→Trueon rerun and breaking byte-identity. Removed it from the artifact; it belongs in the compile report, not the stored record.
6. The four-persona question generator
Gap analysis picks the weakest region; four adversarial personas each propose a next research question; they are ranked by expected information gain, not vote-counting. The Skeptic (falsifiability) gets a multiplier.
# Track A gap analysis → 4 proposals
[selected] Skeptic 0.938 (region=weakest_claims, falsifiable=True)
[logged ] Practitioner 0.709 (region=weak_central_concepts)
[logged ] Historian 0.511 (region=stale_nodes)
[logged ] Analogist 0.047 (region=incoherent_communities)
The loop has an explicit stopping condition: N iterations (default 5) or a confidence gate. No open-ended loops in v0.1.
7. The falsifiability canary (the honest part)
Before trusting the loop's self-assessment, the canary checks the compiled graph against cheaper baselines and external ground truth.
Negative controls (trackB_probes.json, 5 probes):
probe graph keyword random margin ok
probe-ai-agent-def 0.33 0.33 0.00 0.00 Y
probe-compile-cache 0.75 0.75 0.00 0.00 Y
probe-local-first 1.00 1.00 0.67 0.00 Y
probe-community-summary 0.00 0.50 0.00 -0.50 N
probe-conflict-handling 0.00 0.00 0.00 0.00 N
verdict: trusted (pass rate 0.6)
Two probes fail — one where the graph genuinely underperforms keyword on a generic term. That is the canary working: it flagged the weak spot instead of hiding it.
Held-out rediscovery (3 valid probes, real sentences withheld):
probe-local-machine withheld: 4 targeted: False leaked: False
probe-local-fragile withheld: 1 targeted: False leaked: False
probe-compile-artifact withheld: 5 targeted: False leaked: False
verdict: flagged (pass_rate 0.0)
All three withheld sentences were correctly not leaked into the graph (redaction works). But the loop did not regenerate a question targeting the removed fact. On a 40-source extractive corpus, the deterministic gap heuristic targets the weakest scored region, not the specific missing phrase.
This is the headline lesson. The current gap-analysis is a confidence/centrality heuristic. It does not localise to a specific held-out fact well enough to regenerate a targeted question. That is a real v0.2 item, and the canary caught it. A system that never fails this test is more suspicious than one that fails occasionally and says so.
8. What I would do differently / v0.2
- Gap localisation. Replace the region-level heuristic with claim-level coverage gaps so a withheld fact produces a targeted question.
- Real incremental Leiden. The frozen-core append is honest but drifts; a
proper incremental Leiden (or regular full recompute gated by changelog size)
would tighten
stability. - Synthesis passes. The
--localmodel path (llama.cpp on:8080) was available but the synthesis passes (richer summaries, persona questions) want a real model. Deterministic compile works without it; synthesis is a strict upgrade.
9. Reproduce it
git clone https://github.com/kliewerdaniel/hermes-atlas hermes-atlas
cd hermes-atlas
python3.14 -m venv .venv && ./.venv/bin/python -m pip install -q pytest
# Track A: 20 blog posts + 1 repo
./.venv/bin/python -m hermes_atlas.cli --store trackA \
ingest ~/Projects/blogback/sovereign-ai-site/content/blog \
--repo ~/Projects/sovereign-knowledge-compiler --limit 20 --repo-limit 20
./.venv/bin/python -m hermes_atlas.cli --store trackA compile
# Track B: canary
./.venv/bin/python -m hermes_atlas.cli --store trackA canary --probes trackB_probes.json
Expected: ~990 entities, ~565 claims, ~something relationships, ~15 communities,
~6 contradictions after the full compile; delta recompile adds ~11 changelog
entries with 0 prior-record violations; canary negative-controls trusted at 0.6,
held-out rediscovery flagged at 0.0. If you get different numbers, the first
place to look is the determinism bugs in §4–§5 — they are the ones that bite.
The repo is the artifact. The failures above are the findings.
Full source, README, and the longer replication guide: github.com/kliewerdaniel/hermes-atlas
Related research
Aug 9, 2026
Hermes Atlas v0.2: Claim-Level Coverage, a Determinism Gate, and a Knowledge-Mutation Canary
Hermes Atlas v0.2 is a benchmark-and-fix release: claim-level coverage localisation, a determinism gate that proves compile reproducibility, and a knowledge-mutation canary. Every number below was measured, not asserted.
Aug 9, 2026
Hermes Atlas v0.3: An Evidence Ledger, a Provable Claim Lifecycle, and an Explain Command
Hermes Atlas v0.3 adds an evidence ledger to every claim, a provable claim lifecycle (including DELETE-driven invalidation that retains history), and an `atlas explain` command. Every number below was measured, not asserted.
Aug 9, 2026
Hermes Atlas v0.4: Proving the Evidence Ledger & Claim Lifecycle with a Gold-Labeled Benchmark
Hermes Atlas v0.4 proves the v0.3 evidence ledger and provable claim lifecycle with a gold-labeled benchmark. Every number was measured on a fixed, model-free corpus; two real bugs were found and fixed in the process. Everything below is reproducible.
Feb 15, 2026
Building This Blog: A Technical Deep Dive into My Next.js AI-Powered Publishing Platform
An in-depth look at the technical architecture behind this blog - how I built a performant, AI-powered publishing system with Next.js, Vercel AI SDK, MCP, semantic search, and knowledge graph visualization.
Sep 4, 2026
The Sovereign Agent Stack — A Local-First, Compile-Time AI Agent Framework
The Sovereign Agent Stack (SAS) is a local-first, compile-time AI agent framework that operationalizes the sovereignty thesis from The Rented Sovereign. A complete 7-layer architecture with 156 tests, 23 E2E tests, plugin system, MCP server, and package manager distribution.
Jul 23, 2026
Compiling the State of Human Understanding: A Roadmap for the Scientific State Compiler
A research roadmap: the four compiler directions — Mechanistic Reasoning, Scientific Question, Scientific State, and Discovery — are not competing projects. They are five passes in one architecture that compiles the scientific corpus into a versioned, executable model of human understanding. Here is the full plan.