r2mcp 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/LICENSE +21 -0
  3. package/README.md +532 -0
  4. package/dist/breadcrumbs.d.ts +123 -0
  5. package/dist/breadcrumbs.js +135 -0
  6. package/dist/cli/classify-edges.d.ts +2 -0
  7. package/dist/cli/classify-edges.js +130 -0
  8. package/dist/cli/compile-wiki.d.ts +2 -0
  9. package/dist/cli/compile-wiki.js +173 -0
  10. package/dist/cli/dump-edges-json.d.ts +2 -0
  11. package/dist/cli/dump-edges-json.js +21 -0
  12. package/dist/cli/extract-entities.d.ts +17 -0
  13. package/dist/cli/extract-entities.js +166 -0
  14. package/dist/cli/lint-memory.d.ts +16 -0
  15. package/dist/cli/lint-memory.js +94 -0
  16. package/dist/cli/migrate.d.ts +17 -0
  17. package/dist/cli/migrate.js +146 -0
  18. package/dist/cli/setup-helpers.d.ts +7 -0
  19. package/dist/cli/setup-helpers.js +72 -0
  20. package/dist/cli/setup.d.ts +15 -0
  21. package/dist/cli/setup.js +95 -0
  22. package/dist/compiler/clustering.d.ts +29 -0
  23. package/dist/compiler/clustering.js +66 -0
  24. package/dist/compiler/frontmatter.d.ts +35 -0
  25. package/dist/compiler/frontmatter.js +168 -0
  26. package/dist/compiler/manifest.d.ts +32 -0
  27. package/dist/compiler/manifest.js +82 -0
  28. package/dist/compiler/prompts.d.ts +17 -0
  29. package/dist/compiler/prompts.js +82 -0
  30. package/dist/compiler/run.d.ts +52 -0
  31. package/dist/compiler/run.js +186 -0
  32. package/dist/compiler/tier.d.ts +10 -0
  33. package/dist/compiler/tier.js +85 -0
  34. package/dist/compiler/topic.d.ts +16 -0
  35. package/dist/compiler/topic.js +105 -0
  36. package/dist/compiler/types.d.ts +101 -0
  37. package/dist/compiler/types.js +4 -0
  38. package/dist/db.d.ts +10 -0
  39. package/dist/db.js +46 -0
  40. package/dist/edges/candidate-pairs.d.ts +24 -0
  41. package/dist/edges/candidate-pairs.js +35 -0
  42. package/dist/edges/classifier.d.ts +45 -0
  43. package/dist/edges/classifier.js +172 -0
  44. package/dist/edges/signals.d.ts +13 -0
  45. package/dist/edges/signals.js +45 -0
  46. package/dist/edges/stage1-haiku.d.ts +21 -0
  47. package/dist/edges/stage1-haiku.js +33 -0
  48. package/dist/edges/stage2-opus.d.ts +41 -0
  49. package/dist/edges/stage2-opus.js +101 -0
  50. package/dist/edges/state.d.ts +44 -0
  51. package/dist/edges/state.js +79 -0
  52. package/dist/edges/types.d.ts +20 -0
  53. package/dist/edges/types.js +1 -0
  54. package/dist/embeddings.d.ts +13 -0
  55. package/dist/embeddings.js +54 -0
  56. package/dist/entities/db.d.ts +49 -0
  57. package/dist/entities/db.js +109 -0
  58. package/dist/entities/extractor.d.ts +14 -0
  59. package/dist/entities/extractor.js +154 -0
  60. package/dist/entities/normalize.d.ts +5 -0
  61. package/dist/entities/normalize.js +7 -0
  62. package/dist/entities/prompt.d.ts +19 -0
  63. package/dist/entities/prompt.js +100 -0
  64. package/dist/entities/state.d.ts +44 -0
  65. package/dist/entities/state.js +99 -0
  66. package/dist/entities/types.d.ts +62 -0
  67. package/dist/entities/types.js +6 -0
  68. package/dist/env.d.ts +13 -0
  69. package/dist/env.js +32 -0
  70. package/dist/fingerprint.d.ts +2 -0
  71. package/dist/fingerprint.js +12 -0
  72. package/dist/graph-rebuild.d.ts +6 -0
  73. package/dist/graph-rebuild.js +20 -0
  74. package/dist/index.d.ts +4 -0
  75. package/dist/index.js +403 -0
  76. package/dist/instrumentation.d.ts +10 -0
  77. package/dist/instrumentation.js +37 -0
  78. package/dist/lint/checks/contradictions.d.ts +30 -0
  79. package/dist/lint/checks/contradictions.js +52 -0
  80. package/dist/lint/checks/drift.d.ts +5 -0
  81. package/dist/lint/checks/drift.js +34 -0
  82. package/dist/lint/checks/orphans.d.ts +5 -0
  83. package/dist/lint/checks/orphans.js +25 -0
  84. package/dist/lint/checks/stale.d.ts +6 -0
  85. package/dist/lint/checks/stale.js +29 -0
  86. package/dist/lint/checks/superseded-unflagged.d.ts +5 -0
  87. package/dist/lint/checks/superseded-unflagged.js +47 -0
  88. package/dist/lint/run.d.ts +11 -0
  89. package/dist/lint/run.js +95 -0
  90. package/dist/lint/types.d.ts +60 -0
  91. package/dist/lint/types.js +13 -0
  92. package/dist/mcp-response.d.ts +7 -0
  93. package/dist/mcp-response.js +13 -0
  94. package/dist/providers/anthropic.d.ts +13 -0
  95. package/dist/providers/anthropic.js +56 -0
  96. package/dist/providers/claude-code.d.ts +35 -0
  97. package/dist/providers/claude-code.js +175 -0
  98. package/dist/providers/errors.d.ts +12 -0
  99. package/dist/providers/errors.js +19 -0
  100. package/dist/providers/index.d.ts +30 -0
  101. package/dist/providers/index.js +71 -0
  102. package/dist/providers/openrouter.d.ts +19 -0
  103. package/dist/providers/openrouter.js +76 -0
  104. package/dist/providers/semaphore.d.ts +19 -0
  105. package/dist/providers/semaphore.js +51 -0
  106. package/dist/providers/types.d.ts +27 -0
  107. package/dist/providers/types.js +7 -0
  108. package/dist/schema.sql +116 -0
  109. package/dist/server-instructions.d.ts +9 -0
  110. package/dist/server-instructions.js +20 -0
  111. package/dist/telemetry.d.ts +39 -0
  112. package/dist/telemetry.js +130 -0
  113. package/dist/tools/classify.d.ts +44 -0
  114. package/dist/tools/classify.js +121 -0
  115. package/dist/tools/compile.d.ts +31 -0
  116. package/dist/tools/compile.js +132 -0
  117. package/dist/tools/dump-edges-sidecar.d.ts +37 -0
  118. package/dist/tools/dump-edges-sidecar.js +80 -0
  119. package/dist/tools/extract-entities.d.ts +53 -0
  120. package/dist/tools/extract-entities.js +169 -0
  121. package/dist/tools/lint.d.ts +10 -0
  122. package/dist/tools/lint.js +13 -0
  123. package/dist/tools/meditate.d.ts +25 -0
  124. package/dist/tools/meditate.js +128 -0
  125. package/dist/tools/recall.d.ts +66 -0
  126. package/dist/tools/recall.js +409 -0
  127. package/dist/tools/reject.d.ts +10 -0
  128. package/dist/tools/reject.js +24 -0
  129. package/dist/tools/remember.d.ts +26 -0
  130. package/dist/tools/remember.js +140 -0
  131. package/dist/tools/search.d.ts +30 -0
  132. package/dist/tools/search.js +69 -0
  133. package/dist/tools/spawn-cli.d.ts +14 -0
  134. package/dist/tools/spawn-cli.js +41 -0
  135. package/dist/tools/stats.d.ts +31 -0
  136. package/dist/tools/stats.js +88 -0
  137. package/package.json +86 -0
  138. package/skills/remember/SKILL.md +357 -0
