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. ```
6.6 KiB
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 hasfolder == 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.mdis 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 whenrole: claim(legacy categoriesthesis/model). Same gate applies torole: question(legacyquestions).status∈ {active,distilled,archived} — meaningful only forlifecycle: streaming. Topic-style memories ignore it.originSessionId— should be set whensource: 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## Materialsand 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=nulldeletes). 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 (syncowns 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)— flipstatus: archivedand 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 samenameacross calls in one thread to keep extending the same folder. Refuses onstatus: distilled/archivedand returns asuggested_name.
R-M-W decision rules
Apply in order. Stop at the first match.
- SKIP — if material is ALREADY covered by existing topics, reply
with a single line
SKIP: <one-line reason>and call no tools. - CONTRADICT — if material CONTRADICTS an existing block, use
memory_updatewith a unique snippet of the outdated text and the corrected replacement. - EXTEND — if material EXTENDS an existing topic, use
memory_updatewith a unique TAIL snippet of the existing body, andnew_string = tail + blank line + new content. - CREATE — if material warrants a GENUINELY NEW topic, use
memory_createattopics/{folder}/{name}.md. Do NOTmemory_createunderevents/—syncowns that path. - STATUS FLIP — after integrating an event's content into a
topic, flip that event's status to
distilledwithmemory_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, plusconfidencewhenrole: claimorrole: question. - Never delete unless asked. Distillation flips status; it does not remove events.