Skip to content

Changelog

mempill follows semantic versioning. The first published release is 0.2.0, now live on crates.io and PyPI. See Installation for install instructions.


  • TypeScript bindings (napi-rs) — planned
  • Vector search integration (sqlite-vec / pgvector) — planned
  • True bi-temporal point-in-time read — a valid_at parameter distinct from as_of_tx_time, enabling “what did the engine believe was valid on date X?” queries — planned (v0.3). Today, as_of_tx_time rewinds both transaction time and valid-time selection simultaneously; a separate valid_at axis is not yet exposed.
  • Date precision / granularity — partial dates (2020-03) currently normalize to the start of the period (2020-03-01); the filled day is a normalization placeholder, not asserted precision. Granularity-aware valid-time (rendering “March 2020” honestly rather than “March 1, 2020”) is planned (v0.3).
  • PostgreSQL TLS support — planned for a future minor release (NoTls only today)
  • API/authoritative-source oracle reference implementation — planned
  • pdoc-generated Python API reference at https://api.mempill.dev/python/ — planned

446 Rust + ~70 Postgres (feature-gated) + 135 Python tests · 0 warnings (clippy --all-targets -D warnings + missing_docs) · MSRV Rust 1.88 · Apache-2.0

Cross-adapter conformance: SQLite + PostgreSQL 16 + PostgreSQL 18.4 via testcontainers.

