1. Executive Summary
gaius is an "[o]ps memory lifecycle manager for AI coding agents" — Apache-2.0, Python, 29,474 lines across 79 files, one SQLite file with BM25 and sqlite-vec and no network. It extracts facts from Claude Code, Gemini CLI, Grok and Codex sessions, "ranks them into an inject-ready corpus, enforces behavioral gates, and prevents you from breaking prod at 3am."
Its three claims are stated as things other tools skip, and the first of them is unusual to advertise:
"Runs unattended — extract → promote → inject with no human in the hot path; correction is optional."
Most systems in this corpus imply a person somewhere and leave the reader to discover there isn't one. gaius says so on the first screen, which changes how the rest should be read.
The mechanism worth carrying is an enforcement pass that
states its own limits before its purpose.
corpus_audit reclassifies flagged facts from
auto to pending, and the module header bounds
it three ways:
"• DEMOTE-ONLY — never tombstones, never DELETEs." "• Touches ONLY
review_state—confidence_sourceis left untouched…" "• Reversible — an operator flipsreview_stateback toautoto undo."
The three values then do different work. A read filters
review_state != 'rejected', so a rejected fact keeps its
row and leaves the corpus; a pending fact stays retrievable
under "the ranker's 0.6x pending" penalty. Withholding and demotion are
separate outcomes rather than one slider, which is the distinction this
atlas most often finds collapsed.
The gates prevent rather than advise. "[H]ard gates
exit:2 on force-push, unconfirmed live-trade, prod-delete"
— a non-zero exit rather than a warning in a log.
And the deduplication preserves the evidence it merges. Rows sharing a fact key are folded into the oldest, with confirmation counts summed and the agents, sessions, principals and model families unioned rather than picked — so the fact that several independent runs agreed survives the merge that removes the duplicates.
The gap is a familiar one. domain is on
every fact and most reads carry WHERE domain = ?, but the
maturity path builds the clause as
"AND domain = ?" if parsed.domain else "" — the isolation
holds where somebody wrote it carefully and lapses where it was treated
as an option.
2. Mental Model
A fact is extracted, promoted and injected without anyone approving it.
A review state either withholds or discounts, and the two are not the same.
An audit pass may demote and may not destroy.
A gate exits non-zero; it does not warn.
Diagram source
%% caption: facts are extracted and promoted unattended, an audit pass may only demote a flagged fact into a ranking penalty, rejected facts leave the corpus while pending ones stay at a discount, and behavioural gates refuse an action with a non-zero exit
flowchart TB
SESS["Claude Code · Gemini CLI · Grok · Codex sessions"] --> EX["extract"]
EX --> PROMOTE["promote — no human in the hot path;<br/>'correction is optional'"]
PROMOTE --> F[("facts: domain · fact_key · fact_text ·<br/>confirmation_count · agents · sessions · principals ·<br/>provenance · score · outcome · review_state · tombstoned_at")]
DEDUP["rows sharing a fact_key"] --> MERGE["keep the OLDEST row, SUM the confirmation counts,<br/>UNION agents, sessions, principals, model families"]
MERGE -.->|"the evidence that several independent runs agreed<br/>survives the merge that removes the duplicates"| F
MERGE --> TOMB["losers get tombstoned_at, embeddings dropped"]
TOMB -.->|"a dedup marker, not a rejected-value record —<br/>nothing is keyed on the value, so a later session<br/>can re-extract it as new"| NOTOMB["no tombstone mark"]
AUDIT["corpus_audit: flag a fact"] --> DEMOTE["review_state: auto → pending"]
DEMOTE -.->|"DEMOTE-ONLY — never tombstones, never DELETEs;<br/>touches ONLY review_state, so confidence_source<br/>survives; reversible by an operator"| SAFE["a sweep you can run unattended"]
DEMOTE --> F
OPER["an operator disagrees"] --> FLIP["flip review_state back to auto"]
FLIP --> F
F --> READ{"retrieval"}
READ -->|"review_state = 'rejected'"| OUT1["excluded from the corpus —<br/>the row stays in the table"]
READ -->|"review_state = 'pending'"| OUT2["retrieved at a 0.6x penalty"]
READ -->|"review_state = 'auto'"| OUT3["ranked normally"]
READ --> DOM{"WHERE domain = ?"}
DOM -.->|"most reads carry it; maturity builds the clause as<br/>'AND domain = ?' if parsed.domain else '' —<br/>so one path returns the whole corpus"| NOSCOPE["no scope-enforced mark"]
GATES["behavioural gates"] -.->|"exit:2 on force-push, unconfirmed live-trade,<br/>prod-delete — refuses the action rather than<br/>logging a warning about it"| ACT["the action does not happen"]3. Architecture
| Area | Role |
|---|---|
gaius/facts.py |
The schema, the dedup merge, and the read filters |
gaius/corpus_audit.py |
The demote-only enforcement pass and its stated bounds |
gaius/concord.py |
Single-winner resource claims, enforced by a partial unique index |
gaius/maturity.py |
The ranked-set pass, and the conditional domain clause |
gaius/_core.py |
The command table, including a retired verb kept as a signpost |
hooks/, benchmarks/ |
Agent integrations and measurement |
4. Essential Implementation Paths
gaius/corpus_audit.py:53-62 — an enforcement pass that
says what it may not do before saying what it does.
gaius/facts.py:443 — the read filter that makes
rejected mean something.
gaius/facts.py:36-80 — a merge that unions the evidence
rather than choosing among it.
gaius/maturity.py:407 — the conditional scope
clause.
gaius/concord.py:154-158 — a partial unique index as
"the atomic single-winner claim", where "the loser is told, never
queued".
5. Memory Data Model
Facts keyed by domain and fact key, carrying the agents, sessions, principals and model families that produced them, a confirmation count, a provenance record, a score, an outcome, a review state and a tombstone column; sessions, domains, entities and triples beside them, with a separate claims table for resource coordination.
6. Retrieval Mechanics
BM25 with optional sqlite-vec semantic search over facts that are neither tombstoned nor rejected, with pending facts carried at a discount rather than dropped, ranked by a composite score.
7. Write Mechanics
Extraction and promotion run unattended. Duplicates are merged rather than deduplicated destructively. The audit pass demotes. Behavioural gates sit in front of dangerous actions and exit non-zero rather than recording an opinion.
8. Agent Integration
A CLI, an MCP server and hooks for the agents whose sessions it reads, with an offline core and semantic and MCP extras.
9. Reliability, Safety, and Trust
The strong parts are the bounded sweep, the separation of withholding from demotion, the evidence-preserving merge and gates that refuse. The limits are a scope clause that one path treats as optional, a tombstone column that is a dedup marker rather than a rejected-value record, and a pipeline that by design does not wait for a person.
10. Tests, Evals, and Benchmarks
A benchmarks directory sits beside the package, and the corpus audit is written to be run repeatedly and reversed, which is its own kind of check. There are no committed cases asserting that particular material must not be retrieved.
11. For Your Own Build
Bound your enforcement pass in its own header, and bound it downward. "Never tombstones, never DELETEs" is what makes a sweep something an operator will actually let run.
Keep withholding and demotion as different states. A single confidence number cannot express "do not use this" and "use this last" at the same time.
Union your evidence when you merge. Summing confirmation counts and unioning the agents that produced a fact keeps the reason it was believed; picking a winner discards it.
Write your scope clause unconditionally. The path that makes it optional is the path that returns somebody else's corpus.
12. Open Questions
Whether the maturity path's optional domain clause is deliberate. Every other read carries the predicate, which makes the one that does not look like an oversight rather than a decision.
Whether rejected should be keyed on the value. A
rejected fact leaves the corpus and a later session can extract the same
claim again, so the rejection protects the corpus once rather than
standing.
Appendix: File Index
| Path | What to read it for |
|---|---|
gaius/corpus_audit.py:53-62 |
A pass that states its own ceiling first |
gaius/facts.py:443 |
Withholding and demotion as different states |
gaius/facts.py:36-80 |
Merging duplicates without discarding the agreement |
gaius/maturity.py:407 |
The scope clause that became optional |
History
2026-09-16 — b720bdb6…
— first reading, at a commit dated 15 September 2026. Screened before
opening, from a shallow clone: four auto-run surfaces, one build-time
execution point, no unpinned dependency surfaces and two dependency
files inside the seven-day cooldown. Nothing was installed, built or
run, and no session transcript was extracted.