Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/skills/start-better-memory-ui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Use when user asks to start, launch, open, or run the better-memory

# Start better-memory UI

The MCP tool `mcp__better-memory__memory_start_ui` is a stub that returns "UI not yet implemented" — but the UI itself is fully built. Launch it directly.
The MCP tool `mcp__better-memory__memory_start_ui` spawns or reuses the UI and returns `{"url", "reused"}`. This skill launches it directly instead.

## Project

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ It's a memory layer for Claude Code that (with the default sqlite backend) runs

## How it works

<!-- drift-unverified: 1st notice, run 2026-10-13-b27d, block 2ee85463. This describes the code but names nothing in it. Name what it describes, or add drift-ignore: <reason>. -->
1. **As it works**, the assistant records what it tried and how it turned out — a fix that worked, an approach that failed, a preference you stated.
2. **Between sessions**, those raw notes are distilled into short, durable lessons — signal kept, noise dropped.
3. **Next session**, lessons surface exactly when they become relevant: each typed prompt is scored against the memory store (distinct-keyword evidence plus track record), and every tool call is checked against each memory's triggers, so a pitfall about Bash heredocs arrives as the heredoc is about to run and a planning rule arrives when the planning skill is invoked. Session start carries only a one-line index. No firehose, no guessing.
Expand Down Expand Up @@ -238,7 +239,7 @@ The skills in `.claude/skills/` (every directory with a `SKILL.md`) are enumerat

- **`better-memory-synthesize`** — walks Claude through the per-episode reflection synthesis loop (`memory.synthesize_next_get_context` → decide → `memory.synthesize_next_apply`). Fires when `memory.start_episode` reports `pending_synthesis.pending > 0` or when the user asks to consolidate.
- **`rate-session-memories`** — classifies exposed reflections / semantic memories at session end (`cited` / `shaped` / `ignored` / `misled` / `overlooked`) via `memory.list_session_exposures` + `memory.apply_session_ratings`. Triggered by a Stop-block directive from the `session_close` hook when unrated exposures remain.
- **`start-better-memory-ui`** — launches the management UI directly (the `memory.start_ui` MCP tool is a stub; this skill runs `python -m better_memory.ui` itself). Triggered by phrasing like "start ui" / "launch the better-memory UI".
- **`start-better-memory-ui`** — launches the management UI directly (the `memory.start_ui` MCP tool spawns or reuses the UI; this skill runs `python -m better_memory.ui` itself). Triggered by phrasing like "start ui" / "launch the better-memory UI".

`better-memory setup` also writes the managed CLAUDE.md block that tells Claude when to invoke `better-memory-synthesize` (the `pending_synthesis.pending > 0` trigger) — no manual CLAUDE.md editing needed. The rating skill fires from the hook directive and needs no instruction line either.

