@danielmarbach/mnemonic-mcp 0.2.0 → 0.3.1

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,25 @@ All notable changes to `mnemonic` will be documented in this file.
4
4
 
5
5
  The format is loosely based on Keep a Changelog and uses semver-style version headings.
6
6
 
7
+ ## [0.3.1] - 2026-03-11
8
+
9
+ ### Fixed
10
+
11
+ - Path resolution now correctly supports home-directory shorthand (`~`) for user-configurable paths before absolute resolution. `VAULT_PATH` and `CLAUDE_HOME` no longer resolve to accidental cwd-relative paths when configured with tildes.
12
+ - `import-claude-memory` now applies the same home-aware path resolution to CLI options (`--cwd`, `--claude-home`) for consistent behavior across absolute and home-based paths.
13
+
14
+ ## [0.3.0] - 2026-03-10
15
+
16
+ ### Added
17
+
18
+ - `recall` now backfills missing and stale embeddings on demand before searching. Notes that arrived via `git pull` without a local embedding, or that were edited directly in an editor after their embedding was written, are re-embedded automatically. If Ollama is unavailable the backfill fails silently and recall continues with existing embeddings.
19
+
20
+ ### Fixed
21
+
22
+ - `parseNote` in `Storage` now converts gray-matter `Date` objects to ISO strings for `createdAt` and `updatedAt`. YAML frontmatter with unquoted ISO timestamps is parsed by gray-matter as JS `Date` instances; notes arriving via `git pull` from another machine were affected, causing output validation errors on recall.
23
+ - `pushWithStatus` in `GitOps` now returns `{ status: "failed", error }` instead of throwing on push failure. Previously, any push error caused mutating MCP tools (`remember`, `update`, `consolidate`, etc.) to return `isError: true` even though the note was committed successfully. The `PersistenceStatus` schema gains a `"failed"` push status and a `pushError` field to surface the failure detail without blocking the operation.
24
+ - `consolidate` `execute-merge` now reuses an existing consolidated target note on retry when the same source notes already point to the same `supersedes` target with the same title. This prevents duplicate consolidated notes after partial-success retry flows and keeps repeated merge attempts idempotent without requiring caller-supplied ids.
25
+
7
26
  ## [0.2.0] - 2026-03-10
8
27
 
9
28
  ### Added
package/README.md CHANGED
@@ -84,7 +84,7 @@ Packages are published to the public npm registry. No authentication required.
84
84
  npm install @danielmarbach/mnemonic-mcp
85
85
 
86
86
  # Specific release
87
- npm install @danielmarbach/mnemonic-mcp@0.1.0
87
+ npm install @danielmarbach/mnemonic-mcp@0.2.0
88
88
  ```
89
89
 
90
90
  ## MCP client config
@@ -369,6 +369,14 @@ No. The embeddings here are **local vector representations** generated by Ollama
369
369
 
370
370
  When you call `recall` with `cwd`, mnemonic adds a fixed **+0.15 boost** to the cosine similarity score of every note belonging to the detected project. This is a soft boost, not a hard filter — global memories are still included when relevant. The boost ensures project-specific context floats to the top when you're working inside a repo while cross-project knowledge remains accessible further down the list.
371
371
 
372
+ **How does mnemonic differ from Beads?**
373
+
374
+ mnemonic and Beads address complementary concerns. mnemonic is a **knowledge graph**: it stores notes, relationships between them, and lets agents retrieve relevant context through semantic search. [Beads](https://github.com/steveyegge/beads) is a **task and dependency tracker**: it models work items and their dependencies so agents can determine what is ready to execute next. Both tools can coexist in the same workflow — mnemonic stores knowledge and reasoning while Beads manages execution.
375
+
376
+ **What are temporary notes?**
377
+
378
+ mnemonic distinguishes between two lifecycle states. `temporary` notes capture evolving working-state: hypotheses, in-progress plans, experiment results, draft reasoning. `permanent` notes capture durable knowledge: decisions, root cause explanations, architectural guidance, lessons learned. As an investigation progresses, a cluster of temporary notes is typically `consolidate`d into one or more permanent notes, and the scaffolding is discarded. This two-phase lifecycle keeps exploratory thinking from polluting long-term memory while still giving agents a place to reason incrementally before committing to a conclusion.
379
+
372
380
  ## Repository layout
373
381
 
374
382
  ```
package/build/git.d.ts CHANGED
@@ -15,8 +15,9 @@ export interface CommitResult {
15
15
  reason?: "git-disabled" | "no-changes";
16
16
  }
17
17
  export interface PushResult {
18
- status: "pushed" | "skipped";
18
+ status: "pushed" | "skipped" | "failed";
19
19
  reason?: "git-disabled" | "no-remote" | "auto-push-disabled";
20
+ error?: string;
20
21
  }