This release ships the full mempill stack end-to-end:

  • EngineHandle<P, O, V> — the sole async entry point. Eight deterministic engine components C1–C8:
    • C1: Provenance Gate — validates and classifies provenance.
    • C2: Canonical Fold — read-time belief computation (I8: canonical, never stored).
    • C3: Conflict Detector — detects Functional cardinality conflicts.
    • C4: Reconciler — attempts deterministic conflict resolution.
    • C5: Read Path (query_memory, query_audit).
    • C6: Amplification Guard — blocks RecallReEntry echoes.
    • C7: Adjudication Gate — oracle escalation when C4 cannot resolve.
    • C8: Ledger — append-only audit log (I1: no UPDATE/DELETE).
  • All port traits: PersistencePort, OraclePort (with NoOpOracle), VectorPort (with NoOpVector).
  • Application use-cases: IngestClaimUseCase, QueryMemoryUseCase, ReconcileUseCase, AuditUseCase, SubmitAdjudicationUseCase, SweepAdjudicationsUseCase.
  • Public DTOs: IngestClaimRequest/Response, QueryMemoryRequest/Response, ReconcileRequest/Response, AuditQueryRequest/Response.
  • mempill-types: ProvenanceLabel, Disposition (12-state), Cardinality, Confidence, Criticality, ValidTime, BeliefProjection, LedgerEntry, ClaimRef, AgentId.
  • 11 invariants enforced: I1 (append-only), I2 (low-conf → Contested), I3 (fold not stored), I5 (oracle proposal only), I7 (overlap → Contested), I8 (canonical fold), I9 (atomic commit), and others.
  • cargo add mempill re-exports mempill-core + mempill-sqlite for the common embedded case.
  • SqlitePersistenceStore, DefaultEngine type alias.
  • open_default(path), open_default_in_memory().
  • Mandatory PRAGMAs at connection open: WAL + synchronous=FULL + foreign_keys=ON.
  • PostgresPersistenceStore implementing PersistencePort via postgres + r2d2 connection pool (max 20 connections).
  • open_postgres(conn_str, oracle, vector, config) and open_postgres_with_oracle(...) constructors.
  • PostgresEngine<O, V> type alias.
  • Per-agent write serialization: pg_advisory_xact_lock(hashtext(agent_id)::bigint).
  • OCC belt-and-suspenders: UNIQUE(agent_id, stream_seq) on ledger_entries.
  • requires_global_write_serialization() returns false — no global application lock; true per-agent concurrency across agents sharing one database.
  • Schema embedded at compile time via refinery::embed_migrations!; runs automatically on first connection.
  • Cross-adapter conformance harness (run_persistence_conformance, run_oracle_conformance): SQLite and Postgres pass the same behavioral test suite.
  • Known limitation: NoTls only — TLS planned for a future release. Do not expose the connection over an untrusted network.
  • submit_adjudication with Affirm/Deny/Unknown verdicts — both SQLite and PostgreSQL adapters.
  • TTL on pending adjudications; sweep_expired_adjudications() orphan sweep.
  • EngineHandle::list_pending_adjudications(agent_id) — returns the durable pending queue with incumbent and challenger values decoded.
  • PyOracleEngine.list_pending_adjudications(agent_id=...) — Python binding.
  • ConflictType::Succession — when a new claim’s valid-time window starts after the incumbent’s ends, and both have valid_time_confidence ≥ 0.7, the engine commits the new claim as CommittedCheap (not Contested) and supersedes the old one cleanly.
  • Fold selects the claim whose valid-time window contains the query instant (now or as_of_tx_time) — query_memory returns the temporally-correct belief without additional filtering by the caller.
  • Succession matrix test suite: now/past/boundary/gap/n-chain correctness, cross-adapter conformance (SQLite + Postgres 16 + Postgres 18).
  • Overlapping windows → Contested (no regression).
  • Low-confidence valid-time (valid_time_confidence < 0.7) → Contested.
  • Claims without valid_timeContested when conflicting.
  • Known limitation: as_of_tx_time rewinds both transaction time and valid-time selection simultaneously. A future release will add a separate valid_at parameter.
  • history() (Rust facade) / history() (Python ergonomic tier) retrieves the full ordered claim timeline for a (subject, predicate) subject-line.
  • Returns History / HistoryResult with entries: Vec<HistoryEntry> (Rust) or entries: list[HistoryEntry] (Python), ordered oldest→newest.
  • Each HistoryEntry carries: value, valid_from, valid_until, status (Current | Superseded), provenance, value_confidence, claim_ref.
  • history().current() returns the single Current entry — guaranteed to agree with recall() (same canonical fold).
  • history().is_empty() — true when no claims exist for the subject-line.
  • Python History is iterable: for e in history(engine, agent, subject, predicate).
  • Remaining limitation: point-in-time valid-time as-of (valid_at) is still v0.3. history() always reflects the current epoch; separate valid_at querying is not yet exposed.
  • PyO3/maturin wheel (PyO3 0.29, Python ≥ 3.11, abi3).
  • mempill.open(path), mempill.open_in_memory(), mempill.open_oracle(path, oracle), mempill.open_oracle_in_memory(oracle).
  • Duck-typed oracle protocol: request_adjudication(self, agent_id: str, request: dict) -> str.
  • submit_adjudication({handle_id, verdict, evidence_provenance}).
  • sweep_expired_adjudications().
  • mempill.types module: Disposition (12-state str enum), ProvenanceLabel (factory), IngestClaimRequest, IngestClaimResponse, QueryMemoryRequest, QueryMemoryResponse, ReconcileRequest, ReconcileResponse, AuditQueryRequest, AuditQueryResponse TypedDicts.
  • Exception hierarchy: MempillError, ValidationError, NotFoundError, ConflictError, StorageError, ConfigError, InternalError.
  • Toolchain: maturin 1.14.1, PyO3 0.29.
  • FastMCP stdio server (FastMCP, mcp 1.28, pinned <2). Four tools: ingest_claim, query_memory, reconcile, audit.
  • MEMPILL_AGENT_ID required environment variable.
  • MEMPILL_DB_PATH optional (in-memory if absent).
  • status_reason field on non-committed dispositions.
  • Friendly provenance string normalisation ("External:UserAsserted" etc.).
  • Console + LangGraph agents.
  • HumanOracle reference implementation — stateless duck-typed oracle; generates a UUID handle per conflict; engine stores all conflict state in the durable pending queue.
  • /review REPL command — interactive human-in-the-loop adjudication: c(hallenger) → Affirm, i(ncumbent) → Deny, abstain → Unknown, skip → defer.
  • --selftest flag for non-interactive CI validation.
  • Verified: deferred conflicts survive engine restart (same handle_id after close+reopen).

The following notes track internal milestones during development toward 0.2.0. They are recorded for historical context only — the authoritative current state is the 0.2.0 section above.

Internal phase Highlights Rust tests at that point
Core engine + SQLite 8 engine components, 12-state disposition model, port traits 290
Python wheel + MCP PyO3 wheel, FastMCP adapter
PostgreSQL adapter topology-b, cross-adapter conformance (SQLite + PG16 + PG18) 311
Oracle resolution loop + HITL submit_adjudication, HumanOracle, /review REPL 430
Valid-time succession ConflictType::Succession, fold fix, succession matrix tests 461
Additional coverage Oracle conformance, edge cases, cleanup 462
Ergonomic Tier-1 API + Postgres test gating remember/recall + enrichment; PG tests feature-gated 424 default · 69 PG · 107 Python
Bi-temporal history read history() / query_history; full timeline with Current/Superseded status 443 default · ~70 PG · 135 Python
Publish-hardening (API guidelines + Cargo checklist) #[non_exhaustive] enum sweep, facade types::/engine:: modules, leak removal, compiled doctest, missing_docs gate 446 default · ~70 PG · 135 Python (current)

Apache-2.0. Note: a commercial licensing option is planned for future releases.