@@ -0,0 +1,357 @@
1
+ ---
2
+ name: remember
3
+ description: >-
4
+ This skill should be used when the user says "/remember", "/remember <statement>",
5
+ "remember this", "save this to memory", "don't forget", "note this down",
6
+ "keep in mind", "always do X", "never do Y", "that's wrong", "don't do it
7
+ that way", "I told you not to", "stop doing X", or any variation of asking to
8
+ persist information across sessions. Handles classification into the 3-tier
9
+ memory system with explicit operations (ADD/UPDATE/ARCHIVE/REJECTION/NOOP),
10
+ write-time metadata, and cross-references. Also invoked silently
11
+ by the SessionEnd hook to scan for unsaved memories.
12
+ ---
13
+
14
+ # Remember — Memory Discipline Skill
15
+
16
+ Write memories to the 3-tier long memory system with judgment, deduplication, and conflict resolution. This skill is the single source of truth for what's worth remembering and how to file it.
17
+
18
+ ## MCP Mode Detection
19
+
20
+ Before executing any memory write, check whether the Memory MCP Server is available:
21
+
22
+ **Detection:** If the MCP tool `mcp__memory__remember` is available in your tool list, use **MCP Mode**. Otherwise, use **Direct Mode** (the original file-based fallback described throughout this document).
23
+
24
+ The judgment pipeline (classification, conflict-check, operation selection, metadata generation) runs **client-side in both modes** — that is the core design. Only the storage layer differs:
25
+
26
+ ### MCP Mode (preferred)
27
+
28
+ When `mcp__memory__remember` is available, replace all Edit/Write tool calls to memory tier files with a single MCP tool call:
29
+
30
+ ```
31
+ mcp__memory__remember({
32
+ operation: "ADD" | "UPDATE" | "ARCHIVE" | "REJECTION" | "NOOP",
33
+ tier: "preferences" | "project-context" | "conversations",
34
+ content: "The memory entry text (without the HTML metadata comment)",
35
+ metadata: {
36
+ type: "preference" | "decision" | "context" | "relationship" | "observation" | "rejection",
37
+ topics: ["topic1", "topic2"],
38
+ people: ["name1"], // optional
39
+ section: "Section Heading", // optional — nearest markdown heading
40
+ date: "YYYY-MM-DD" // optional
41
+ },
42
+ target_id: "uuid" // required for UPDATE and ARCHIVE operations
43
+ })
44
+ ```
45
+
46
+ **Key differences in MCP Mode:**
47
+ - Do NOT use Edit/Write tools to modify `preferences.md`, `project-context.md`, or `conversations.md`
48
+ - Do NOT run any local graph-rebuild script — the MCP server handles graph rebuilds automatically
49
+ - Do NOT write HTML metadata comments (`<!-- type:... -->`) into the content — pass metadata as structured fields instead
50
+ - Cross-references are handled by the MCP server's embedding index — no need to add `[see also: ...]` annotations manually
51
+ - For UPDATE/ARCHIVE: use `mcp__memory__search` or `mcp__memory__recall` to find the `target_id` of the entry to modify
52
+ - The `content` field should be the clean entry text only (e.g., "Always use bun instead of npm")
53
+
54
+ **For conflict-checking in MCP Mode:** Use `mcp__memory__recall` to search for existing entries on the same topic before deciding the operation (ADD vs UPDATE vs ARCHIVE). This replaces the "Read the target tier file" step in Direct Mode.
55
+
56
+ ### Direct Mode (fallback)
57
+
58
+ When the MCP server is NOT available, use the original behavior described in the rest of this document: read tier files with the Read tool, write with Edit/Write tools, add HTML metadata comments, manage cross-references manually, and run the graph rebuild script.
59
+
60
+ ## Two Modes
61
+
62
+ ### Mode 1: With Arguments
63
+
64
+ When invoked as `/remember <statement>` (e.g., `/remember always use bun instead of npm`):
65
+
66
+ 1. Classify the statement against the 3-tier system below
67
+ 2. Read the target tier file
68
+ 3. Check for existing related entries — decide operation (ADD, UPDATE, ARCHIVE, or NOOP)
69
+ 4. Execute the operation — write the entry with metadata per the Entry Format section
70
+ 5. Output a brief summary with operation type: e.g., "ADD to preferences.md <!-- type:preference topics:tooling -->"
71
+
72
+ ### Mode 2: Conversation Scan (No Arguments)
73
+
74
+ When invoked as `/remember` with no arguments, or triggered by the SessionEnd hook:
75
+
76
+ 1. Scan the full conversation for anything worth saving, including **correction patterns** (user saying "no", "don't", "actually...", redirecting approach). Apply the structural test from the REJECTION operation to any corrections found.
77
+ 2. Apply the skip criteria — discard anything that doesn't pass
78
+ 3. For each finding: classify tier, read target file, decide operation (ADD/UPDATE/ARCHIVE/NOOP), execute with metadata
79
+ 4. Output a brief summary: e.g., "Saved 2 memories (1 preference, 1 project context)"
80
+ 5. If nothing worth saving is found, output: "Nothing new to save."
81
+
82
+ **When invoked from a SessionEnd hook context:** Operate silently — no user-facing output. Perform all the same judgment and writes, but produce no summary text.
83
+
84
+ ## 3-Tier Classification
85
+
86
+ ### Tier 1 — Preferences & Decisions → `preferences.md`
87
+
88
+ Durable choices that shape how the assistant works with the user.
89
+
90
+ - "Always/never do X" statements
91
+ - Tool or workflow choices (e.g., "use bun instead of npm")
92
+ - Communication preferences (e.g., "emojis are welcome")
93
+ - Decisions with rationale (e.g., "chose Approach A because...")
94
+ - Working style preferences (e.g., "prefers short PRs")
95
+
96
+ ### Tier 2 — Project Context → `project-context.md`
97
+
98
+ Facts about what exists, what's been built, and system state.
99
+
100
+ - New things built or deployed
101
+ - Architecture decisions and their rationale
102
+ - System state changes (new integrations, config changes, migrations)
103
+ - What's currently in progress or planned
104
+ - Key file paths and their purposes
105
+
106
+ ### Tier 3 — Relationship Continuity → `conversations.md`
107
+
108
+ Context that makes the next session feel continuous, not cold.
109
+
110
+ - Running threads or recurring topics
111
+ - Things mentioned in passing that might matter later
112
+ - Shared vocabulary, jokes, or references
113
+ - Relationship dynamics and communication patterns
114
+ - Context that would be lost between sessions
115
+
116
+ ### MEMORY.md — Active Work Threads Only
117
+
118
+ Update `MEMORY.md` only when there's a change to the **Active Work Threads** section — new threads starting, existing threads completing, or status changes. Do not duplicate tier file content here. Keep MEMORY.md under 200 lines total.
119
+
120
+ ## Skip Criteria
121
+
122
+ Do NOT save:
123
+
124
+ - **Session-specific debugging** — temporary errors, stack traces, one-off fixes
125
+ - **Temporary state** — "I'm currently in directory X", "this file is open"
126
+ - **One-off commands** — commands run for a specific task with no recurring value
127
+ - **Already captured in codebase** — information already in committed docs, CLAUDE.md, or design docs
128
+ - **Speculative/unverified** — conclusions from reading a single file, guesses about architecture
129
+ - **Trivial context** — things obvious from the codebase or project structure
130
+
131
+ ## Entry Format — Write-Time Metadata
132
+
133
+ Every new memory entry MUST include inline metadata as an HTML comment at the end of the bullet point:
134
+
135
+ ```
136
+ - Memory content here <!-- type:TYPE topics:TOPIC1,TOPIC2 people:NAME1 -->
137
+ ```
138
+
139
+ ### Metadata Fields
140
+
141
+ | Field | Required | Values | Example |
142
+ |-------|----------|--------|---------|
143
+ | `type` | Yes | `preference`, `decision`, `context`, `relationship`, `observation`, `rejection` | `type:preference` |
144
+ | `topics` | Yes | 1-3 lowercase, hyphenated tags | `topics:tooling,package-management` |
145
+ | `people` | No | Lowercase names, comma-separated | `people:alex` |
146
+
147
+ ### Type Classification Guide
148
+
149
+ | Type | When to Use | Example |
150
+ |------|-------------|---------|
151
+ | `preference` | "Always/never do X", tool choices, style preferences | "Use bun instead of npm" |
152
+ | `decision` | Choices with rationale, approach selections | "Chose Approach A because..." |
153
+ | `context` | Facts about what exists, system state, what's built | "CI pipeline deployed" |
154
+ | `relationship` | Running threads, shared vocabulary, personal context | "User out of office next week" |
155
+ | `observation` | Things mentioned in passing, future ideas, loose ends | "Mentioned wanting a staging environment" |
156
+ | `rejection` | Corrections, "don't do X" patterns, rejected approaches with reasoning | "Don't add verbose error handling for internal functions" |
157
+
158
+ ### Examples
159
+
160
+ ```markdown
161
+ - Always use bun instead of npm <!-- type:preference topics:tooling,package-management -->
162
+ - Chose tiered files over lifecycle metadata — simpler at current scale <!-- type:decision topics:memory-system,architecture -->
163
+ - CI pipeline deployed and running on GitHub Actions <!-- type:context topics:ci,deployment -->
164
+ - User out of office the week of 2026-03-02 <!-- type:relationship topics:scheduling people:alex -->
165
+ - Mentioned wanting a dedicated staging environment <!-- type:observation topics:infrastructure people:alex -->
166
+ - Don't add verbose error handling for internal functions — trust framework guarantees, only validate at system boundaries <!-- type:rejection topics:code-style,error-handling -->
167
+ ```
168
+
169
+ ### Backward Compatibility
170
+
171
+ Existing untagged entries (plain bullet points without `<!-- ... -->`) are valid. Do NOT retroactively tag old entries. When reading files, handle both tagged and untagged entries gracefully. Only new entries get metadata.
172
+
173
+ ### MEMORY.md Exception
174
+
175
+ Do NOT add metadata to MEMORY.md entries. MEMORY.md is a hub file for active work threads — it stays lean and human-readable without metadata tags.
176
+
177
+ ## Memory File Paths
178
+
179
+ All memory files live in the auto-memory directory for your project (Claude Code creates this automatically):
180
+
181
+ ```
182
+ ~/.claude/projects/<your-project-hash>/memory/
183
+ ├── MEMORY.md # Hub file — active work threads only
184
+ ├── preferences.md # Tier 1 — preferences & decisions
185
+ ├── project-context.md # Tier 2 — project context
186
+ ├── conversations.md # Tier 3 — relationship continuity
187
+ └── archive/ # Cold storage (quarterly)
188
+ ```
189
+
190
+ The exact path depends on your project's working directory. Claude Code sets it automatically — you can find it by running `claude --print-config` or looking in `~/.claude/projects/`.
191
+
192
+ Full paths (example — your path will differ):
193
+ - **Tier 1:** `~/.claude/projects/<project-hash>/memory/preferences.md`
194
+ - **Tier 2:** `~/.claude/projects/<project-hash>/memory/project-context.md`
195
+ - **Tier 3:** `~/.claude/projects/<project-hash>/memory/conversations.md`
196
+ - **Hub:** `~/.claude/projects/<project-hash>/memory/MEMORY.md`
197
+
198
+ ## Operations — Explicit Decision Framework
199
+
200
+ For every memory candidate, choose exactly ONE operation before acting. Log the operation in the output summary.
201
+
202
+ ### ADD — New information, no conflicts
203
+ **When:** No existing entry covers this topic. This is genuinely new information.
204
+ **Action:** Append a new bullet point with metadata to the target tier file.
205
+ **Example:** First time the user mentions a tool preference → ADD to preferences.md
206
+
207
+ ### UPDATE — Refine or extend an existing entry
208
+ **When:** An existing entry covers the same topic but has evolved, gained nuance, or needs minor correction. The core fact is still true — it just needs updating.
209
+ **Action:** Edit the existing entry in-place. Preserve the original meaning where it still holds; extend or refine where it has evolved. Update metadata tags if needed.
210
+ **Example:** "Prefers short PRs" → "Prefers short PRs, ideally under 200 lines"
211
+
212
+ ### ARCHIVE — Old fact is no longer true, replace it
213
+ **When:** An existing entry directly contradicts newer information. The old fact is superseded — not just refined, but wrong or outdated.
214
+ **Action:**
215
+ 1. Move the old entry to `archive/YYYY-QN.md` (create the file/directory if needed)
216
+ 2. Add a supersession link to the archived entry: `[superseded: YYYY-MM-DD, see FILE#SECTION]`
217
+ 3. Write the new replacement entry (with metadata) to the active tier file
218
+ **Example:** "Use npm" is contradicted by "Use bun" → ARCHIVE old entry, ADD new one
219
+
220
+ **Archive file naming:** `archive/2026-Q1.md` (quarterly: Q1=Jan-Mar, Q2=Apr-Jun, Q3=Jul-Sep, Q4=Oct-Dec)
221
+
222
+ **Archive entry format:**
223
+ ```markdown
224
+ - Use npm for package management <!-- type:preference topics:tooling --> [superseded: 2026-03-04, see preferences.md#tooling]
225
+ ```
226
+
227
+ ### REJECTION — Structural correction worth preserving
228
+ **When:** The user corrects your approach and the correction would apply again in similar future situations (structural, not situational). Detected during conversation scan (or proactively, if your project configures a rejection-detection rule under `.claude/rules/`).
229
+ **Action:**
230
+ 1. Apply the structural test: "Would this rejection apply again in a similar future situation?"
231
+ 2. If structural: write entry with `type:rejection` metadata to the appropriate tier file
232
+ 3. Confirm briefly: `"📝 Captured rejection: 'Don't X because Y'"`
233
+ 4. If situational: skip silently
234
+ **Entry format:** Always capture both the rejected approach AND the reasoning: `- Don't X because Y <!-- type:rejection topics:... -->`
235
+ **Example:** User says "Don't add docstrings to code you didn't change" → REJECTION to preferences.md
236
+ **Undo:** If user says "undo that" or "that was situational," delete the entry entirely (no archive).
237
+
238
+ ### NOOP — Already known, skip
239
+ **When:** The candidate is a duplicate of an existing entry (same info, same meaning) OR falls under the skip criteria.
240
+ **Action:** Do nothing. Log "NOOP" in the summary for transparency.
241
+
242
+ ### Ambiguous Tension
243
+ **When:** Unclear whether this conflicts with an existing entry — could be a contradiction or could be a different context.
244
+ **Action:** ADD the new entry with a `(may conflict with: 'EXISTING_ENTRY')` note. Leave resolution for a future `/meditation` reconciliation pass.
245
+
246
+ ### Decision Boundary: UPDATE vs ARCHIVE
247
+
248
+ | Situation | Operation | Rationale |
249
+ |-----------|-----------|-----------|
250
+ | Same fact, more detail | UPDATE | Core truth unchanged, just richer |
251
+ | Same fact, minor correction | UPDATE | Fixing, not replacing |
252
+ | Same topic, different conclusion | ARCHIVE | Old conclusion is wrong |
253
+ | Same tool category, different tool | ARCHIVE | Switched tools entirely |
254
+ | Unclear if conflict or context-dependent | ADD with tension note | Let /meditation resolve |
255
+
256
+ ### Decision Boundary: REJECTION vs Other Operations
257
+
258
+ | Situation | Operation | Rationale |
259
+ |-----------|-----------|-----------|
260
+ | User corrects approach, will apply again | REJECTION | Structural — captures the "don't" with reasoning |
261
+ | User states a preference proactively | ADD | Positive preference, not a correction |
262
+ | User corrects a factual error about the system | UPDATE | Fixing existing knowledge, not a pattern |
263
+ | User says "not now" or "not for this task" | Skip (no op) | Situational, won't recur |
264
+ | User rejects approach but gives no reason | REJECTION (ask why) | Prompt briefly for reasoning to make entry useful |
265
+
266
+ ## Proactive Rejection Detection
267
+
268
+ Rejections are detected during conversation scans by default. Projects that want *proactive* detection (flagging corrections the moment they happen) can add an always-loaded rule under `.claude/rules/` that references this section for the full detection logic.
269
+
270
+ ### Detection Heuristics
271
+
272
+ Watch for these patterns in user messages:
273
+
274
+ - **Direct negation:** "No", "Don't do that", "Never do X", "Stop doing X"
275
+ - **Correction:** "Actually...", "That's wrong because...", "Instead of X, do Y"
276
+ - **Quality judgment:** "Too verbose", "Over-engineered", "Unnecessary", "That's overkill"
277
+ - **Pattern redirect:** "I'd prefer...", "The way I want this is...", "Do it like..."
278
+
279
+ ### Structural Test
280
+
281
+ When a correction is detected, apply: **"Would this rejection apply again in a similar future situation?"**
282
+
283
+ - **Structural** (save): "Don't add verbose error handling for internal functions" — general principle
284
+ - **Situational** (skip): "No, use port 3001 for this server" — one-off for this task
285
+ - **Ambiguous**: When uncertain, lean toward saving — `/meditation` can prune later
286
+
287
+ ### Proactive Flow
288
+
289
+ 1. Detect correction pattern in user message
290
+ 2. Apply structural test
291
+ 3. If structural → save to appropriate tier and confirm: `"📝 Captured rejection: 'Don't X because Y'"`
292
+ 4. If situational → skip silently (no interruption)
293
+
294
+ Confirmation is brief (one line) and non-blocking. If misjudged, user can say "undo that" or "that was situational" — delete the entry entirely (no archive).
295
+
296
+ ## Cross-References Between Tier Files
297
+
298
+ When writing a new entry (ADD or UPDATE), check if the topic relates to entries in OTHER tier files. If it does, add an inline cross-reference.
299
+
300
+ ### Format
301
+
302
+ ```markdown
303
+ - Prefers tabs over spaces <!-- type:preference topics:code-style --> [see also: project-context.md#code-conventions]
304
+ ```
305
+
306
+ ### Trigger Heuristic
307
+
308
+ Add a cross-reference when ANY of these conditions are true:
309
+ 1. The new entry shares a topic tag with an existing entry in a different tier file
310
+ 2. The new entry references the same person, tool, or system as an entry in a different tier file
311
+ 3. The new entry is a decision that was discussed in a conversation thread (preference <-> conversation link)
312
+
313
+ ### Rules
314
+ - Maximum 1 cross-reference per entry (keep it lightweight)
315
+ - Use the format `[see also: FILENAME#SECTION-HEADING]` where SECTION-HEADING is the nearest markdown heading above the related entry
316
+ - Cross-references are one-directional — no need to update the target file
317
+ - Do NOT add cross-references to MEMORY.md entries
318
+
319
+ ## Procedure
320
+
321
+ For each memory candidate:
322
+
323
+ 0. **Detect corrections** — Before classifying memory candidates, check if the user's message contains a correction pattern (see Proactive Rejection Detection above). If a structural correction is found, generate a REJECTION candidate and proceed through steps 1-7 with it.
324
+ 1. **Classify** — Which tier does this belong to? If unclear, skip (NOOP).
325
+ 2. **Read** — Load the target tier file using the Read tool.
326
+ 3. **Search** — Scan existing entries for related content on the same topic.
327
+ 4. **Decide operation** — Based on the search results, choose: ADD, UPDATE, ARCHIVE, or NOOP.
328
+ 5. **Check cross-references** — Does this memory relate to entries in OTHER tier files? If so, add a cross-reference per the Cross-References section above.
329
+ 6. **Execute** — Perform the chosen operation:
330
+ - ADD: Append new entry with metadata
331
+ - UPDATE: Edit existing entry in-place, update metadata if needed
332
+ - ARCHIVE: Move old entry to archive/ with supersession link, then ADD replacement
333
+ - NOOP: Do nothing
334
+ 7. **Summarize** — Track operation type and tier for the output summary.
335
+
336
+ ## Output Format
337
+
338
+ **Manual invocation (with or without args):**
339
+ > Saved 3 memories: 1 ADD (preference), 1 UPDATE (project context), 1 ARCHIVE (conversation). 1 NOOP.
340
+
341
+ Or if nothing found:
342
+ > Nothing new to save.
343
+
344
+ **SessionEnd/PreCompact hook context:**
345
+ Silent — no output. Perform all judgment and writes silently.
346
+
347
+ ## Post-Write Hook
348
+
349
+ **Direct Mode only** — skip this section entirely in MCP Mode (the server handles graph rebuilds).
350
+
351
+ After writing to any memory tier file (preferences.md, project-context.md, conversations.md), you may optionally run a graph/index build script if your project has one configured, e.g.:
352
+
353
+ ```bash
354
+ node path/to/your-graph-build-script.js 2>/dev/null || true
355
+ ```
356
+
357
+ This is a best-effort rebuild — if no such script is present, silently continue.