docs(protocol): add typed edge link protocol documentation Add comprehensive documentation for the link protocol supporting typed edges in body text. This includes specification for three legal inline forms (bare wikilink, line-level Dataview, inline-bracketed Dataview), predicate syntax rules, and the machine-managed Relations section convention for organizing discovered edges. fix(memory): update path reference from vault_root to working_dir Change the memory_create operation's path anchoring from vault_root to working_dir to maintain consistency with the current working directory configuration. refactor(components): remove edge_extractor module and simplify parsing Remove the edge_extractor component module entirely and inline edge extraction logic directly into LinkedFileParser using parse_wikilinks utility. This simplifies the architecture by eliminating the separate edge extraction component and delegating edge discovery to the maintainer's enrichment operations. feat(parser): update parse method signature and simplify edge extraction Modify LinkedFileParser to return (FileNode, list[FileChunk]) tuple instead of ParsedFile, remove dependency on BaseEdgeExtractor, and implement direct wikilink parsing from body text only. ```
8.2 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.
Link protocol — typed edges in body text
Edges live only in body text. YAML frontmatter is not walked for
links; a links: block in frontmatter is silently ignored by the
parser. Three legal inline forms:
| Form | Example | Predicate |
|---|---|---|
| Bare wikilink | [[X]] |
None |
| Line-level Dataview | extends:: [[X]] |
extends |
| Inline-bracketed Dataview | [extends:: [[X]]] |
extends |
Multi-target on one field expands to multiple edges:
concerns:: [[Topic A]], [[Topic B]]
Bullet markers are tolerated (- extends:: [[X]], * extends:: [[X]]).
Predicate syntax
A predicate is any identifier-shaped token: starts with a letter,
followed by letters / digits / underscore (regex
[A-Za-z][A-Za-z0-9_]*). The parser preserves whatever it sees — no
closed vocabulary at the schema layer. Choose predicates that read
well in prose (extends, contradicts, derives_from, concerns,
supersedes, …); the maintainer's lint pass can later surface
inconsistencies if a vocabulary policy is desired.
## Relations section (machine-managed)
The maintainer's discover op appends newly discovered edges as
Dataview line-level fields under a ## Relations heading at the end
of the file (creating the heading if absent). Example:
## Relations
extends:: [[Source Topic]]
concerns:: [[Topic A]]
## Relations is a convention, not a protocol — the parser treats
edges anywhere in the body uniformly. The heading is just the default
write location so machine-added edges stay separate from prose for
human review.
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 working_dir.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.