21
22
  export declare class GitOps {
22
23
  private git;
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAEA,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,SAAS,EAAE,QAAQ,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO;CAKzD;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,2CAA2C;IAC3C,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,cAAc,GAAG,YAAY,CAAC;CACxC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,MAAM,CAAC,EAAE,cAAc,GAAG,WAAW,GAAG,oBAAoB,CAAC;CAC9D;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,OAAO,CAAU;gBAEb,OAAO,EAAE,MAAM,EAAE,WAAW,GAAE,MAAgB;IAMpD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B;;;;;;;;;;;;;;;;;;OAkBG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKzE,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAwB9F;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IA6BjC,uEAAuE;IACjE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,cAAc,IAAI,OAAO,CAAC,UAAU,CAAC;YAgB7B,WAAW;YASX,oBAAoB;IASlC;;;OAGG;YACW,cAAc;CAuC7B"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAEA,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,SAAS,EAAE,QAAQ,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO;CAKzD;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,2CAA2C;IAC3C,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,cAAc,GAAG,YAAY,CAAC;CACxC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC,MAAM,CAAC,EAAE,cAAc,GAAG,WAAW,GAAG,oBAAoB,CAAC;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,OAAO,CAAU;gBAEb,OAAO,EAAE,MAAM,EAAE,WAAW,GAAE,MAAgB;IAMpD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B;;;;;;;;;;;;;;;;;;OAkBG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKzE,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAwB9F;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IA6BjC,uEAAuE;IACjE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,cAAc,IAAI,OAAO,CAAC,UAAU,CAAC;YAiB7B,WAAW;YASX,oBAAoB;IASlC;;;OAGG;YACW,cAAc;CAuC7B"}
package/build/git.js CHANGED
@@ -129,8 +129,9 @@ export class GitOps {
129
129
  return { status: "pushed" };
130
130
  }
131
131
  catch (err) {
132
- console.error(`[git] Push failed: ${err}`);
133
- throw new GitOperationError("push", err);
132
+ const message = err instanceof Error ? err.message : String(err);
133
+ console.error(`[git] Push failed: ${message}`);
134
+ return { status: "failed", error: message };
134
135
  }
135
136
  }
136
137
  // ── Private helpers ──────────────────────────────────────────────────────────
package/build/git.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
package/build/index.js CHANGED
@@ -17,12 +17,13 @@ import { detectProject, resolveProjectIdentity } from "./project.js";
17
17
  import { VaultManager } from "./vault.js";
18
18
  import { Migrator } from "./migration.js";
19
19
  import { parseMemorySections } from "./import.js";
20
+ import { defaultClaudeHome, defaultVaultPath, resolveUserPath } from "./paths.js";
20
21
  import { RememberResultSchema, RecallResultSchema, ListResultSchema, GetResultSchema, UpdateResultSchema, ForgetResultSchema, MoveResultSchema, RelateResultSchema, RecentResultSchema, MemoryGraphResultSchema, ProjectSummaryResultSchema, SyncResultSchema, WhereIsResultSchema, ConsolidateResultSchema, ProjectIdentityResultSchema, MigrationListResultSchema, MigrationExecuteResultSchema, PolicyResultSchema, } from "./structured-content.js";
21
22
  // ── CLI Migration Command ─────────────────────────────────────────────────────
22
23
  if (process.argv[2] === "migrate") {
23
24
  const VAULT_PATH = process.env["VAULT_PATH"]
24
- ? path.resolve(process.env["VAULT_PATH"])
25
- : path.join(process.env["HOME"] ?? "~", "mnemonic-vault");
25
+ ? resolveUserPath(process.env["VAULT_PATH"])
26
+ : defaultVaultPath();
26
27
  async function runMigrationCli() {
27
28
  const cwd = process.cwd();
28
29
  const argv = process.argv.slice(3);
@@ -129,13 +130,12 @@ Examples:
129
130
  }
130
131
  // ── CLI: import-claude-memory ─────────────────────────────────────────────────
131
132
  if (process.argv[2] === "import-claude-memory") {
132
- const homeDir = process.env["HOME"] ?? process.env["USERPROFILE"] ?? "~";
133
133
  const VAULT_PATH = process.env["VAULT_PATH"]
134
- ? path.resolve(process.env["VAULT_PATH"])
135
- : path.join(homeDir, "mnemonic-vault");
134
+ ? resolveUserPath(process.env["VAULT_PATH"])
135
+ : defaultVaultPath();
136
136
  const CLAUDE_HOME = process.env["CLAUDE_HOME"]
137
- ? path.resolve(process.env["CLAUDE_HOME"])
138
- : path.join(homeDir, ".claude");
137
+ ? resolveUserPath(process.env["CLAUDE_HOME"])
138
+ : defaultClaudeHome();
139
139
  function makeImportNoteId(title) {
140
140
  const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
141
141
  const suffix = randomUUID().split("-")[0];
@@ -173,9 +173,9 @@ Examples:
173
173
  }
174
174
  const dryRun = argv.includes("--dry-run");
175
175
  const cwdOption = argv.find(arg => arg.startsWith("--cwd="));
176
- const targetCwd = cwdOption ? path.resolve(cwdOption.split("=")[1]) : process.cwd();
176
+ const targetCwd = cwdOption ? resolveUserPath(cwdOption.split("=")[1]) : process.cwd();
177
177
  const claudeHomeOption = argv.find(arg => arg.startsWith("--claude-home="));
178
- const claudeHome = claudeHomeOption ? path.resolve(claudeHomeOption.split("=")[1]) : CLAUDE_HOME;
178
+ const claudeHome = claudeHomeOption ? resolveUserPath(claudeHomeOption.split("=")[1]) : CLAUDE_HOME;
179
179
  // Encode the project path the same way Claude Code does:
180
180
  // /Users/foo/Projects/bar → -Users-foo-Projects-bar
181
181
  // On Windows both \ and / are replaced with -
@@ -273,8 +273,8 @@ Examples:
273
273
  }
274
274
  // ── Config ────────────────────────────────────────────────────────────────────
275
275
  const VAULT_PATH = process.env["VAULT_PATH"]
276
- ? path.resolve(process.env["VAULT_PATH"])
277
- : path.join(process.env["HOME"] ?? "~", "mnemonic-vault");
276
+ ? resolveUserPath(process.env["VAULT_PATH"])
277
+ : defaultVaultPath();
278
278
  const DEFAULT_RECALL_LIMIT = 5;
279
279
  const DEFAULT_MIN_SIMILARITY = 0.3;
280
280
  async function readPackageVersion() {
@@ -464,7 +464,7 @@ async function embedMissingNotes(storage, noteIds, force = false) {
464
464
  }
465
465
  if (!force) {
466
466
  const existing = await storage.readEmbedding(note.id);
467
- if (existing?.model === embedModel) {
467
+ if (existing?.model === embedModel && existing.updatedAt >= note.updatedAt) {
468
468
  continue;
469
469
  }
470
470
  }
@@ -542,6 +542,7 @@ function buildPersistenceStatus(args) {
542
542
  commitBody: args.commitBody,
543
543
  commitReason: args.commit.reason,
544
544
  pushReason: args.push.reason,
545
+ pushError: args.push.error,
545
546
  },
546
547
  durability: resolveDurability(args.commit, args.push),
547
548
  };
@@ -1170,7 +1171,8 @@ server.registerTool("recall", {
1170
1171
  description: "Semantic search over memories. " +
1171
1172
  "When `cwd` is provided, searches both the project vault (.mnemonic/) and the " +
1172
1173
  "main vault — project memories are boosted by +0.15 and shown first. " +
1173
- "Without `cwd`, searches only the main vault.",
1174
+ "Without `cwd`, searches only the main vault. " +
1175
+ "Missing or stale embeddings (e.g. from a git pull or direct editor edit) are backfilled on demand before searching.",
1174
1176
  inputSchema: z.object({
1175
1177
  query: z.string().describe("What to search for"),
1176
1178
  cwd: projectParam,
@@ -1190,6 +1192,9 @@ server.registerTool("recall", {
1190
1192
  const project = await resolveProject(cwd);
1191
1193
  const queryVec = await embed(query);
1192
1194
  const vaults = await vaultManager.searchOrder(cwd);
1195
+ for (const vault of vaults) {
1196
+ await embedMissingNotes(vault.storage).catch(() => { });
1197
+ }
1193
1198
  const scored = [];
1194
1199
  for (const vault of vaults) {
1195
1200
  const embeddings = await vault.storage.listEmbeddings();
@@ -2414,8 +2419,9 @@ async function executeMerge(entries, mergePlan, defaultConsolidationMode, projec
2414
2419
  sourceEntries.push(entry);
2415
2420
  }
2416
2421
  const consolidationMode = resolveEffectiveConsolidationMode(sourceEntries.map((entry) => entry.note), defaultConsolidationMode, explicitMode);
2422
+ const existingTargetEntry = findExistingExecuteMergeTarget(entries, sourceEntries, targetTitle);
2417
2423
  const projectVault = cwd ? await vaultManager.getOrCreateProjectVault(cwd) : null;
2418
- const targetVault = projectVault ?? vaultManager.main;
2424
+ const targetVault = existingTargetEntry?.vault ?? projectVault ?? vaultManager.main;
2419
2425
  const now = new Date().toISOString();
2420
2426
  // Build consolidated content
2421
2427
  const sections = [];
@@ -2444,9 +2450,12 @@ async function executeMerge(entries, mergePlan, defaultConsolidationMode, projec
2444
2450
  const combinedTags = tags ?? Array.from(new Set(sourceEntries.flatMap((e) => e.note.tags)));
2445
2451
  // Collect all unique relationships from sources (excluding relationships among sources)
2446
2452
  const sourceIdsSet = new Set(sourceIds);
2447
- const allRelationships = mergeRelationshipsFromNotes(sourceEntries.map((entry) => entry.note), sourceIdsSet);
2448
- // Create consolidated note
2449
- const targetId = makeId(targetTitle);
2453
+ const relationshipSources = existingTargetEntry
2454
+ ? [...sourceEntries.map((entry) => entry.note), existingTargetEntry.note]
2455
+ : sourceEntries.map((entry) => entry.note);
2456
+ const allRelationships = mergeRelationshipsFromNotes(relationshipSources, sourceIdsSet);
2457
+ // Create or update the consolidated note
2458
+ const targetId = existingTargetEntry?.note.id ?? makeId(targetTitle);
2450
2459
  const consolidatedNote = {
2451
2460
  id: targetId,
2452
2461
  title: targetTitle,
@@ -2456,7 +2465,7 @@ async function executeMerge(entries, mergePlan, defaultConsolidationMode, projec
2456
2465
  project: project?.id,
2457
2466
  projectName: project?.name,
2458
2467
  relatedTo: allRelationships,
2459
- createdAt: now,
2468
+ createdAt: existingTargetEntry?.note.createdAt ?? now,
2460
2469
  updatedAt: now,
2461
2470
  memoryVersion: 1,
2462
2471
  };
@@ -2580,6 +2589,9 @@ async function executeMerge(entries, mergePlan, defaultConsolidationMode, projec
2580
2589
  lines.push(`Consolidated ${sourceIds.length} notes into '${targetId}'`);
2581
2590
  lines.push(`Mode: ${consolidationMode}`);
2582
2591
  lines.push(`Stored in: ${targetVault.isProject ? "project-vault" : "main-vault"}`);
2592
+ if (existingTargetEntry) {
2593
+ lines.push("Idempotency: reused existing target note.");
2594
+ }
2583
2595
  lines.push(formatPersistenceSummary(persistence));
2584
2596
  switch (consolidationMode) {
2585
2597
  case "supersedes":
@@ -2605,6 +2617,33 @@ async function executeMerge(entries, mergePlan, defaultConsolidationMode, projec
2605
2617
  };
2606
2618
  return { content: [{ type: "text", text: lines.join("\n") }], structuredContent };
2607
2619
  }
2620
+ function findExistingExecuteMergeTarget(entries, sourceEntries, targetTitle) {
2621
+ const normalizedTitle = targetTitle.trim();
2622
+ const targetSlug = slugify(normalizedTitle);
2623
+ const sourceIds = new Set(sourceEntries.map((entry) => entry.note.id));
2624
+ let sharedTargetIds;
2625
+ for (const entry of sourceEntries) {
2626
+ const supersededTargetIds = new Set((entry.note.relatedTo ?? [])
2627
+ .filter((rel) => rel.type === "supersedes")
2628
+ .map((rel) => rel.id)
2629
+ .filter((id) => !sourceIds.has(id)));
2630
+ if (supersededTargetIds.size === 0) {
2631
+ return undefined;
2632
+ }
2633
+ sharedTargetIds = sharedTargetIds
2634
+ ? new Set([...sharedTargetIds].filter((id) => supersededTargetIds.has(id)))
2635
+ : supersededTargetIds;
2636
+ if (sharedTargetIds.size === 0) {
2637
+ return undefined;
2638
+ }
2639
+ }
2640
+ const candidates = entries
2641
+ .filter((entry) => sharedTargetIds?.has(entry.note.id))
2642
+ .filter((entry) => entry.note.title.trim() === normalizedTitle)
2643
+ .filter((entry) => !targetSlug || entry.note.id === targetSlug || entry.note.id.startsWith(`${targetSlug}-`))
2644
+ .sort((left, right) => right.note.updatedAt.localeCompare(left.note.updatedAt));
2645
+ return candidates[0];
2646
+ }
2608
2647
  async function pruneSuperseded(entries, consolidationMode, project) {
2609
2648
  if (consolidationMode !== "delete") {
2610
2649
  const structuredContent = {