ReMe/reme2/memory/protocol.md
huangsen dd2de16481 ```
feat(file_watcher): add directory deletion support with descendant indexing

Add support for deleting entire directories and their indexed descendants
in the file watcher. Previously only individual file deletions were
handled properly. Now when a directory is deleted, the system finds all
indexed files beneath that directory path and removes them along with
their metadata and chunks.

The implementation includes:
- New `_descendant_indexed_paths` method to find all indexed files
  under a given directory path
- Updated `_on_deleted` method to process both the target path and
  all its indexed descendants
- Proper handling of symlinks and path resolution differences
- Enhanced logging to show directory deletion with child count

Also adds necessary os import for path operations.

refactor(config): restructure configuration profiles for clarity

Rename curated.yaml to remove outdated configuration file and
rename full.yaml to expert.yaml with updated documentation.
Add new service.yaml configuration profile that provides a
service-aligned MCP surface with three main tools:
- retrieve: graph-aware hybrid retrieval
- remember: single write entry point with log/distill modes
- maintain: vault hygiene sweep

The expert configuration now excludes the ingest tool since
cold-path operations are handled by external agents, and adds
memory_lint tool for structural issue detection.

Updated documentation to clarify the different configuration
profiles and their intended usage patterns.
```
2026-05-11 10:52:25 +08:00

147 lines
6.6 KiB
Markdown

