Documentation
¶
Overview ¶
detail_level.go provides shared constants and parsing for the detail_level parameter used across memory and SDD tools.
Three verbosity levels enable progressive disclosure (Anthropic, 2025):
- summary: minimal tokens — IDs, titles, metadata only
- standard: default behavior — truncated content snippets
- full: complete untruncated content for deep analysis
Package memory implements the persistent memory engine for SDD-Hoffy.
It uses SQLite with FTS5 full-text search to store and retrieve observations from AI coding sessions. Adapted from Engram's store (github.com/Gentleman-Programming/engram) with full feature parity.
Index ¶
- Constants
- func BudgetFooter(tokensUsed, budget, shown, total int) string
- func ClassifyTool(toolName string) string
- func DetailLevelValues() []string
- func EstimateTokens(text string) int
- func ExtractLearnings(text string) []string
- func NavigationHint(showing, total int, hint string) string
- func Now() string
- func ParseDetailLevel(s string) string
- func SuggestTopicKey(typ, title, content string) string
- func TokenFooter(estimatedTokens int) string
- func Truncate(s string, max int) string
- type AddObservationParams
- type AddPromptParams
- type AddRelationParams
- type CompactParams
- type CompactResult
- type Config
- type ContextFormatOptions
- type ContextNode
- type ContextResult
- type ExportData
- type ImportResult
- type Observation
- type PassiveCaptureParams
- type PassiveCaptureResult
- type Prompt
- type Relation
- type SearchOptions
- type SearchResult
- type Session
- type SessionSummary
- type Stats
- type Store
- func (s *Store) AddObservation(p AddObservationParams) (int64, error)
- func (s *Store) AddPrompt(p AddPromptParams) (int64, error)
- func (s *Store) AddRelation(p AddRelationParams) ([]int64, error)
- func (s *Store) BuildContext(observationID int64, maxDepth int) (*ContextResult, error)
- func (s *Store) Close() error
- func (s *Store) CompactObservations(p CompactParams) (*CompactResult, error)
- func (s *Store) CountObservations(project, scope, namespace string) (int, error)
- func (s *Store) CountSearchResults(query string, opts SearchOptions) (int, error)
- func (s *Store) CreateSession(id, project, directory string) error
- func (s *Store) DeleteObservation(id int64, hardDelete bool) error
- func (s *Store) EndSession(id string, summary string) error
- func (s *Store) Export() (*ExportData, error)
- func (s *Store) FindByTopicKey(topicKey, project, scope string) (*Observation, error)
- func (s *Store) FindStaleObservations(project, scope, namespace string, olderThanDays, limit int) ([]Observation, error)
- func (s *Store) FormatContext(project, scope string) (string, error)
- func (s *Store) FormatContextDetailed(project, scope string, opts ContextFormatOptions) (string, error)
- func (s *Store) GetObservation(id int64) (*Observation, error)
- func (s *Store) GetRelations(observationID int64) ([]Relation, error)
- func (s *Store) GetSession(id string) (*Session, error)
- func (s *Store) Import(data *ExportData) (*ImportResult, error)
- func (s *Store) PassiveCapture(p PassiveCaptureParams) (*PassiveCaptureResult, error)
- func (s *Store) RecentObservations(project, scope, namespace string, limit int) ([]Observation, error)
- func (s *Store) RecentPrompts(project string, limit int) ([]Prompt, error)
- func (s *Store) RecentSessions(project string, limit int) ([]SessionSummary, error)
- func (s *Store) RemoveRelation(id int64) error
- func (s *Store) Search(query string, opts SearchOptions) ([]SearchResult, error)
- func (s *Store) SearchPrompts(query string, project string, limit int) ([]Prompt, error)
- func (s *Store) Stats() (*Stats, error)
- func (s *Store) Timeline(observationID int64, before, after int) (*TimelineResult, error)
- func (s *Store) UpdateObservation(id int64, p UpdateObservationParams) (*Observation, error)
- type TimelineEntry
- type TimelineResult
- type UpdateObservationParams
Constants ¶
const ( DetailSummary = "summary" DetailStandard = "standard" DetailFull = "full" )
Detail level constants.
SummaryFooter is appended to summary-mode responses to guide the AI toward progressive disclosure — fetch more detail only when needed.
Variables ¶
This section is empty.
Functions ¶
func BudgetFooter ¶ added in v0.9.0
BudgetFooter returns a footer indicating that a response was truncated due to a token budget constraint. Includes tokens used, budget, and items shown vs total.
func ClassifyTool ¶
ClassifyTool returns the observation type for a given tool name.
func DetailLevelValues ¶ added in v0.9.0
func DetailLevelValues() []string
DetailLevelValues returns the enum values for MCP tool definitions. Use this to avoid duplicating the list across tool definitions.
func EstimateTokens ¶ added in v0.9.0
EstimateTokens approximates the token count for a text string using the chars/4 heuristic (standard approximation for GPT/Claude tokenizers). Returns 0 for empty strings, at least 1 for non-empty strings. This is O(1) — uses len() only, no iteration.
func ExtractLearnings ¶
ExtractLearnings parses structured learning items from text. Looks for "## Key Learnings:" or "## Aprendizajes Clave:" sections and extracts numbered or bullet items.
func NavigationHint ¶ added in v0.9.0
NavigationHint returns a one-line footer when results are capped by a limit. Returns an empty string when all results fit (showing >= total) or total is 0. The hint parameter provides tool-specific guidance (e.g., "Use mem_get_observation #ID for full content.").
func ParseDetailLevel ¶ added in v0.9.0
ParseDetailLevel normalizes a detail_level string, defaulting to "standard" for empty or unrecognized values.
func SuggestTopicKey ¶
SuggestTopicKey generates a stable topic key suggestion from type/title/content.
func TokenFooter ¶ added in v0.9.0
TokenFooter returns a one-line footer with the estimated token count for a tool response. Appended to all read-heavy tool responses to give the AI visibility into context cost.
Types ¶
type AddObservationParams ¶
type AddObservationParams struct {
SessionID string `json:"session_id"`
Type string `json:"type"`
Title string `json:"title"`
Content string `json:"content"`
ToolName string `json:"tool_name,omitempty"`
Project string `json:"project,omitempty"`
Scope string `json:"scope,omitempty"`
TopicKey string `json:"topic_key,omitempty"`
Namespace string `json:"namespace,omitempty"`
}
AddObservationParams holds the input for creating a new observation.
type AddPromptParams ¶
type AddPromptParams struct {
SessionID string `json:"session_id"`
Content string `json:"content"`
Project string `json:"project,omitempty"`
Namespace string `json:"namespace,omitempty"`
}
AddPromptParams holds the input for saving a user prompt.
type AddRelationParams ¶ added in v0.7.0
type AddRelationParams struct {
FromID int64 `json:"from_id"`
ToID int64 `json:"to_id"`
Type string `json:"type"`
Note string `json:"note,omitempty"`
Bidirectional bool `json:"bidirectional,omitempty"`
}
AddRelationParams holds input for creating a new relation.
type CompactParams ¶ added in v0.9.0
type CompactParams struct {
IDs []int64 `json:"ids"`
SummaryTitle string `json:"summary_title,omitempty"`
SummaryContent string `json:"summary_content,omitempty"`
Project string `json:"project,omitempty"`
Scope string `json:"scope,omitempty"`
SessionID string `json:"session_id,omitempty"`
}
CompactParams holds the input for batch compaction of observations.
type CompactResult ¶ added in v0.9.0
type CompactResult struct {
DeletedCount int `json:"deleted_count"`
SummaryID *int64 `json:"summary_id,omitempty"`
TotalBefore int `json:"total_before"`
TotalAfter int `json:"total_after"`
}
CompactResult holds the output of a compaction operation.
type Config ¶
type Config struct {
DataDir string
MaxObservationLength int
MaxContextResults int
MaxSearchResults int
DedupeWindow time.Duration
}
Config holds memory store configuration.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns the default configuration for the memory store.
type ContextFormatOptions ¶ added in v0.9.0
type ContextFormatOptions struct {
// DetailLevel controls verbosity: "summary", "standard", or "full".
// Defaults to "standard" if empty.
DetailLevel string
// Limit overrides the number of observations to retrieve.
// 0 means use the configured default (MaxContextResults).
Limit int
// Namespace filters observations to a specific sub-agent namespace.
// Empty means no namespace filter (see all).
Namespace string
// MaxTokens sets a token budget cap. When > 0, the response is built
// incrementally and stops adding items when the budget would be exceeded.
// 0 means no budget cap (default — return everything).
MaxTokens int
}
ContextFormatOptions controls verbosity and limits for FormatContextDetailed.
type ContextNode ¶ added in v0.7.0
type ContextNode struct {
ID int64 `json:"id"`
Title string `json:"title"`
Type string `json:"type"`
Project string `json:"project,omitempty"`
CreatedAt string `json:"created_at"`
RelationType string `json:"relation_type"`
Direction string `json:"direction"` // "outgoing" or "incoming"
Note string `json:"note,omitempty"`
Depth int `json:"depth"`
}
ContextNode represents one node in a graph traversal result.
type ContextResult ¶ added in v0.7.0
type ContextResult struct {
Root Observation `json:"root"`
Connected []ContextNode `json:"connected"`
TotalNodes int `json:"total_nodes"`
MaxDepth int `json:"max_depth"`
}
ContextResult holds the full graph traversal output.
type ExportData ¶
type ExportData struct {
Version string `json:"version"`
ExportedAt string `json:"exported_at"`
Sessions []Session `json:"sessions"`
Observations []Observation `json:"observations"`
Prompts []Prompt `json:"prompts"`
}
ExportData is the full serializable dump of the memory database.
type ImportResult ¶
type ImportResult struct {
SessionsImported int `json:"sessions_imported"`
ObservationsImported int `json:"observations_imported"`
PromptsImported int `json:"prompts_imported"`
}
ImportResult holds counts of imported records.
type Observation ¶
type Observation struct {
ID int64 `json:"id"`
SessionID string `json:"session_id"`
Type string `json:"type"`
Title string `json:"title"`
Content string `json:"content"`
ToolName *string `json:"tool_name,omitempty"`
Project *string `json:"project,omitempty"`
Scope string `json:"scope"`
TopicKey *string `json:"topic_key,omitempty"`
Namespace *string `json:"namespace,omitempty"`
RevisionCount int `json:"revision_count"`
DuplicateCount int `json:"duplicate_count"`
LastSeenAt *string `json:"last_seen_at,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
DeletedAt *string `json:"deleted_at,omitempty"`
}
Observation represents a single memory entry — a decision, pattern, bug fix, etc.
type PassiveCaptureParams ¶
type PassiveCaptureParams struct {
SessionID string `json:"session_id"`
Content string `json:"content"`
Project string `json:"project,omitempty"`
Source string `json:"source,omitempty"`
}
PassiveCaptureParams holds the input for passive memory capture.
type PassiveCaptureResult ¶
type PassiveCaptureResult struct {
Extracted int `json:"extracted"`
Saved int `json:"saved"`
Duplicates int `json:"duplicates"`
}
PassiveCaptureResult holds the output of passive memory capture.
type Prompt ¶
type Prompt struct {
ID int64 `json:"id"`
SessionID string `json:"session_id"`
Content string `json:"content"`
Project string `json:"project,omitempty"`
CreatedAt string `json:"created_at"`
}
Prompt represents a saved user prompt.
type Relation ¶ added in v0.7.0
type Relation struct {
ID int64 `json:"id"`
FromID int64 `json:"from_id"`
ToID int64 `json:"to_id"`
Type string `json:"type"`
Note string `json:"note,omitempty"`
CreatedAt string `json:"created_at"`
}
Relation represents a typed directional edge between two observations.
type SearchOptions ¶
type SearchOptions struct {
Type string `json:"type,omitempty"`
Project string `json:"project,omitempty"`
Scope string `json:"scope,omitempty"`
Namespace string `json:"namespace,omitempty"`
Limit int `json:"limit,omitempty"`
}
SearchOptions holds filters for FTS5 search queries.
type SearchResult ¶
type SearchResult struct {
Observation
Rank float64 `json:"rank"`
}
SearchResult embeds an Observation with FTS5 rank score.
type Session ¶
type Session struct {
ID string `json:"id"`
Project string `json:"project"`
Directory string `json:"directory"`
StartedAt string `json:"started_at"`
EndedAt *string `json:"ended_at,omitempty"`
Summary *string `json:"summary,omitempty"`
}
Session represents a coding session with start/end timestamps.
type SessionSummary ¶
type SessionSummary struct {
ID string `json:"id"`
Project string `json:"project"`
StartedAt string `json:"started_at"`
EndedAt *string `json:"ended_at,omitempty"`
Summary *string `json:"summary,omitempty"`
ObservationCount int `json:"observation_count"`
}
SessionSummary is a compact view of a session with observation count.
type Stats ¶
type Stats struct {
TotalSessions int `json:"total_sessions"`
TotalObservations int `json:"total_observations"`
TotalPrompts int `json:"total_prompts"`
Projects []string `json:"projects"`
}
Stats holds aggregate memory statistics.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the persistent memory engine backed by SQLite + FTS5.
func New ¶
New creates a new Store with the given configuration. It creates the data directory if needed, opens SQLite with WAL mode, and runs migrations.
func (*Store) AddObservation ¶
func (s *Store) AddObservation(p AddObservationParams) (int64, error)
AddObservation creates a new observation with topic_key upsert and deduplication.
func (*Store) AddPrompt ¶
func (s *Store) AddPrompt(p AddPromptParams) (int64, error)
AddPrompt saves a user prompt to persistent memory.
func (*Store) AddRelation ¶ added in v0.7.0
func (s *Store) AddRelation(p AddRelationParams) ([]int64, error)
AddRelation creates a typed directional edge between two observations. If Bidirectional is true, both directions are created atomically. Returns the IDs of created relations (1 or 2).
func (*Store) BuildContext ¶ added in v0.7.0
func (s *Store) BuildContext(observationID int64, maxDepth int) (*ContextResult, error)
BuildContext traverses the relation graph from a starting observation using BFS. It returns a compact context tree with observation metadata (no full content). Default depth is 2, max is 5. Cycle detection prevents infinite loops.
func (*Store) CompactObservations ¶ added in v0.9.0
func (s *Store) CompactObservations(p CompactParams) (*CompactResult, error)
CompactObservations batch soft-deletes the given observation IDs and optionally creates a summary observation as a replacement. The entire operation is atomic — if the summary insert fails, the soft-deletes are rolled back.
func (*Store) CountObservations ¶ added in v0.9.0
CountObservations returns the total number of non-deleted observations matching the given project, scope, and namespace filters. Used for "Showing X of Y" navigation hints when results are capped by a limit.
func (*Store) CountSearchResults ¶ added in v0.9.0
func (s *Store) CountSearchResults(query string, opts SearchOptions) (int, error)
CountSearchResults returns the total number of observations matching an FTS5 query and filters, without applying a LIMIT. Used for "Showing X of Y" navigation hints in mem_search responses.
func (*Store) CreateSession ¶
CreateSession registers a new coding session.
func (*Store) DeleteObservation ¶
DeleteObservation soft-deletes (or hard-deletes) an observation by ID.
func (*Store) EndSession ¶
EndSession marks a session as completed with an optional summary.
func (*Store) Export ¶
func (s *Store) Export() (*ExportData, error)
Export dumps the entire memory database as a serializable struct.
func (*Store) FindByTopicKey ¶ added in v0.7.0
func (s *Store) FindByTopicKey(topicKey, project, scope string) (*Observation, error)
FindByTopicKey returns the latest non-deleted observation matching the given topic_key, project, and scope. Returns nil (not an error) when no matching observation exists.
func (*Store) FindStaleObservations ¶ added in v0.9.0
func (s *Store) FindStaleObservations(project, scope, namespace string, olderThanDays, limit int) ([]Observation, error)
FindStaleObservations returns non-deleted observations older than the specified number of days, filtered by project and scope. Results are ordered oldest-first so the caller can prioritize the stalest entries.
func (*Store) FormatContext ¶
FormatContext returns a markdown-formatted summary of recent memory. This is the backward-compatible wrapper that always uses standard detail.
func (*Store) FormatContextDetailed ¶ added in v0.9.0
func (s *Store) FormatContextDetailed(project, scope string, opts ContextFormatOptions) (string, error)
FormatContextDetailed returns a markdown-formatted summary of recent memory with configurable verbosity (summary/standard/full) and observation limit.
func (*Store) GetObservation ¶
func (s *Store) GetObservation(id int64) (*Observation, error)
GetObservation retrieves a single observation by ID (excludes soft-deleted).
func (*Store) GetRelations ¶ added in v0.7.0
GetRelations returns all relations where the observation is either source or target.
func (*Store) GetSession ¶
GetSession retrieves a session by ID.
func (*Store) Import ¶
func (s *Store) Import(data *ExportData) (*ImportResult, error)
Import loads exported data into the memory database.
func (*Store) PassiveCapture ¶
func (s *Store) PassiveCapture(p PassiveCaptureParams) (*PassiveCaptureResult, error)
PassiveCapture extracts learnings from text and saves them as observations.
func (*Store) RecentObservations ¶
func (s *Store) RecentObservations(project, scope, namespace string, limit int) ([]Observation, error)
RecentObservations returns recent observations filtered by project, scope, and namespace.
func (*Store) RecentPrompts ¶
RecentPrompts returns recent user prompts filtered by project.
func (*Store) RecentSessions ¶
func (s *Store) RecentSessions(project string, limit int) ([]SessionSummary, error)
RecentSessions returns recent sessions with observation counts.
func (*Store) RemoveRelation ¶ added in v0.7.0
RemoveRelation hard-deletes a relation by its ID.
func (*Store) Search ¶
func (s *Store) Search(query string, opts SearchOptions) ([]SearchResult, error)
Search performs full-text search across observations with filters. If the query is empty or whitespace-only, falls back to returning recent observations.
func (*Store) SearchPrompts ¶
SearchPrompts searches user prompts using FTS5.
func (*Store) Timeline ¶
func (s *Store) Timeline(observationID int64, before, after int) (*TimelineResult, error)
Timeline provides chronological context around a specific observation. Progressive disclosure pattern: search → timeline → get_observation.
func (*Store) UpdateObservation ¶
func (s *Store) UpdateObservation(id int64, p UpdateObservationParams) (*Observation, error)
UpdateObservation partially updates an observation by ID.
type TimelineEntry ¶
type TimelineEntry struct {
ID int64 `json:"id"`
SessionID string `json:"session_id"`
Type string `json:"type"`
Title string `json:"title"`
Content string `json:"content"`
ToolName *string `json:"tool_name,omitempty"`
Project *string `json:"project,omitempty"`
Scope string `json:"scope"`
TopicKey *string `json:"topic_key,omitempty"`
Namespace *string `json:"namespace,omitempty"`
RevisionCount int `json:"revision_count"`
DuplicateCount int `json:"duplicate_count"`
LastSeenAt *string `json:"last_seen_at,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
DeletedAt *string `json:"deleted_at,omitempty"`
IsFocus bool `json:"is_focus"`
}
TimelineEntry is an observation in a timeline with a focus flag.
type TimelineResult ¶
type TimelineResult struct {
Focus Observation `json:"focus"`
Before []TimelineEntry `json:"before"`
After []TimelineEntry `json:"after"`
SessionInfo *Session `json:"session_info"`
TotalInRange int `json:"total_in_range"`
}
TimelineResult holds the progressive disclosure result around a focus observation.
type UpdateObservationParams ¶
type UpdateObservationParams struct {
Type *string `json:"type,omitempty"`
Title *string `json:"title,omitempty"`
Content *string `json:"content,omitempty"`
Project *string `json:"project,omitempty"`
Scope *string `json:"scope,omitempty"`
TopicKey *string `json:"topic_key,omitempty"`
}
UpdateObservationParams holds partial update fields for an observation.