memory

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 7, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package memory defines the core domain types for Thoughtline.

A Memory is a single observation persisted by the user (via an AI assistant calling tl_save). Each Memory carries:

  • Type — one of the values in the memory taxonomy (see docs/design/memory-domain.md). Examples: game-design-decision, scene-pattern, asset-reference, perf-gotcha, pipeline-step, bugfix, convention.
  • Scope — project (default; tied to a project id) or personal (cross-project, per-developer ergonomics).
  • TopicKey — optional stable key for evolving topics. When set, tl_save upserts: same project + same topic_key replaces the prior row, preserving created_at and bumping revision_count.
  • Project — string identifier of the active project (typically the working directory's basename, but explicitly configurable).
  • Title — short, searchable headline. Imperative form preferred ("Fix N+1 in InventoryList").
  • Content — the body. Markdown. No length cap is enforced at the domain layer; storage layer applies a soft limit and returns a clear error rather than truncating silently.
  • CreatedAt — first time this memory (or its topic) appeared.
  • UpdatedAt — last time this memory (or its topic) was upserted.
  • Revision — number of times the topic has been re-saved (0 for first save, incremented on every upsert).

This package contains pure data types and validation. No I/O, no persistence concerns — those belong in internal/storage. The split keeps the domain reusable across storage backends.

Status: skeleton. Concrete types arrive in milestone M1.

Index

Constants

View Source
const (
	MaxAgentLabelChars     = 64
	MaxSessionSummaryBytes = MaxContentBytes
)

Limits exported so callers can show meaningful validation messages.

View Source
const (
	MaxTitleChars   = 200
	MaxContentBytes = 64 * 1024
	MaxTopicKeyLen  = 128
	MaxTagLen       = 40
)

Limits — exported so callers can show meaningful validation messages.

Variables

View Source
var (
	ErrInvalidSessionID        = errors.New("session: invalid id (must be a UUIDv7)")
	ErrEmptySessionProject     = errors.New("session: project must not be empty")
	ErrAgentLabelTooLong       = errors.New("session: agent_label exceeds maximum characters")
	ErrEmptySessionSummary     = errors.New("session: summary must not be empty when ending a session")
	ErrSessionSummaryTooLong   = errors.New("session: summary exceeds maximum bytes")
	ErrSessionEndedBeforeStart = errors.New("session: ended_at must be at or after started_at")
)

Errors returned by ValidateSession. Tests assert against these directly.

View Source
var (
	ErrInvalidType                = errors.New("memory: invalid type")
	ErrInvalidScope               = errors.New("memory: invalid scope")
	ErrPreferenceMustBePersonal   = errors.New("memory: preference type requires personal scope")
	ErrNonPreferenceMustBeProject = errors.New("memory: non-preference types require project scope")
	ErrEmptyProject               = errors.New("memory: project must not be empty")
	ErrEmptyTitle                 = errors.New("memory: title must not be empty")
	ErrTitleTooLong               = errors.New("memory: title exceeds 200 characters")
	ErrEmptyContent               = errors.New("memory: content must not be empty")
	ErrContentTooLong             = errors.New("memory: content exceeds maximum bytes")
	ErrInvalidTopicKey            = errors.New("memory: invalid topic_key format")
	ErrInvalidTag                 = errors.New("memory: invalid tag format")
)

Errors returned by Validate. Tests assert against these directly.

Functions

func Validate

func Validate(m Memory) error

Validate enforces every domain rule documented in docs/design/memory-domain.md. It mutates nothing — callers can apply trimming themselves before saving.

Errors returned are sentinel values from this package (e.g. ErrEmptyTitle). Use errors.Is to match.

func ValidateSession

func ValidateSession(s Session) error

ValidateSession enforces the Session invariants. Used by storage at StartSession / EndSession boundaries — the server layer never persists a Session that has not passed this check.

Types

type Memory

type Memory struct {
	// ID is the local autoincrement primary key. Zero for unsaved memories.
	ID int64
	// SyncID is a UUIDv7 stable across upserts. Set by storage on first save.
	SyncID string
	// Project is the project identifier the memory belongs to. Required.
	Project string
	// Scope governs cross-project visibility.
	Scope Scope
	// Type categorises the memory.
	Type Type
	// TopicKey, when non-empty, makes (Project, TopicKey) the upsert key.
	TopicKey string
	// Title is a short, searchable headline.
	Title string
	// Content is the markdown body.
	Content string
	// Tags are free-form labels (engine name, platform, etc.). Optional.
	Tags []string
	// NormalizedHash is a content fingerprint used for noop detection. Set by
	// storage on save; callers should leave this zero.
	NormalizedHash string
	// RevisionCount is the number of upserts on this topic. 0 for first save.
	RevisionCount int
	// CreatedAt is the first time this memory (or its topic) was saved.
	CreatedAt time.Time
	// UpdatedAt is the last time this memory (or its topic) was saved.
	UpdatedAt time.Time
	// DeletedAt is non-nil for soft-deleted memories.
	DeletedAt *time.Time
	// SessionID optionally associates this memory with a Session (UUIDv7).
	// Empty when the memory was saved outside any session. Set via tl_save's
	// optional session_id argument.
	SessionID string
}

Memory is the canonical in-memory representation of a stored observation. Storage maps this to/from the SQL row; the server (MCP) maps this to/from the JSON request payload.

type Scope

type Scope string

Scope governs whether a memory belongs to a specific project or travels with the developer across projects.

const (
	ScopeProject  Scope = "project"
	ScopePersonal Scope = "personal"
)

func (Scope) Valid

func (s Scope) Valid() bool

Valid reports whether s is one of the supported scopes.

type Session

type Session struct {
	// ID is a UUIDv7 string assigned by storage at start time.
	ID string
	// Project the session belongs to. Required.
	Project string
	// AgentLabel is an optional client-provided tag like "claude-code",
	// "cursor", "zed". Useful for cross-session forensics.
	AgentLabel string
	// StartedAt is when tl_session_start was called.
	StartedAt time.Time
	// EndedAt is non-nil once tl_session_summary has closed the session.
	EndedAt *time.Time
	// Summary is the structured end-of-session digest. Empty until ended.
	Summary string
}

Session bookends a coding interaction so the AI has a stable narrative across context compactions. Sessions are append-once: started by tl_session_start, closed exactly once by tl_session_summary. A Memory may optionally reference its parent session via Memory.SessionID.

IDs are UUIDv7 strings — sortable by time, generated client-side.

func (Session) Duration

func (s Session) Duration() time.Duration

Duration returns ended_at - started_at. Zero if the session is still open.

func (Session) IsOpen

func (s Session) IsOpen() bool

IsOpen reports whether the session has not yet been closed by tl_session_summary.

type Type

type Type string

Type is the kind of memory being stored. The set is closed by design — see docs/design/memory-domain.md for the rationale and per-type usage.

const (
	TypeGameDesignDecision Type = "game-design-decision"
	TypeScenePattern       Type = "scene-pattern"
	TypeAssetReference     Type = "asset-reference"
	TypePerfGotcha         Type = "perf-gotcha"
	TypePipelineStep       Type = "pipeline-step"
	TypeScriptPattern      Type = "script-pattern"
	TypeBugfix             Type = "bugfix"
	TypeConvention         Type = "convention"
	TypePreference         Type = "preference"
	TypeDecision           Type = "decision"     // migrated from Engram; project-scoped
	TypeArchitecture       Type = "architecture" // migrated from Engram; project-scoped
)

func AllTypes

func AllTypes() []Type

AllTypes returns the canonical type set in stable order.

func (Type) Valid

func (t Type) Valid() bool

Valid reports whether t is one of the catalogued types.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL