Retrieval
Retrieval is the read path. RememberStack does not try to be a clever NL planner. It tries to be composable, self-describing, and honest — because the caller is an agent that must reason about the answer before acting.
Why this read path wins
| Design choice | Why agents care |
|---|---|
| No LLM completion on query path | No black-box rewrite of intent; plans stay inspectable (semantic paths may still embed the query) |
| Projections nominate; Postgres confirms | Stale indexes cannot serve dead facts as live |
| Grain-typed answers | Never confuse testimony with belief |
| Envelope self-accounts | Truncation, contradictions, freshness, typed “no”s |
| Filesystem-first + query parity | Use harness strengths; full power when unmounted |

Mental model in three steps
- Nominate — P1 search, live graph SQL, open SQL, or an assured op’s internal chain proposes candidates (P1 may lag; graph does not).
- Confirm — by-ID hydration against live Postgres re-reads validity, invalidation, contradiction membership, currency.
- Account — response envelope (or
QueryResult/v1for open query) states grain, freshness, drops, truncation, negatives.
Mounts skip step 2 by construction (snapshot files). Rule: orient on mounts; verify load-bearing facts on the spine.
Choose a surface
| Need | Use |
|---|---|
| Navigate / read / grep | Mounts (P3, artifacts, K) when published for the deployment |
| “What is true now?” with typed envelope | fact_context |
| High-recall source context for a question | testimony_context |
| Both complete authority views | answer_context |
| Exact name → entity | resolve_entity (T0 exact) |
| Ad-hoc analytics / joins / graph patterns | Open SQL / graph helpers / saved queries |
| Why do we believe X? | Evidence hydration / audit SQL / transcript endpoints where exposed |
| Change feed | Open query / delta-oriented saved patterns |
Wire contracts: API · CLI · MCP.
Assured operations (exactly four)
These are the top-level intent tools on API/CLI/MCP. Seventeen older stock patterns ship only as discoverable examples.* saved queries — not as compatibility aliases.
| Operation | Args (required) | Grain | Intent |
|---|---|---|---|
resolve_entity | name | entity candidates (envelope packaging) | Exact-name disambiguation |
testimony_context | query (optional entity_ids, k, candidate_k) | evidence | Current claims + source chunks only |
fact_context | query (optional entity_ids, hops, predicate, k, evidence_per_fact, time) | fact | Entity-neighborhood relations and observations + associated testimony |
answer_context | query (optional entity_ids, hops, predicate, time) | ContextBundle/v1 | Complete testimony and neighborhood-aware fact envelopes, kept separate |
Entity IDs are optional. Omit them for deployment-wide retrieval. Testimony accepts up to 20 confirmed IDs; the neighborhood-aware fact and answer operations accept up to 19 so the 20-entity combined scope always reserves one neighbor slot. Resolve ambiguous names first. The operations never guess a name or silently drop an unknown ID.
For a current or point-in-time read with entity_ids, fact_context starts
from those anchors, walks one live-graph hop by default, then searches relation labels
and observation statements only inside the anchor-plus-neighbor scope. The
default predicate list is empty, which means all stored relations, including
other:*; predicate is an optional narrowing string, not an enum. Observations
remain fact rows and never become graph nodes; when predicate is supplied,
the exact relation-only filter excludes observations. The combined scope is
capped at 20 entities and the envelope marks graph or fact truncation. A
missing live-graph authority or current anchor absent from it returns a boundary, never a
silent anchor-only current answer. A stale neighbor is omitted and counted in
dropped_by_hydration, preserving current facts inside the surviving scope.
Omitting entity_ids keeps deployment-wide fact search and also lets matching
entity profile prose nominate a bounded scope. That is how a query such as
“list banks” can find an “Acme is a bank” observation without an entity-type
filter. It reuses the query embedding and adds no completion model call.
Anti-patterns
| Don’t | Do |
|---|---|
Answer present-tense from testimony_context alone | Verify with fact_context / facts |
| Filter claim validity windows as “true at T” | Use fact valid_at / facts_current |
| Hide one side of a contradiction | Report co-members |
| Trust a compiled K page as live | Check freshness.k; verify facts |
| Assume empty = unknown entity | Read negative kind |
| Assume fuzzy resolve on misspellings | Use evidence search or fix the name |
Open query space
Three neutral powers:
- SQL — sandboxed live/evidence-composable reads over versioned views + allowlisted SRFs (semantic/lexical nomination bridges and graph helpers).
- Typed graph methods — SQL/PGQ for fixed one-hop patterns and bounded recursive SQL for deeper/shortest paths, all live in PostgreSQL.
- Assured ops — typed envelopes for the common intents.
Discovery: GET /query/space opens with the two-layer headline, honesty warnings, and worked examples. Full page: Open query space.
Envelope (assured path)
Single-grain answers are flat (facts, evidence, fact_evidence,
freshness.pg_live_ts, …). answer_context is the separate
ContextBundle/v1 wrapper around two complete envelopes. Full wire contract:
Response envelope.
Engine primitives vs public call surface
Assured ops and operations compose typed zero-LLM engine primitives internally (resolve, lookup, search, hydrate, …).
Agents should not invent HTTP paths for every primitive. Callable public surfaces are:
- assured ops (
/operations/…) - open query (
/query/sql, discovery, saved queries) - a smaller set of direct primitive endpoints (see API reference and Primitives surface column)
Temporal parameters
| Param | Meaning |
|---|---|
fact_context.time | World-time selection: current, at, overlap, or history under current system belief |
facts_as_of(valid_at, believed_at, …) | Open-SQL audit of what the system believed about world time at a past system time |
Every envelope carries a required discriminated temporal_scope describing
the exact selection applied and the identity regime. Default identity follows
today’s merge redirects.
Live graph traversal requires one world-time instant: current and at use
neighborhood expansion; overlap and history preserve the supplied anchor
scope.
Correctness invariant
Stale projections may nominate; only Postgres confirms truth for query-engine results.
| Cost of lag | Never allowed |
|---|---|
| Miss a too-new fact (recall) | Serve a superseded fact as current |
| Drop a path unit after edge invalidation | Return a path with a hole |
Reading motion

- Orient — K + P3
- Verify — fact grain
- Audit — claims + raw locators
The consumption skill encodes this; cold-agent skill checks fail plans that treat claim search as current truth.
Progressive disclosure
| Depth | Page |
|---|---|
| Map (this page) | Surfaces, assured ops, invariant |
| Envelope contract | Response envelope |
| SQL/graph helpers/saved | Open query space |
| Primitive catalog | Primitives |
| Mounts + skill | Mounts |