Memory — API reference¶
CLI¶
Storage¶
connection
¶
Context manager that opens and closes a memory database connection.
ensure_schema
¶
Apply any pending migrations to the database.
Safe to call on every connection open — checks a single integer and returns immediately if the schema is current. Gracefully skips vec0 migrations if the sqlite-vec extension is not loaded.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
get_connection
¶
Open a memory database connection with sqlite-vec loaded.
The connection has the sqlite-vec extension loaded (for vec0
support), WAL journal mode enabled (for concurrent reads), and the
current schema applied via migrations.
| PARAMETER | DESCRIPTION |
|---|---|
db_path
|
Override the database path (defaults to
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Connection
|
A |
Embeddings¶
EmbeddingProvider
¶
check_dimension_match
¶
Check whether the vec table dimension matches the configured provider.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
A tuple |
int | None
|
|
embed_text
¶
Embed a single text string.
| PARAMETER | DESCRIPTION |
|---|---|
text
|
The text to embed.
TYPE:
|
prefix
|
Task prefix for nomic-embed. Use
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[float] | None
|
The embedding vector, or |
embed_texts
¶
Embed a batch of texts.
| PARAMETER | DESCRIPTION |
|---|---|
texts
|
The texts to embed.
TYPE:
|
prefix
|
Task prefix for nomic-embed. Ignored for Bedrock providers.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[list[float]] | None
|
The list of embedding vectors, or |
get_provider
¶
get_provider() -> EmbeddingProvider | None
Return the lazily-initialised embedding provider, or None.
On first call, instantiates the provider configured by
MAIT_CODE_EMBEDDING_PROVIDER. If instantiation fails, returns
None on this and all subsequent calls.
| RETURNS | DESCRIPTION |
|---|---|
EmbeddingProvider | None
|
The provider instance, or |
serialize_f32
¶
Serialise a float vector to raw bytes for sqlite-vec.
Search¶
delete_entry
¶
Delete a memory entry by ID.
The memory_vec cleanup is handled by the database trigger
(memory_entries_vec_ad), so no explicit vec deletion is needed.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
entry_id
|
Primary-key id of the entry to delete.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
|
hybrid_search
¶
hybrid_search(
conn: Connection,
query: str,
limit: int = 20,
entry_type: str | None = None,
*,
project: str | None = None,
branch: str | None = None,
include_superseded: bool = False,
) -> list[dict]
Run a combined FTS5 + vector search and return merged results.
Runs both search methods, merges by entry ID, and assigns a relevance
score suitable for composite_score():
- Entries found by both: use vector similarity as relevance.
- Vector-only entries: keep their cosine similarity as relevance.
- FTS-only entries: default relevance
0.3(no vector to score with).
Falls back to FTS-only if no embeddings are available.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
query
|
Query text.
TYPE:
|
limit
|
Maximum number of results from each underlying search.
TYPE:
|
entry_type
|
Optional entry-type filter.
TYPE:
|
project
|
Project context for scope filtering.
TYPE:
|
branch
|
Branch context for scope filtering.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
A list of dicts with the standard fields plus a |
list_entries
¶
list_entries(
conn: Connection,
limit: int = 20,
entry_type: str | None = None,
since: str | None = None,
*,
project: str | None = None,
branch: str | None = None,
scope: str | None = None,
include_superseded: bool = False,
) -> list[dict]
List recent memory entries, optionally filtered by type, time, and scope.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
limit
|
Maximum number of results.
TYPE:
|
entry_type
|
Optional entry-type filter.
TYPE:
|
since
|
Human-readable period like
TYPE:
|
project
|
Filter to this project context (includes global).
TYPE:
|
branch
|
Filter to this branch context.
TYPE:
|
scope
|
Explicit scope filter (
TYPE:
|
include_superseded
|
Include entries that have been superseded (hidden by default).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
A list of dicts with the standard memory entry fields, ordered by |
list[dict]
|
|
list_projects
¶
List the distinct projects current memory entries span, alphabetically.
Feeds filter UIs (the memory browser's project Select); global entries
carry no project and so don't contribute a name, and superseded entries
don't keep a project alive on their own.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[str]
|
Sorted distinct project names (possibly empty). |
search_entries
¶
search_entries(
conn: Connection,
query: str,
limit: int = 20,
entry_type: str | None = None,
*,
project: str | None = None,
branch: str | None = None,
include_superseded: bool = False,
) -> list[dict]
Search memory entries using FTS5 BM25 ranking.
Falls back to LIKE if FTS5 is not available. When project is
provided, filters to global plus matching project/branch entries.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
query
|
FTS5 query string (or substring for the fallback path).
TYPE:
|
limit
|
Maximum number of results.
TYPE:
|
entry_type
|
Optional entry-type filter.
TYPE:
|
project
|
Project context for scope filtering.
TYPE:
|
branch
|
Branch context for scope filtering.
TYPE:
|
include_superseded
|
Include entries that have been superseded (hidden by default).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
A list of dicts with the standard memory entry fields. |
vector_search_entries
¶
vector_search_entries(
conn: Connection,
query: str,
limit: int = 20,
entry_type: str | None = None,
*,
project: str | None = None,
branch: str | None = None,
include_superseded: bool = False,
) -> list[dict]
Search memory entries using vector similarity via sqlite-vec.
Over-fetches and post-filters by scope, since sqlite-vec doesn't
support arbitrary WHERE clauses in k-NN queries.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
query
|
Query text to embed and search.
TYPE:
|
limit
|
Maximum number of results.
TYPE:
|
entry_type
|
Optional entry-type filter.
TYPE:
|
project
|
Project context for scope filtering.
TYPE:
|
branch
|
Branch context for scope filtering.
TYPE:
|
include_superseded
|
Include entries that have been superseded (hidden by default).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
A list of dicts with the standard fields plus a |
list[dict]
|
key in |
Scoring¶
composite_score
¶
composite_score(
created_at: str | datetime,
importance: int,
relevance: float = 0.5,
*,
memory_class: str | None = None,
entry_scope: str | None = None,
entry_project: str | None = None,
entry_branch: str | None = None,
query_project: str | None = None,
query_branch: str | None = None,
w_recency: float = W_RECENCY,
w_importance: float = W_IMPORTANCE,
w_relevance: float = W_RELEVANCE,
now: datetime | None = None,
) -> float
Compute the composite score for a memory entry.
| PARAMETER | DESCRIPTION |
|---|---|
created_at
|
When the entry was created (ISO string or datetime).
TYPE:
|
importance
|
Importance level 1-10.
TYPE:
|
relevance
|
Relevance score 0.0-1.0 (from search or default 0.5).
TYPE:
|
memory_class
|
TYPE:
|
entry_scope
|
Scope of the entry (
TYPE:
|
entry_project
|
Project of the entry.
TYPE:
|
entry_branch
|
Branch of the entry.
TYPE:
|
query_project
|
Project context for the query.
TYPE:
|
query_branch
|
Branch context for the query.
TYPE:
|
w_recency
|
Weight for the recency component.
TYPE:
|
w_importance
|
Weight for the importance component.
TYPE:
|
w_relevance
|
Weight for the relevance component.
TYPE:
|
now
|
Override current time (for testing).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Composite score, roughly in |
importance_score
¶
Normalise an importance value (1-10) to [0.0, 1.0].
rank_results
¶
rank_results(
results: list[dict],
*,
limit: int,
query_project: str | None = None,
query_branch: str | None = None,
) -> list[tuple[float, dict]]
Score search results with :func:composite_score and keep the best.
The shared ranking step behind mc-tool-memory search and
:func:mait_code.remote.search_memories, so both order results the same
way. A result without a relevance key scores as 0.5.
| PARAMETER | DESCRIPTION |
|---|---|
results
|
Entries from one of the search functions.
TYPE:
|
limit
|
Maximum number of results to keep.
TYPE:
|
query_project
|
Project context the query was made in.
TYPE:
|
query_branch
|
Branch context the query was made in.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[tuple[float, dict]]
|
|
recency_score
¶
recency_score(
created_at: str | datetime,
now: datetime | None = None,
*,
memory_class: str | None = None,
) -> float
Compute the recency score using exponential decay.
Half-life depends on memory_class:
episodic: 3 days (events decay fast).semantic: 90 days (facts persist).procedural: 180 days (workflows go stale when superseded, not with time).None/unknown: 7 days (fallback).
| PARAMETER | DESCRIPTION |
|---|---|
created_at
|
When the entry was created (ISO string or datetime).
TYPE:
|
now
|
Override current time (for testing); defaults to UTC now.
TYPE:
|
memory_class
|
Memory class controlling the decay rate.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
A score in |
float
|
be parsed. |
scope_boost
¶
scope_boost(
entry_scope: str,
entry_project: str | None,
entry_branch: str | None,
*,
query_project: str | None = None,
query_branch: str | None = None,
) -> float
Compute a multiplicative boost based on scope match.
| PARAMETER | DESCRIPTION |
|---|---|
entry_scope
|
The entry's scope (
TYPE:
|
entry_project
|
The entry's project, or
TYPE:
|
entry_branch
|
The entry's branch, or
TYPE:
|
query_project
|
Project context for the query, or
TYPE:
|
query_branch
|
Branch context for the query, or
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
|
float
|
|
float
|
|
float
|
|
Entities¶
find_entity_by_name
¶
Look up an entity by name (case-insensitive).
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
name
|
Entity name to find.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict | None
|
A dict with entity fields, or |
get_ego_graph
¶
The 1-hop neighbourhood of an entity: its node, neighbours, and edges.
The graph explorer's centre query. Both orderings are deterministic (neighbours by mention count then name; relationships with the centre's own edges first, then by source/type/target) so renders and snapshot tests are stable for a given database state.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
name
|
Centre entity name (case-insensitive).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict | None
|
A dict with |
dict | None
|
first, then neighbours), and |
dict | None
|
to the centre, with source/target names) — or |
dict | None
|
matches name. |
get_entity_relationships
¶
Return all relationships involving an entity (as source or target).
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
entity_id
|
Entity id to look up.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
A list of relationship dicts, each including the source and target |
list[dict]
|
entity names. |
list_graph_entities
¶
list_graph_entities(
conn: Connection,
query: str = "",
*,
min_mentions: int = 1,
require_relationship: bool = False,
limit: int | None = None,
) -> list[dict]
List entities with their relationship degree, for graph surfaces.
The graph explorer's entity list: every entity matching query, each
carrying a degree (the number of relationships it participates in)
so callers can filter or weight by connectedness. The default filters
are permissive; pass min_mentions=2 and require_relationship=True
for the noise-hiding defaults the explorer uses (84% of entities are
single-mention tail).
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
query
|
Substring to match against entity names ("" matches all).
TYPE:
|
min_mentions
|
Keep entities mentioned at least this many times.
TYPE:
|
require_relationship
|
Drop entities with no relationships (degree 0).
TYPE:
|
limit
|
Maximum number of results, or
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
A list of entity dicts (including |
list[dict]
|
|
list[dict]
|
— a deterministic order for rendering and tests. |
merge_entities
¶
Merge one entity into another, repointing its relationships.
Aliases accumulate in the graph (e.g. "User" alongside the user's real
name) and split what should be one node. Merging folds the source entity
into the target: relationships are repointed (deduplicating against the
target's existing edges on the (source, target, type) unique index),
mention counts are summed, the seen window widens to span both, the
target's type is upgraded from "unknown" if the source's is more
specific, and the source entity is deleted. Edges directly between the
two (which would become self-loops) are dropped.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
source_name
|
Name of the entity to fold in (case-insensitive).
TYPE:
|
target_name
|
Name of the surviving entity (case-insensitive).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
A summary dict: |
dict
|
|
dict
|
|
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If either entity does not exist, or both names resolve to the same entity. |
search_entities
¶
Search entities by name using a LIKE substring match.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
query
|
Substring to match against entity names.
TYPE:
|
limit
|
Maximum number of results to return.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
A list of entity dicts ordered by |
list[dict]
|
then |
upsert_entity
¶
Insert or update an entity by name and return its id.
On conflict, increments mention_count, refreshes last_seen, and
upgrades entity_type from "unknown" if a more specific type is
provided.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
name
|
Entity name (case-insensitive unique key).
TYPE:
|
entity_type
|
Entity type (e.g.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int
|
The entity's primary-key id. |
upsert_relationship
¶
upsert_relationship(
conn: Connection,
source_entity_id: int,
target_entity_id: int,
relationship_type: str,
context: str,
) -> int
Insert or update a relationship and return its id.
On conflict (same source/target/type), refreshes last_seen and
updates context when the new value differs from the stored one.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
source_entity_id
|
Source entity id.
TYPE:
|
target_entity_id
|
Target entity id.
TYPE:
|
relationship_type
|
Relationship label (e.g.
TYPE:
|
context
|
Free-text context describing the relationship.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int
|
The relationship's primary-key id. |
Writer¶
find_duplicate
¶
find_duplicate(
conn: Connection,
content: str,
entry_type: str,
*,
project: str | None = None,
) -> int | None
Check for near-duplicate content in the database.
Thin wrapper over :func:_assess_candidates that discards the
contradiction-band candidates and returns only the merge target.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
content
|
The candidate memory content.
TYPE:
|
entry_type
|
Entry type used to scope the candidate search.
TYPE:
|
project
|
Project identifier;
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int | None
|
The id of the duplicate if found, otherwise |
merge_memories
¶
merge_memories(
conn: Connection,
old_ids: list[int],
content: str,
*,
importance: int | None = None,
) -> dict
Fold several memory entries into one consolidated entry.
Inserts content as a single fresh entry, then supersedes every existing
row in old_ids by pointing each superseded_by at the new id. This is
the N→1 counterpart to :func:supersede_memory: use it when reflection
finds two or more overlapping facts that should read as one.
The new entry inherits type, class, and scope (project/branch) from the
first existing row in old_ids. Its importance defaults to the highest
importance among the merged rows — a merge promotes, it does not dilute —
unless overridden. Ids that don't exist are skipped and reported back in
not_found; the merge proceeds on whatever remains.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
old_ids
|
Ids of the entries being merged. Order matters only in that the first existing id donates type/class/scope.
TYPE:
|
content
|
The consolidated content for the new entry.
TYPE:
|
importance
|
Optional importance for the new entry (1-10, clamped). Defaults to the maximum importance among the merged rows.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
On success, a dict with |
dict
|
actually superseded), |
dict
|
(the new entry), |
dict
|
none of |
retire_memory
¶
Retire a memory entry — drop it with no replacement.
Stamps superseded_at while leaving superseded_by NULL. That pair is
the retired marker: the row is hidden from default surfacing (see
:data:~mait_code.tools.memory.db.LIVE_ENTRY_SQL) but kept for
auditability. Use this when a fact is stale or contradicted and has no
successor; reach for :func:supersede_memory when there is a replacement.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
entry_id
|
Id of the entry to retire.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
|
dict
|
not exist, |
dict
|
superseded or retired, ``{"action": "already_superseded" | |
dict
|
"already_retired", "id": entry_id}`` and nothing is written. |
store_memory
¶
store_memory(
conn: Connection,
content: str,
entry_type: str = "fact",
importance: int = 5,
*,
scope: str = "global",
project: str | None = None,
branch: str | None = None,
) -> dict
Store a memory entry, deduplicating near-identical content.
On duplicate, refreshes the timestamp and keeps the maximum importance.
On a new entry, inserts with memory_class derived from entry_type.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Database connection (with schema applied).
TYPE:
|
content
|
The memory content to store.
TYPE:
|
entry_type
|
One of
TYPE:
|
importance
|
Importance level 1-10 (clamped).
TYPE:
|
scope
|
Memory scope —
TYPE:
|
project
|
Project identifier (e.g. repo basename).
TYPE:
|
branch
|
Branch name (for branch-scoped memories).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
A dict with keys |
dict
|
|
dict
|
|
dict
|
for existing entries in the contradiction band that this write may |
dict
|
contradict. The write is never blocked; the conflicts are surfaced so |
dict
|
the companion can suggest superseding one of them. Empty on a |
dict
|
deduplicated write. |
supersede_memory
¶
supersede_memory(
conn: Connection,
old_id: int,
content: str,
*,
importance: int | None = None,
) -> dict
Supersede an existing memory entry with an evolved version.
Inserts content as a fresh entry that inherits the old entry's type,
class, and scope (project/branch), then marks the old entry superseded —
pointing superseded_by at the new id and stamping superseded_at.
The old row is kept for auditability but hidden from default surfacing.
This is the explicit, manually-driven counterpart to dedup: it is called
when a fact has genuinely changed rather than merely been repeated.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
old_id
|
Id of the entry being superseded.
TYPE:
|
content
|
The new, current content.
TYPE:
|
importance
|
Optional importance for the new entry (1-10, clamped). Defaults to the superseded entry's importance.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
On success, a dict with |
dict
|
(the new entry), |
dict
|
|
Stats¶
MemoryStats
dataclass
¶
collect_stats
¶
collect_stats(conn: Connection) -> MemoryStats
Collect store statistics from an open memory connection.
All counts come from SQL; provider/model/dimension come from
configuration. unreflected and last_reflected_at describe the
global reflection watermark (observation backlog and freshness).
Reflection¶
count_unreflected
¶
Return the number of entries above the reflection watermark.
Counts the non-insight entries that a future :func:reflect run would
consider — the observation backlog. With no watermark (no reflection has
ever run for the scope), every non-insight entry counts.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
project
|
Project identifier to scope the count;
TYPE:
|
get_last_reflected_at
¶
Return when reflection last ran for a project (or global scope).
Reads last_reflected_at from the watermark table — the authoritative
record of the most recent :func:reflect run, regardless of whether it
produced insights.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
project
|
Project identifier, or
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
datetime | None
|
The parsed timestamp, or |
reflect
¶
Reflection system — synthesise recent observations into durable insights.
Reads recent memory entries and observation logs, calls Claude to identify
patterns and themes, stores insights back to memory.db, and proposes
updates to MEMORY.md.
get_watermark
¶
Return the last reflected entry ID for a project (or global scope).
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
project
|
Project identifier, or
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int | None
|
The watermark, or |
int | None
|
this scope. |
update_watermark
¶
Set the watermark for a project (or global) to last_id.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
last_id
|
The new high-water-mark entry ID.
TYPE:
|
project
|
Project identifier, or
TYPE:
|
count_unreflected
¶
Return the number of entries above the reflection watermark.
Counts the non-insight entries that a future :func:reflect run would
consider — the observation backlog. With no watermark (no reflection has
ever run for the scope), every non-insight entry counts.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
project
|
Project identifier to scope the count;
TYPE:
|
get_last_reflected_at
¶
Return when reflection last ran for a project (or global scope).
Reads last_reflected_at from the watermark table — the authoritative
record of the most recent :func:reflect run, regardless of whether it
produced insights.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
project
|
Project identifier, or
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
datetime | None
|
The parsed timestamp, or |
check_novelty_gate_v2
¶
Return True if there are enough unreflected entries to justify reflection.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
min_new
|
Minimum number of new non-insight entries required.
TYPE:
|
project
|
Project identifier to scope the check;
TYPE:
|
get_unreflected_entries
¶
get_unreflected_entries(
conn: Connection,
batch_size: int = 50,
days: int | None = None,
exclude_types: tuple[str, ...] = ("insight",),
*,
project: str | None = None,
watermark: int | None = None,
) -> list[tuple]
Return entries that haven't been reflected on yet.
Uses watermark (last reflected ID) for idempotency. If no watermark
exists and days is provided, uses days as a bootstrap window.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
batch_size
|
Maximum number of entries to return.
TYPE:
|
days
|
Bootstrap window in days when no watermark exists.
TYPE:
|
exclude_types
|
Entry types to exclude (e.g.
TYPE:
|
project
|
Project identifier; when set, includes global plus project-scoped entries.
TYPE:
|
watermark
|
High-water-mark entry ID; only entries above this are returned.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[tuple]
|
Tuples of |
get_last_reflection_date
¶
Return the timestamp of the most recent insight entry.
Deprecated: replaced by get_watermark(); kept for backward compat.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
project
|
Project identifier, or
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
datetime | None
|
The parsed timestamp, or |
count_entries_since
¶
count_entries_since(
conn: Connection,
since: datetime,
exclude_types: tuple[str, ...] = ("insight",),
*,
project: str | None = None,
) -> int
Count non-insight memory entries added since a given timestamp.
Deprecated: replaced by check_novelty_gate_v2(); kept for backward
compat.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
since
|
Lower bound timestamp.
TYPE:
|
exclude_types
|
Entry types to exclude from the count.
TYPE:
|
project
|
Project identifier, or
TYPE:
|
check_novelty_gate
¶
Return True if there are enough new observations to justify reflection.
Deprecated: replaced by check_novelty_gate_v2(); kept for backward
compat.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
min_new
|
Minimum number of new non-insight entries required.
TYPE:
|
project
|
Project identifier, or
TYPE:
|
get_recent_entries
¶
get_recent_entries(
conn: Connection,
days: int = 7,
limit: int = 200,
exclude_types: tuple[str, ...] = ("insight",),
*,
project: str | None = None,
) -> list[tuple]
Return memory entries from the last days days.
Deprecated: replaced by get_unreflected_entries(); kept for backward
compat.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
days
|
Lookback window in days.
TYPE:
|
limit
|
Maximum number of entries to return.
TYPE:
|
exclude_types
|
Entry types to exclude.
TYPE:
|
project
|
Project identifier; when set, includes global plus project-scoped entries.
TYPE:
|
read_observation_logs
¶
Read JSONL observation files from the last days days.
Parses extraction dicts and formats them into readable text for the reflection prompt.
| PARAMETER | DESCRIPTION |
|---|---|
days
|
Lookback window in days.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
A newline-joined string of formatted extraction items. |
format_entries_text
¶
Format DB entries as text for the reflection prompt.
Accepts both 4-tuples (legacy:
(content, type, importance, created_at)) and 5-tuples
((id, content, type, importance, created_at)).
| PARAMETER | DESCRIPTION |
|---|---|
entries
|
Rows fetched from
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
A newline-joined string of formatted entries. |
parse_reflection_response
¶
Parse the LLM response into insights and structured memory operations.
Recognises INSIGHT: lines plus the consolidation op markers in
:data:_OP_MARKERS. Each op is a dict with keys op ("add" /
"rewrite" / "merge" / "retire"), old (existing MEMORY.md
text, or None), new (new text, or None for retire), and
entry_ids (backing db entries to consolidate, possibly empty).
Unrecognised or malformed lines are ignored, not fatal.
| PARAMETER | DESCRIPTION |
|---|---|
response
|
The raw LLM response text.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
A dict |
store_insights
¶
Store insights in the memory database with fixed importance=6.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
insights
|
Insight strings to store.
TYPE:
|
project
|
Project identifier; when set, insights are project-scoped, otherwise they are stored globally.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int
|
The number of insights stored. |
read_memory_md
¶
Return the current MEMORY.md content, or None if missing.
generate_memory_diff
¶
Render proposed MEMORY.md operations as a readable before/after diff.
Additions show as +, retirements as -, rewrites as the old line
(~) followed by its replacement (→), and merges as one - per
folded db entry followed by the single consolidated + line. Each op that
names backing db entries is annotated with the store-level verb applied to
them.
| PARAMETER | DESCRIPTION |
|---|---|
ops
|
Structured ops from :func:
TYPE:
|
previews
|
Optional
TYPE:
|
reflect
¶
reflect(
conn: Connection,
days: int = 7,
min_new: int = 3,
batch_size: int = 50,
*,
project: str | None = None,
branch: str | None = None,
) -> dict
Run the main reflection orchestrator.
Uses a watermark to track which entries have been reflected on, ensuring
idempotent operation. Processes entries in batches. When project is
provided, reflects only on global plus project-scoped entries.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
days
|
Bootstrap window in days when no watermark exists.
TYPE:
|
min_new
|
Minimum new non-insight entries required to proceed.
TYPE:
|
batch_size
|
Maximum entries processed per reflection.
TYPE:
|
project
|
Project identifier scoping the reflection.
TYPE:
|
branch
|
Branch name included in the prompt context only.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
A dict with keys |
dict
|
structured MEMORY.md operations proposed — see |
dict
|
func: |
dict
|
|
dict
|
counts, or |
Observations¶
daily_batches
¶
Summarise a day's capture batches from its JSONL observation log.
Each observe-hook run appends one record to
memory/observations/<day>.jsonl; this reads them back as light
summaries — when and why a capture happened and how much it extracted —
without the extraction bodies (those live in memory.db).
Best-effort by design: a missing file, an unreadable file, or a malformed line yields no batch rather than raising — the JSONL is supplementary metadata, never load-bearing.
| PARAMETER | DESCRIPTION |
|---|---|
day
|
The log's date stamp,
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
Dicts with |
list[dict]
|
|
list[dict]
|
categories omitted), in file (chronological) order. |
list_observations
¶
list_observations(
conn: Connection,
*,
project: str | None = None,
limit: int = _FETCH_LIMIT,
) -> list[dict]
List the raw observations, newest first, flagged against the watermark.
Returns every non-insight entry (insights are reflection output, not
observations), each carrying the standard entry fields plus reflected:
whether the entry sits at or below the relevant reflection watermark — the
project's own when project is given, the global one otherwise, matching
:func:~mait_code.tools.memory.reflect.count_unreflected. With no
watermark for the scope, nothing has been reflected yet.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
project
|
Filter to this project context (includes global entries) and
judge against its watermark;
TYPE:
|
limit
|
Maximum number of results.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
A list of dicts ordered by entry ID descending (newest first). |
observation_projects
¶
List the distinct projects observations span, alphabetically.
Feeds filter UIs (the observations browser's project Select); global
entries carry no project and so don't contribute a name.
| PARAMETER | DESCRIPTION |
|---|---|
conn
|
Open memory database connection.
TYPE:
|
Native auto memory¶
list_native_memories
¶
Enumerate every project's native memory files, across all projects.
Scans projects_dir (default :func:native_projects_dir) for
<slug>/memory/**/*.md. Projects without a memory directory, or whose
memory directory holds no markdown, are skipped — only projects with
something to read appear. A missing or unreadable projects dir yields an
empty list rather than an error.
| PARAMETER | DESCRIPTION |
|---|---|
projects_dir
|
The Claude Code projects directory to scan.
TYPE:
|
root
|
Filesystem root for :func:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[dict]
|
One dict per project, sorted by label: |
list[dict]
|
name), |
list[dict]
|
unresolvable), |
list[dict]
|
string, or |
list[dict]
|
first, the rest alphabetical, each |
native_projects_dir
¶
Claude Code's per-project state root, usually ~/.claude/projects.
Honours CLAUDE_CONFIG_DIR when set (Claude Code's own override for
relocating ~/.claude).
| RETURNS | DESCRIPTION |
|---|---|
Path
|
The projects directory path; it may not exist. |
resolve_slug
¶
Best-effort reverse of Claude Code's path munging, filesystem-guided.
The munge is lossy — any non-alphanumeric character became - — so the
reverse can't be computed from the string alone. Instead this walks the
real filesystem from root: at each level it re-munges every existing
subdirectory's name (with :func:munge_path) and follows the one whose
munged form the remaining slug starts with, backtracking when a branch
dead-ends. So -home-w-mait-code resolves to /home/w/mait.code,
/home/w/mait_code or /home/w/mait-code — whichever exists.
| PARAMETER | DESCRIPTION |
|---|---|
slug
|
A munged directory name from the projects dir.
TYPE:
|
root
|
Filesystem root the munged path is relative to (tests inject a temporary tree here).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Path | None
|
The resolved original path, or |
Path | None
|
chain re-munges to the slug (e.g. the project has since been deleted, |
Path | None
|
or its slug was hash-truncated for length). |