Expand Down Expand Up @@ -304,7 +305,7 @@ Three shipped upgrades sit on top of that foundation (specs: `2026-07-23-retriev

## Observation lifecycle

Observations don't live forever. They flow through four states (`active` → `consumed_*` → `archived` → deleted) driven by two pipelines: **synthesis** (LLM-driven, runs from the UI button or automatically by `memory.start_episode`) and **retention** (manual; spec §13 explicitly defers auto-scheduling).
Observations don't live forever. They flow through four states (`active` → `consumed_*` → `archived` → deleted) driven by two pipelines: **synthesis** (LLM-driven, runs from the UI button or automatically by `memory.start_episode`) and **retention** (runs automatically at most once per 24h from `memory.retrieve`, or manually via `memory.run_retention`).

```mermaid
stateDiagram-v2
Expand Down Expand Up @@ -340,7 +341,7 @@ stateDiagram-v2

**Prune** (opt-in, `RetentionService.run(..., prune=True, prune_age_days=N)`): hard-deletes `archived` rows older than `prune_age_days`. `dry_run=True` previews the count without deleting. Reflections are **never** auto-deleted.

Retention is invoked manually — there's no scheduler. Triggers today:
Retention runs automatically from `memory.retrieve` (`RetentionScheduler.maybe_run`, at most once per 24h) and can also be invoked manually. Triggers today:
- `memory.run_retention` MCP tool, or
- Direct call from a script / cron / CI step.

Expand Down
4 changes: 2 additions & 2 deletions better_memory/skills/memory-retrieve.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ When to use: before starting any meaningful coding task, or when entering a new
- `dont` — **hard constraints**. Do NOT repeat these approaches. If
you're tempted to try something here, stop and reconsider.
- `neutral` — general context, no strong signal either way.
4. Also read `insights` (confirmed patterns) and `knowledge` (standards,
language conventions, project docs).
4. Standards, language conventions and project docs are not in the
result — look them up with `knowledge.list` / `knowledge.search`.
5. When a returned reflection or semantic memory actually shapes your
work, call `memory.credit(kind, id, class, evidence)` — see
"Crediting memories you use" below. `memory.record_use` is a
Expand Down
12 changes: 6 additions & 6 deletions docs/agentcore-ui/agentcore-mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ Observations and Semantic tabs — kept once, HARD).
|---|---|---|---|---|---|
| Reflection drawer — rating evidence receipts | Reflections | read | local `session_memory_exposure` (services/exposure_log) | Session-operational state kept in local memory.db in both modes; backend already reads/writes this exact table via the local conn. | agentcore.py:88-97; queries.py:800; design §1 |
| Reflection edit form (pre-populate use_cases/hints) | Reflections | read | `get_memory_record` + `_parse_reflection_record` | Form needs only use_cases + hints from the single row, both parsed body-first off a get_memory_record fetch. Only work is decoupling from the join-heavy `reflection_detail` query. | agentcore.py:732-885, 972-983 |
| Retire reflection | Reflections | write | `retire_reflection` | Direct existing map: sets status='retired', moves record to retired namespace, handles AWS-extracted and migrated records; declared on protocol. Only route the UI write through the backend. | agentcore.py:1585-1591; protocol.py:245-247 |
| Promote reflection to general scope | Reflections | write | `promote_reflection` | Direct existing map: sets status='promoted', moves to general/reflections namespace; promotion fully modelled and admitted by the buckets fetch. Only route the UI write through the backend. | agentcore.py:1578-1583; protocol.py:241-243 |
| Episodes tab shell (page load) | Episodes | read | `supports_episodes` capability flag (False) | Shell route issues no query; the tab is hidden by the existing capability flag. Data-less shell gated by a working backend property. | app.py:205-207; agentcore.py:106-107; protocol.py:58-64 |
| Retire reflection | Reflections | write | `retire_reflection` | Direct existing map: sets status='retired', moves record to retired namespace, handles AWS-extracted and migrated records; declared on protocol. Only route the UI write through the backend. | agentcore.py:1845-1851; protocol.py:363-365 |
| Promote reflection to general scope | Reflections | write | `promote_reflection` | Direct existing map: sets status='promoted', moves to general/reflections namespace; promotion fully modelled and admitted by the buckets fetch. Only route the UI write through the backend. | agentcore.py:1838-1843; protocol.py:359-361 |
| Episodes tab shell (page load) | Episodes | read | `supports_episodes` capability flag (False) | Shell route issues no query; the tab is hidden by the existing capability flag. Data-less shell gated by a working backend property. | app.py:205-207; agentcore.py:156-157; protocol.py:58-64 |
| Semantic tab shell (filter form + panel mount) | Semantic | read | none (static render) | Pure static shell, zero DB access, hardcoded initial filters; all data arrives via the /semantic/panel sub-request. Backend-agnostic. | app.py:487; templates/semantic.html |
| List / filter / search semantic memories (panel) | Semantic | read | `semantic_list` (ListMemoryRecords / RetrieveMemoryRecords) | Working method fans out to list/retrieve and maps into the same SemanticMemory dataclass with every counter; Wilson ranking is Python over those counters. Exposure side-effect stays local. Only wiring: route through backend.semantic_list instead of raw SQL. | agentcore.py:1246, 1285, 1691; services/semantic.py:220 |
| Semantic memory detail drawer | Semantic | read | `_get_semantic_record` (GetMemoryRecord) + local exposure ledger | Single-record read maps to GetMemoryRecord (needs a thin public get-one accessor); evidence leg reads the local session_memory_exposure ledger. Both serviceable. | agentcore.py:1193, 1285; queries.py:800 |
| Create semantic memory | Semantic | write | `semantic_observe` (BatchCreateMemoryRecords) | Direct one-to-one: inserts content as a BASE record under userPreference strategy, namespace from scope, content-hash dedup. (Sqlite mode has no local embedding write either any more — embeddings were removed repo-wide in remove-ollama-embeddings.) | agentcore.py:1199; _agentcore_strategies.py:60 |
| Create semantic memory | Semantic | write | `semantic_observe` (BatchCreateMemoryRecords) | Direct one-to-one: inserts content as a BASE record under userPreference strategy, namespace from scope, content-hash dedup. (Sqlite mode has no local embedding write either any more — embeddings were removed repo-wide in remove-ollama-embeddings.) | agentcore.py:1428; _agentcore_strategies.py:60 |
| Update semantic memory text | Semantic | write | `semantic_update_text` (BatchUpdateMemoryRecords) | Direct one-to-one: get + batch_update with full metadata snapshot (reserved keys stripped), transient-404 retry. Re-embedding is AWS-managed. | agentcore.py:1383, 1012 |
| Set semantic memory scope (project<->general) | Semantic | write | `semantic_set_scope` (BatchUpdateMemoryRecords namespaces move) | Direct one-to-one: validates scope, moves record between project/general semantic namespaces. Scope is namespace membership rather than a column. | agentcore.py:1410 |
| Delete semantic memory | Semantic | write | `semantic_delete` (BatchDeleteMemoryRecords) | Direct one-to-one: removes record, AWS reclaims embedding. Minor: raises on not-found vs sqlite idempotency (trivial wrapper). | agentcore.py:1444 |
| Set semantic memory scope (project<->general) | Semantic | write | `semantic_set_scope` (BatchUpdateMemoryRecords namespaces move) | Direct one-to-one: validates scope, moves record between project/general semantic namespaces. Scope is namespace membership rather than a column. | agentcore.py:1657 |
| Delete semantic memory | Semantic | write | `semantic_delete` (BatchDeleteMemoryRecords) | Direct one-to-one: removes record, AWS reclaims embedding. Minor: raises on not-found vs sqlite idempotency (trivial wrapper). | agentcore.py:1691 |
| Rating diagnostics counters (session_id_missing etc.) | Diagnostics | read | local `rating_diagnostics` | Operational/telemetry state; stays local. The rating sweep that writes these becomes real on agentcore and runs against local memory.db. | design §1, §2; protocol.py:281-288 |
| Hook errors panel (grouped-by-day list) | Diagnostics | read | local `hook_errors` | Session-operational state, local in both modes; queries read local sqlite directly. Backend-independent. | design §1 (line 54) |
| Hook error detail drawer | Diagnostics | read | local `hook_errors` | Single hook_errors row from local sqlite; local-only operational state. | design §1 (line 54) |
Expand Down
Loading
Loading