Every row in memories carries the canonical envelope as of schema v14 (A3) + v15 (hardening).
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
TEXT | yes | raw | distilled | superseded | archived. Default distilled. Append-only when kind='raw'. |
scope |
TEXT | no | NULL = global / un-scoped. Format conventions: team:<id>, project:<id>, customer:<id>. A5 will tighten tenant semantics. |
owner |
TEXT | no | user:<id> or agent:<id>. |
artifact_ref |
TEXT | no | URI to the source artifact. Examples: slack://team/channel/<ts>, gh://owner/repo/pr/<n>, file:///abs/path. |
session_id |
TEXT | no | Aliased to existing source_session_id column. Same field, named in the envelope for clarity. |
confidence |
TEXT | yes | verified | observed | inferred | stale. Existing field, repurposed as part of the envelope. |
created |
TEXT | yes | Existing timestamp; satisfies envelope timestamp. |
- Append-only on raw.
DELETE FROM memories WHERE kind='raw'aborts viatrg_memories_raw_append_only. The only legitimate path to remove akind='raw'row isarchiveRawMemory(db, id, { reason, who })fromsrc/raw-archive.ts, which snapshots intoraw_archive, flipskindto'archived', then deletes in one SAVEPOINT (also purges thememories_ftsrow so archived content is not searchable post-archive). - Kind enforcement. INSERT/UPDATE with
kind=NULLorkindoutside{raw, distilled, superseded, archived}aborts viatrg_memories_kind_check_insert/_update(v15). ALTER TABLE cannot add CHECK on existing-data columns in SQLite, so triggers fill the gap. - Provenance discipline. New tables introduced after v14 must include
kindand (post-A5)tenant_id. SeeROADMAP-RESEARCH.md§"Schema migration order".
--kindacceptsdistilled(default) orsupersededonly.rawis reserved for ingestion connectors (E1.x: Slack/Jira/Gmail) that route deletions througharchiveRawMemory. Existinghippo forget/ consolidation / conflict-resolution paths abort onkind='raw'via the append-only trigger, so exposing--kind rawwould create unforgettable memories.archivedis an internal sentinel set only insidearchiveRawMemory's SAVEPOINT.--scope <value>writes the envelopescopecolumn AND adds ascope:<value>tag (additive dual-write). Recall's--scopefilter currently matches the tag form. When envelope-column-based filtering lands (post-A5), this dual-write becomes a transition aid; until then the duplication is intentional.--owner <value>and--artifact-ref <uri>are passed through unchanged; format is advisory (user:<id>/agent:<id>for owner; URI scheme for artifact_ref).
- Do not use
INSERT OR REPLACEonmemories. SQLite fires theBEFORE DELETEtrigger during conflict resolution; on akind='raw'row this aborts the upsert. UseupsertEntryRow(ON CONFLICT DO UPDATE) insrc/store.tsorarchiveRawMemoryfor raw rows. - Do not directly
DELETE FROM memoriesforkind='raw'. Always go througharchiveRawMemory(db, id, { reason, who })so the audit trail inraw_archiveis preserved. - Ingestion code must declare
kindexplicitly when writing genuinely raw transcripts. The default increateMemory()is'distilled'; current callers (importers.tsfor ChatGPT/Claude/Cursor pastes,capture.tsfor session capture) keep this default because their content is curated/processed, not raw transcript. When E1.x connectors land (Slack/Jira/Gmail), they MUST setkind: 'raw'explicitly.
hippo recall --whyprints envelope lines under each result.hippo rememberaccepts--kind,--scope,--owner,--artifact-refflags.- The TypeScript type
MemoryEntry(insrc/memory.ts) carries the envelope;createMemorydefaults missing fields tokind='distilled'+ nulls.
- A4 right-to-be-forgotten.
archiveRawMemoryis the primitive; A4 will wrap it in ahippo forget --user X --everywhereworkflow. - A5 multi-tenancy.
scope+ownerare the foundation; A5 addstenant_idand RLS / app-layer enforcement. - E1 ingestion connectors. Every Slack/Jira/GitHub message lands as
kind='raw'with full provenance;hippo sleeppromotes selected receipts tokind='distilled'. - E3 graph layer. Graph indexer reads only
kind IN ('distilled','superseded')rows;kind='raw'is structurally inaccessible.
tenant_idcolumn (A5)- Encryption-at-rest, secret-scrub, PII redaction (A4)
- Right-to-be-forgotten workflow (A4 —
archiveRawMemoryprimitive lands here only) - Connector code that writes
kind='raw'rows (E1.x) - Graph extraction queue table (E3.1)