# Memory Protocol
Single source of truth for vault schema, conventions, and the R-M-W
write loop. Consumed by:
- **Ingestor's embedded ReAct prompt** (`reme2/memory/ingestor.yaml`
injected as `{protocol}` at load time).
- **Strong-agent SKILL** (`reme-plugin/skills/reme/SKILL.md`
transcluded so the host agent sees the same rules).
Anything that defines schema invariants, path templates, write tool
semantics, or the R-M-W decision tree belongs here. Anything role-
specific (caller framing, audit trail expectations, summary
requirements) stays in the consumer.
## Vault layout
- **Topics** — long-lived cognitive memory at `topics/{folder}/{name}.md`.
A **folder topic** has `folder == name`; it's the cluster's index head.
Short wikilink `[[X]]` resolves to the folder topic if one exists,
else falls back to a unique same-stem file.
- **Events** — fact log of one session at
`events/{YYYY-MM-DD}/{name}/{name}.md`. The `.md` is the **index**
inside a folder; sibling files are **materials** (raw conversation,
tool outputs, data dumps). The index lists them under `## Materials`.
## Frontmatter — 4 schema axes
Every memory declares 4 orthogonal axes. The legacy `category` field is
auto-translated to these axes for back-compat reads, but new writes
should set the axes directly.
| Axis | Values | Meaning |
|---|---|---|
| `lifecycle` | `streaming` / `evolving` / `frozen` | streaming = events (decay/archive); evolving = topics (long-lived, edited); frozen = materials (immutable references) |
| `scope` | `instance` / `class` | instance = a specific moment / object; class = abstract concept / role / pattern |
| `source` | `auto` / `curated` / `derived` | auto = system-captured; curated = human/LLM intent; derived = computed from other memories |
| `role` | `observation` / `claim` / `question` / `profile` / `concept` / `method` / `reference` / `fundamentals` | cognitive role — drives ranking + role-specific validation |
### Conditional fields
- `confidence` ∈ {⏳, ✅, ❌} — **REQUIRED** when `role: claim` (legacy
categories `thesis` / `model`). Same gate applies to `role: question`
(legacy `questions`).
- `status` ∈ {`active`, `distilled`, `archived`} — meaningful only for
`lifecycle: streaming`. Topic-style memories ignore it.
- `originSessionId` — should be set when `source: auto`.
### Standard identity fields
`title`, `description`, `tags`, `created`, `updated`, `topics`,
`parent`. Use today's date for `created` / `updated` on new writes.
## Cross-file references
`[[wikilink]]` syntax. Two forms:
- **Stem form** `[[X]]` — resolved against the file_store's stem index;
prefers the folder topic if one exists.
- **Path form** `[[topics/X/X]]` or `[[topics/X/X.md]]` — anchored at
the vault root.
## Status state machine
`active → distilled → archived` (single direction, no skip). A reverse
or skip transition will be flagged by the Maintainer.
## Wikilink uniqueness
Every create path routes through `MemoryCreate.write`, which refuses to
introduce ambiguity (existing `[[X]]` would resolve to ≥2 paths). When
rejected, the response includes a `suggested_name`. Retry with that, or
pick a domain-specific qualifier (`Apple-Inc` beats `Apple-2`). Never
bypass with `force=true` unless you fully understand the ambiguity.
## Available tools
### Read tools (gather context BEFORE writing)
- `memory_get(path, include_chunks=False)` — full file content +
frontmatter. On an event index, follow `## Materials` and read each
artifact whose content you need.
- `memory_list(path_prefix=None, tags=None, metadata=None, limit=100)`
— list indexed files filtered by prefix / tags / frontmatter.
- `memory_resolve_wikilink(wikilink)` — resolve `[[X]]` to a path;
flags ambiguity / dangling.
- `memory_backlinks(path)` — files linking TO the given path.
- `memory_links(path)` — files the given path links to.
- `memory_search(query, …)` — hybrid (vector + keyword) chunk search.
- `memory_graph_search(query, seeds, graph_depth, …)` — vector +
keyword + graph BFS fusion.
### Write tools (mutations are SSOT-routed; each returns success +
payload + records to audit)
- `memory_update(path, old_string, new_string, replace_all=False)`
body edit by exact-string substitution. Use a tail snippet to append.
- `memory_property_update(path, key, value)` — change one frontmatter
key (`value=null` deletes). Use this to flip status.
- `memory_create(path, metadata, content, overwrite=False, force=False)`
— new file. Reserve for genuinely NEW topics. Do NOT use for events
(`sync` owns events). All paths must be ABSOLUTE under vault_root.
- `memory_rename(old_path, new_path)` — move file + rewrite cross-vault
wikilinks. Refuses on destination conflict or stem ambiguity.
- `memory_delete(path)` — remove a file.
- `memory_archive(path)` — flip `status: archived` and move under
`<vault>/Archive/`.
### Hot-write helper (deterministic, no LLM)
- `sync(name, description?, content?, topics?, tags?, materials?,
on_date?)` — idempotent upsert of an event FOLDER per `(date, name)`.
Reuse the same `name` across calls in one thread to keep extending
the same folder. Refuses on `status: distilled` / `archived` and
returns a `suggested_name`.
## R-M-W decision rules
Apply in order. Stop at the first match.
1. **SKIP** — if material is ALREADY covered by existing topics, reply
with a single line `SKIP: <one-line reason>` and call no tools.
2. **CONTRADICT** — if material CONTRADICTS an existing block, use
`memory_update` with a unique snippet of the outdated text and the
corrected replacement.
3. **EXTEND** — if material EXTENDS an existing topic, use
`memory_update` with a unique TAIL snippet of the existing body, and
`new_string = tail + blank line + new content`.
4. **CREATE** — if material warrants a GENUINELY NEW topic, use
`memory_create` at `topics/{folder}/{name}.md`. Do NOT
`memory_create` under `events/` — `sync` owns that path.
5. **STATUS FLIP** — after integrating an event's content into a
topic, flip that event's status to `distilled` with
`memory_property_update`.
## Operating principles
- **Read before write.** Always inspect related topics before deciding
CONTRADICT vs EXTEND vs CREATE. The wikilink-uniqueness gate refuses
blind creates; reading first prevents wasted attempts.
- **Minimal edits.** Edit only what must change. Don't restructure
while updating content.
- **Frontmatter on create.** Always include reasonable frontmatter:
the 4 axes, `title`, `created`, `updated`, plus `confidence` when
`role: claim` or `role: question`.
- **Never delete unless asked.** Distillation flips status; it does
not remove events.