Memorex
A governed personal memory substrate for AI products.
Memorex gives assistant systems a policy-aware memory layer with provenance, consent, lifecycle state, user review, correction workflows, and auditable retrieval.
A memory layer designed for systems that must be inspected.
Memorex is not a chatbot UI. It is the substrate underneath assistants — separating observations, claims, accepted facts, memories, lessons, consent, and audit traces.
Provenance-first memory
Every accepted fact carries the chain of observations and claims it came from. No fact exists without a source.
Consent-aware retrieval
ConsentGrants gate what can be returned, to whom, and for which intent. Policy decides — never score.
Lifecycle-governed facts
Claims, accepted facts, memories, and corrections move through explicit, auditable lifecycle states.
Review and correction
Humans approve identity-bearing claims. Corrections supersede facts; nothing is silently overwritten.
Advisory scoring, authoritative policy
Reasoning may rank candidates. Capsulang policy decides whether they are returned.
Traceable state transitions
Every transition emits a hash-linked trace event. Mutation and reordering are detectable.
From observation to retrieval — every step is governed.
Memorex enforces a strict separation between what was observed, what was interpreted, what was accepted, and what may be returned.
A raw, attributable signal entering the runtime. Observations are facts about what was seen — never about what it means.
- Must carry a source identity and timing.
- Must declare a trust band; untrusted sources cannot escalate themselves.
- No interpretation is recorded at this stage — only what was observed.
{ "source": "client.web", "trust": "low", "ts": "…" }- Rejects observations without a verifiable source.
- Rejects observations claiming higher trust than their channel allows.
Assistant interpretations are not treated as facts.
Identity claims are never silently promoted.
Restricted memories cannot bypass policy gates.
Lessons are advisory and visible — not hidden filters.
Every state transition emits a trace event.
Every accepted fact has provenance.
Twelve composable surfaces, one governed pipeline.
Each surface is a small, typed module you can adopt independently. They compose into a complete governed memory runtime.
Observation ingestion
Capture raw signals from clients with source identity, timing, and trust band.
Claim validation
Validate structural and semantic invariants before a claim is allowed to enter review.
Fact lifecycle
Pending → reviewed → accepted → superseded. State changes are auditable transitions.
Memory lifecycle
Active, archived, restricted. Restriction is policy state, not a search filter.
ConsentGrant lifecycle
Grant, expire, revoke. Retrieval consults grants for every package.
Review queue
Identity-bearing and high-trust claims surface for human approval.
Correction workflow
Corrections supersede prior accepted facts and emit linked trace events.
Lesson advisory presentation
Lessons surface to operators as advisory signals — never silent filters.
Policy-gated retrieval
Retrieval returns context packages only when consent and policy permit.
Trace event hash chaining
Each trace event hash-links to its predecessor for tamper detection.
In-memory & SurrealDB adapters
Swap operational and trace stores for tests, local runtime, or production.
Static analysis & dep-free tests
Ruff, mypy, and unittest discovery run with zero runtime dependencies.
From zero to a governed retrieval in 60 seconds.
Spin up the runtime with the in-memory adapters, walk a fact through the full pipeline, then inspect every trace event the runtime emitted.
Install
The runtime is dependency-free. Install from PyPI or clone the source and set PYTHONPATH.
pip install memorex
# or, dependency-free from source:
git clone https://github.com/memorex/runtime
export PYTHONPATH=runtime/srcWalk a fact through the pipeline
Wire two in-memory adapters, then ingest → claim → approve → consent → retrieve. No external services required.
from memorex.storage.memory import (
InMemoryOperationalStore,
InMemoryTraceStore,
)
from memorex.observation import ingest_observation
from memorex.claim import propose_claim
from memorex.review import approve_claim
from memorex.consent import grant_consent
from memorex.retrieval import retrieve_context_package
# 1. Wire two in-memory adapters — zero external deps.
store = InMemoryOperationalStore()
trace_store = InMemoryTraceStore()
# 2. Ingest a raw observation from a trusted client.
observation = ingest_observation(
{
"subject_user_id": "user_123",
"source": "client.web",
"trust_band": "medium",
"payload": {"text": "I prefer replies after 6pm."},
},
operational_store=store,
trace_store=trace_store,
)
# 3. Propose a typed claim from that observation.
claim = propose_claim(
{
"from_observations": [observation["id"]],
"kind": "preference.reply_timing",
"value": {"after_hour_local": 18},
},
operational_store=store,
trace_store=trace_store,
)
# 4. Approve the claim — it becomes an accepted fact with provenance.
approve_claim(
claim["id"],
reviewer="user_123", # self-approved preference
rule="self_declared_preference",
operational_store=store,
trace_store=trace_store,
)
# 5. Grant consent for the intent that will retrieve it.
grant_consent(
{
"subject_user_id": "user_123",
"intent": "assistant_personalization",
"scope": ["preference.*"],
},
operational_store=store,
trace_store=trace_store,
)
# 6. Retrieve a policy-gated context package.
package = retrieve_context_package(
{
"id": "retrieval_001",
"subject_user_id": "user_123",
"intent": "assistant_personalization",
"query_text": "reply timing",
},
memory_store=store,
trace_store=trace_store,
)
for fact in package["facts"]:
print(fact["kind"], "->", fact["value"])
# preference.reply_timing -> {'after_hour_local': 18}Inspect the trace chain
Every state transition emits a hash-linked trace event. Iterate them, verify the chain, and export per-subject audit slices.
# Inspect every trace event the runtime emitted, in order,
# and verify the hash chain is intact.
from memorex.trace import iter_trace_events, verify_trace_chain
events = list(iter_trace_events(trace_store))
for ev in events:
print(
f"{ev['ts']} "
f"{ev['event_type']:28} "
f"prev={ev['prev_hash'][:8]}… "
f"hash={ev['hash'][:8]}…"
)
# 2025-… observation.ingested prev=00000000… hash=9af3c1d2…
# 2025-… claim.proposed prev=9af3c1d2… hash=4e21ba07…
# 2025-… review.decided prev=4e21ba07… hash=71cd9e10…
# 2025-… fact.accepted prev=71cd9e10… hash=ab02f534…
# 2025-… consent.granted prev=ab02f534… hash=2d4419c8…
# 2025-… retrieval.requested prev=2d4419c8… hash=88e7a601…
# 2025-… retrieval.package_emitted prev=88e7a601… hash=c3915bdf…
# verify_trace_chain raises ChainBroken on any mutation or reorder.
report = verify_trace_chain(trace_store)
assert report.ok, report.first_break # -> AssertionError if tampered
# Filter to a single subject for an audit export.
subject_events = [
ev for ev in events
if ev["subject_user_id"] == "user_123"
]
print(f"emitted {len(subject_events)} events for user_123")A small surface area. Strong invariants behind it.
Each entry point is a pure function over typed inputs and storage adapters. Side effects are explicit, traceable, and policy-checked.
Returns a policy-gated retrieval package for a given subject and intent.
from memorex.retrieval import retrieve_context_package
package = retrieve_context_package(
{
"id": "retrieval_001",
"subject_user_id": "user_123",
"intent": "assistant_personalization",
"query_text": "reply timing",
},
memory_store=store,
trace_store=trace_store,
)Supersedes a prior accepted fact. Never overwrites — emits a linked trace event.
from memorex.correction import apply_fact_correction
result = apply_fact_correction(
correction,
semantic_graph_store=graph,
operational_store=store,
trace_store=trace_store,
)Moves grants to expired state and propagates retrieval visibility.
from memorex.consent import expire_consent_grants
expire_consent_grants(
store.list_consent_grants_by_user("user_123"),
operational_store=store,
trace_store=trace_store,
)Capsulang policy. Enforced, not advised.
Reasoning may score candidates. Policy decides whether they may leave the runtime. These invariants are enforced at the gate.
- P001No assistant inference as fact without approval/evidence
- P002No silent identity promotion
- P003No hidden lesson application
- P004/P010Retrieval score cannot override access policy
- P005No external communication without approval
- P006No third-party biometric inference
- P007Preserve ambiguity
- P008Provenance required
- P009Corrections supersede, never overwrite
- P012Consent and user sovereignty checks
Eleven modules. One clear separation of powers.
TensorLang / reasoning may score. Capsulang / runtime policy decides.
The trace chain is the memory of the memory.
Current trace chains detect accidental mutation and reordering inside the same trust boundary. External-auditor-grade deployments add signing, anchoring, or immutable storage.
In-memory adapters
First-class adapters for tests and local runtime. Zero external dependencies.
SurrealDB adapters
Operational and trace stores backed by SurrealDB for production deployments.
Hash-linked trace chain
Trace events use deterministic hashes and previous-event links for tamper detection.
Auditor-grade extensions
Add signing, anchoring, or storage immutability for external-auditor-grade deployments.
Run the whole suite without installing anything.
The runtime ships dependency-free. Tests run on a clean Python install. Static analysis is a single command.
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src \
python3 -m unittest discover -s testspython3 -m ruff check .
python3 -m mypyQuestions engineers ask before adopting a memory layer.
Concrete answers about consent enforcement, provenance guarantees, review and correction workflows, and what the trace chain actually proves.
Build AI memory systems that can be inspected, corrected, and governed.
Adopt Memorex incrementally — start with the runtime API, swap storage adapters when you're ready, and keep every transition auditable.