The enforcement pass can only demote, never tombstone and never delete

gaius

An ops memory for coding agents that runs unattended by design, where a flagged fact is reclassified into a ranking penalty rather than removed, and behavioural gates exit non-zero on force-push and prod-delete.

Carries 2 of 7 rubric mechanisms. Most systems here carry none or one (41%), and a dash means the mechanism was not found at this commit — not that the system needed it. Each mark is one LLM reviewer's reading of the code at this commit rather than a run of it — known limits.

  • Tombstone
  • Trust state
  • Bi-temporal
  • Scope enforced
  • Mutation audit
  • Human review
  • Negative evals

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_stateconfidence_source is left untouched…" "• Reversible — an operator flips review_state back to auto to 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 — 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
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-16b720bdb6… — 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.