Project Status
Target release coordinate: v0.17.0 on PyPI and GHCR (release coordinate is remember==0.17.0 with terminal transition package rememberstack==0.17.0).
What ships today
Core memory engine
- Full evidence spine: ingest → convert → structure → chunk → claim extract → entity resolve → fact adjudicate
- Immutable claims with occurrence-level multi-span source grounding, adjudicated relations and observations, bi-temporal validity, supersession, contradiction groups
- Frozen Selection results share bounded, source-backed references with later extraction; version reuse covers all cited ranges and earlier context inputs
- Testimony currency and lineage-based evidence counting when documents change or extractors re-run
- Watched sources and versioned document lineages (including a local directory watcher)
Facts use one mutable chosen world-time window with explicit precision. Contextual adjudication handles identity and date corrections together; immutable source claims remain available as evidence. Processing prompts treat a shared person or event as distinct from the proposition being made, and the adjudicator reads compact semantic evidence rather than database bookkeeping. Retrieval distinguishes confirmed temporal matches from incomplete-date candidates. Entity descriptions and fact labels show dated history. Stores created before chosen world dates are recreated, not converted; see deployment.
Retrieval and agent surfaces
- PostgreSQL-native search indexes, a live SQL/PGQ graph, and a browsable corpus filesystem
- Four assured operations:
resolve_entity,claims_and_sources_context,facts_context,combined_context - ID-scoped
facts_context/combined_contextuse bounded live graph neighborhoods forcurrentandat; unavailable graph authority is an explicit boundary, whilehistoryandoverlapremain visibly anchor-scoped - Open query: sandboxed SQL, typed live-graph helpers, saved examples, schema discovery
- MCP assured-operation and open-query tools (stdio client transport)
- Self-accounting response envelopes (grain, freshness, contradictions, typed negatives)
- API, CLI, and MCP in lockstep; optional filesystem mounts and a deployment-rendered consumption skill
- An OpenAPI document for the query API a self-host deployment serves, kept in the repository and compared against the code in CI, so a client can be generated rather than transcribed. The liveness probe stays out of it deliberately. A deployment does not serve the document either — the schema route sits outside the auth perimeter — and releases from here on attach it as an asset
- Cold-agent skill checks so harnesses keep claims and facts straight
Knowledge pages
- Compiled and authored markdown knowledge in git
- Mechanical routing and staleness; authored principles are never machine-rewritten
Operations
- Docker Compose single-deployment self-host (PostgreSQL 19 prerelease, object storage, API, continuous workers)
- Optional API Bearer BIND (
REMEMBERSTACK_SELFHOST_API_BEARER_BIND); default Compose stays open - Optional signed-credential perimeter
(
REMEMBERSTACK_SELFHOST_API_SIGNING_KEYS, a JWKS of Ed25519 public keys): verifies EdDSA credentials issued elsewhere, so more than one caller can reach a deployment without pushing a secret per caller. Composes with the Bearer BIND when both are set; unset changes nothing - PostgreSQL-native P1 search indexes; no separate search-store maintenance process
- Work ledger with retries, dead-letter queue, optional spend ceilings
- Request-path surface metering plus a content-free
v_cost_receiptsexport (remember ops cost-exportand optional second-bind HTTP) - Optional managed-hosting ingest metering under the Compose
managedprofile: exact normalized document-text receipts, durable replay and outcome handling, and hard-forget cancellation. Default self-host Compose does not start it. remember login/logoutvia a token-host device grant (CLI credential file only)- Machine-verifiable readiness; projection rebuilds; hard-forget; portable restore order
- Optional observability exporters (off until configured)
Packaging
- Single canonical
rememberwheel on PyPI providing the unified platform CLI (remember) and Python SDK (from remember import RememberClient, MemoryClient, with 100% backward-compatibleClientandCloudClientinterfaces) - Container-first engine distribution via
ghcr.io/writeitai/remember-stackand Docker Compose - One semantic version across PyPI, GHCR image, and Compose
Smoke-profile limits (be honest)
| Area | Status in default Compose smoke |
|---|---|
| Markdown ingest | Supported |
| PDF / HTML conversion | Engine-capable (mistral_ocr, markitdown); register routes — not auto-wired in the smoke profile |
| Static image conversion | Engine-capable dual-lane route image_ocr_description (dedicated OCR + independent vision-LLM description for static image/png and image/jpeg); register routes and both provider keys — not auto-wired in the smoke profile. Video/audio conversion is not shipped |
| Query-time entity resolve | Exact-name match; richer matching runs at write time |
| Competitive benchmark scores | Operator-run protocols; not a continuous public scoreboard |
What landed after v0.3.0 (in v0.4.0)
- MCP memory write verbs
ingest+pipeline_readinessshipped in v0.3.0. - v0.4.0 adds request-path surface metering,
rememberstack.cost_export.v1(CLI + optional second-bind HTTP), andremember login/logout.
What landed after v0.4.0 (in v0.4.1)
- Remote MCP
tools/listtreatsGET /operations404 as “registry not mounted” and still advertisesingest+pipeline_readiness(managed UMC token surface). Auth and transport failures still fail the list.
What landed after v0.4.1 (in v0.4.2)
- Stock self-host convert routes
text/plainthrough the same UTF-8 passthrough astext/markdown(#302). CLI/SDK.txtingest no longer dead-letters as unroutable MIME.
What landed after v0.4.2 (in v0.4.3)
- Optional API perimeter: SHA-256 Bearer BIND
{issued_deployment_uuid}:{sha256hex}(#305). Unset keeps the open quickstart.GET /healthzstays unauthenticated.
What landed after v0.4.3 (in v0.5.0)
- PostgreSQL 19 SQL/PGQ now serves fixed one-hop live graph patterns; bounded recursive SQL serves deeper neighborhood, shortest-path, and citation traversal with explicit expansion, frontier, result, time, memory, and connection limits.
- PostgreSQL is the single graph authority. The legacy embedded graph store, public Cypher, graph-build workers, and snapshot serving were removed in this pre-1.0 clean cut.
- Typed graph HTTP and Python SDK operations expose current and bi-temporal as-of traversal. The release also publishes a multi-architecture PostgreSQL 19 Beta 3 foundation with pinned pgvector, pg_textsearch, and pg_partman.
What landed after v0.5.0 (in v0.6.0)
facts_contextnow composes lexical/vector search, referent resolution, bounded live-graph expansion, and evidence hydration under one snapshot and deadline. Same-name exact matches remain visible candidates rather than a silent entity choice.- The assured-operation registry publishes the new retrieval contract as operation version 2, and the bundled saved query follows the same default.
- Graph planner settings are deployment-local and transaction-contained, with migrations and readiness checks for the PostgreSQL 19 execution plans.
Unreleased on main
- Stored originals remain usable without a converter (D117). Otherwise
admissible uploads retain their raw bytes. Conversion starts parked with
defer_reason=no_route; missing routing does not mark the version failed. A worker with stale configuration also parks without consuming an attempt allowance. - Raw availability and processed currency are separate. After P3 rebuild
and mount publication, the stub's
stored_raw_uripoints to the latest durable original. A separate processed-version section retains any older working summary and full text. Configure real provider raw/artifact mount roots as described in Mounts; default empty directories do not serve bytes. - Resume only supported backlog. Run
remember ops resume-no-route --deployment <uuid>with the new route configuration after restarting workers. Only now-routable live versions are released. Previously dead-lettered versions still requireremember ops replay. - Breaking for library consumers:
UploadIngestorrequiresroutable_mimes=frozenset(conversion_routes). The catalog checks the canonical stored MIME, including when the same bytes return with a different declaration. - Managed text admission and classification are unchanged. Unaccepted staged originals are omitted from P3. After approval, a worker missing the route parks conversion; this does not introduce cloud binary admission or storage-only billing.
What landed after v0.9.0 (in v0.10.0)
- A shared name no longer costs a candidate anything. The generic-identifier guard flagged any name linking two or more entities and used that flag as the primary blocking sort key — ahead of match score. A near-exact hit on a common name could rank below a barely-matching unusual one and be truncated out of the candidate list entirely.
- The premise was wrong: it counted entity rows, not people. Because T0 never auto-merges, the resolver deliberately mints a second row for one real person pending adjudication — and the guard read its own conservatism as proof the name was generic. Ten unrelated Jan Nováks and one Jan Novák recorded twice were indistinguishable to it, and it demoted both.
- Fuzzy blocking now ranks by match score, then by how closely the entity's own canonical name resembles the query, then by age, then by id. That replaces a tiebreak that fell through to a random UUID whenever candidates matched through the same name.
- D21's promiscuous-signal concern (
[email protected], placeholders) moves to the mechanisms that decide identity — T3 profile evidence, T4, and cannot-link exclusion edges — rather than demoting candidates before anything examines them. - What this costs, stated plainly: an overflowing fuzzy block no longer truncates promiscuous-string matches first. The candidate set still reports honestly when it was truncated. On a deliberately degenerate shape (100k entities sharing one fuzzy name) the ranking query is measurably slower — runs ranged +3.3% to +31%, consistent in direction, not in magnitude.
- Operators: migration
p9_23_0044dropsgeneric_identifier_guard. Because that table carries a foreign key todeployments, the drop briefly takes anAccessExclusiveLockon the tenancy root, which blocks readers as well as writers; it is scan-free and short, and the migration sets a 5slock_timeoutso it fails fast rather than queueing behind a long read. The resolver generation moves toresolver-2026.08g, so evaluation curves measured under08fare not comparable and a fresh run is required.
What landed after v0.15.0 (in v0.16.0)
Dated events no longer collapse merely because their words match. The
observation adjudicator now uses each claim's resolved world-time window.
Events with disjoint dates stay distinct unless a date-aware verdict identifies
one occurrence with disputed dates; a dated event also cannot serve as
evidence for an undated summary. Recurring same-shaped events therefore
survive as separate facts, and ingestion provenance changes
(#360).
Claim windows have one canonical half-open meaning. Day, month, quarter,
and year precision cover their complete calendar unit; instants remain
non-empty points; open and unknown bounds stay explicit. claims_as_of now
finds a day-precision claim from an intraday or point query, and observation
adjudication uses the same bounds
(#372).
Operators: migration p9_26_0047 adds the canonical-bound SQL functions
and the partial expression index used by claims_as_of; claim storage is
unchanged. Observation generations roll, so rebuilding changes stored
ingestion provenance, and claims_as_of results change under the corrected
window semantics. Migration p9_27_0048 publishes those bounds to open SQL as
memory_v1.canonical_bounds and claims_canonical; the shipped
examples.claims_as_of query overlaps the canonical window and counts
unknown-precision claims by precision.
A release now carries the API contract beside the binaries. The generated
openapi.json is attached to the GitHub release, so client generation can pin
the exact schema served by the installed engine rather than following main
(#358).
Browser uploads have their own narrow credential. The signed perimeter now
has read, ingest, and write scopes. ingest reaches only POST /ingest:
it cannot search, list memory, run operations, or create a connector that keeps
pulling after the browser leaves. Full write still reaches ingest. A narrow
credential also cannot assert immutable principal attribution
(#363,
#370).
Managed login uses the deployment hostname it receives. When the token
host advertises a live data-plane hostname, remember login derives the query
API URL, so managed users need only --token-host. An explicit --api-url
still wins for self-hosted and local deployments. A missing hostname asks for
that flag, while a hostname that is not live prints the name and asks the user
to retry; neither refusal replaces an existing credential
(#371).
What landed after v0.14.0 (in v0.15.0)
A deployment can tell you what it holds. GET /documents lists document
lineages — title, source, when each was ingested, the newest version's
processing state, and the engine's own error when one failed. It is what lets
an app show somebody which file arrived rather than only how many.
The ordering is first_seen_at and never moves. "Most recently touched" is
the tempting order and the wrong one: re-ingesting a document would raise it
and tombstoning a version would lower it, and a keyset cursor against a moving
key silently drops rows a reader never sees and repeats ones they already
have.
Search without putting the query in the URL. POST /search/claims and
POST /search/chunks take the terms in a body. A query is usually the most
sensitive string in the exchange, and a URL is written to access logs, kept by
proxies and retained in browser history. The GET forms are unchanged for
clients on a private path.
A deployment can name the browser origins allowed to call it.
REMEMBERSTACK_SELFHOST_BROWSER_ORIGINS, empty by default. Without it a
browser refuses every cross-origin request before the credential is even
examined, and the failure looks like the deployment being down.
What landed after v0.13.0 (in v0.14.0)
remember loginworks again. It has failed since 2026-08-25 with a validation error: the managed token host began returning two fields the client's response model refused. 0.13.0 does not contain this fix — it was released frommainwhile the change was still on its branch, so an 0.13.0 install is as broken as an 0.12.0 one. That model now ignores fields it does not know, the way a client of a separately deployed service has to (#351).- Login mints before it revokes. Replacing a credential no longer starts by destroying the one you have, so a login interrupted at the browser step leaves the existing credential working. The credential being replaced is journalled until the token host confirms it is gone, and any command will tell you if one is still outstanding.
- A credential can carry an expiry.
loginprints it, it is stored, and every command warns on stderr within 30 days of it — so a scheduled job does not fail at 3am with an unexplained 401. No expiry recorded means none was sent, not that the credential never expires. - The signed-credential perimeter is stricter. Exactly one audience, and it
must be this deployment;
nbf,scopeand a non-empty credential id are required; the key set must be Ed25519 public keys and is refused if any declared key fails to load. Nothing here changes an open quickstart or a deployment using only the Bearer BIND.
What landed after v0.8.1 (in v0.9.0)
- Ingest records who created a version as a typed principal
(
user | api_credential | service). A machine credential is never collapsed into the person who minted it; attributing token activity to that person would be false attribution. - Attribution is creation-scoped and immutable. Bytes identical to the lineage's latest version remain the D55 no-op, so a later submitter of the same bytes never rewrites who created it.
- The pair travels in
X-Ingest-Principal-Kind/-Refheaders, never the query string: the reference is erasable PII and a URL is copied verbatim into access logs, proxies and traces. - It is honoured only where the deployment declares
REMEMBERSTACK_SELFHOST_TRUSTED_PRINCIPAL_SOURCE(default off, for a control-plane-only perimeter) and, when an API perimeter is configured, the caller has fullwriteauthority. Elsewhere attribution is ignored, never rejected — metadata must not be able to fail an otherwise valid ingest. - Deleting a principal nulls attribution and never destroys the document version. This is row deletion, not a D74-grade hard forget; a person-grain forget target is a later slice.
What landed after v0.8.0 (in v0.8.1)
- Write-time T4 makes one binary, match-biased simple-model call over the
complete bounded candidate snapshot. It selects a supplied entity id or
new; confidence is audit evidence and never routes to a frontier model. - The T4 prompt includes ordered candidates, aliases, current profile descriptions, salient facts, and T3 scores/gates. Missing overlap or a different topic is not evidence for a new entity.
RS-LoCoMo-Full-v17fingerprints this resolver generation while retaining v16's read surface, answer/judge seats, budgets, and content-before-Unknownguard.
Document-local exact T0 (current release behavior)
- Resolver
resolver-2026.08hcan replay an exact canonical-name match at T0 (a behavior introduced in08f) only inside the same document and only after a T4 match established one unambiguous live binding. Fuzzy T1/T2 signals remain candidate-only. - The derived binding projection is generation-gated as
document-t0-v1, rebuilt before it is enabled for existing deployments, and cleared by normal lineage deletion and hard forget. - Historical
RS-LoCoMo-Full-v18pins the binding generation in addition to the v17 retrieval, answering, judging, budget, and answer-attempt contracts. - Historical
RS-LoCoMo-Full-v19changed only the frozen answer prompt: a hypothetical may follow causal or motivational relationships in retrieved evidence even when no source states the hypothetical verbatim. It adds no retrieval, retry, reasoning-effort, or call-budget work. - Historical
RS-LoCoMo-Full-v20also requires every distinct retrieved value that directly satisfies the question. It does not add a retrieval or retry. - The current
RS-LoCoMo-Full-v24pins D107 WP-T.4: all four claim temporal kinds, open-ended state windows, and full source timestamp headers. The extractor generation rolls; the fact schema and query-space contract do not. - Historical
RS-LoCoMo-Full-v23pins the query-space publication of those bounds (D107 WP-T.0b):memory_v1.canonical_bounds,claims_canonical, and the rewrittenexamples.claims_as_of. Ingestion and the libraryclaims_as_ofpath are unchanged from v22; the surface manifest hash rolls. - Historical
RS-LoCoMo-Full-v22pins canonical half-open claim bounds (D107 WP-T.0a): a day-precision claim is found from an intradayclaims_as_ofwindow and the observation adjudicator no longer treats a day as a zero-width point. Ingestion provenance andclaims_as_ofresults change; the benchmark's tool set does not. - Historical
RS-LoCoMo-Full-v21pins the D106 observation adjudicator: dated events with disjoint resolved windows never collapse onto or supersede each other (a same-occurrence date dispute may contradict), and a dated event is neverevidencefor an undated statement. Recurring same-shaped events (seven tournament wins months apart) now survive as distinct facts. It changes ingestion provenance only; retrieval, prompts, budgets, and scoring are those of v20.
Mutable temporal facts
Facts have one chosen world-time window. Ordinary adjudication uses source dates
and surrounding context to identify repeated events and revise a fact's dates.
Claims retain the source's original testimony. Historical retrieval and dated
summaries use the chosen window without a stored state/event taxonomy or separate
verdict dates. The evaluator generation is Full-v36; this change does not establish
a benchmark score improvement. Full-v36 requires the ground_claims
ingest stage, pins D122 source-backed references plus D123 contextual
nomination, uses structure generation e0-structure-2026.07g:d79-wave2
so the fallback nested JSON field is subsections, pins normalizer
generation …:both-lists-1:t4-format-1:nested-fields-1 so both
observations and relations arrays are required, nested observation /
relation / EntityRef fields are named, and T4 names all four existing
fields, pins resolver resolver-2026.08h, and pins fact-application
generations …:output-fields-1:new-fact-refs-1 so all nine existing
fact-decision fields are named, window=null when no explicit date
replacement is intended, and a new fact is declared as N1 rather than an
invented F-name. Dataset, models, retrieval, budgets, and scoring are
unchanged.
Stores created before this change are recreated and re-ingested; the migration refuses a populated database rather than converting it (deployment).
What landed after v0.6.0 (in v0.7.0; historical resolver generation)
- Entity adjudication is tri-state. Thin evidence and bounded-prefix truncation mint explicit provisional fragments without poisoning later convergence; only positively supported difference creates an effective cannot-link.
- T3/T4 provider calls no longer hold the normalized-lemma advisory-lock transaction. Candidate/profile authority is revalidated before commit with bounded retry on contention.
- Successful profile publication invokes bounded local convergence. Automatic merge remains fail-closed by default, and equivalent review proposals are deterministic and deduplicated.
RS-LoCoMo-Full-v16retained v15's read surface and budgets while enforcing a content-bearing attempt before terminalUnknownafter identity-only reads.
Intentionally not in the library
- Multi-tenant hosted control plane, billing, or dashboards
- Production SLA claims from these docs
- Automatic free-model routing for publication benchmarks
- Secret management product (use your own secret store)
Docs map
- Why RememberStack · Getting started · vs passage RAG
- Concepts · Architecture · Knowledge
- Ingestion · Retrieval
- Mounts · Deployment · Configuration
- Troubleshooting · Evaluation
- API · CLI · MCP
Following along
- GitHub repository — releases and pull requests
- Public docs — this site, versioned with the code