Skip to content

epic: privacy-first graph memory in t27 (specs/memory/graph) #7828

Description

@gHashTag

Port of the Zep/Graphiti memory model into .t27 with privacy designed in, replacing the empty stub specs/tri/agent/memory.t27.

Model (from reading graphiti_core): episodes (raw messages), entities (name, summary), facts (edges between entities) with four time fields (valid_at, invalid_at, created_at, expired_at); a contradicting fact expires the old one. Graphiti scopes only by group_id in a WHERE clause and has no encryption or access control.

Honest boundary: LLM extraction and embeddings need plaintext, and embeddings leak content. Encryption at rest stops dump/backup reads; keeping operators out needs client-side processing or a TEE with attestation.

Slices:

  1. types.t27 + temporal.t27: records, time fields, invalidation rules as pure functions with tests (this slice)
  2. scope.t27: group/user/thread scoping, no cross-group read by construction
  3. crypt.t27: per-user key, AEAD layout, HMAC tokens, forget = crypto-shred
  4. ingest.t27: extraction state machine, LLM calls as effect slots marked requires_plaintext + trust_domain
  5. dedup.t27, index.t27, search.t27: MinHash over keyed shingles, HMAC-BM25, BFS/RRF/MMR, context block
  6. attest.t27: optional TEE key-release policy

Related: gHashTag/999-multibots-telegraf#3876, #3877, #3878.

User Scenarios

  • Given the empty stub specs/tri/agent/memory.t27 exists, When the privacy-first graph memory specification is authored under specs/memory/graph/, Then the stub is replaced by a directory containing types.t27 and temporal.t27 that define episodes, entities, facts, and four time fields with invalidation rules as pure functions.
  • Given a fact with valid_at and invalid_at fields, When a new contradicting fact is inserted with overlapping validity, Then the old fact's invalid_at is set to the new fact's valid_at and the new fact becomes the sole valid edge between those entities.
  • Given the temporal module exports pure functions for time-field validation, When the test suite runs, Then all invalidation rules pass without side effects.

Requirements

  • FR-001: The specification specs/memory/graph/types.t27 MUST define record types for Episode, Entity, and Fact with fields matching the Graphiti model (episodes as raw messages, entities with name and summary, facts as edges between entities).
  • FR-002: The specification specs/memory/graph/temporal.t27 MUST define four time fields on Fact: valid_at, invalid_at, created_at, expired_at with precise semantics.
  • FR-003: The temporal module MUST provide pure functions for fact invalidation: inserting a contradicting fact MUST expire the old one by setting its invalid_at to the new fact's valid_at.
  • FR-004: The stub specs/tri/agent/memory.t27 MUST be removed or replaced by a re-export pointing to the new graph memory specs.
  • FR-005: All types and temporal functions MUST be compilable by t27c and have accompanying property tests in the same .t27 files.

Success Criteria

  • t27c specs/memory/graph/types.t27 exits 0 and emits type definitions for Episode, Entity, Fact
  • t27c specs/memory/graph/temporal.t27 exits 0 and emits pure invalidation functions
  • t27c --test specs/memory/graph/types.t27 specs/memory/graph/temporal.t27 exits 0 with at least 10 tests passing
  • specs/tri/agent/memory.t27 no longer exists or re-exports specs/memory/graph

Boundary

  • specs/memory/graph/types.t27
  • specs/memory/graph/temporal.t27
  • specs/tri/agent/memory.t27

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions