claude-launchpad 1.0.0 → 1.1.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 (38) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-GRL3DOCP.js → chunk-F5PNKQKW.js} +16 -3
  3. package/dist/chunk-F5PNKQKW.js.map +1 -0
  4. package/dist/{chunk-ZXJK7CHB.js → chunk-FQRM2BKL.js} +3 -3
  5. package/dist/{chunk-PGDSAUP4.js → chunk-LYLUXVWT.js} +2 -2
  6. package/dist/{chunk-TSTTFR4B.js → chunk-N6X3E5AX.js} +2 -2
  7. package/dist/{chunk-AUV2JTXX.js → chunk-ULYVGZCJ.js} +2 -2
  8. package/dist/{chunk-4JNFXVVC.js → chunk-UN23WZVQ.js} +2 -1
  9. package/dist/chunk-UN23WZVQ.js.map +1 -0
  10. package/dist/cli.js +23 -14
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/memory/server.js +24 -19
  13. package/dist/commands/memory/server.js.map +1 -1
  14. package/dist/{context-Q5ZQBY7O.js → context-5AV2WCYW.js} +5 -5
  15. package/dist/{install-LS7DTMIE.js → install-6VOUHJTI.js} +5 -5
  16. package/dist/{pull-4NRD4GQ4.js → pull-KRU2DRPZ.js} +8 -8
  17. package/dist/{push-BHYEETGP.js → push-KCT2J6FR.js} +8 -8
  18. package/dist/{require-deps-3GIE6TAG.js → require-deps-DVEP4QBF.js} +3 -3
  19. package/dist/{stats-NQ5NRUZC.js → stats-7K6GKTVB.js} +6 -6
  20. package/dist/{sync-clean-QWEQVAYO.js → sync-clean-P75QVF5Z.js} +2 -2
  21. package/dist/{sync-status-ZMXMEBGC.js → sync-status-QF6QK3NN.js} +8 -8
  22. package/dist/{tui-YL5NWME5.js → tui-QNOPH3I5.js} +4 -4
  23. package/package.json +1 -1
  24. package/dist/chunk-4JNFXVVC.js.map +0 -1
  25. package/dist/chunk-GRL3DOCP.js.map +0 -1
  26. /package/dist/{chunk-ZXJK7CHB.js.map → chunk-FQRM2BKL.js.map} +0 -0
  27. /package/dist/{chunk-PGDSAUP4.js.map → chunk-LYLUXVWT.js.map} +0 -0
  28. /package/dist/{chunk-TSTTFR4B.js.map → chunk-N6X3E5AX.js.map} +0 -0
  29. /package/dist/{chunk-AUV2JTXX.js.map → chunk-ULYVGZCJ.js.map} +0 -0
  30. /package/dist/{context-Q5ZQBY7O.js.map → context-5AV2WCYW.js.map} +0 -0
  31. /package/dist/{install-LS7DTMIE.js.map → install-6VOUHJTI.js.map} +0 -0
  32. /package/dist/{pull-4NRD4GQ4.js.map → pull-KRU2DRPZ.js.map} +0 -0
  33. /package/dist/{push-BHYEETGP.js.map → push-KCT2J6FR.js.map} +0 -0
  34. /package/dist/{require-deps-3GIE6TAG.js.map → require-deps-DVEP4QBF.js.map} +0 -0
  35. /package/dist/{stats-NQ5NRUZC.js.map → stats-7K6GKTVB.js.map} +0 -0
  36. /package/dist/{sync-clean-QWEQVAYO.js.map → sync-clean-P75QVF5Z.js.map} +0 -0
  37. /package/dist/{sync-status-ZMXMEBGC.js.map → sync-status-QF6QK3NN.js.map} +0 -0
  38. /package/dist/{tui-YL5NWME5.js.map → tui-QNOPH3I5.js.map} +0 -0
@@ -6,8 +6,9 @@ import {
6
6
  import {
7
7
  MEMORY_SOURCES,
8
8
  MEMORY_TYPES,
9
- RELATION_TYPES
10
- } from "../../chunk-GRL3DOCP.js";
9
+ RELATION_TYPES,
10
+ coerceStringArray
11
+ } from "../../chunk-F5PNKQKW.js";
11
12
  import {
12
13
  detectProject
13
14
  } from "../../chunk-NAW47BYA.js";
@@ -23,9 +24,9 @@ import {
23
24
  loadConfig,
24
25
  migrate,
25
26
  resolveDataDir
26
- } from "../../chunk-ZXJK7CHB.js";
27
- import "../../chunk-PGDSAUP4.js";
28
- import "../../chunk-4JNFXVVC.js";
27
+ } from "../../chunk-FQRM2BKL.js";
28
+ import "../../chunk-LYLUXVWT.js";
29
+ import "../../chunk-UN23WZVQ.js";
29
30
 
30
31
  // src/commands/memory/server.ts
31
32
  import { createRequire } from "module";
@@ -471,17 +472,17 @@ var inputSchema = {
471
472
  type: z.enum(MEMORY_TYPES).describe("Memory type: working, episodic, semantic, procedural, or pattern"),
472
473
  content: z.string().min(1).describe("The memory content (aim for ~2000 chars / ~500 tokens). Keep memories concise: capture the decision or insight, not the full context. Split large topics into separate memories."),
473
474
  title: z.string().max(200).optional().describe("Short title for the memory"),
474
- tags: z.array(z.string()).max(20).default([]).describe("Tags for categorization. Suggested: #bug, #decision, #gotcha, #howto, #pattern"),
475
+ tags: coerceStringArray.pipe(z.array(z.string()).max(20)).default([]).describe("Tags for categorization. Suggested: #bug, #decision, #gotcha, #howto, #pattern"),
475
476
  importance: z.number().min(0).max(1).default(0.5).describe("0-0.3 ephemeral, 0.3-0.6 reference, 0.6-0.8 important, 0.8-1.0 critical"),
476
477
  context: z.string().optional().describe('JSON: {"files": [...], "branch": "...", "intent": "..."}. Auto-detected from git if omitted.'),
477
478
  source: z.enum(MEMORY_SOURCES).default("manual").describe("How this memory was created"),
478
- project: z.string().max(200).optional().describe("Project scope (auto-detected from CWD if omitted)")
479
+ project: z.string().max(200).optional().describe("Project scope. Omit to auto-detect from CWD (default). Pass a project name to scope the memory to that project. Omit for global/cross-project memories.")
479
480
  };
480
481
  function registerStore(server, deps) {
481
482
  server.registerTool(
482
483
  "memory_store",
483
484
  {
484
- description: 'Save something worth remembering to the knowledge base. Use when you learn a fact, make a decision, hit a bug, or discover a pattern that future sessions should know. Always search first to avoid duplicates \u2014 update existing memories when possible. Types: semantic (facts/decisions), procedural (how-to), episodic (what happened), pattern (recurring), working (scratch). Importance: 0.1 trivial, 0.5 useful, 0.8 important, 1.0 critical. Tags and git context are auto-detected if omitted. "Skipped" responses mean a duplicate was caught \u2014 not an error.',
485
+ description: 'Save something worth remembering to the knowledge base. Use when you learn a fact, make a decision, hit a bug, or discover a pattern that future sessions should know. Always search first to avoid duplicates \u2014 update existing memories when possible. Types: semantic (facts/decisions), procedural (how-to), episodic (what happened), pattern (recurring), working (scratch). Importance: 0.1 trivial, 0.5 useful, 0.8 important, 1.0 critical. Tags and git context are auto-detected if omitted. "OK" responses mean the memory already exists \u2014 no follow-up needed.',
485
486
  inputSchema,
486
487
  annotations: { idempotentHint: false }
487
488
  },
@@ -503,12 +504,12 @@ function registerStore(server, deps) {
503
504
  const lastStored = recentStores.get(contentHash);
504
505
  if (lastStored && now - lastStored < DEDUP_WINDOW_MS) {
505
506
  return {
506
- content: [{ type: "text", text: "Skipped: identical memory already exists (stored moments ago)." }]
507
+ content: [{ type: "text", text: "OK: this memory already exists in the knowledge base (duplicate detected). No action needed." }]
507
508
  };
508
509
  }
509
510
  if (pendingStores.has(contentHash)) {
510
511
  return {
511
- content: [{ type: "text", text: "Skipped: identical memory is being stored by another call." }]
512
+ content: [{ type: "text", text: "OK: this memory is already being stored by a parallel call. No action needed." }]
512
513
  };
513
514
  }
514
515
  pendingStores.add(contentHash);
@@ -550,7 +551,7 @@ function registerStore(server, deps) {
550
551
  pendingStores.delete(contentHash);
551
552
  if (!memory) {
552
553
  return {
553
- content: [{ type: "text", text: "Skipped: identical memory already exists in the knowledge base." }]
554
+ content: [{ type: "text", text: "OK: this memory already exists in the knowledge base (content_hash match). No action needed." }]
554
555
  };
555
556
  }
556
557
  for (const c of contradictions) {
@@ -584,19 +585,21 @@ var inputSchema2 = {
584
585
  query: z2.string().min(1).max(500).describe("Search query (natural language or keywords)"),
585
586
  id: z2.string().optional().describe("Direct lookup by memory ID (bypasses search)"),
586
587
  type: z2.enum(MEMORY_TYPES).optional().describe("Filter by memory type"),
587
- tags: z2.array(z2.string()).max(10).optional().describe("Filter to memories containing ALL of these tags"),
588
+ tags: coerceStringArray.pipe(z2.array(z2.string()).max(10)).optional().describe("Filter to memories containing ALL of these tags"),
588
589
  limit: z2.number().int().min(1).max(50).default(10).describe("Maximum results to return"),
589
- min_importance: z2.number().min(0).max(1).default(0).describe("Minimum importance threshold")
590
+ min_importance: z2.number().min(0).max(1).default(0).describe("Minimum importance threshold"),
591
+ project: z2.string().max(200).optional().describe('Project scope. Omit to search current project + global memories (default). Pass "*" to search ALL projects. Pass a project name to search that specific project + global memories.')
590
592
  };
591
593
  function registerSearch(server, deps) {
592
594
  server.registerTool(
593
595
  "memory_search",
594
596
  {
595
- description: "Look up what you already know. Query the knowledge base before solving a problem or storing new information. Use when: checking if something was already decided, finding how-to steps, recalling past bugs, or deduping before a store. Related memories are surfaced automatically. Pass `id` for direct lookup, or filter by `type` and `tags`.",
597
+ description: 'Look up what you already know. Query the knowledge base before solving a problem or storing new information. Use when: checking if something was already decided, finding how-to steps, recalling past bugs, or deduping before a store. Related memories are surfaced automatically. Pass `id` for direct lookup, or filter by `type` and `tags`. Project scoping: by default, returns memories for the current project + global (unscoped) memories. Pass project="*" to search across all projects. Pass a specific project name to search that project instead.',
596
598
  inputSchema: inputSchema2,
597
599
  annotations: { readOnlyHint: true, idempotentHint: true }
598
600
  },
599
601
  async (args) => {
602
+ const project = args.project === "*" ? void 0 : args.project ?? deps.project ?? void 0;
600
603
  const results = await deps.retrievalService.search({
601
604
  query: args.query,
602
605
  id: args.id,
@@ -604,7 +607,7 @@ function registerSearch(server, deps) {
604
607
  tags: args.tags,
605
608
  limit: args.limit,
606
609
  min_importance: args.min_importance,
607
- project: deps.project ?? void 0
610
+ project
608
611
  });
609
612
  if (results.length === 0) {
610
613
  return {
@@ -812,20 +815,22 @@ function registerStats(server, deps) {
812
815
  import { z as z5 } from "zod";
813
816
  var inputSchema5 = {
814
817
  limit: z5.number().int().min(1).max(50).default(10).describe("Maximum memories to return"),
815
- type: z5.enum(MEMORY_TYPES).optional().describe("Filter by memory type")
818
+ type: z5.enum(MEMORY_TYPES).optional().describe("Filter by memory type"),
819
+ project: z5.string().max(200).optional().describe('Project scope. Omit for current project + global memories (default). Pass "*" for ALL projects. Pass a project name for that specific project.')
816
820
  };
817
821
  function registerRecent(server, deps) {
818
822
  server.registerTool(
819
823
  "memory_recent",
820
824
  {
821
- description: "Get caught up on what happened before this session. Returns memories relevant to the current branch/files, recent activity, and related context. Typically called at session start to restore working context. No query needed \u2014 it uses git state to find what matters.",
825
+ description: 'Get caught up on what happened before this session. Returns memories relevant to the current branch/files, recent activity, and related context. Typically called at session start to restore working context. No query needed \u2014 it uses git state to find what matters. Project scoping: by default, returns memories for the current project + global memories. Pass project="*" to include all projects.',
822
826
  inputSchema: inputSchema5,
823
827
  annotations: { readOnlyHint: true, idempotentHint: true }
824
828
  },
825
829
  async (args) => {
830
+ const project = args.project === "*" ? void 0 : args.project ?? deps.project ?? void 0;
826
831
  const results = deps.retrievalService.loadSessionContext({
827
832
  limit: args.limit,
828
- project: deps.project ?? void 0,
833
+ project,
829
834
  type: args.type
830
835
  });
831
836
  if (results.length === 0) {
@@ -865,7 +870,7 @@ var inputSchema6 = {
865
870
  id: z6.string().describe("Memory ID to update (use memory_search to find it)"),
866
871
  title: z6.string().max(200).optional().describe("Updated title"),
867
872
  content: z6.string().min(1).max(1e4).optional().describe("Updated content"),
868
- tags: z6.array(z6.string()).max(20).optional().describe("Updated tags"),
873
+ tags: coerceStringArray.pipe(z6.array(z6.string()).max(20)).optional().describe("Updated tags"),
869
874
  importance: z6.number().min(0).max(1).optional().describe("Updated importance (0-1)"),
870
875
  context: z6.string().optional().describe("Updated context JSON")
871
876
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/memory/server.ts","../../../src/commands/memory/services/retrieval-service.ts","../../../src/commands/memory/tools/store.ts","../../../src/commands/memory/utils/content-validation.ts","../../../src/commands/memory/utils/contradiction.ts","../../../src/commands/memory/tools/search.ts","../../../src/commands/memory/tools/forget.ts","../../../src/commands/memory/utils/errors.ts","../../../src/commands/memory/tools/relate.ts","../../../src/commands/memory/tools/stats.ts","../../../src/commands/memory/tools/recent.ts","../../../src/commands/memory/tools/update.ts","../../../src/commands/memory/tools/register.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nconst require = createRequire(import.meta.url);\nconst { version } = require('../../../package.json') as { version: string };\nimport { createDatabase, closeDatabase } from './storage/database.js';\nimport { migrate } from './storage/migrator.js';\nimport { MemoryRepo } from './storage/memory-repo.js';\nimport { RelationRepo } from './storage/relation-repo.js';\nimport { SearchRepo } from './storage/search-repo.js';\nimport { RetrievalService } from './services/retrieval-service.js';\nimport { loadConfig, resolveDataDir } from './config.js';\nimport type { Config } from './config.js';\nimport { registerTools } from './tools/register.js';\nimport { detectProject } from './utils/project.js';\n\nexport interface ServerDeps {\n readonly config: Config;\n}\n\nexport async function startServer(deps?: Partial<ServerDeps>): Promise<void> {\n const config = deps?.config ?? loadConfig();\n const dataDir = resolveDataDir(config.dataDir);\n\n const db = createDatabase({ dataDir });\n migrate(db);\n\n const memoryRepo = new MemoryRepo(db);\n const relationRepo = new RelationRepo(db);\n const searchRepo = new SearchRepo(db);\n\n const retrievalService = new RetrievalService({\n memoryRepo,\n relationRepo,\n searchRepo,\n });\n\n const server = new McpServer(\n { name: 'agentic-memory', version },\n {\n instructions:\n 'This is your knowledge base — persistent context that survives across sessions. '\n + 'Search before storing to avoid duplicates. Update existing memories instead of creating new ones. '\n + 'Store decisions, patterns, and insights — capture WHY, not just WHAT. '\n + 'Only save what future sessions will need. NEVER store secrets, API keys, or passwords. '\n + 'Session context is injected automatically at startup — no need to call memory_recent.',\n },\n );\n\n const project = detectProject(process.cwd());\n\n registerTools(server, { memoryRepo, relationRepo, retrievalService, dataDir, project });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n const shutdown = async () => {\n await server.close();\n closeDatabase(db);\n process.exit(0);\n };\n process.on('SIGINT', () => void shutdown());\n process.on('SIGTERM', () => void shutdown());\n}\n\n// Auto-start when invoked directly as MCP server entry point\nstartServer().catch((err) => {\n process.stderr.write(`[agentic-memory] ${err}\\n`);\n process.exit(1);\n});\n","import type { Memory, MemoryType, SearchResult, SearchInput, RelationType } from '../types.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport type { SearchRepo } from '../storage/search-repo.js';\nimport { SCORING_WEIGHTS } from '../config.js';\nimport { type GitContext, getGitContext, computeContextScore } from '../utils/git-context.js';\n\nconst STALENESS_THRESHOLDS = {\n working: 1,\n episodic: 7,\n pattern: 14,\n semantic: 30,\n procedural: 90,\n} as const;\n\nexport interface RetrievalDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly searchRepo: SearchRepo;\n readonly gitContext?: GitContext;\n}\n\nexport class RetrievalService {\n readonly #deps: RetrievalDeps;\n readonly #gitContext: GitContext;\n\n constructor(deps: RetrievalDeps) {\n this.#deps = deps;\n this.#gitContext = deps.gitContext ?? getGitContext();\n }\n\n /**\n * FTS5 keyword search with multi-signal scoring, context awareness,\n * and relation-based graph expansion.\n */\n async search(input: SearchInput): Promise<readonly SearchResult[]> {\n // Direct ID lookup\n if (input.id) {\n const memory = this.#deps.memoryRepo.getById(input.id);\n if (!memory) return [];\n this.#deps.memoryRepo.incrementAccess(input.id);\n return [{\n memory,\n score: 1.0,\n explanation: 'Direct lookup by ID',\n }];\n }\n\n // Phase 1: FTS5 keyword search\n const ftsResults = this.#deps.searchRepo.searchFts({\n query: input.query,\n limit: input.limit * 3,\n type: input.type,\n minImportance: input.min_importance,\n project: input.project,\n });\n\n const textScores = ftsOnlyScores(ftsResults);\n if (textScores.size === 0) return [];\n\n // Phase 2: Load memories and compute composite scores\n const candidates: { memory: Memory; composite: number; parts: ScoreParts }[] = [];\n\n for (const [memoryId, textScore] of textScores) {\n const memory = this.#deps.memoryRepo.getById(memoryId);\n if (!memory) continue;\n if (input.type && memory.type !== input.type) continue;\n if (memory.importance < input.min_importance) continue;\n if (input.tags?.length) {\n const memTags = new Set(memory.tags);\n if (!input.tags.every(t => memTags.has(t))) continue;\n }\n\n const parts = computeScoreParts(memory, textScore, this.#gitContext, input.query);\n const composite = computeComposite(parts);\n candidates.push({ memory, composite, parts });\n }\n\n // Phase 3: Sort by composite score\n candidates.sort((a, b) => b.composite - a.composite);\n let topN = candidates.slice(0, input.limit);\n\n // Phase 4: Relation expansion — surface connected memories\n const seenIds = new Set(topN.map(c => c.memory.id));\n const expanded = this.#expandWithRelations(topN, input.limit, seenIds, input.min_importance, input.type);\n if (expanded.length > 0) {\n topN = [...topN, ...expanded].sort((a, b) => b.composite - a.composite).slice(0, input.limit);\n }\n\n // Phase 5: Build results with explanations, increment access\n return topN.map(({ memory, composite, parts }) => {\n this.#deps.memoryRepo.incrementAccess(memory.id);\n return {\n memory,\n score: composite,\n explanation: parts.relationSource\n ? `Related (${parts.relationSource.type}) to: ${parts.relationSource.title ?? parts.relationSource.id}`\n : buildExplanation(parts, memory),\n };\n });\n }\n\n /**\n * Smart session loading: returns context-matched, recent, and related memories\n * for session start context injection.\n */\n loadSessionContext(input: {\n readonly limit: number;\n readonly project?: string;\n readonly type?: MemoryType;\n }): readonly SessionContextResult[] {\n const contextBudget = Math.floor(input.limit * 0.4);\n const recentBudget = Math.floor(input.limit * 0.4);\n const relatedBudget = input.limit - contextBudget - recentBudget;\n const seenIds = new Set<string>();\n\n const contextMatched = this.#loadContextMatched(contextBudget, input.project, input.type, seenIds);\n const recent = this.#loadRecent(recentBudget, input.project, input.type, seenIds);\n\n const sourceIds = [...contextMatched, ...recent].map(r => r.result.memory.id);\n const related = this.#loadRelatedExpansion(sourceIds, relatedBudget, seenIds, input.type);\n\n const all = [...contextMatched, ...recent, ...related];\n for (const entry of all) {\n this.#deps.memoryRepo.incrementInjection(entry.result.memory.id);\n }\n return all;\n }\n\n #loadContextMatched(\n budget: number, project?: string, type?: MemoryType, seenIds?: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const candidates = this.#deps.memoryRepo.getRecent(budget * 5, project, type);\n const scored: { memory: Memory; ctxScore: number; composite: number }[] = [];\n\n for (const m of candidates) {\n const ctxScore = computeContextScore(m.context, this.#gitContext, '');\n if (ctxScore <= 0.1) continue;\n const composite = ctxScore * 0.5 + m.importance * 0.3 + computeRecencyScore(m.updatedAt) * 0.2;\n scored.push({ memory: m, ctxScore, composite });\n }\n\n scored.sort((a, b) => b.composite - a.composite);\n const results: SessionContextResult[] = [];\n for (const s of scored.slice(0, budget)) {\n seenIds?.add(s.memory.id);\n results.push({ section: 'context', result: { memory: s.memory, score: s.composite, explanation: 'Context match' } });\n }\n return results;\n }\n\n #loadRecent(\n budget: number, project?: string, type?: MemoryType, seenIds?: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const candidates = this.#deps.memoryRepo.getRecent(budget * 2, project, type);\n const results: SessionContextResult[] = [];\n\n for (const m of candidates) {\n if (seenIds?.has(m.id)) continue;\n const score = m.importance * 0.4 + computeRecencyScore(m.updatedAt) * 0.6;\n seenIds?.add(m.id);\n results.push({ section: 'recent', result: { memory: m, score, explanation: 'Recent' } });\n if (results.length >= budget) break;\n }\n return results;\n }\n\n #loadRelatedExpansion(\n sourceIds: readonly string[], budget: number, seenIds: Set<string>, typeFilter?: MemoryType,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const results: SessionContextResult[] = [];\n\n for (const srcId of sourceIds) {\n const relations = this.#deps.relationRepo.getByMemory(srcId);\n for (const rel of relations) {\n const otherId = rel.sourceId === srcId ? rel.targetId : rel.sourceId;\n if (otherId === srcId || seenIds.has(otherId)) continue;\n\n const other = this.#deps.memoryRepo.getById(otherId);\n if (!other) continue;\n if (typeFilter && other.type !== typeFilter) continue;\n\n const src = this.#deps.memoryRepo.getById(srcId);\n const weight = RELATION_TYPE_WEIGHTS[rel.relationType] ?? 0.5;\n seenIds.add(otherId);\n results.push({\n section: 'related',\n result: {\n memory: other,\n score: other.importance * weight,\n explanation: `Related (${rel.relationType}) to: ${src?.title ?? srcId}`,\n },\n });\n if (results.length >= budget) return results;\n }\n }\n return results;\n }\n\n #expandWithRelations(\n topResults: readonly { memory: Memory; composite: number; parts: ScoreParts }[],\n limit: number,\n seenIds: Set<string>,\n minImportance: number,\n typeFilter?: MemoryType,\n ): { memory: Memory; composite: number; parts: ScoreParts }[] {\n if (topResults.length >= limit) return [];\n\n const expanded: { memory: Memory; composite: number; parts: ScoreParts }[] = [];\n const remaining = limit - topResults.length;\n const sourcesToExpand = topResults.slice(0, 5);\n\n for (const parent of sourcesToExpand) {\n const relations = this.#deps.relationRepo.getByMemory(parent.memory.id);\n for (const rel of relations) {\n const otherId = rel.sourceId === parent.memory.id ? rel.targetId : rel.sourceId;\n if (otherId === parent.memory.id || seenIds.has(otherId)) continue;\n\n const other = this.#deps.memoryRepo.getById(otherId);\n if (!other || other.importance < minImportance) continue;\n if (typeFilter && other.type !== typeFilter) continue;\n\n const weight = RELATION_TYPE_WEIGHTS[rel.relationType] ?? 0.5;\n const composite = parent.composite * 0.7 * weight;\n const parts: ScoreParts = {\n textScore: 0,\n importanceScore: other.importance,\n recencyScore: computeRecencyScore(other.updatedAt),\n accessScore: computeAccessScore(other.accessCount, other.lastAccessed),\n contextScore: 0,\n relationSource: { id: parent.memory.id, title: parent.memory.title, type: rel.relationType },\n };\n\n seenIds.add(otherId);\n expanded.push({ memory: other, composite, parts });\n if (expanded.length >= remaining) return expanded;\n }\n }\n\n return expanded;\n }\n}\n\n// ── Relation Expansion ──────────────────────────────────────\n\nconst RELATION_TYPE_WEIGHTS: Record<RelationType, number> = {\n depends_on: 1.0,\n extends: 0.9,\n implements: 0.9,\n relates_to: 0.7,\n derived_from: 0.6,\n contradicts: 0.3,\n};\n\n// ── FTS5-Only Fallback ───────────────────────────────────────\n\nfunction ftsOnlyScores(ftsResults: readonly { memoryId: string; rank: number }[]): Map<string, number> {\n const scores = new Map<string, number>();\n for (const r of ftsResults) {\n const score = Math.min(1, -r.rank / 20);\n scores.set(r.memoryId, score);\n }\n return scores;\n}\n\n// ── Scoring ───────────────────────────────────────────────────\n\ninterface ScoreParts {\n readonly textScore: number;\n readonly importanceScore: number;\n readonly recencyScore: number;\n readonly accessScore: number;\n readonly contextScore: number;\n readonly relationSource?: { readonly id: string; readonly title: string | null; readonly type: RelationType };\n}\n\nfunction computeScoreParts(\n memory: Memory,\n textScore: number,\n gitContext: GitContext,\n query: string,\n): ScoreParts {\n return {\n textScore,\n importanceScore: memory.importance,\n recencyScore: computeRecencyScore(memory.updatedAt),\n accessScore: computeAccessScore(memory.accessCount, memory.lastAccessed),\n contextScore: computeContextScore(memory.context, gitContext, query),\n };\n}\n\nfunction computeComposite(parts: ScoreParts): number {\n return (\n parts.textScore * SCORING_WEIGHTS.text +\n parts.importanceScore * SCORING_WEIGHTS.importance +\n parts.recencyScore * SCORING_WEIGHTS.recency +\n parts.accessScore * SCORING_WEIGHTS.access +\n parts.contextScore * SCORING_WEIGHTS.context\n );\n}\n\n/**\n * Recency score: 1.0 for today, decays exponentially.\n * Uses a 30-day half-life.\n */\nfunction computeRecencyScore(updatedAt: string): number {\n const ageMs = Date.now() - new Date(updatedAt).getTime();\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n if (ageDays < 0) return 1.0;\n return Math.exp(-ageDays * Math.LN2 / 30);\n}\n\n/**\n * Access score: logarithmic count x recency of last access.\n */\nfunction computeAccessScore(accessCount: number, lastAccessed: string | null): number {\n if (accessCount <= 0) return 0;\n const countScore = Math.min(1.0, Math.log10(accessCount + 1) / Math.log10(31));\n if (!lastAccessed) return countScore * 0.5;\n const ageDays = (Date.now() - new Date(lastAccessed).getTime()) / 86_400_000;\n const recency = Math.exp(-ageDays * Math.LN2 / 30);\n return countScore * (0.5 + 0.5 * recency);\n}\n\n// ── Explanation ───────────────────────────────────────────────\n\nfunction buildExplanation(parts: ScoreParts, memory: Memory): string {\n const factors: string[] = [];\n\n if (parts.textScore > 0.7) {\n factors.push(`High text match (${(parts.textScore * 100).toFixed(0)}%)`);\n } else if (parts.textScore > 0.3) {\n factors.push(`Moderate text match (${(parts.textScore * 100).toFixed(0)}%)`);\n }\n\n if (memory.importance > 0.7) {\n factors.push('High importance');\n }\n\n if (parts.recencyScore > 0.8) {\n factors.push('Very recent');\n } else if (parts.recencyScore > 0.5) {\n factors.push('Recent');\n }\n\n if (memory.accessCount > 10) {\n factors.push(`Frequently accessed (${memory.accessCount}x)`);\n } else if (memory.accessCount > 3) {\n factors.push(`Accessed ${memory.accessCount}x`);\n }\n\n if (parts.contextScore > 0.3) {\n factors.push('Context match');\n }\n\n const ageDays = Math.floor((Date.now() - new Date(memory.createdAt).getTime()) / 86_400_000);\n const stalenessThreshold = STALENESS_THRESHOLDS[memory.type];\n if (stalenessThreshold !== undefined && ageDays > stalenessThreshold) {\n factors.push(`${ageDays}d old - verify before acting`);\n }\n\n return factors.length > 0 ? factors.join(' + ') : 'Matched query';\n}\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface SessionContextResult {\n readonly section: 'context' | 'recent' | 'related';\n readonly result: SearchResult;\n}\n\n// Exported for testing\nexport { computeRecencyScore, computeAccessScore, computeComposite, computeScoreParts, ftsOnlyScores };\nexport type { ScoreParts };\n","import { z } from 'zod';\nimport { createHash } from 'node:crypto';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES, MEMORY_SOURCES } from '../types.js';\nimport { getGitContext } from '../utils/git-context.js';\nimport { validateMemoryContent } from '../utils/content-validation.js';\nimport { checkContradiction } from '../utils/contradiction.js';\n\n// In-memory dedup: content hash → timestamp. Catches parallel calls within same request.\nconst recentStores = new Map<string, number>();\nconst pendingStores = new Set<string>();\nconst DEDUP_WINDOW_MS = 10_000;\n\n// Tag normalization: lowercase, strip #, singularize common suffixes, apply aliases\nconst TAG_ALIASES: Record<string, string> = {\n bugs: 'bug', bugfix: 'bug', debugging: 'bug',\n decisions: 'decision', decided: 'decision',\n gotchas: 'gotcha', pitfall: 'gotcha', pitfalls: 'gotcha',\n howtos: 'howto', 'how-to': 'howto',\n patterns: 'pattern',\n todos: 'todo', fixme: 'todo',\n architectures: 'architecture', arch: 'architecture',\n};\n\nfunction normalizeTags(tags: readonly string[]): string[] {\n return [...new Set(tags.map((t) => {\n const stripped = t.replace(/^#/, '').toLowerCase().trim();\n return TAG_ALIASES[stripped] ?? stripped;\n }).filter(Boolean))];\n}\n\n// Auto-tag: detect common patterns in content\nconst AUTO_TAG_PATTERNS: readonly { readonly pattern: RegExp; readonly tag: string }[] = [\n { pattern: /\\b(bug|crash|error|fix(ed)?|broke)\\b/i, tag: 'bug' },\n { pattern: /\\b(decid|chose|decision|went with|picked)\\b/i, tag: 'decision' },\n { pattern: /\\b(gotcha|careful|watch out|trap|pitfall)\\b/i, tag: 'gotcha' },\n { pattern: /\\b(how to|steps to|run|install|deploy|command)\\b/i, tag: 'howto' },\n { pattern: /\\b(pattern|recurring|always|every time)\\b/i, tag: 'pattern' },\n];\n\nfunction autoTag(content: string, existingTags: readonly string[]): string[] {\n const existing = new Set(existingTags);\n const detected: string[] = [];\n for (const { pattern, tag } of AUTO_TAG_PATTERNS) {\n if (!existing.has(tag) && pattern.test(content)) {\n detected.push(tag);\n }\n }\n return detected;\n}\n\nconst inputSchema = {\n type: z.enum(MEMORY_TYPES).describe('Memory type: working, episodic, semantic, procedural, or pattern'),\n content: z.string().min(1).describe('The memory content (aim for ~2000 chars / ~500 tokens). Keep memories concise: capture the decision or insight, not the full context. Split large topics into separate memories.'),\n title: z.string().max(200).optional().describe('Short title for the memory'),\n tags: z.array(z.string()).max(20).default([]).describe('Tags for categorization. Suggested: #bug, #decision, #gotcha, #howto, #pattern'),\n importance: z.number().min(0).max(1).default(0.5).describe('0-0.3 ephemeral, 0.3-0.6 reference, 0.6-0.8 important, 0.8-1.0 critical'),\n context: z.string().optional().describe('JSON: {\"files\": [...], \"branch\": \"...\", \"intent\": \"...\"}. Auto-detected from git if omitted.'),\n source: z.enum(MEMORY_SOURCES).default('manual').describe('How this memory was created'),\n project: z.string().max(200).optional().describe('Project scope (auto-detected from CWD if omitted)'),\n};\n\nexport function registerStore(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_store',\n {\n description:\n 'Save something worth remembering to the knowledge base. '\n + 'Use when you learn a fact, make a decision, hit a bug, or discover a pattern that future sessions should know. '\n + 'Always search first to avoid duplicates — update existing memories when possible. '\n + 'Types: semantic (facts/decisions), procedural (how-to), episodic (what happened), pattern (recurring), working (scratch). '\n + 'Importance: 0.1 trivial, 0.5 useful, 0.8 important, 1.0 critical. '\n + 'Tags and git context are auto-detected if omitted. \"Skipped\" responses mean a duplicate was caught — not an error.',\n inputSchema,\n annotations: { idempotentHint: false },\n },\n async (args) => {\n const validation = validateMemoryContent(args.content);\n if (!validation.valid) {\n return {\n content: [{\n type: 'text' as const,\n text: `Rejected: ${validation.reason}`,\n }],\n isError: true,\n };\n }\n\n const context = args.context ?? JSON.stringify(getGitContext());\n const project = args.project ?? deps.project ?? undefined;\n\n // Dedup: in-memory guard catches parallel calls within same request.\n // Uses a pending Set to catch calls that arrive in the same tick.\n const contentHash = createHash('sha256').update(args.content).digest('hex');\n const now = Date.now();\n const lastStored = recentStores.get(contentHash);\n if (lastStored && (now - lastStored) < DEDUP_WINDOW_MS) {\n return {\n content: [{ type: 'text' as const, text: 'Skipped: identical memory already exists (stored moments ago).' }],\n };\n }\n if (pendingStores.has(contentHash)) {\n return {\n content: [{ type: 'text' as const, text: 'Skipped: identical memory is being stored by another call.' }],\n };\n }\n pendingStores.add(contentHash);\n // Prune old entries\n for (const [key, ts] of recentStores) {\n if (now - ts > DEDUP_WINDOW_MS) recentStores.delete(key);\n }\n\n // Contradiction detection\n const contradictions: { id: string; title: string | null }[] = [];\n try {\n const existing = await deps.retrievalService.search({\n query: args.content.slice(0, 200),\n limit: 3,\n min_importance: 0,\n project,\n });\n for (const result of existing) {\n if (result.score > 0.6 && checkContradiction(args.content, result.memory.content)) {\n contradictions.push({ id: result.memory.id, title: result.memory.title });\n }\n }\n } catch {\n // Contradiction check is best-effort\n }\n\n // Normalize tags + auto-tag from content\n const normalizedTags = normalizeTags(args.tags);\n const autoTags = autoTag(args.content, normalizedTags);\n const finalTags = [...new Set([...normalizedTags, ...autoTags])];\n\n const memory = deps.memoryRepo.create(\n {\n type: args.type,\n content: args.content,\n title: args.title,\n tags: finalTags,\n importance: args.importance,\n context,\n source: args.source,\n project,\n },\n null,\n );\n\n // Mark as stored (dedup window starts now)\n recentStores.set(contentHash, Date.now());\n pendingStores.delete(contentHash);\n\n if (!memory) {\n return {\n content: [{ type: 'text' as const, text: 'Skipped: identical memory already exists in the knowledge base.' }],\n };\n }\n\n // Create contradiction relations\n for (const c of contradictions) {\n try {\n deps.relationRepo.create(memory.id, c.id, 'contradicts');\n } catch {\n // Relation creation is best-effort\n }\n }\n\n const parts: string[] = [\n `Stored memory ${memory.id} (type: ${memory.type}, importance: ${memory.importance})`,\n ];\n\n for (const warning of validation.warnings) {\n parts.push(`Warning: ${warning}`);\n }\n\n for (const c of contradictions) {\n parts.push(`Warning: potential contradiction with memory ${c.id}${c.title ? ` (\"${c.title}\")` : ''}. Linked with 'contradicts' relation.`);\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: parts.join('\\n'),\n }],\n };\n },\n );\n}\n","// ── Content Validation for memory_store ─────────────────────\n\nexport interface ValidationResult {\n readonly valid: boolean;\n readonly reason?: string;\n readonly warnings: readonly string[];\n}\n\nconst SOFT_LENGTH_LIMIT = 1500;\nconst HARD_LENGTH_LIMIT = 5000;\nconst CODE_RATIO_THRESHOLD = 0.5;\n\n/**\n * Validate memory content before storage.\n * Returns hard rejections (don't store) and soft warnings (store but warn).\n */\nexport function validateMemoryContent(content: string): ValidationResult {\n const warnings: string[] = [];\n\n // Hard reject: git log output\n if (isGitLog(content)) {\n return { valid: false, reason: 'Content looks like raw git log output. Use git log directly — don\\'t store it as memory.', warnings: [] };\n }\n\n // Hard reject: code-heavy content\n if (isCodeHeavy(content)) {\n return { valid: false, reason: 'Content is >50% code blocks. Code belongs in files, not memory. Store the insight or decision instead.', warnings: [] };\n }\n\n // Hard reject: too long\n if (content.length > HARD_LENGTH_LIMIT) {\n return { valid: false, reason: `Content is ${content.length} chars (limit: ${HARD_LENGTH_LIMIT}). Break it into smaller, atomic memories.`, warnings: [] };\n }\n\n // Soft warn: lengthy\n if (content.length > SOFT_LENGTH_LIMIT) {\n warnings.push(`Content is ${content.length} chars. Shorter memories (<${SOFT_LENGTH_LIMIT} chars) are easier to retrieve and less likely to decay.`);\n }\n\n return { valid: true, warnings };\n}\n\n/**\n * Content is >50% fenced code blocks.\n */\nexport function isCodeHeavy(content: string): boolean {\n const fencedBlockPattern = /```[\\s\\S]*?```/g;\n let codeChars = 0;\n let match: RegExpExecArray | null;\n\n while ((match = fencedBlockPattern.exec(content)) !== null) {\n codeChars += match[0].length;\n }\n\n return content.length > 0 && codeChars / content.length > CODE_RATIO_THRESHOLD;\n}\n\n/**\n * Content looks like raw git log output.\n * Matches patterns like \"commit abc123\\nAuthor: ...\\nDate: ...\"\n */\nexport function isGitLog(content: string): boolean {\n const lines = content.split('\\n');\n let gitLogLines = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (/^commit\\s+[0-9a-f]{7,40}$/i.test(trimmed)) gitLogLines++;\n else if (/^Author:\\s+.+/i.test(trimmed)) gitLogLines++;\n else if (/^Date:\\s+.+/i.test(trimmed)) gitLogLines++;\n else if (/^[0-9a-f]{7,12}\\s+\\S+/i.test(trimmed) && trimmed.length < 200) gitLogLines++;\n }\n\n // At least 3 git-log-like lines and they make up >30% of non-empty lines\n const nonEmptyLines = lines.filter(l => l.trim().length > 0).length;\n return gitLogLines >= 3 && nonEmptyLines > 0 && gitLogLines / nonEmptyLines > 0.3;\n}\n","// ── Contradiction Detection (keyword-overlap heuristic) ─────\n\nconst NEGATION_PATTERNS = [\n /\\bnot\\b/i,\n /\\bno longer\\b/i,\n /\\binstead of\\b/i,\n /\\breplaced\\b/i,\n /\\bremoved\\b/i,\n /\\bdon'?t\\b/i,\n /\\bwon'?t\\b/i,\n /\\bshouldn'?t\\b/i,\n /\\bdeprecated\\b/i,\n /\\bdisabled\\b/i,\n /\\bstopped\\b/i,\n /\\bavoid\\b/i,\n /\\bnever\\b/i,\n /\\bwithout\\b/i,\n];\n\nconst KEYWORD_OVERLAP_THRESHOLD = 0.4;\nconst MIN_KEYWORD_LENGTH = 3;\nconst STOP_WORDS = new Set([\n 'the', 'and', 'for', 'are', 'but', 'not', 'you', 'all', 'can', 'had',\n 'her', 'was', 'one', 'our', 'out', 'has', 'have', 'been', 'from', 'that',\n 'this', 'with', 'they', 'will', 'each', 'make', 'like', 'than', 'them',\n 'then', 'what', 'when', 'into', 'more', 'some', 'such', 'also', 'use',\n 'used', 'using', 'should', 'would', 'could', 'about', 'which', 'their',\n 'there', 'these', 'those', 'does', 'done', 'just', 'very',\n]);\n\n/**\n * Extract meaningful keywords from text.\n */\nfunction extractKeywords(text: string): ReadonlySet<string> {\n const words = text.toLowerCase().match(/[a-z][a-z0-9_-]+/g) ?? [];\n return new Set(\n words.filter(w => w.length >= MIN_KEYWORD_LENGTH && !STOP_WORDS.has(w)),\n );\n}\n\n/**\n * Check if new content potentially contradicts existing content.\n *\n * Heuristic: high keyword overlap + negation markers = likely contradiction.\n * Not perfect, but catches the common case of \"we used X\" vs \"we no longer use X\".\n */\nexport function checkContradiction(newContent: string, existingContent: string): boolean {\n const newKeywords = extractKeywords(newContent);\n const existingKeywords = extractKeywords(existingContent);\n\n if (newKeywords.size === 0 || existingKeywords.size === 0) return false;\n\n // Compute Jaccard-like overlap: |intersection| / |smaller set|\n let overlap = 0;\n for (const kw of newKeywords) {\n if (existingKeywords.has(kw)) overlap++;\n }\n\n const smallerSize = Math.min(newKeywords.size, existingKeywords.size);\n const overlapRatio = overlap / smallerSize;\n\n if (overlapRatio < KEYWORD_OVERLAP_THRESHOLD) return false;\n\n // High overlap — check for negation markers in the NEW content only.\n return NEGATION_PATTERNS.some(pattern => pattern.test(newContent));\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\n\nconst inputSchema = {\n query: z.string().min(1).max(500).describe('Search query (natural language or keywords)'),\n id: z.string().optional().describe('Direct lookup by memory ID (bypasses search)'),\n type: z.enum(MEMORY_TYPES).optional().describe('Filter by memory type'),\n tags: z.array(z.string()).max(10).optional().describe('Filter to memories containing ALL of these tags'),\n limit: z.number().int().min(1).max(50).default(10).describe('Maximum results to return'),\n min_importance: z.number().min(0).max(1).default(0).describe('Minimum importance threshold'),\n};\n\nexport function registerSearch(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_search',\n {\n description:\n 'Look up what you already know. Query the knowledge base before solving a problem or storing new information. '\n + 'Use when: checking if something was already decided, finding how-to steps, recalling past bugs, or deduping before a store. '\n + 'Related memories are surfaced automatically. Pass `id` for direct lookup, or filter by `type` and `tags`.',\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (args) => {\n const results = await deps.retrievalService.search({\n query: args.query,\n id: args.id,\n type: args.type,\n tags: args.tags,\n limit: args.limit,\n min_importance: args.min_importance,\n project: deps.project ?? undefined,\n });\n\n if (results.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No memories found matching your query.' }],\n };\n }\n\n const formatted = results.map((r, i) => ({\n rank: i + 1,\n id: r.memory.id,\n type: r.memory.type,\n title: r.memory.title,\n content: r.memory.content,\n score: Math.round(r.score * 100) / 100,\n explanation: r.explanation,\n importance: r.memory.importance,\n tags: r.memory.tags,\n accessCount: r.memory.accessCount,\n createdAt: r.memory.createdAt,\n }));\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(formatted, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { memoryNotFound, formatMcpError } from '../utils/errors.js';\n\nconst inputSchema = {\n id: z.string().describe('ID of the memory to forget'),\n hard_delete: z.boolean().default(false).describe('true = permanent delete, false = set importance to 0 (soft delete)'),\n};\n\nexport function registerForget(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_forget',\n {\n description:\n 'Remove outdated or wrong information from the knowledge base. '\n + 'Default: soft-delete (fades away naturally). Pass hard_delete=true to erase permanently. '\n + 'Use memory_search to find the ID first.',\n inputSchema,\n annotations: { destructiveHint: true, idempotentHint: true },\n },\n async (args) => {\n const memory = deps.memoryRepo.getById(args.id);\n if (!memory) {\n return formatMcpError(memoryNotFound(args.id));\n }\n\n if (deps.project && memory.project !== null && memory.project !== deps.project) {\n return formatMcpError({\n what: `Memory ${args.id} belongs to project \"${memory.project}\".`,\n why: `Current project is \"${deps.project}\". Cross-project deletion is not allowed.`,\n fix: 'Switch to the correct project or use a global context.',\n });\n }\n\n if (args.hard_delete) {\n deps.memoryRepo.hardDelete(args.id);\n return {\n content: [{\n type: 'text' as const,\n text: `Permanently deleted memory ${args.id} (\"${memory.title ?? memory.content.slice(0, 50)}\")`,\n }],\n };\n }\n\n deps.memoryRepo.softDelete(args.id);\n return {\n content: [{\n type: 'text' as const,\n text: `Soft-deleted memory ${args.id} (importance set to 0, will decay naturally)`,\n }],\n };\n },\n );\n}\n","// ── Structured Error Formatting ──────────────────────────────\n// Every error answers: What happened? Why? What to do?\n\nexport interface StructuredError {\n readonly what: string;\n readonly why: string;\n readonly fix: string;\n}\n\nexport function formatError(err: StructuredError): string {\n return `${err.what}\\nWhy: ${err.why}\\nFix: ${err.fix}`;\n}\n\nexport function formatMcpError(err: StructuredError): { isError: true; content: [{ type: 'text'; text: string }] } {\n return {\n isError: true,\n content: [{ type: 'text' as const, text: formatError(err) }],\n };\n}\n\n// ── Common Error Templates ───────────────────────────────────\n\nexport function memoryNotFound(id: string): StructuredError {\n return {\n what: `Memory \"${id}\" not found.`,\n why: 'The ID may be incorrect, or the memory was deleted or pruned.',\n fix: 'Use memory_search to find valid IDs.',\n };\n}\n\nexport function databaseLocked(): StructuredError {\n return {\n what: 'Database is temporarily locked.',\n why: 'Another process is writing to the database (SQLITE_BUSY).',\n fix: 'Retry in a moment. If persistent, run: claude-launchpad doctor --fix',\n };\n}\n\nexport function databaseCorrupt(): StructuredError {\n return {\n what: 'Database integrity check failed.',\n why: 'The database file may be corrupted (disk error, incomplete write).',\n fix: 'Run: claude-launchpad doctor --fix (creates backup, reinitializes DB)',\n };\n}\n\nexport function diskFull(): StructuredError {\n return {\n what: 'Disk write failed — not enough space.',\n why: 'The disk partition containing ~/.agentic-memory is full.',\n fix: 'Free disk space, then run: claude-launchpad doctor --fix',\n };\n}\n\nexport function invalidInput(field: string, reason: string): StructuredError {\n return {\n what: `Invalid input: ${field}`,\n why: reason,\n fix: 'Check the parameter value and try again.',\n };\n}\n\n// ── SQLite Retry Logic ───────────────────────────────────────\n\nconst RETRY_DELAYS = [100, 200, 400] as const;\n\nexport function withRetry<T>(fn: () => T, label: string): T {\n for (let attempt = 0; attempt < RETRY_DELAYS.length; attempt++) {\n try {\n return fn();\n } catch (err) {\n if (isSqliteBusy(err) && attempt < RETRY_DELAYS.length - 1) {\n const delay = RETRY_DELAYS[attempt]!;\n process.stderr.write(`[memory] ${label}: SQLITE_BUSY, retrying in ${delay}ms\\n`);\n sleepSync(delay);\n continue;\n }\n throw err;\n }\n }\n // Unreachable, but TypeScript needs it\n throw new Error(`${label}: exhausted retries`);\n}\n\nfunction isSqliteBusy(err: unknown): boolean {\n if (err instanceof Error) {\n return err.message.includes('SQLITE_BUSY') || err.message.includes('database is locked');\n }\n return false;\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { RELATION_TYPES } from '../types.js';\nimport { memoryNotFound, formatMcpError } from '../utils/errors.js';\n\nconst inputSchema = {\n source_id: z.string().describe('ID of the source memory'),\n target_id: z.string().describe('ID of the target memory'),\n relation_type: z.enum(RELATION_TYPES).describe(\n 'Type of relation: relates_to, depends_on, contradicts, extends, implements, derived_from'\n ),\n};\n\nexport function registerRelate(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_relate',\n {\n description:\n 'Link two memories together so they surface as a group. '\n + 'Use when one memory extends, contradicts, depends on, or implements another. '\n + 'Linked memories stay relevant longer and appear together in search results.',\n inputSchema,\n annotations: { idempotentHint: true },\n },\n async (args) => {\n if (args.source_id === args.target_id) {\n return formatMcpError({\n what: 'Cannot create self-relation.',\n why: 'source_id and target_id are the same memory.',\n fix: 'Provide two different memory IDs.',\n });\n }\n\n const source = deps.memoryRepo.getById(args.source_id);\n if (!source) {\n return formatMcpError(memoryNotFound(args.source_id));\n }\n\n const target = deps.memoryRepo.getById(args.target_id);\n if (!target) {\n return formatMcpError(memoryNotFound(args.target_id));\n }\n\n if (deps.project) {\n for (const mem of [source, target]) {\n if (mem.project !== null && mem.project !== deps.project) {\n return formatMcpError({\n what: `Memory ${mem.id} belongs to project \"${mem.project}\".`,\n why: `Current project is \"${deps.project}\". Cross-project relations are not allowed.`,\n fix: 'Both memories must belong to the same project.',\n });\n }\n }\n }\n\n const created = deps.relationRepo.create(args.source_id, args.target_id, args.relation_type);\n\n if (!created) {\n return {\n content: [{\n type: 'text' as const,\n text: `Relation already exists: ${args.source_id} --[${args.relation_type}]--> ${args.target_id}`,\n }],\n };\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: `Created relation: \"${source.title ?? source.content.slice(0, 40)}\" --[${args.relation_type}]--> \"${target.title ?? target.content.slice(0, 40)}\"`,\n }],\n };\n },\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\nimport type { MemoryStats } from '../types.js';\nimport { statSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport function registerStats(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_stats',\n {\n description:\n 'See how much is in the knowledge base — total count, breakdown by type, storage size, and most-used memories.',\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async () => {\n const countByType = deps.memoryRepo.countByType();\n const total = deps.memoryRepo.count();\n const topInjected = deps.memoryRepo.topInjected(5);\n const totalRelations = deps.relationRepo.count();\n\n let dbSizeBytes = 0;\n try {\n const dbPath = join(deps.dataDir, 'memory.db');\n dbSizeBytes = statSync(dbPath).size;\n } catch {\n // :memory: or file not found\n }\n\n const { oldest, newest } = deps.memoryRepo.dateRange();\n\n const stats: MemoryStats = {\n totalMemories: total,\n byType: Object.fromEntries(\n MEMORY_TYPES.map(t => [t, countByType[t] ?? 0])\n ) as Record<string, number>,\n totalRelations,\n dbSizeBytes,\n oldestMemory: oldest,\n newestMemory: newest,\n topInjected,\n };\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(stats, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\n\nconst inputSchema = {\n limit: z.number().int().min(1).max(50).default(10).describe('Maximum memories to return'),\n type: z.enum(MEMORY_TYPES).optional().describe('Filter by memory type'),\n};\n\nexport function registerRecent(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_recent',\n {\n description:\n 'Get caught up on what happened before this session. '\n + 'Returns memories relevant to the current branch/files, recent activity, and related context. '\n + 'Typically called at session start to restore working context. No query needed — it uses git state to find what matters.',\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (args) => {\n const results = deps.retrievalService.loadSessionContext({\n limit: args.limit,\n project: deps.project ?? undefined,\n type: args.type,\n });\n\n if (results.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No memories found for this project.' }],\n };\n }\n\n const formatEntry = (entry: typeof results[number], rank: number) => ({\n rank,\n section: entry.section,\n id: entry.result.memory.id,\n type: entry.result.memory.type,\n title: entry.result.memory.title,\n content: entry.result.memory.content,\n importance: entry.result.memory.importance,\n tags: entry.result.memory.tags,\n score: Math.round(entry.result.score * 100) / 100,\n explanation: entry.result.explanation,\n createdAt: entry.result.memory.createdAt,\n });\n\n const contextMatched = results.filter(r => r.section === 'context').map((r, i) => formatEntry(r, i + 1));\n const recent = results.filter(r => r.section === 'recent').map((r, i) => formatEntry(r, i + 1));\n const related = results.filter(r => r.section === 'related').map((r, i) => formatEntry(r, i + 1));\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({ contextMatched, recent, related }, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\n\nconst inputSchema = {\n id: z.string().describe('Memory ID to update (use memory_search to find it)'),\n title: z.string().max(200).optional().describe('Updated title'),\n content: z.string().min(1).max(10000).optional().describe('Updated content'),\n tags: z.array(z.string()).max(20).optional().describe('Updated tags'),\n importance: z.number().min(0).max(1).optional().describe('Updated importance (0-1)'),\n context: z.string().optional().describe('Updated context JSON'),\n};\n\nexport function registerUpdate(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_update',\n {\n description:\n 'Correct or improve an existing memory instead of creating a duplicate. '\n + 'Use when information has changed, a decision was revised, or a memory needs more detail. '\n + 'Keeps the memory\\'s history intact. Use memory_search to find the ID first.',\n inputSchema,\n annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },\n },\n async (args) => {\n const hasUpdate = args.title !== undefined || args.content !== undefined\n || args.tags !== undefined || args.importance !== undefined\n || args.context !== undefined;\n\n if (!hasUpdate) {\n return {\n content: [{ type: 'text' as const, text: 'No fields to update. Provide at least one of: title, content, tags, importance, context.' }],\n isError: true,\n };\n }\n\n const existing = deps.memoryRepo.getById(args.id);\n if (!existing) {\n return {\n content: [{ type: 'text' as const, text: `Memory ${args.id} not found.` }],\n isError: true,\n };\n }\n\n const updated = deps.memoryRepo.updateContent(args.id, {\n title: args.title,\n content: args.content,\n tags: args.tags,\n importance: args.importance,\n context: args.context,\n });\n\n if (!updated) {\n return {\n content: [{ type: 'text' as const, text: `Failed to update memory ${args.id}.` }],\n isError: true,\n };\n }\n\n const fields = [\n args.title !== undefined && 'title',\n args.content !== undefined && 'content',\n args.tags !== undefined && 'tags',\n args.importance !== undefined && 'importance',\n args.context !== undefined && 'context',\n ].filter(Boolean).join(', ');\n\n return {\n content: [{ type: 'text' as const, text: `Updated memory ${args.id} (fields: ${fields})` }],\n };\n },\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport type { RetrievalService } from '../services/retrieval-service.js';\nimport { registerStore } from './store.js';\nimport { registerSearch } from './search.js';\nimport { registerForget } from './forget.js';\nimport { registerRelate } from './relate.js';\nimport { registerStats } from './stats.js';\nimport { registerRecent } from './recent.js';\nimport { registerUpdate } from './update.js';\n\nexport interface ToolDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly retrievalService: RetrievalService;\n readonly dataDir: string;\n readonly project: string | null;\n}\n\nexport function registerTools(server: McpServer, deps: ToolDeps): void {\n registerStore(server, deps);\n registerSearch(server, deps);\n registerRecent(server, deps);\n registerForget(server, deps);\n registerRelate(server, deps);\n registerStats(server, deps);\n registerUpdate(server, deps);\n}\n"],"mappings":"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","names":["z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema","require"]}
1
+ {"version":3,"sources":["../../../src/commands/memory/server.ts","../../../src/commands/memory/services/retrieval-service.ts","../../../src/commands/memory/tools/store.ts","../../../src/commands/memory/utils/content-validation.ts","../../../src/commands/memory/utils/contradiction.ts","../../../src/commands/memory/tools/search.ts","../../../src/commands/memory/tools/forget.ts","../../../src/commands/memory/utils/errors.ts","../../../src/commands/memory/tools/relate.ts","../../../src/commands/memory/tools/stats.ts","../../../src/commands/memory/tools/recent.ts","../../../src/commands/memory/tools/update.ts","../../../src/commands/memory/tools/register.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nconst require = createRequire(import.meta.url);\nconst { version } = require('../../../package.json') as { version: string };\nimport { createDatabase, closeDatabase } from './storage/database.js';\nimport { migrate } from './storage/migrator.js';\nimport { MemoryRepo } from './storage/memory-repo.js';\nimport { RelationRepo } from './storage/relation-repo.js';\nimport { SearchRepo } from './storage/search-repo.js';\nimport { RetrievalService } from './services/retrieval-service.js';\nimport { loadConfig, resolveDataDir } from './config.js';\nimport type { Config } from './config.js';\nimport { registerTools } from './tools/register.js';\nimport { detectProject } from './utils/project.js';\n\nexport interface ServerDeps {\n readonly config: Config;\n}\n\nexport async function startServer(deps?: Partial<ServerDeps>): Promise<void> {\n const config = deps?.config ?? loadConfig();\n const dataDir = resolveDataDir(config.dataDir);\n\n const db = createDatabase({ dataDir });\n migrate(db);\n\n const memoryRepo = new MemoryRepo(db);\n const relationRepo = new RelationRepo(db);\n const searchRepo = new SearchRepo(db);\n\n const retrievalService = new RetrievalService({\n memoryRepo,\n relationRepo,\n searchRepo,\n });\n\n const server = new McpServer(\n { name: 'agentic-memory', version },\n {\n instructions:\n 'This is your knowledge base — persistent context that survives across sessions. '\n + 'Search before storing to avoid duplicates. Update existing memories instead of creating new ones. '\n + 'Store decisions, patterns, and insights — capture WHY, not just WHAT. '\n + 'Only save what future sessions will need. NEVER store secrets, API keys, or passwords. '\n + 'Session context is injected automatically at startup — no need to call memory_recent.',\n },\n );\n\n const project = detectProject(process.cwd());\n\n registerTools(server, { memoryRepo, relationRepo, retrievalService, dataDir, project });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n const shutdown = async () => {\n await server.close();\n closeDatabase(db);\n process.exit(0);\n };\n process.on('SIGINT', () => void shutdown());\n process.on('SIGTERM', () => void shutdown());\n}\n\n// Auto-start when invoked directly as MCP server entry point\nstartServer().catch((err) => {\n process.stderr.write(`[agentic-memory] ${err}\\n`);\n process.exit(1);\n});\n","import type { Memory, MemoryType, SearchResult, SearchInput, RelationType } from '../types.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport type { SearchRepo } from '../storage/search-repo.js';\nimport { SCORING_WEIGHTS } from '../config.js';\nimport { type GitContext, getGitContext, computeContextScore } from '../utils/git-context.js';\n\nconst STALENESS_THRESHOLDS = {\n working: 1,\n episodic: 7,\n pattern: 14,\n semantic: 30,\n procedural: 90,\n} as const;\n\nexport interface RetrievalDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly searchRepo: SearchRepo;\n readonly gitContext?: GitContext;\n}\n\nexport class RetrievalService {\n readonly #deps: RetrievalDeps;\n readonly #gitContext: GitContext;\n\n constructor(deps: RetrievalDeps) {\n this.#deps = deps;\n this.#gitContext = deps.gitContext ?? getGitContext();\n }\n\n /**\n * FTS5 keyword search with multi-signal scoring, context awareness,\n * and relation-based graph expansion.\n */\n async search(input: SearchInput): Promise<readonly SearchResult[]> {\n // Direct ID lookup\n if (input.id) {\n const memory = this.#deps.memoryRepo.getById(input.id);\n if (!memory) return [];\n this.#deps.memoryRepo.incrementAccess(input.id);\n return [{\n memory,\n score: 1.0,\n explanation: 'Direct lookup by ID',\n }];\n }\n\n // Phase 1: FTS5 keyword search\n const ftsResults = this.#deps.searchRepo.searchFts({\n query: input.query,\n limit: input.limit * 3,\n type: input.type,\n minImportance: input.min_importance,\n project: input.project,\n });\n\n const textScores = ftsOnlyScores(ftsResults);\n if (textScores.size === 0) return [];\n\n // Phase 2: Load memories and compute composite scores\n const candidates: { memory: Memory; composite: number; parts: ScoreParts }[] = [];\n\n for (const [memoryId, textScore] of textScores) {\n const memory = this.#deps.memoryRepo.getById(memoryId);\n if (!memory) continue;\n if (input.type && memory.type !== input.type) continue;\n if (memory.importance < input.min_importance) continue;\n if (input.tags?.length) {\n const memTags = new Set(memory.tags);\n if (!input.tags.every(t => memTags.has(t))) continue;\n }\n\n const parts = computeScoreParts(memory, textScore, this.#gitContext, input.query);\n const composite = computeComposite(parts);\n candidates.push({ memory, composite, parts });\n }\n\n // Phase 3: Sort by composite score\n candidates.sort((a, b) => b.composite - a.composite);\n let topN = candidates.slice(0, input.limit);\n\n // Phase 4: Relation expansion — surface connected memories\n const seenIds = new Set(topN.map(c => c.memory.id));\n const expanded = this.#expandWithRelations(topN, input.limit, seenIds, input.min_importance, input.type);\n if (expanded.length > 0) {\n topN = [...topN, ...expanded].sort((a, b) => b.composite - a.composite).slice(0, input.limit);\n }\n\n // Phase 5: Build results with explanations, increment access\n return topN.map(({ memory, composite, parts }) => {\n this.#deps.memoryRepo.incrementAccess(memory.id);\n return {\n memory,\n score: composite,\n explanation: parts.relationSource\n ? `Related (${parts.relationSource.type}) to: ${parts.relationSource.title ?? parts.relationSource.id}`\n : buildExplanation(parts, memory),\n };\n });\n }\n\n /**\n * Smart session loading: returns context-matched, recent, and related memories\n * for session start context injection.\n */\n loadSessionContext(input: {\n readonly limit: number;\n readonly project?: string;\n readonly type?: MemoryType;\n }): readonly SessionContextResult[] {\n const contextBudget = Math.floor(input.limit * 0.4);\n const recentBudget = Math.floor(input.limit * 0.4);\n const relatedBudget = input.limit - contextBudget - recentBudget;\n const seenIds = new Set<string>();\n\n const contextMatched = this.#loadContextMatched(contextBudget, input.project, input.type, seenIds);\n const recent = this.#loadRecent(recentBudget, input.project, input.type, seenIds);\n\n const sourceIds = [...contextMatched, ...recent].map(r => r.result.memory.id);\n const related = this.#loadRelatedExpansion(sourceIds, relatedBudget, seenIds, input.type);\n\n const all = [...contextMatched, ...recent, ...related];\n for (const entry of all) {\n this.#deps.memoryRepo.incrementInjection(entry.result.memory.id);\n }\n return all;\n }\n\n #loadContextMatched(\n budget: number, project?: string, type?: MemoryType, seenIds?: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const candidates = this.#deps.memoryRepo.getRecent(budget * 5, project, type);\n const scored: { memory: Memory; ctxScore: number; composite: number }[] = [];\n\n for (const m of candidates) {\n const ctxScore = computeContextScore(m.context, this.#gitContext, '');\n if (ctxScore <= 0.1) continue;\n const composite = ctxScore * 0.5 + m.importance * 0.3 + computeRecencyScore(m.updatedAt) * 0.2;\n scored.push({ memory: m, ctxScore, composite });\n }\n\n scored.sort((a, b) => b.composite - a.composite);\n const results: SessionContextResult[] = [];\n for (const s of scored.slice(0, budget)) {\n seenIds?.add(s.memory.id);\n results.push({ section: 'context', result: { memory: s.memory, score: s.composite, explanation: 'Context match' } });\n }\n return results;\n }\n\n #loadRecent(\n budget: number, project?: string, type?: MemoryType, seenIds?: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const candidates = this.#deps.memoryRepo.getRecent(budget * 2, project, type);\n const results: SessionContextResult[] = [];\n\n for (const m of candidates) {\n if (seenIds?.has(m.id)) continue;\n const score = m.importance * 0.4 + computeRecencyScore(m.updatedAt) * 0.6;\n seenIds?.add(m.id);\n results.push({ section: 'recent', result: { memory: m, score, explanation: 'Recent' } });\n if (results.length >= budget) break;\n }\n return results;\n }\n\n #loadRelatedExpansion(\n sourceIds: readonly string[], budget: number, seenIds: Set<string>, typeFilter?: MemoryType,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const results: SessionContextResult[] = [];\n\n for (const srcId of sourceIds) {\n const relations = this.#deps.relationRepo.getByMemory(srcId);\n for (const rel of relations) {\n const otherId = rel.sourceId === srcId ? rel.targetId : rel.sourceId;\n if (otherId === srcId || seenIds.has(otherId)) continue;\n\n const other = this.#deps.memoryRepo.getById(otherId);\n if (!other) continue;\n if (typeFilter && other.type !== typeFilter) continue;\n\n const src = this.#deps.memoryRepo.getById(srcId);\n const weight = RELATION_TYPE_WEIGHTS[rel.relationType] ?? 0.5;\n seenIds.add(otherId);\n results.push({\n section: 'related',\n result: {\n memory: other,\n score: other.importance * weight,\n explanation: `Related (${rel.relationType}) to: ${src?.title ?? srcId}`,\n },\n });\n if (results.length >= budget) return results;\n }\n }\n return results;\n }\n\n #expandWithRelations(\n topResults: readonly { memory: Memory; composite: number; parts: ScoreParts }[],\n limit: number,\n seenIds: Set<string>,\n minImportance: number,\n typeFilter?: MemoryType,\n ): { memory: Memory; composite: number; parts: ScoreParts }[] {\n if (topResults.length >= limit) return [];\n\n const expanded: { memory: Memory; composite: number; parts: ScoreParts }[] = [];\n const remaining = limit - topResults.length;\n const sourcesToExpand = topResults.slice(0, 5);\n\n for (const parent of sourcesToExpand) {\n const relations = this.#deps.relationRepo.getByMemory(parent.memory.id);\n for (const rel of relations) {\n const otherId = rel.sourceId === parent.memory.id ? rel.targetId : rel.sourceId;\n if (otherId === parent.memory.id || seenIds.has(otherId)) continue;\n\n const other = this.#deps.memoryRepo.getById(otherId);\n if (!other || other.importance < minImportance) continue;\n if (typeFilter && other.type !== typeFilter) continue;\n\n const weight = RELATION_TYPE_WEIGHTS[rel.relationType] ?? 0.5;\n const composite = parent.composite * 0.7 * weight;\n const parts: ScoreParts = {\n textScore: 0,\n importanceScore: other.importance,\n recencyScore: computeRecencyScore(other.updatedAt),\n accessScore: computeAccessScore(other.accessCount, other.lastAccessed),\n contextScore: 0,\n relationSource: { id: parent.memory.id, title: parent.memory.title, type: rel.relationType },\n };\n\n seenIds.add(otherId);\n expanded.push({ memory: other, composite, parts });\n if (expanded.length >= remaining) return expanded;\n }\n }\n\n return expanded;\n }\n}\n\n// ── Relation Expansion ──────────────────────────────────────\n\nconst RELATION_TYPE_WEIGHTS: Record<RelationType, number> = {\n depends_on: 1.0,\n extends: 0.9,\n implements: 0.9,\n relates_to: 0.7,\n derived_from: 0.6,\n contradicts: 0.3,\n};\n\n// ── FTS5-Only Fallback ───────────────────────────────────────\n\nfunction ftsOnlyScores(ftsResults: readonly { memoryId: string; rank: number }[]): Map<string, number> {\n const scores = new Map<string, number>();\n for (const r of ftsResults) {\n const score = Math.min(1, -r.rank / 20);\n scores.set(r.memoryId, score);\n }\n return scores;\n}\n\n// ── Scoring ───────────────────────────────────────────────────\n\ninterface ScoreParts {\n readonly textScore: number;\n readonly importanceScore: number;\n readonly recencyScore: number;\n readonly accessScore: number;\n readonly contextScore: number;\n readonly relationSource?: { readonly id: string; readonly title: string | null; readonly type: RelationType };\n}\n\nfunction computeScoreParts(\n memory: Memory,\n textScore: number,\n gitContext: GitContext,\n query: string,\n): ScoreParts {\n return {\n textScore,\n importanceScore: memory.importance,\n recencyScore: computeRecencyScore(memory.updatedAt),\n accessScore: computeAccessScore(memory.accessCount, memory.lastAccessed),\n contextScore: computeContextScore(memory.context, gitContext, query),\n };\n}\n\nfunction computeComposite(parts: ScoreParts): number {\n return (\n parts.textScore * SCORING_WEIGHTS.text +\n parts.importanceScore * SCORING_WEIGHTS.importance +\n parts.recencyScore * SCORING_WEIGHTS.recency +\n parts.accessScore * SCORING_WEIGHTS.access +\n parts.contextScore * SCORING_WEIGHTS.context\n );\n}\n\n/**\n * Recency score: 1.0 for today, decays exponentially.\n * Uses a 30-day half-life.\n */\nfunction computeRecencyScore(updatedAt: string): number {\n const ageMs = Date.now() - new Date(updatedAt).getTime();\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n if (ageDays < 0) return 1.0;\n return Math.exp(-ageDays * Math.LN2 / 30);\n}\n\n/**\n * Access score: logarithmic count x recency of last access.\n */\nfunction computeAccessScore(accessCount: number, lastAccessed: string | null): number {\n if (accessCount <= 0) return 0;\n const countScore = Math.min(1.0, Math.log10(accessCount + 1) / Math.log10(31));\n if (!lastAccessed) return countScore * 0.5;\n const ageDays = (Date.now() - new Date(lastAccessed).getTime()) / 86_400_000;\n const recency = Math.exp(-ageDays * Math.LN2 / 30);\n return countScore * (0.5 + 0.5 * recency);\n}\n\n// ── Explanation ───────────────────────────────────────────────\n\nfunction buildExplanation(parts: ScoreParts, memory: Memory): string {\n const factors: string[] = [];\n\n if (parts.textScore > 0.7) {\n factors.push(`High text match (${(parts.textScore * 100).toFixed(0)}%)`);\n } else if (parts.textScore > 0.3) {\n factors.push(`Moderate text match (${(parts.textScore * 100).toFixed(0)}%)`);\n }\n\n if (memory.importance > 0.7) {\n factors.push('High importance');\n }\n\n if (parts.recencyScore > 0.8) {\n factors.push('Very recent');\n } else if (parts.recencyScore > 0.5) {\n factors.push('Recent');\n }\n\n if (memory.accessCount > 10) {\n factors.push(`Frequently accessed (${memory.accessCount}x)`);\n } else if (memory.accessCount > 3) {\n factors.push(`Accessed ${memory.accessCount}x`);\n }\n\n if (parts.contextScore > 0.3) {\n factors.push('Context match');\n }\n\n const ageDays = Math.floor((Date.now() - new Date(memory.createdAt).getTime()) / 86_400_000);\n const stalenessThreshold = STALENESS_THRESHOLDS[memory.type];\n if (stalenessThreshold !== undefined && ageDays > stalenessThreshold) {\n factors.push(`${ageDays}d old - verify before acting`);\n }\n\n return factors.length > 0 ? factors.join(' + ') : 'Matched query';\n}\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface SessionContextResult {\n readonly section: 'context' | 'recent' | 'related';\n readonly result: SearchResult;\n}\n\n// Exported for testing\nexport { computeRecencyScore, computeAccessScore, computeComposite, computeScoreParts, ftsOnlyScores };\nexport type { ScoreParts };\n","import { z } from 'zod';\nimport { createHash } from 'node:crypto';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES, MEMORY_SOURCES } from '../types.js';\nimport { coerceStringArray } from '../types.js';\nimport { getGitContext } from '../utils/git-context.js';\nimport { validateMemoryContent } from '../utils/content-validation.js';\nimport { checkContradiction } from '../utils/contradiction.js';\n\n// In-memory dedup: content hash → timestamp. Catches parallel calls within same request.\nconst recentStores = new Map<string, number>();\nconst pendingStores = new Set<string>();\nconst DEDUP_WINDOW_MS = 10_000;\n\n// Tag normalization: lowercase, strip #, singularize common suffixes, apply aliases\nconst TAG_ALIASES: Record<string, string> = {\n bugs: 'bug', bugfix: 'bug', debugging: 'bug',\n decisions: 'decision', decided: 'decision',\n gotchas: 'gotcha', pitfall: 'gotcha', pitfalls: 'gotcha',\n howtos: 'howto', 'how-to': 'howto',\n patterns: 'pattern',\n todos: 'todo', fixme: 'todo',\n architectures: 'architecture', arch: 'architecture',\n};\n\nfunction normalizeTags(tags: readonly string[]): string[] {\n return [...new Set(tags.map((t) => {\n const stripped = t.replace(/^#/, '').toLowerCase().trim();\n return TAG_ALIASES[stripped] ?? stripped;\n }).filter(Boolean))];\n}\n\n// Auto-tag: detect common patterns in content\nconst AUTO_TAG_PATTERNS: readonly { readonly pattern: RegExp; readonly tag: string }[] = [\n { pattern: /\\b(bug|crash|error|fix(ed)?|broke)\\b/i, tag: 'bug' },\n { pattern: /\\b(decid|chose|decision|went with|picked)\\b/i, tag: 'decision' },\n { pattern: /\\b(gotcha|careful|watch out|trap|pitfall)\\b/i, tag: 'gotcha' },\n { pattern: /\\b(how to|steps to|run|install|deploy|command)\\b/i, tag: 'howto' },\n { pattern: /\\b(pattern|recurring|always|every time)\\b/i, tag: 'pattern' },\n];\n\nfunction autoTag(content: string, existingTags: readonly string[]): string[] {\n const existing = new Set(existingTags);\n const detected: string[] = [];\n for (const { pattern, tag } of AUTO_TAG_PATTERNS) {\n if (!existing.has(tag) && pattern.test(content)) {\n detected.push(tag);\n }\n }\n return detected;\n}\n\nconst inputSchema = {\n type: z.enum(MEMORY_TYPES).describe('Memory type: working, episodic, semantic, procedural, or pattern'),\n content: z.string().min(1).describe('The memory content (aim for ~2000 chars / ~500 tokens). Keep memories concise: capture the decision or insight, not the full context. Split large topics into separate memories.'),\n title: z.string().max(200).optional().describe('Short title for the memory'),\n tags: coerceStringArray.pipe(z.array(z.string()).max(20)).default([]).describe('Tags for categorization. Suggested: #bug, #decision, #gotcha, #howto, #pattern'),\n importance: z.number().min(0).max(1).default(0.5).describe('0-0.3 ephemeral, 0.3-0.6 reference, 0.6-0.8 important, 0.8-1.0 critical'),\n context: z.string().optional().describe('JSON: {\"files\": [...], \"branch\": \"...\", \"intent\": \"...\"}. Auto-detected from git if omitted.'),\n source: z.enum(MEMORY_SOURCES).default('manual').describe('How this memory was created'),\n project: z.string().max(200).optional().describe('Project scope. Omit to auto-detect from CWD (default). Pass a project name to scope the memory to that project. Omit for global/cross-project memories.'),\n};\n\nexport function registerStore(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_store',\n {\n description:\n 'Save something worth remembering to the knowledge base. '\n + 'Use when you learn a fact, make a decision, hit a bug, or discover a pattern that future sessions should know. '\n + 'Always search first to avoid duplicates — update existing memories when possible. '\n + 'Types: semantic (facts/decisions), procedural (how-to), episodic (what happened), pattern (recurring), working (scratch). '\n + 'Importance: 0.1 trivial, 0.5 useful, 0.8 important, 1.0 critical. '\n + 'Tags and git context are auto-detected if omitted. \"OK\" responses mean the memory already exists — no follow-up needed.',\n inputSchema,\n annotations: { idempotentHint: false },\n },\n async (args) => {\n const validation = validateMemoryContent(args.content);\n if (!validation.valid) {\n return {\n content: [{\n type: 'text' as const,\n text: `Rejected: ${validation.reason}`,\n }],\n isError: true,\n };\n }\n\n const context = args.context ?? JSON.stringify(getGitContext());\n const project = args.project ?? deps.project ?? undefined;\n\n // Dedup: in-memory guard catches parallel calls within same request.\n // Uses a pending Set to catch calls that arrive in the same tick.\n const contentHash = createHash('sha256').update(args.content).digest('hex');\n const now = Date.now();\n const lastStored = recentStores.get(contentHash);\n if (lastStored && (now - lastStored) < DEDUP_WINDOW_MS) {\n return {\n content: [{ type: 'text' as const, text: 'OK: this memory already exists in the knowledge base (duplicate detected). No action needed.' }],\n };\n }\n if (pendingStores.has(contentHash)) {\n return {\n content: [{ type: 'text' as const, text: 'OK: this memory is already being stored by a parallel call. No action needed.' }],\n };\n }\n pendingStores.add(contentHash);\n // Prune old entries\n for (const [key, ts] of recentStores) {\n if (now - ts > DEDUP_WINDOW_MS) recentStores.delete(key);\n }\n\n // Contradiction detection\n const contradictions: { id: string; title: string | null }[] = [];\n try {\n const existing = await deps.retrievalService.search({\n query: args.content.slice(0, 200),\n limit: 3,\n min_importance: 0,\n project,\n });\n for (const result of existing) {\n if (result.score > 0.6 && checkContradiction(args.content, result.memory.content)) {\n contradictions.push({ id: result.memory.id, title: result.memory.title });\n }\n }\n } catch {\n // Contradiction check is best-effort\n }\n\n // Normalize tags + auto-tag from content\n const normalizedTags = normalizeTags(args.tags);\n const autoTags = autoTag(args.content, normalizedTags);\n const finalTags = [...new Set([...normalizedTags, ...autoTags])];\n\n const memory = deps.memoryRepo.create(\n {\n type: args.type,\n content: args.content,\n title: args.title,\n tags: finalTags,\n importance: args.importance,\n context,\n source: args.source,\n project,\n },\n null,\n );\n\n // Mark as stored (dedup window starts now)\n recentStores.set(contentHash, Date.now());\n pendingStores.delete(contentHash);\n\n if (!memory) {\n return {\n content: [{ type: 'text' as const, text: 'OK: this memory already exists in the knowledge base (content_hash match). No action needed.' }],\n };\n }\n\n // Create contradiction relations\n for (const c of contradictions) {\n try {\n deps.relationRepo.create(memory.id, c.id, 'contradicts');\n } catch {\n // Relation creation is best-effort\n }\n }\n\n const parts: string[] = [\n `Stored memory ${memory.id} (type: ${memory.type}, importance: ${memory.importance})`,\n ];\n\n for (const warning of validation.warnings) {\n parts.push(`Warning: ${warning}`);\n }\n\n for (const c of contradictions) {\n parts.push(`Warning: potential contradiction with memory ${c.id}${c.title ? ` (\"${c.title}\")` : ''}. Linked with 'contradicts' relation.`);\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: parts.join('\\n'),\n }],\n };\n },\n );\n}\n","// ── Content Validation for memory_store ─────────────────────\n\nexport interface ValidationResult {\n readonly valid: boolean;\n readonly reason?: string;\n readonly warnings: readonly string[];\n}\n\nconst SOFT_LENGTH_LIMIT = 1500;\nconst HARD_LENGTH_LIMIT = 5000;\nconst CODE_RATIO_THRESHOLD = 0.5;\n\n/**\n * Validate memory content before storage.\n * Returns hard rejections (don't store) and soft warnings (store but warn).\n */\nexport function validateMemoryContent(content: string): ValidationResult {\n const warnings: string[] = [];\n\n // Hard reject: git log output\n if (isGitLog(content)) {\n return { valid: false, reason: 'Content looks like raw git log output. Use git log directly — don\\'t store it as memory.', warnings: [] };\n }\n\n // Hard reject: code-heavy content\n if (isCodeHeavy(content)) {\n return { valid: false, reason: 'Content is >50% code blocks. Code belongs in files, not memory. Store the insight or decision instead.', warnings: [] };\n }\n\n // Hard reject: too long\n if (content.length > HARD_LENGTH_LIMIT) {\n return { valid: false, reason: `Content is ${content.length} chars (limit: ${HARD_LENGTH_LIMIT}). Break it into smaller, atomic memories.`, warnings: [] };\n }\n\n // Soft warn: lengthy\n if (content.length > SOFT_LENGTH_LIMIT) {\n warnings.push(`Content is ${content.length} chars. Shorter memories (<${SOFT_LENGTH_LIMIT} chars) are easier to retrieve and less likely to decay.`);\n }\n\n return { valid: true, warnings };\n}\n\n/**\n * Content is >50% fenced code blocks.\n */\nexport function isCodeHeavy(content: string): boolean {\n const fencedBlockPattern = /```[\\s\\S]*?```/g;\n let codeChars = 0;\n let match: RegExpExecArray | null;\n\n while ((match = fencedBlockPattern.exec(content)) !== null) {\n codeChars += match[0].length;\n }\n\n return content.length > 0 && codeChars / content.length > CODE_RATIO_THRESHOLD;\n}\n\n/**\n * Content looks like raw git log output.\n * Matches patterns like \"commit abc123\\nAuthor: ...\\nDate: ...\"\n */\nexport function isGitLog(content: string): boolean {\n const lines = content.split('\\n');\n let gitLogLines = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (/^commit\\s+[0-9a-f]{7,40}$/i.test(trimmed)) gitLogLines++;\n else if (/^Author:\\s+.+/i.test(trimmed)) gitLogLines++;\n else if (/^Date:\\s+.+/i.test(trimmed)) gitLogLines++;\n else if (/^[0-9a-f]{7,12}\\s+\\S+/i.test(trimmed) && trimmed.length < 200) gitLogLines++;\n }\n\n // At least 3 git-log-like lines and they make up >30% of non-empty lines\n const nonEmptyLines = lines.filter(l => l.trim().length > 0).length;\n return gitLogLines >= 3 && nonEmptyLines > 0 && gitLogLines / nonEmptyLines > 0.3;\n}\n","// ── Contradiction Detection (keyword-overlap heuristic) ─────\n\nconst NEGATION_PATTERNS = [\n /\\bnot\\b/i,\n /\\bno longer\\b/i,\n /\\binstead of\\b/i,\n /\\breplaced\\b/i,\n /\\bremoved\\b/i,\n /\\bdon'?t\\b/i,\n /\\bwon'?t\\b/i,\n /\\bshouldn'?t\\b/i,\n /\\bdeprecated\\b/i,\n /\\bdisabled\\b/i,\n /\\bstopped\\b/i,\n /\\bavoid\\b/i,\n /\\bnever\\b/i,\n /\\bwithout\\b/i,\n];\n\nconst KEYWORD_OVERLAP_THRESHOLD = 0.4;\nconst MIN_KEYWORD_LENGTH = 3;\nconst STOP_WORDS = new Set([\n 'the', 'and', 'for', 'are', 'but', 'not', 'you', 'all', 'can', 'had',\n 'her', 'was', 'one', 'our', 'out', 'has', 'have', 'been', 'from', 'that',\n 'this', 'with', 'they', 'will', 'each', 'make', 'like', 'than', 'them',\n 'then', 'what', 'when', 'into', 'more', 'some', 'such', 'also', 'use',\n 'used', 'using', 'should', 'would', 'could', 'about', 'which', 'their',\n 'there', 'these', 'those', 'does', 'done', 'just', 'very',\n]);\n\n/**\n * Extract meaningful keywords from text.\n */\nfunction extractKeywords(text: string): ReadonlySet<string> {\n const words = text.toLowerCase().match(/[a-z][a-z0-9_-]+/g) ?? [];\n return new Set(\n words.filter(w => w.length >= MIN_KEYWORD_LENGTH && !STOP_WORDS.has(w)),\n );\n}\n\n/**\n * Check if new content potentially contradicts existing content.\n *\n * Heuristic: high keyword overlap + negation markers = likely contradiction.\n * Not perfect, but catches the common case of \"we used X\" vs \"we no longer use X\".\n */\nexport function checkContradiction(newContent: string, existingContent: string): boolean {\n const newKeywords = extractKeywords(newContent);\n const existingKeywords = extractKeywords(existingContent);\n\n if (newKeywords.size === 0 || existingKeywords.size === 0) return false;\n\n // Compute Jaccard-like overlap: |intersection| / |smaller set|\n let overlap = 0;\n for (const kw of newKeywords) {\n if (existingKeywords.has(kw)) overlap++;\n }\n\n const smallerSize = Math.min(newKeywords.size, existingKeywords.size);\n const overlapRatio = overlap / smallerSize;\n\n if (overlapRatio < KEYWORD_OVERLAP_THRESHOLD) return false;\n\n // High overlap — check for negation markers in the NEW content only.\n return NEGATION_PATTERNS.some(pattern => pattern.test(newContent));\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES, coerceStringArray } from '../types.js';\n\nconst inputSchema = {\n query: z.string().min(1).max(500).describe('Search query (natural language or keywords)'),\n id: z.string().optional().describe('Direct lookup by memory ID (bypasses search)'),\n type: z.enum(MEMORY_TYPES).optional().describe('Filter by memory type'),\n tags: coerceStringArray.pipe(z.array(z.string()).max(10)).optional().describe('Filter to memories containing ALL of these tags'),\n limit: z.number().int().min(1).max(50).default(10).describe('Maximum results to return'),\n min_importance: z.number().min(0).max(1).default(0).describe('Minimum importance threshold'),\n project: z.string().max(200).optional().describe('Project scope. Omit to search current project + global memories (default). Pass \"*\" to search ALL projects. Pass a project name to search that specific project + global memories.'),\n};\n\nexport function registerSearch(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_search',\n {\n description:\n 'Look up what you already know. Query the knowledge base before solving a problem or storing new information. '\n + 'Use when: checking if something was already decided, finding how-to steps, recalling past bugs, or deduping before a store. '\n + 'Related memories are surfaced automatically. Pass `id` for direct lookup, or filter by `type` and `tags`. '\n + 'Project scoping: by default, returns memories for the current project + global (unscoped) memories. '\n + 'Pass project=\"*\" to search across all projects. Pass a specific project name to search that project instead.',\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (args) => {\n // Project scoping: explicit param > auto-detected > undefined\n // \"*\" means search all projects (no project filter)\n const project = args.project === '*'\n ? undefined\n : (args.project ?? deps.project ?? undefined);\n\n const results = await deps.retrievalService.search({\n query: args.query,\n id: args.id,\n type: args.type,\n tags: args.tags,\n limit: args.limit,\n min_importance: args.min_importance,\n project,\n });\n\n if (results.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No memories found matching your query.' }],\n };\n }\n\n const formatted = results.map((r, i) => ({\n rank: i + 1,\n id: r.memory.id,\n type: r.memory.type,\n title: r.memory.title,\n content: r.memory.content,\n score: Math.round(r.score * 100) / 100,\n explanation: r.explanation,\n importance: r.memory.importance,\n tags: r.memory.tags,\n accessCount: r.memory.accessCount,\n createdAt: r.memory.createdAt,\n }));\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(formatted, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { memoryNotFound, formatMcpError } from '../utils/errors.js';\n\nconst inputSchema = {\n id: z.string().describe('ID of the memory to forget'),\n hard_delete: z.boolean().default(false).describe('true = permanent delete, false = set importance to 0 (soft delete)'),\n};\n\nexport function registerForget(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_forget',\n {\n description:\n 'Remove outdated or wrong information from the knowledge base. '\n + 'Default: soft-delete (fades away naturally). Pass hard_delete=true to erase permanently. '\n + 'Use memory_search to find the ID first.',\n inputSchema,\n annotations: { destructiveHint: true, idempotentHint: true },\n },\n async (args) => {\n const memory = deps.memoryRepo.getById(args.id);\n if (!memory) {\n return formatMcpError(memoryNotFound(args.id));\n }\n\n if (deps.project && memory.project !== null && memory.project !== deps.project) {\n return formatMcpError({\n what: `Memory ${args.id} belongs to project \"${memory.project}\".`,\n why: `Current project is \"${deps.project}\". Cross-project deletion is not allowed.`,\n fix: 'Switch to the correct project or use a global context.',\n });\n }\n\n if (args.hard_delete) {\n deps.memoryRepo.hardDelete(args.id);\n return {\n content: [{\n type: 'text' as const,\n text: `Permanently deleted memory ${args.id} (\"${memory.title ?? memory.content.slice(0, 50)}\")`,\n }],\n };\n }\n\n deps.memoryRepo.softDelete(args.id);\n return {\n content: [{\n type: 'text' as const,\n text: `Soft-deleted memory ${args.id} (importance set to 0, will decay naturally)`,\n }],\n };\n },\n );\n}\n","// ── Structured Error Formatting ──────────────────────────────\n// Every error answers: What happened? Why? What to do?\n\nexport interface StructuredError {\n readonly what: string;\n readonly why: string;\n readonly fix: string;\n}\n\nexport function formatError(err: StructuredError): string {\n return `${err.what}\\nWhy: ${err.why}\\nFix: ${err.fix}`;\n}\n\nexport function formatMcpError(err: StructuredError): { isError: true; content: [{ type: 'text'; text: string }] } {\n return {\n isError: true,\n content: [{ type: 'text' as const, text: formatError(err) }],\n };\n}\n\n// ── Common Error Templates ───────────────────────────────────\n\nexport function memoryNotFound(id: string): StructuredError {\n return {\n what: `Memory \"${id}\" not found.`,\n why: 'The ID may be incorrect, or the memory was deleted or pruned.',\n fix: 'Use memory_search to find valid IDs.',\n };\n}\n\nexport function databaseLocked(): StructuredError {\n return {\n what: 'Database is temporarily locked.',\n why: 'Another process is writing to the database (SQLITE_BUSY).',\n fix: 'Retry in a moment. If persistent, run: claude-launchpad doctor --fix',\n };\n}\n\nexport function databaseCorrupt(): StructuredError {\n return {\n what: 'Database integrity check failed.',\n why: 'The database file may be corrupted (disk error, incomplete write).',\n fix: 'Run: claude-launchpad doctor --fix (creates backup, reinitializes DB)',\n };\n}\n\nexport function diskFull(): StructuredError {\n return {\n what: 'Disk write failed — not enough space.',\n why: 'The disk partition containing ~/.agentic-memory is full.',\n fix: 'Free disk space, then run: claude-launchpad doctor --fix',\n };\n}\n\nexport function invalidInput(field: string, reason: string): StructuredError {\n return {\n what: `Invalid input: ${field}`,\n why: reason,\n fix: 'Check the parameter value and try again.',\n };\n}\n\n// ── SQLite Retry Logic ───────────────────────────────────────\n\nconst RETRY_DELAYS = [100, 200, 400] as const;\n\nexport function withRetry<T>(fn: () => T, label: string): T {\n for (let attempt = 0; attempt < RETRY_DELAYS.length; attempt++) {\n try {\n return fn();\n } catch (err) {\n if (isSqliteBusy(err) && attempt < RETRY_DELAYS.length - 1) {\n const delay = RETRY_DELAYS[attempt]!;\n process.stderr.write(`[memory] ${label}: SQLITE_BUSY, retrying in ${delay}ms\\n`);\n sleepSync(delay);\n continue;\n }\n throw err;\n }\n }\n // Unreachable, but TypeScript needs it\n throw new Error(`${label}: exhausted retries`);\n}\n\nfunction isSqliteBusy(err: unknown): boolean {\n if (err instanceof Error) {\n return err.message.includes('SQLITE_BUSY') || err.message.includes('database is locked');\n }\n return false;\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { RELATION_TYPES } from '../types.js';\nimport { memoryNotFound, formatMcpError } from '../utils/errors.js';\n\nconst inputSchema = {\n source_id: z.string().describe('ID of the source memory'),\n target_id: z.string().describe('ID of the target memory'),\n relation_type: z.enum(RELATION_TYPES).describe(\n 'Type of relation: relates_to, depends_on, contradicts, extends, implements, derived_from'\n ),\n};\n\nexport function registerRelate(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_relate',\n {\n description:\n 'Link two memories together so they surface as a group. '\n + 'Use when one memory extends, contradicts, depends on, or implements another. '\n + 'Linked memories stay relevant longer and appear together in search results.',\n inputSchema,\n annotations: { idempotentHint: true },\n },\n async (args) => {\n if (args.source_id === args.target_id) {\n return formatMcpError({\n what: 'Cannot create self-relation.',\n why: 'source_id and target_id are the same memory.',\n fix: 'Provide two different memory IDs.',\n });\n }\n\n const source = deps.memoryRepo.getById(args.source_id);\n if (!source) {\n return formatMcpError(memoryNotFound(args.source_id));\n }\n\n const target = deps.memoryRepo.getById(args.target_id);\n if (!target) {\n return formatMcpError(memoryNotFound(args.target_id));\n }\n\n if (deps.project) {\n for (const mem of [source, target]) {\n if (mem.project !== null && mem.project !== deps.project) {\n return formatMcpError({\n what: `Memory ${mem.id} belongs to project \"${mem.project}\".`,\n why: `Current project is \"${deps.project}\". Cross-project relations are not allowed.`,\n fix: 'Both memories must belong to the same project.',\n });\n }\n }\n }\n\n const created = deps.relationRepo.create(args.source_id, args.target_id, args.relation_type);\n\n if (!created) {\n return {\n content: [{\n type: 'text' as const,\n text: `Relation already exists: ${args.source_id} --[${args.relation_type}]--> ${args.target_id}`,\n }],\n };\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: `Created relation: \"${source.title ?? source.content.slice(0, 40)}\" --[${args.relation_type}]--> \"${target.title ?? target.content.slice(0, 40)}\"`,\n }],\n };\n },\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\nimport type { MemoryStats } from '../types.js';\nimport { statSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport function registerStats(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_stats',\n {\n description:\n 'See how much is in the knowledge base — total count, breakdown by type, storage size, and most-used memories.',\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async () => {\n const countByType = deps.memoryRepo.countByType();\n const total = deps.memoryRepo.count();\n const topInjected = deps.memoryRepo.topInjected(5);\n const totalRelations = deps.relationRepo.count();\n\n let dbSizeBytes = 0;\n try {\n const dbPath = join(deps.dataDir, 'memory.db');\n dbSizeBytes = statSync(dbPath).size;\n } catch {\n // :memory: or file not found\n }\n\n const { oldest, newest } = deps.memoryRepo.dateRange();\n\n const stats: MemoryStats = {\n totalMemories: total,\n byType: Object.fromEntries(\n MEMORY_TYPES.map(t => [t, countByType[t] ?? 0])\n ) as Record<string, number>,\n totalRelations,\n dbSizeBytes,\n oldestMemory: oldest,\n newestMemory: newest,\n topInjected,\n };\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(stats, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\n\nconst inputSchema = {\n limit: z.number().int().min(1).max(50).default(10).describe('Maximum memories to return'),\n type: z.enum(MEMORY_TYPES).optional().describe('Filter by memory type'),\n project: z.string().max(200).optional().describe('Project scope. Omit for current project + global memories (default). Pass \"*\" for ALL projects. Pass a project name for that specific project.'),\n};\n\nexport function registerRecent(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_recent',\n {\n description:\n 'Get caught up on what happened before this session. '\n + 'Returns memories relevant to the current branch/files, recent activity, and related context. '\n + 'Typically called at session start to restore working context. No query needed — it uses git state to find what matters. '\n + 'Project scoping: by default, returns memories for the current project + global memories. '\n + 'Pass project=\"*\" to include all projects.',\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (args) => {\n const project = args.project === '*'\n ? undefined\n : (args.project ?? deps.project ?? undefined);\n\n const results = deps.retrievalService.loadSessionContext({\n limit: args.limit,\n project,\n type: args.type,\n });\n\n if (results.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No memories found for this project.' }],\n };\n }\n\n const formatEntry = (entry: typeof results[number], rank: number) => ({\n rank,\n section: entry.section,\n id: entry.result.memory.id,\n type: entry.result.memory.type,\n title: entry.result.memory.title,\n content: entry.result.memory.content,\n importance: entry.result.memory.importance,\n tags: entry.result.memory.tags,\n score: Math.round(entry.result.score * 100) / 100,\n explanation: entry.result.explanation,\n createdAt: entry.result.memory.createdAt,\n });\n\n const contextMatched = results.filter(r => r.section === 'context').map((r, i) => formatEntry(r, i + 1));\n const recent = results.filter(r => r.section === 'recent').map((r, i) => formatEntry(r, i + 1));\n const related = results.filter(r => r.section === 'related').map((r, i) => formatEntry(r, i + 1));\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({ contextMatched, recent, related }, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { coerceStringArray } from '../types.js';\n\nconst inputSchema = {\n id: z.string().describe('Memory ID to update (use memory_search to find it)'),\n title: z.string().max(200).optional().describe('Updated title'),\n content: z.string().min(1).max(10000).optional().describe('Updated content'),\n tags: coerceStringArray.pipe(z.array(z.string()).max(20)).optional().describe('Updated tags'),\n importance: z.number().min(0).max(1).optional().describe('Updated importance (0-1)'),\n context: z.string().optional().describe('Updated context JSON'),\n};\n\nexport function registerUpdate(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_update',\n {\n description:\n 'Correct or improve an existing memory instead of creating a duplicate. '\n + 'Use when information has changed, a decision was revised, or a memory needs more detail. '\n + 'Keeps the memory\\'s history intact. Use memory_search to find the ID first.',\n inputSchema,\n annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },\n },\n async (args) => {\n const hasUpdate = args.title !== undefined || args.content !== undefined\n || args.tags !== undefined || args.importance !== undefined\n || args.context !== undefined;\n\n if (!hasUpdate) {\n return {\n content: [{ type: 'text' as const, text: 'No fields to update. Provide at least one of: title, content, tags, importance, context.' }],\n isError: true,\n };\n }\n\n const existing = deps.memoryRepo.getById(args.id);\n if (!existing) {\n return {\n content: [{ type: 'text' as const, text: `Memory ${args.id} not found.` }],\n isError: true,\n };\n }\n\n const updated = deps.memoryRepo.updateContent(args.id, {\n title: args.title,\n content: args.content,\n tags: args.tags,\n importance: args.importance,\n context: args.context,\n });\n\n if (!updated) {\n return {\n content: [{ type: 'text' as const, text: `Failed to update memory ${args.id}.` }],\n isError: true,\n };\n }\n\n const fields = [\n args.title !== undefined && 'title',\n args.content !== undefined && 'content',\n args.tags !== undefined && 'tags',\n args.importance !== undefined && 'importance',\n args.context !== undefined && 'context',\n ].filter(Boolean).join(', ');\n\n return {\n content: [{ type: 'text' as const, text: `Updated memory ${args.id} (fields: ${fields})` }],\n };\n },\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport type { RetrievalService } from '../services/retrieval-service.js';\nimport { registerStore } from './store.js';\nimport { registerSearch } from './search.js';\nimport { registerForget } from './forget.js';\nimport { registerRelate } from './relate.js';\nimport { registerStats } from './stats.js';\nimport { registerRecent } from './recent.js';\nimport { registerUpdate } from './update.js';\n\nexport interface ToolDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly retrievalService: RetrievalService;\n readonly dataDir: string;\n readonly project: string | null;\n}\n\nexport function registerTools(server: McpServer, deps: ToolDeps): void {\n registerStore(server, deps);\n registerSearch(server, deps);\n registerRecent(server, deps);\n registerForget(server, deps);\n registerRelate(server, deps);\n registerStats(server, deps);\n registerUpdate(server, deps);\n}\n"],"mappings":"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","names":["z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","require"]}
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-NAW47BYA.js";
9
9
  import {
10
10
  initStorage
11
- } from "./chunk-AUV2JTXX.js";
11
+ } from "./chunk-ULYVGZCJ.js";
12
12
  import "./chunk-V4NXT4KB.js";
13
13
  import {
14
14
  DEFAULT_DECAY_PARAMS,
@@ -22,9 +22,9 @@ import {
22
22
  RECENCY_HALF_LIFE,
23
23
  TYPE_INJECTION_BONUS,
24
24
  estimateTokens
25
- } from "./chunk-ZXJK7CHB.js";
26
- import "./chunk-PGDSAUP4.js";
27
- import "./chunk-4JNFXVVC.js";
25
+ } from "./chunk-FQRM2BKL.js";
26
+ import "./chunk-LYLUXVWT.js";
27
+ import "./chunk-UN23WZVQ.js";
28
28
 
29
29
  // src/commands/memory/subcommands/context.ts
30
30
  import { readFileSync, writeFileSync } from "fs";
@@ -439,4 +439,4 @@ async function runContext(opts) {
439
439
  export {
440
440
  runContext
441
441
  };
442
- //# sourceMappingURL=context-Q5ZQBY7O.js.map
442
+ //# sourceMappingURL=context-5AV2WCYW.js.map
@@ -5,8 +5,8 @@ import {
5
5
  loadConfig,
6
6
  migrate,
7
7
  resolveDataDir
8
- } from "./chunk-ZXJK7CHB.js";
9
- import "./chunk-PGDSAUP4.js";
8
+ } from "./chunk-FQRM2BKL.js";
9
+ import "./chunk-LYLUXVWT.js";
10
10
  import {
11
11
  getMemoryPlacement,
12
12
  log,
@@ -14,7 +14,7 @@ import {
14
14
  readSettingsLocalJson,
15
15
  writeSettingsJson,
16
16
  writeSettingsLocalJson
17
- } from "./chunk-4JNFXVVC.js";
17
+ } from "./chunk-UN23WZVQ.js";
18
18
 
19
19
  // src/commands/memory/subcommands/install.ts
20
20
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -181,7 +181,7 @@ function addToolPermissions(settings) {
181
181
  };
182
182
  }
183
183
  async function ensureNativeDeps() {
184
- const { cwdRequire } = await import("./require-deps-3GIE6TAG.js");
184
+ const { cwdRequire } = await import("./require-deps-DVEP4QBF.js");
185
185
  try {
186
186
  cwdRequire("better-sqlite3");
187
187
  return;
@@ -308,4 +308,4 @@ export {
308
308
  detectExistingSetup,
309
309
  runInstall
310
310
  };
311
- //# sourceMappingURL=install-LS7DTMIE.js.map
311
+ //# sourceMappingURL=install-6VOUHJTI.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  mergeFromRemote,
4
4
  parsePayload
5
- } from "./chunk-TSTTFR4B.js";
5
+ } from "./chunk-N6X3E5AX.js";
6
6
  import {
7
7
  assertGhAvailable,
8
8
  filenameToProject,
@@ -11,19 +11,19 @@ import {
11
11
  projectToFilename,
12
12
  readGistFile
13
13
  } from "./chunk-3UJYOWGF.js";
14
- import "./chunk-GRL3DOCP.js";
14
+ import "./chunk-F5PNKQKW.js";
15
15
  import {
16
16
  detectProject
17
17
  } from "./chunk-NAW47BYA.js";
18
18
  import {
19
19
  initStorage
20
- } from "./chunk-AUV2JTXX.js";
20
+ } from "./chunk-ULYVGZCJ.js";
21
21
  import "./chunk-V4NXT4KB.js";
22
- import "./chunk-ZXJK7CHB.js";
23
- import "./chunk-PGDSAUP4.js";
22
+ import "./chunk-FQRM2BKL.js";
23
+ import "./chunk-LYLUXVWT.js";
24
24
  import {
25
25
  log
26
- } from "./chunk-4JNFXVVC.js";
26
+ } from "./chunk-UN23WZVQ.js";
27
27
 
28
28
  // src/commands/memory/subcommands/pull.ts
29
29
  async function runPull(opts) {
@@ -33,7 +33,7 @@ async function runPull(opts) {
33
33
  log.error("No sync gist found. Run `memory push` first.");
34
34
  return;
35
35
  }
36
- const { requireMemoryDeps } = await import("./require-deps-3GIE6TAG.js");
36
+ const { requireMemoryDeps } = await import("./require-deps-DVEP4QBF.js");
37
37
  await requireMemoryDeps();
38
38
  const ctx = initStorage();
39
39
  try {
@@ -112,4 +112,4 @@ function printResult(result, project) {
112
112
  export {
113
113
  runPull
114
114
  };
115
- //# sourceMappingURL=pull-4NRD4GQ4.js.map
115
+ //# sourceMappingURL=pull-KRU2DRPZ.js.map