@remnic/core 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/access-cli.js +10 -9
  2. package/dist/access-cli.js.map +1 -1
  3. package/dist/access-http.d.ts +1 -1
  4. package/dist/access-mcp.d.ts +1 -1
  5. package/dist/access-schema.d.ts +40 -40
  6. package/dist/access-service.d.ts +1 -1
  7. package/dist/bootstrap.d.ts +1 -1
  8. package/dist/calibration.js +3 -2
  9. package/dist/calibration.js.map +1 -1
  10. package/dist/causal-consolidation.js +3 -2
  11. package/dist/causal-consolidation.js.map +1 -1
  12. package/dist/{chunk-QFQVZOGA.js → chunk-6UJQNRIO.js} +2 -2
  13. package/dist/{chunk-CDW777AI.js → chunk-LP47L3ZX.js} +2 -2
  14. package/dist/{chunk-LU3GQNDQ.js → chunk-M5ZBBBJI.js} +12 -1
  15. package/dist/chunk-M5ZBBBJI.js.map +1 -0
  16. package/dist/chunk-OOSWAUYB.js +47 -0
  17. package/dist/chunk-OOSWAUYB.js.map +1 -0
  18. package/dist/{chunk-YAPUAHAY.js → chunk-OTFNI3OO.js} +32 -32
  19. package/dist/{chunk-TKO4HZCK.js → chunk-UYSKNO6E.js} +1 -1
  20. package/dist/{chunk-KT4NEUNF.js → chunk-XUHI52HK.js} +80 -22
  21. package/dist/chunk-XUHI52HK.js.map +1 -0
  22. package/dist/cli.d.ts +2 -2
  23. package/dist/cli.js +1 -1
  24. package/dist/{engine-P26JFSVY.js → engine-2A6J4XEX.js} +2 -2
  25. package/dist/explicit-capture.d.ts +1 -1
  26. package/dist/extraction.js +4 -3
  27. package/dist/fallback-llm.d.ts +22 -3
  28. package/dist/fallback-llm.js +3 -2
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.js +10 -9
  31. package/dist/index.js.map +1 -1
  32. package/dist/models-json.d.ts +17 -0
  33. package/dist/models-json.js +12 -0
  34. package/dist/models-json.js.map +1 -0
  35. package/dist/orchestrator.d.ts +1 -1
  36. package/dist/orchestrator.js +10 -9
  37. package/dist/resolve-provider-secret.d.ts +29 -1
  38. package/dist/resolve-provider-secret.js +3 -1
  39. package/dist/schemas.d.ts +42 -42
  40. package/dist/summarizer.js +4 -3
  41. package/package.json +2 -1
  42. package/dist/chunk-KT4NEUNF.js.map +0 -1
  43. package/dist/chunk-LU3GQNDQ.js.map +0 -1
  44. package/dist/{chunk-QFQVZOGA.js.map → chunk-6UJQNRIO.js.map} +0 -0
  45. package/dist/{chunk-CDW777AI.js.map → chunk-LP47L3ZX.js.map} +0 -0
  46. package/dist/{chunk-YAPUAHAY.js.map → chunk-OTFNI3OO.js.map} +0 -0
  47. package/dist/{chunk-TKO4HZCK.js.map → chunk-UYSKNO6E.js.map} +0 -0
  48. package/dist/{engine-P26JFSVY.js.map → engine-2A6J4XEX.js.map} +0 -0
  49. package/dist/{orchestrator-zTa-Qo-1.d.ts → orchestrator-CIvLFHx3.d.ts} +2 -2
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/projection/index.ts","../src/utils/category-dir.ts","../src/onboarding/index.ts","../src/curation/index.ts","../src/dedup/index.ts","../src/review/index.ts","../src/sync/index.ts","../src/connectors/index.ts","../src/spaces/index.ts"],"sourcesContent":["/**\n * @remnic/core — Workspace Tree Projection\n *\n * Generates a human-readable `.engram/context-tree/` from canonical memory.\n * Each node is a `.md` file with rich metadata, * (provenance, trust, confidence, source anchors).\n * Manual edits are preserved in fenced blocks.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getCategoryDir, ALL_CATEGORY_KEYS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface TreeNode {\n /** Relative path from context-tree root, e.g. \"entities/claude.md\" */\n path: string;\n /** Category from canonical memory */\n category: string;\n /** Human-readable title */\n title: string;\n /** File content (rendered markdown) */\n content: string;\n /** Source memory IDs that contributed to this node */\n sourceAnchors: string[];\n /** Confidence (0-1) */\n confidence: number;\n /** Trust zone classification */\n confidenceTier: string;\n /** When this node was generated */\n generatedAt: string;\n /** Provenance chain */\n provenance: ProvenanceEntry[];\n}\n\nexport interface ProvenanceEntry {\n memoryId: string;\n source: string;\n extracted: string;\n}\n\nexport interface GenerateOptions {\n /** Memory root directory (e.g. ~/.openclaw/workspace/memory/local) */\n memoryDir: string;\n /** Output directory (e.g. .engram/context-tree) */\n outputDir: string;\n /** Categories to include (default: all) */\n categories?: string[];\n /** Whether to include entity graph */\n includeEntities?: boolean;\n /** Whether to include orphaned questions */\n includeQuestions?: boolean;\n /** Max nodes per category (default: unlimited) */\n maxPerCategory?: number;\n /** Whether to watch for changes and regenerate incrementally */\n watch?: boolean;\n}\n\nexport interface GenerateResult {\n nodesGenerated: number;\n nodesSkipped: number;\n categories: Record<string, number>;\n durationMs: number;\n outputDir: string;\n}\n\n// ── Generation ──────────────────────────────────────────────────────────────\n\n/**\n * Generate a context tree from canonical memory.\n *\n * Reads memory `.md` files from the source directory, * and projects them into a clean, * human-readable tree structure at `outputDir`.\n */\nexport async function generateContextTree(options: GenerateOptions): Promise<GenerateResult> {\n const startTime = Date.now();\n const {\n memoryDir,\n outputDir,\n categories: filterCategories,\n includeEntities = true,\n includeQuestions = true,\n maxPerCategory = Infinity,\n } = options;\n\n let nodesGenerated = 0;\n let nodesSkipped = 0;\n const categoryCounts: Record<string, number> = {};\n\n // Ensure output directory exists\n fs.mkdirSync(outputDir, { recursive: true });\n\n // Process each category (exclude 'question' — handled by separate includeQuestions pass)\n const allCategories = filterCategories ?? ALL_CATEGORY_KEYS.filter((c) => c !== \"question\");\n\n for (const category of allCategories) {\n const categoryDir = getCategoryDir(memoryDir, category);\n if (!fs.existsSync(categoryDir)) continue;\n\n categoryCounts[category] = 0;\n const files = walkR(categoryDir);\n let count = 0;\n\n for (const filePath of files) {\n if (count >= maxPerCategory) {\n nodesSkipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const fm = parseFrontmatter(content);\n if (!fm) {\n nodesSkipped++;\n continue;\n }\n\n const node = projectNode(filePath, category, fm, content);\n if (!node) {\n nodesSkipped++;\n continue;\n }\n\n // Write node to output\n const outputPath = path.join(outputDir, node.path);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, node.content);\n\n nodesGenerated++;\n categoryCounts[category] = (categoryCounts[category] ?? 0) + 1;\n count++;\n }\n }\n\n // Process entities\n if (includeEntities) {\n const entitiesDir = path.join(memoryDir, \"entities\");\n if (fs.existsSync(entitiesDir)) {\n categoryCounts[\"entity\"] = 0;\n const entityFiles = walkR(entitiesDir);\n let count = 0;\n\n for (const filePath of entityFiles) {\n if (count >= maxPerCategory) {\n nodesSkipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const fileName = path.basename(filePath, \".md\");\n const node = projectEntityNode(fileName, content);\n\n const outputPath = path.join(outputDir, \"entities\", `${fileName}.md`);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, node.content);\n\n nodesGenerated++;\n categoryCounts[\"entity\"] = (categoryCounts[\"entity\"] ?? 0) + 1;\n count++;\n }\n }\n }\n\n // Process questions\n if (includeQuestions) {\n const questionsDir = path.join(memoryDir, \"questions\");\n if (fs.existsSync(questionsDir)) {\n categoryCounts[\"question\"] = 0;\n const qFiles = walkR(questionsDir);\n let count = 0;\n\n for (const filePath of qFiles) {\n if (count >= maxPerCategory) {\n nodesSkipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const fm = parseFrontmatter(content);\n if (!fm) {\n nodesSkipped++;\n continue;\n }\n\n const node = projectNode(filePath, \"question\", fm, content);\n if (!node) {\n nodesSkipped++;\n continue;\n }\n\n const outputPath = path.join(outputDir, node.path);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, node.content);\n\n nodesGenerated++;\n categoryCounts[\"question\"] = (categoryCounts[\"question\"] ?? 0) + 1;\n count++;\n }\n }\n }\n\n // Write index\n const index = generateIndex(categoryCounts, outputDir);\n fs.writeFileSync(path.join(outputDir, \"INDEX.md\"), index);\n\n return {\n nodesGenerated,\n nodesSkipped,\n categories: categoryCounts,\n durationMs: Date.now() - startTime,\n outputDir,\n };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n\nfunction walkR(dir: string): string[] {\n const results: string[] = [];\n function walk(directory: string): void {\n for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {\n const fullPath = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath);\n } else if (entry.name.endsWith(\".md\")) {\n results.push(fullPath);\n }\n }\n }\n walk(dir);\n return results;\n}\n\ninterface Frontmatter {\n id: string;\n category: string;\n created: string;\n updated: string;\n confidence: number;\n confidenceTier: string;\n tags: string[];\n source: string;\n entityRef?: string;\n lifecycleState?: string;\n}\n\nfunction parseFrontmatter(content: string): Frontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fmText = match[1];\n const fm: Record<string, unknown> = {};\n for (const line of fmText.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n if (key === \"tags\") {\n try {\n fm[key] = JSON.parse(value) as string[];\n } catch {\n fm[key] = [] as string[];\n }\n } else if (key === \"confidence\") {\n const parsed = parseFloat(value);\n fm[key] = Number.isFinite(parsed) ? parsed : 0;\n } else {\n fm[key] = value;\n }\n }\n return fm as unknown as Frontmatter;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction projectNode(\n filePath: string,\n category: string,\n fm: Frontmatter,\n rawContent: string,\n): TreeNode | null {\n const body = extractBody(rawContent);\n const fileName = path.basename(filePath, \".md\");\n const dateDir = path.basename(path.dirname(filePath));\n\n // Build relative path: category/date/file or just category/file\n let relPath: string;\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(dateDir)) {\n relPath = path.join(category, dateDir, `${fileName}.md`);\n } else {\n relPath = path.join(category, `${fileName}.md`);\n }\n\n const generatedAt = new Date().toISOString();\n\n const md = `# ${fm.id}\n\n> **Category:** ${fm.category}\n> **Created:** ${fm.created}\n> **Updated:** ${fm.updated ?? fm.created}\n> **Confidence:** ${fm.confidence} (${fm.confidenceTier}${fm.lifecycleState ? `, ${fm.lifecycleState}` : \"\"})\n${fm.tags?.length ? `\\n> **Tags:** ${fm.tags.join(\", \")}` : \"\"}\n${fm.entityRef ? `\\n> **Entity:** ${fm.entityRef}` : \"\"}\n> **Source:** ${fm.source ?? \"unknown\"}\n> **Projected:** ${generatedAt}\n\n---\n\n${body}\n`;\n\n return {\n path: relPath,\n category,\n title: fm.id,\n content: md,\n sourceAnchors: [fm.id],\n confidence: fm.confidence ?? 0,\n confidenceTier: fm.confidenceTier ?? \"unknown\",\n generatedAt,\n provenance: [{\n memoryId: fm.id,\n source: fm.source ?? \"unknown\",\n extracted: fm.created,\n }],\n };\n}\n\nfunction projectEntityNode(fileName: string, content: string): TreeNode {\n const generatedAt = new Date().toISOString();\n\n const md = `> **Projected:** ${generatedAt}\n> **Source:** canonical\n\n---\n\n${content}\n`;\n\n return {\n path: path.join(\"entities\", `${fileName}.md`),\n category: \"entity\",\n title: fileName,\n content: md,\n sourceAnchors: [fileName],\n confidence: 1,\n confidenceTier: \"explicit\",\n generatedAt,\n provenance: [{\n memoryId: fileName,\n source: \"canonical\",\n extracted: generatedAt,\n }],\n };\n}\n\nfunction generateIndex(\n categoryCounts: Record<string, number>,\n outputDir: string,\n): string {\n const lines = [\n \"# Context Tree Index\",\n \"\",\n `Generated: ${new Date().toISOString()}`,\n \"\",\n \"## Summary\",\n \"\",\n `| Category | Count |`,\n `|----------|-------|`,\n ];\n\n let total = 0;\n for (const [cat, count] of Object.entries(categoryCounts).sort()) {\n lines.push(`| ${cat} | ${count} |`);\n total += count;\n }\n\n lines.push(\"\");\n lines.push(`**Total:** ${total} nodes`);\n lines.push(\"\");\n lines.push(\"## Structure\");\n lines.push(\"\");\n lines.push(\"```\");\n lines.push(\"context-tree/\");\n lines.push(\"├── entities/ # Entity knowledge graph\");\n lines.push(\"├── fact/ # Factual memories (date-partitioned)\");\n lines.push(\"├── correction/ # Correction memories\");\n lines.push(\"├── decision/ # Decisions\");\n lines.push(\"├── moment/ # Notable moments\");\n lines.push(\"├── preference/ # Preferences\");\n lines.push(\"├── principle/ # Principles\");\n lines.push(\"├── question/ # Open questions\");\n lines.push(\"└── INDEX.md # This file\");\n lines.push(\"```\");\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","/**\n * @remnic/core — Category Directory Map\n *\n * Shared mapping of memory category names to directory names.\n * Single source of truth — import from here instead of copy-pasting.\n */\n\nimport path from \"node:path\";\n\nexport const CATEGORY_DIR_MAP: Record<string, string> = {\n correction: \"corrections\",\n question: \"questions\",\n preference: \"preferences\",\n decision: \"decisions\",\n moment: \"moments\",\n commitment: \"commitments\",\n principle: \"principles\",\n rule: \"rules\",\n skill: \"skills\",\n relationship: \"relationships\",\n};\n\n/** All directory names derived from CATEGORY_DIR_MAP, plus \"facts\" (the default). */\nexport const ALL_CATEGORY_DIRS: string[] = [\n \"facts\",\n ...Object.values(CATEGORY_DIR_MAP),\n];\n\n/** All category keys (singular form) — used when iterating categories and calling getCategoryDir. */\nexport const ALL_CATEGORY_KEYS: string[] = [\n \"fact\",\n ...Object.keys(CATEGORY_DIR_MAP),\n];\n\n/**\n * Resolve a category name to its directory path under memoryDir.\n * Falls back to `facts/` for unknown categories.\n */\nexport function getCategoryDir(memoryDir: string, category: string): string {\n const dir = CATEGORY_DIR_MAP[category];\n return dir ? path.join(memoryDir, dir) : path.join(memoryDir, \"facts\");\n}\n","/**\n * @remnic/core — Onboarding\n *\n * Detects project language, shape, and documentation to produce\n * an onboarding plan for memory ingestion.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface OnboardOptions {\n /** Directory to scan (defaults to cwd) */\n directory: string;\n /** Max depth to walk (default: 6) */\n maxDepth?: number;\n /** Directories to skip */\n excludeDirs?: string[];\n}\n\nexport interface LanguageInfo {\n /** Language name (e.g. \"TypeScript\", \"Python\") */\n language: string;\n /** Confidence in detection (0-1) */\n confidence: number;\n /** Evidence (e.g. [\"package.json\", \"tsconfig.json\", \"*.ts files\"]) */\n evidence: string[];\n}\n\nexport interface DocFile {\n /** Absolute path */\n path: string;\n /** Relative path from project root */\n relativePath: string;\n /** Estimated type */\n kind: \"readme\" | \"changelog\" | \"contributing\" | \"license\" | \"config\" | \"docs\" | \"other\";\n /** File size in bytes */\n size: number;\n}\n\nexport type ProjectShape = \"app\" | \"library\" | \"monorepo\" | \"workspace\" | \"script\" | \"unknown\";\n\nexport interface OnboardResult {\n /** Project root */\n directory: string;\n /** Detected languages (sorted by confidence) */\n languages: LanguageInfo[];\n /** Detected project shape */\n shape: ProjectShape;\n /** Shape evidence */\n shapeEvidence: string[];\n /** Discovered documentation files */\n docs: DocFile[];\n /** Total files scanned */\n totalFiles: number;\n /** Duration in ms */\n durationMs: number;\n /** Suggested ingestion plan */\n plan: IngestionPlan;\n}\n\nexport interface IngestionPlan {\n /** Priority files to ingest first */\n priorityFiles: DocFile[];\n /** Estimated total files to ingest */\n estimatedFiles: number;\n /** Recommended categories */\n categories: string[];\n /** Suggested memory namespace */\n suggestedNamespace: string;\n}\n\n// ── Language detection rules ─────────────────────────────────────────────────\n\ninterface LanguageRule {\n language: string;\n extensions: string[];\n manifests: string[];\n configFiles: string[];\n}\n\nconst LANGUAGE_RULES: LanguageRule[] = [\n {\n language: \"TypeScript\",\n extensions: [\".ts\", \".tsx\"],\n manifests: [\"package.json\"],\n configFiles: [\"tsconfig.json\", \"tsup.config.ts\"],\n },\n {\n language: \"JavaScript\",\n extensions: [\".js\", \".jsx\", \".mjs\", \".cjs\"],\n manifests: [\"package.json\"],\n configFiles: [\".eslintrc\", \".prettierrc\"],\n },\n {\n language: \"Python\",\n extensions: [\".py\", \".pyi\"],\n manifests: [\"pyproject.toml\", \"setup.py\", \"setup.cfg\", \"requirements.txt\"],\n configFiles: [\"mypy.ini\", \".flake8\", \"tox.ini\"],\n },\n {\n language: \"Go\",\n extensions: [\".go\"],\n manifests: [\"go.mod\", \"go.sum\"],\n configFiles: [],\n },\n {\n language: \"Rust\",\n extensions: [\".rs\"],\n manifests: [\"Cargo.toml\"],\n configFiles: [],\n },\n {\n language: \"Ruby\",\n extensions: [\".rb\"],\n manifests: [\"Gemfile\", \"*.gemspec\"],\n configFiles: [\".rubocop.yml\"],\n },\n {\n language: \"PHP\",\n extensions: [\".php\"],\n manifests: [\"composer.json\"],\n configFiles: [\"phpcs.xml\"],\n },\n {\n language: \"Java\",\n extensions: [\".java\", \".kt\"],\n manifests: [\"pom.xml\", \"build.gradle\", \"build.gradle.kts\"],\n configFiles: [],\n },\n {\n language: \"Swift\",\n extensions: [\".swift\"],\n manifests: [\"Package.swift\", \"Podfile\"],\n configFiles: [],\n },\n {\n language: \"C#\",\n extensions: [\".cs\"],\n manifests: [\"*.csproj\", \"*.sln\"],\n configFiles: [],\n },\n {\n language: \"Shell\",\n extensions: [\".sh\", \".bash\", \".zsh\"],\n manifests: [],\n configFiles: [],\n },\n {\n language: \"Dart\",\n extensions: [\".dart\"],\n manifests: [\"pubspec.yaml\"],\n configFiles: [],\n },\n {\n language: \"Elixir\",\n extensions: [\".ex\", \".exs\"],\n manifests: [\"mix.exs\"],\n configFiles: [],\n },\n];\n\nconst DEFAULT_EXCLUDE = new Set([\n \"node_modules\",\n \".git\",\n \"vendor\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n \"dist\",\n \"build\",\n \".next\",\n \".nuxt\",\n \"target\",\n \"coverage\",\n \".engram\",\n]);\n\n// ── Main function ────────────────────────────────────────────────────────────\n\nexport function onboard(options: OnboardOptions): OnboardResult {\n const startTime = Date.now();\n const {\n directory,\n maxDepth = 6,\n excludeDirs = [],\n } = options;\n\n const exclude = new Set([...DEFAULT_EXCLUDE, ...excludeDirs]);\n\n // Collect all files\n const files = walkDir(directory, exclude, maxDepth);\n\n // Detect languages\n const languages = detectLanguages(files, directory);\n\n // Detect shape\n const { shape, evidence: shapeEvidence } = detectShape(files, directory);\n\n // Discover docs\n const docs = discoverDocs(files, directory);\n\n // Build plan\n const plan = buildPlan(languages, shape, docs, directory);\n\n return {\n directory,\n languages,\n shape,\n shapeEvidence,\n docs,\n totalFiles: files.length,\n durationMs: Date.now() - startTime,\n plan,\n };\n}\n\n// ── Walk directory ───────────────────────────────────────────────────────────\n\nfunction walkDir(\n root: string,\n exclude: Set<string>,\n maxDepth: number,\n): string[] {\n const results: string[] = [];\n\n function walk(dir: string, depth: number): void {\n if (depth > maxDepth) return;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (exclude.has(entry.name)) continue;\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath, depth + 1);\n } else if (entry.isFile()) {\n results.push(fullPath);\n }\n }\n }\n\n walk(root, 0);\n return results;\n}\n\n// ── Language detection ───────────────────────────────────────────────────────\n\nfunction detectLanguages(files: string[], root: string): LanguageInfo[] {\n const results: LanguageInfo[] = [];\n\n // Count extensions\n const extCounts = new Map<string, number>();\n for (const f of files) {\n const ext = path.extname(f).toLowerCase();\n if (ext) extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);\n }\n\n // Check manifests at root level\n const rootFiles = new Set(\n files\n .filter((f) => path.dirname(f) === root)\n .map((f) => path.basename(f)),\n );\n\n for (const rule of LANGUAGE_RULES) {\n const evidence: string[] = [];\n let score = 0;\n\n // Extension matches\n let extMatch = 0;\n for (const ext of rule.extensions) {\n const count = extCounts.get(ext) ?? 0;\n if (count > 0) {\n extMatch += count;\n evidence.push(`${ext} files (${count})`);\n }\n }\n score += Math.min(extMatch * 0.05, 0.5);\n\n // Manifest matches\n for (const manifest of rule.manifests) {\n if (manifest.includes(\"*\")) {\n // Glob pattern — e.g. \"*.gemspec\" matches files ending with \".gemspec\"\n const suffix = manifest.replaceAll(/\\*/g, \"\");\n if ([...rootFiles].some((f) => f.endsWith(suffix))) {\n score += 0.2;\n evidence.push(manifest);\n }\n } else if (rootFiles.has(manifest)) {\n score += 0.2;\n evidence.push(manifest);\n }\n }\n\n // Config matches\n for (const cfg of rule.configFiles) {\n if (rootFiles.has(cfg)) {\n score += 0.1;\n evidence.push(cfg);\n }\n }\n\n if (score > 0) {\n results.push({\n language: rule.language,\n confidence: Math.min(score, 1),\n evidence,\n });\n }\n }\n\n return results.sort((a, b) => b.confidence - a.confidence);\n}\n\n// ── Shape detection ──────────────────────────────────────────────────────────\n\nfunction detectShape(\n files: string[],\n root: string,\n): { shape: ProjectShape; evidence: string[] } {\n const rootFiles = new Set(\n files\n .filter((f) => path.dirname(f) === root)\n .map((f) => path.basename(f)),\n );\n\n const rootDirs = new Set<string>();\n try {\n for (const entry of fs.readdirSync(root, { withFileTypes: true })) {\n if (entry.isDirectory()) rootDirs.add(entry.name);\n }\n } catch {\n // ignore\n }\n\n const evidence: string[] = [];\n\n // Monorepo: workspace packages/ or libs/ dirs + root package.json with workspaces\n if (rootFiles.has(\"package.json\")) {\n const pkg = readJsonSafe(path.join(root, \"package.json\"));\n if (pkg?.workspaces) {\n evidence.push(\"package.json has workspaces\");\n return { shape: \"monorepo\", evidence };\n }\n }\n\n if (rootDirs.has(\"packages\") || rootDirs.has(\"libs\")) {\n evidence.push(\"has packages/ or libs/ directory\");\n return { shape: \"monorepo\", evidence };\n }\n\n // Workspace: pnpm-workspace.yaml, Cargo workspace, go.work\n if (rootFiles.has(\"pnpm-workspace.yaml\") || rootFiles.has(\"go.work\")) {\n evidence.push(\"workspace manifest found\");\n return { shape: \"workspace\", evidence };\n }\n\n const cargoToml = readTomlWorkspace(path.join(root, \"Cargo.toml\"));\n if (cargoToml) {\n evidence.push(\"Cargo.toml has workspace\");\n return { shape: \"workspace\", evidence };\n }\n\n // Library: has lib/ or src/index.*, exports in package.json\n if (rootFiles.has(\"package.json\")) {\n const pkg = readJsonSafe(path.join(root, \"package.json\"));\n if (pkg?.exports || pkg?.main) {\n // If it also has \"bin\", it's more of an app\n if (pkg?.bin) {\n evidence.push(\"package.json has bin\");\n return { shape: \"app\", evidence };\n }\n evidence.push(\"package.json has exports/main\");\n return { shape: \"library\", evidence };\n }\n }\n\n // Check for app indicators\n if (\n rootFiles.has(\"Dockerfile\") ||\n rootFiles.has(\"docker-compose.yml\") ||\n rootFiles.has(\"docker-compose.yaml\") ||\n rootDirs.has(\"app\") ||\n rootDirs.has(\"src\") && rootDirs.has(\"public\")\n ) {\n evidence.push(\"app-like structure detected\");\n return { shape: \"app\", evidence };\n }\n\n // Script: few files, no package manifest\n if (files.length <= 5 && !rootFiles.has(\"package.json\") && !rootFiles.has(\"pyproject.toml\")) {\n evidence.push(\"few files, no manifest\");\n return { shape: \"script\", evidence };\n }\n\n return { shape: \"unknown\", evidence: [\"no strong shape signal\"] };\n}\n\n// ── Doc discovery ────────────────────────────────────────────────────────────\n\nfunction discoverDocs(files: string[], root: string): DocFile[] {\n const docs: DocFile[] = [];\n const docPatterns: Array<{ pattern: RegExp; kind: DocFile[\"kind\"] }> = [\n { pattern: /^readme(\\.\\w+)?$/i, kind: \"readme\" },\n { pattern: /^changelog(\\.\\w+)?$/i, kind: \"changelog\" },\n { pattern: /^changes(\\.\\w+)?$/i, kind: \"changelog\" },\n { pattern: /^contributing(\\.\\w+)?$/i, kind: \"contributing\" },\n { pattern: /^code[_-]of[_-]conduct(\\.\\w+)?$/i, kind: \"contributing\" },\n { pattern: /^license(\\.\\w+)?$/i, kind: \"license\" },\n { pattern: /^copying(\\.\\w+)?$/i, kind: \"license\" },\n { pattern: /^\\.env\\.example$/i, kind: \"config\" },\n { pattern: /^\\.editorconfig$/i, kind: \"config\" },\n ];\n\n for (const filePath of files) {\n const basename = path.basename(filePath).toLowerCase();\n const relPath = path.relative(root, filePath);\n let kind: DocFile[\"kind\"] | undefined;\n\n // Check against patterns\n for (const { pattern, kind: k } of docPatterns) {\n if (pattern.test(basename)) {\n kind = k;\n break;\n }\n }\n\n // Check docs/ directories\n if (!kind && isUnderDocsDir(relPath)) {\n kind = \"docs\";\n }\n\n // Check markdown files at root or in docs/\n if (!kind && (basename.endsWith(\".md\") || basename.endsWith(\".mdx\"))) {\n if (path.dirname(relPath) === \".\" || isUnderDocsDir(relPath)) {\n kind = \"docs\";\n }\n }\n\n if (kind) {\n let size = 0;\n try {\n size = fs.statSync(filePath).size;\n } catch {\n // ignore\n }\n docs.push({\n path: filePath,\n relativePath: relPath,\n kind,\n size,\n });\n }\n }\n\n return docs;\n}\n\nfunction isUnderDocsDir(relPath: string): boolean {\n const parts = relPath.split(path.sep);\n return parts[0] === \"docs\" || parts[0] === \"doc\" || parts[0] === \"documentation\";\n}\n\n// ── Plan generation ──────────────────────────────────────────────────────────\n\nfunction buildPlan(\n languages: LanguageInfo[],\n shape: ProjectShape,\n docs: DocFile[],\n _root: string,\n): IngestionPlan {\n // Priority: README, CONTRIBUTING, then other docs\n const priorityOrder: Record<DocFile[\"kind\"], number> = {\n readme: 0,\n contributing: 1,\n changelog: 2,\n license: 3,\n docs: 4,\n config: 5,\n other: 6,\n };\n\n const priorityFiles = [...docs]\n .filter((d) => d.size > 0)\n .sort((a, b) => priorityOrder[a.kind] - priorityOrder[b.kind]);\n\n // Recommended categories based on project shape\n const categories: string[] = [\"fact\", \"preference\", \"decision\", \"principle\"];\n if (shape === \"monorepo\" || shape === \"workspace\") {\n categories.push(\"entity\");\n }\n\n // Namespace suggestion from primary language\n const suggestedNamespace = languages.length > 0\n ? languages[0].language.toLowerCase()\n : \"project\";\n\n return {\n priorityFiles,\n estimatedFiles: docs.filter((d) => d.size > 0).length,\n categories,\n suggestedNamespace,\n };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction readJsonSafe(filePath: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(filePath, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction readTomlWorkspace(filePath: string): boolean {\n try {\n const content = fs.readFileSync(filePath, \"utf8\");\n return content.includes(\"[workspace]\");\n } catch {\n return false;\n }\n}\n","/**\n * @remnic/core — Curation\n *\n * Deliberate ingestion of files into memory with provenance tracking.\n * Supports statement-level extraction, dedup, and contradiction checks.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { getCategoryDir, ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface CurateOptions {\n /** File or directory path to curate */\n targetPath: string;\n /** Memory root directory for writing */\n memoryDir: string;\n /** Source label (e.g. \"manual\", \"docs\", \"onboarding\") */\n source?: string;\n /** Category override (default: auto-detect) */\n category?: string;\n /** Confidence to assign (default: 0.9 for curated items) */\n confidence?: number;\n /** Entity reference to attach */\n entityRef?: string;\n /** Tags to add */\n tags?: string[];\n /** Whether to perform dedup check against existing memories */\n checkDuplicates?: boolean;\n /** Whether to detect contradictions */\n checkContradictions?: boolean;\n /** Whether to write files (default: true). False = dry run */\n write?: boolean;\n}\n\nexport interface CuratedStatement {\n /** Unique ID for this statement */\n id: string;\n /** The extracted statement text */\n content: string;\n /** Category */\n category: string;\n /** Confidence */\n confidence: number;\n /** Provenance info */\n provenance: StatementProvenance;\n /** Hash of content for dedup */\n contentHash: string;\n /** Tags */\n tags: string[];\n /** Entity reference */\n entityRef?: string;\n}\n\nexport interface StatementProvenance {\n /** Source file path */\n sourcePath: string;\n /** Relative path from project root */\n relativePath: string;\n /** Source label */\n source: string;\n /** Line number if extractable (0 = unknown) */\n lineNumber: number;\n /** Timestamp of ingestion */\n ingestedAt: string;\n /** Hash of the source file for diff tracking */\n sourceFileHash: string;\n}\n\nexport interface CurateResult {\n /** Statements extracted */\n statements: CuratedStatement[];\n /** Files processed */\n filesProcessed: number;\n /** Files skipped (empty, binary, etc.) */\n filesSkipped: number;\n /** Duplicate statements found (if checkDuplicates) */\n duplicates: DuplicateResult[];\n /** Contradictions found (if checkContradictions) */\n contradictions: ContradictionResult[];\n /** Memory files written */\n written: string[];\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface DuplicateResult {\n /** New statement */\n newStatement: CuratedStatement;\n /** Existing memory ID that matches */\n existingId: string;\n /** Similarity score (0-1) */\n similarity: number;\n /** Recommended action */\n action: \"skip\" | \"merge\" | \"keep\";\n}\n\nexport interface ContradictionResult {\n /** New statement */\n newStatement: CuratedStatement;\n /** Conflicting memory ID */\n conflictingId: string;\n /** The conflicting content */\n conflictingContent: string;\n /** Severity */\n severity: \"high\" | \"medium\" | \"low\";\n}\n\n// ── Main function ────────────────────────────────────────────────────────────\n\nexport async function curate(options: CurateOptions): Promise<CurateResult> {\n const startTime = Date.now();\n const {\n targetPath,\n memoryDir,\n source = \"curation\",\n category: categoryOverride,\n confidence = 0.9,\n entityRef,\n tags = [],\n checkDuplicates = true,\n checkContradictions = false,\n write = true,\n } = options;\n\n const statements: CuratedStatement[] = [];\n const written: string[] = [];\n const duplicates: DuplicateResult[] = [];\n const contradictions: ContradictionResult[] = [];\n let filesProcessed = 0;\n let filesSkipped = 0;\n\n // Determine targets\n const targets = resolveTargets(targetPath);\n\n // Load existing memories for dedup/contradiction checks\n const existingMemories = checkDuplicates || checkContradictions\n ? loadExistingMemories(memoryDir)\n : new Map();\n\n // Process each file\n for (const filePath of targets) {\n const content = readFileSafe(filePath);\n if (!content) {\n filesSkipped++;\n continue;\n }\n\n if (isBinary(content)) {\n filesSkipped++;\n continue;\n }\n\n filesProcessed++;\n\n const sourceFileHash = hashContent(content);\n const fileStatements = extractStatements(\n content,\n filePath,\n targetPath,\n source,\n sourceFileHash,\n categoryOverride,\n confidence,\n entityRef,\n tags,\n );\n\n for (const stmt of fileStatements) {\n // Dedup check\n if (checkDuplicates) {\n const dup = findDuplicate(stmt, existingMemories);\n if (dup) {\n duplicates.push(dup);\n if (dup.action === \"skip\") continue;\n }\n }\n\n // Contradiction check\n if (checkContradictions) {\n const contra = findContradiction(stmt, existingMemories);\n if (contra) {\n contradictions.push(contra);\n }\n }\n\n statements.push(stmt);\n\n // Write to memory\n if (write) {\n const writtenPath = writeStatement(stmt, memoryDir);\n if (writtenPath) {\n written.push(writtenPath);\n existingMemories.set(stmt.contentHash, {\n id: stmt.id,\n content: stmt.content,\n category: stmt.category,\n });\n }\n }\n }\n }\n\n return {\n statements,\n filesProcessed,\n filesSkipped,\n duplicates,\n contradictions,\n written,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Target resolution ────────────────────────────────────────────────────────\n\nfunction resolveTargets(targetPath: string): string[] {\n const stat = fs.statSync(targetPath);\n if (stat.isFile()) return [targetPath];\n\n // Directory — walk for .md, .txt, .mdx\n const results: string[] = [];\n const extensions = new Set([\".md\", \".txt\", \".mdx\", \".rst\"]);\n\n function walk(dir: string): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== \"node_modules\" && entry.name !== \".git\") {\n walk(fullPath);\n }\n } else if (extensions.has(path.extname(entry.name).toLowerCase())) {\n results.push(fullPath);\n }\n }\n }\n\n walk(targetPath);\n return results;\n}\n\n// ── Statement extraction ─────────────────────────────────────────────────────\n\nfunction extractStatements(\n content: string,\n filePath: string,\n projectRoot: string,\n source: string,\n sourceFileHash: string,\n categoryOverride: string | undefined,\n confidence: number,\n entityRef: string | undefined,\n tags: string[],\n): CuratedStatement[] {\n const relativePath = path.relative(projectRoot, filePath);\n const statements: CuratedStatement[] = [];\n const now = new Date().toISOString();\n\n // Split content into paragraphs/lines and extract meaningful statements\n const paragraphs = content\n .split(/\\n{2,}/)\n .map((p) => p.trim())\n .filter((p) => p.length > 20 && p.length < 2000);\n\n // Also extract list items\n const listItems = content\n .split(\"\\n\")\n .filter((l) => /^\\s*[-*]\\s+/.test(l))\n .map((l) => l.replace(/^\\s*[-*]\\s+/, \"\").trim())\n .filter((l) => l.length > 10 && l.length < 500);\n\n const allItems = [...paragraphs, ...listItems];\n\n // Deduplicate within file\n const seen = new Set<string>();\n for (const item of allItems) {\n const hash = hashContent(item.toLowerCase());\n if (seen.has(hash)) continue;\n seen.add(hash);\n\n const id = generateId();\n const category = categoryOverride ?? detectCategory(item);\n\n statements.push({\n id,\n content: item,\n category,\n confidence,\n provenance: {\n sourcePath: filePath,\n relativePath,\n source,\n lineNumber: 0,\n ingestedAt: now,\n sourceFileHash,\n },\n contentHash: hash,\n tags: [...tags],\n entityRef,\n });\n }\n\n return statements;\n}\n\n// ── Category detection ───────────────────────────────────────────────────────\n\nfunction detectCategory(text: string): string {\n const lower = text.toLowerCase();\n\n if (/^(always|never|must|should|don't|avoid|ensure)/.test(lower)) return \"principle\";\n if (/^(we|team|project)\\s+(decided|chose|will|use)/.test(lower)) return \"decision\";\n if (/^(i|we)\\s+(prefer|like|want|hate|dislike)/.test(lower)) return \"preference\";\n if (/fix|bug|issue|broken|error/i.test(lower)) return \"correction\";\n if (/\\?.+$/.test(lower.trim())) return \"question\";\n\n return \"fact\";\n}\n\n// ── Dedup ────────────────────────────────────────────────────────────────────\n\ninterface ExistingMemory {\n id: string;\n content: string;\n category: string;\n}\n\nfunction findDuplicate(\n stmt: CuratedStatement,\n existing: Map<string, ExistingMemory>,\n): DuplicateResult | null {\n const stmtLower = stmt.content.toLowerCase();\n\n // Exact hash match\n const exactMatch = existing.get(stmt.contentHash);\n if (exactMatch) {\n return {\n newStatement: stmt,\n existingId: exactMatch.id,\n similarity: 1,\n action: \"skip\",\n };\n }\n\n // Fuzzy match — check substring containment\n for (const [_, mem] of existing) {\n const memLower = mem.content.toLowerCase();\n if (memLower.length > 50 && stmtLower.length > 50) {\n // Check if one contains the other\n if (memLower.includes(stmtLower.slice(0, 40)) || stmtLower.includes(memLower.slice(0, 40))) {\n return {\n newStatement: stmt,\n existingId: mem.id,\n similarity: 0.85,\n action: \"skip\",\n };\n }\n }\n }\n\n return null;\n}\n\n// ── Contradiction detection ──────────────────────────────────────────────────\n\nfunction findContradiction(\n stmt: CuratedStatement,\n existing: Map<string, ExistingMemory>,\n): ContradictionResult | null {\n const negationPatterns = [\n /\\b(not|don't|doesn't|isn't|aren't|won't|can't|never|no)\\b/i,\n ];\n\n const hasNegation = negationPatterns.some((p) => p.test(stmt.content));\n if (!hasNegation) return null;\n\n // Strip negation and look for positive version\n const stripped = stmt.content\n .toLowerCase()\n .replace(/\\b(not|don't|doesn't|isn't|aren't|won't|can't|never|no)\\b/gi, \"\")\n .trim();\n\n if (stripped.length < 20) return null;\n\n for (const [_, mem] of existing) {\n const memLower = mem.content.toLowerCase();\n // If an existing memory affirms what this statement negates\n if (memLower.includes(stripped.slice(0, Math.min(30, stripped.length)))) {\n return {\n newStatement: stmt,\n conflictingId: mem.id,\n conflictingContent: mem.content,\n severity: \"high\",\n };\n }\n }\n\n return null;\n}\n\n// ── Memory loading ───────────────────────────────────────────────────────────\n\nfunction loadExistingMemories(memoryDir: string): Map<string, ExistingMemory> {\n const result = new Map<string, ExistingMemory>();\n if (!fs.existsSync(memoryDir)) return result;\n\n // Walk all known category dirs for existing memories\n const dirs = ALL_CATEGORY_DIRS;\n for (const dir of dirs) {\n const fullDir = path.join(memoryDir, dir);\n if (!fs.existsSync(fullDir)) continue;\n\n walkFiles(fullDir, (filePath) => {\n const content = readFileSafe(filePath);\n if (!content) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id || !body) return;\n\n const hash = hashContent(body.toLowerCase());\n result.set(hash, {\n id: fm.id,\n content: body,\n category: fm.category ?? dir.slice(0, -1),\n });\n });\n }\n\n return result;\n}\n\n// ── Writing ──────────────────────────────────────────────────────────────────\n\nfunction writeStatement(stmt: CuratedStatement, memoryDir: string): string | null {\n const now = new Date();\n const dateDir = now.toISOString().split(\"T\")[0];\n const categoryDir = getCategoryDir(memoryDir, stmt.category);\n\n const dir = path.join(categoryDir, dateDir);\n fs.mkdirSync(dir, { recursive: true });\n\n const fileName = `${stmt.category}-${Date.now()}-${stmt.id.slice(0, 8)}.md`;\n const filePath = path.join(dir, fileName);\n\n const frontmatter = [\n \"---\",\n `id: ${stmt.id}`,\n `category: ${stmt.category}`,\n `created: ${stmt.provenance.ingestedAt}`,\n `updated: ${stmt.provenance.ingestedAt}`,\n `confidence: ${stmt.confidence}`,\n `confidenceTier: ${tierFromConfidence(stmt.confidence)}`,\n `source: ${stmt.provenance.source}`,\n `tags: ${JSON.stringify(stmt.tags)}`,\n stmt.entityRef ? `entityRef: ${stmt.entityRef}` : null,\n `provenanceFile: ${stmt.provenance.relativePath}`,\n `provenanceHash: ${stmt.provenance.sourceFileHash}`,\n \"---\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n\n const body = `${frontmatter}\\n\\n${stmt.content}\\n`;\n\n try {\n fs.writeFileSync(filePath, body);\n return filePath;\n } catch {\n return null;\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction generateId(): string {\n return crypto.randomUUID();\n}\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nfunction tierFromConfidence(confidence: number): string {\n if (confidence >= 0.95) return \"explicit\";\n if (confidence >= 0.8) return \"high\";\n if (confidence >= 0.5) return \"medium\";\n return \"low\";\n}\n\nfunction readFileSafe(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction isBinary(content: string): boolean {\n // Simple heuristic: if content has null bytes, it's binary\n for (let i = 0; i < Math.min(content.length, 8000); i++) {\n if (content.charCodeAt(i) === 0) return true;\n }\n return false;\n}\n\ninterface SimpleFrontmatter {\n id?: string;\n category?: string;\n [key: string]: unknown;\n}\n\nfunction parseFrontmatter(content: string): SimpleFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: SimpleFrontmatter = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n (fm as Record<string, unknown>)[key] = value;\n }\n return fm;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction walkFiles(dir: string, callback: (filePath: string) => void): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkFiles(fullPath, callback);\n } else if (entry.name.endsWith(\".md\")) {\n callback(fullPath);\n }\n }\n}\n","/**\n * @remnic/core — Dedup & Contradiction Detection\n *\n * Statement-level deduplication and contradiction detection\n * against existing memories. Can be used standalone or via curation.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MemoryEntry {\n /** Memory ID */\n id: string;\n /** Content text */\n content: string;\n /** Category */\n category: string;\n /** File path (if known) */\n filePath?: string;\n}\n\nexport interface DedupOptions {\n /** Memory root directory */\n memoryDir: string;\n /** Categories to scan (default: all) */\n categories?: string[];\n /** Similarity threshold for fuzzy matching (0-1, default: 0.85) */\n threshold?: number;\n /** Max memories to load (default: 10000) */\n maxLoad?: number;\n}\n\nexport interface DedupResult {\n /** Total memories scanned */\n scanned: number;\n /** Duplicate pairs found */\n duplicates: DuplicatePair[];\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface DuplicatePair {\n /** First memory */\n left: MemoryEntry;\n /** Second memory */\n right: MemoryEntry;\n /** Similarity score */\n similarity: number;\n /** Recommended action */\n action: \"merge\" | \"keep_left\" | \"keep_right\";\n}\n\nexport interface ContradictionOptions {\n /** Memory root directory */\n memoryDir: string;\n /** Categories to scan (default: all) */\n categories?: string[];\n /** Max memories to load (default: 10000) */\n maxLoad?: number;\n}\n\nexport interface ContradictionResult {\n /** Total memories scanned */\n scanned: number;\n /** Contradictions found */\n contradictions: ContradictionPair[];\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface ContradictionPair {\n /** First statement */\n left: MemoryEntry;\n /** Contradicting statement */\n right: MemoryEntry;\n /** Severity */\n severity: \"high\" | \"medium\" | \"low\";\n /** Reason */\n reason: string;\n}\n\n// ── Main functions ───────────────────────────────────────────────────────────\n\nexport function findDuplicates(options: DedupOptions): DedupResult {\n const startTime = Date.now();\n const { memoryDir, threshold = 0.85, maxLoad = 10000 } = options;\n\n const memories = loadMemories(memoryDir, options.categories, maxLoad);\n const duplicates: DuplicatePair[] = [];\n\n // Compare all pairs (O(n^2) but bounded by maxLoad)\n for (let i = 0; i < memories.length; i++) {\n for (let j = i + 1; j < memories.length; j++) {\n const sim = computeSimilarity(memories[i].content, memories[j].content);\n if (sim >= threshold) {\n duplicates.push({\n left: memories[i],\n right: memories[j],\n similarity: sim,\n action: sim >= 0.98 ? \"merge\" : sim >= 0.9 ? \"keep_right\" : \"keep_left\",\n });\n }\n }\n }\n\n return {\n scanned: memories.length,\n duplicates,\n durationMs: Date.now() - startTime,\n };\n}\n\nexport function findContradictions(options: ContradictionOptions): ContradictionResult {\n const startTime = Date.now();\n const { memoryDir, maxLoad = 10000 } = options;\n\n const memories = loadMemories(memoryDir, options.categories, maxLoad);\n const contradictions: ContradictionPair[] = [];\n\n for (let i = 0; i < memories.length; i++) {\n for (let j = i + 1; j < memories.length; j++) {\n const contra = detectContradiction(memories[i], memories[j]);\n if (contra) {\n contradictions.push(contra);\n }\n }\n }\n\n return {\n scanned: memories.length,\n contradictions,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Similarity computation ───────────────────────────────────────────────────\n\nfunction computeSimilarity(a: string, b: string): number {\n // Normalize\n const normA = normalize(a);\n const normB = normalize(b);\n\n // Exact match\n if (normA === normB) return 1;\n\n // Hash-based exact match\n if (hashContent(normA) === hashContent(normB)) return 0.99;\n\n // Substring containment\n if (normA.length > 50 && normB.length > 50) {\n if (normA.includes(normB.slice(0, 40)) || normB.includes(normA.slice(0, 40))) {\n return 0.9;\n }\n }\n\n // Word overlap (Jaccard)\n const wordsA = new Set(normA.split(/\\s+/));\n const wordsB = new Set(normB.split(/\\s+/));\n const intersection = new Set([...wordsA].filter((w) => wordsB.has(w)));\n const union = new Set([...wordsA, ...wordsB]);\n\n if (union.size === 0) return 0;\n return intersection.size / union.size;\n}\n\nfunction normalize(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s']/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n// ── Contradiction detection ──────────────────────────────────────────────────\n\nconst NEGATION_WORDS = new Set([\n \"not\", \"don't\", \"doesn't\", \"isn't\", \"aren't\", \"won't\", \"can't\",\n \"never\", \"no\", \"none\", \"neither\", \"nor\", \"nothing\", \"nowhere\",\n]);\n\nfunction detectContradiction(\n a: MemoryEntry,\n b: MemoryEntry,\n): ContradictionPair | null {\n const normA = normalize(a.content);\n const normB = normalize(b.content);\n\n // Check if one has negation and the other doesn't\n const aHasNegation = containsNegation(normA);\n const bHasNegation = containsNegation(normB);\n\n if (aHasNegation === bHasNegation) return null;\n\n // Strip negation and compare core content\n const strippedA = stripNegation(normA);\n const strippedB = stripNegation(normB);\n\n const sim = computeSimilarity(strippedA, strippedB);\n if (sim < 0.7) return null;\n\n // Check for opposite quantifiers\n const oppQuantifiers = [\n [\"always\", \"never\"],\n [\"all\", \"none\"],\n [\"every\", \"no\"],\n [\"must\", \"must not\"],\n [\"should\", \"should not\"],\n [\"can\", \"cannot\"],\n ];\n\n for (const [pos, neg] of oppQuantifiers) {\n if (\n (a.content.toLowerCase().includes(pos) && b.content.toLowerCase().includes(neg)) ||\n (a.content.toLowerCase().includes(neg) && b.content.toLowerCase().includes(pos))\n ) {\n return {\n left: a,\n right: b,\n severity: \"high\",\n reason: `Opposite quantifiers: \"${pos}\" vs \"${neg}\"`,\n };\n }\n }\n\n return {\n left: a,\n right: b,\n severity: sim >= 0.85 ? \"high\" : \"medium\",\n reason: \"Negated version of similar content\",\n };\n}\n\nfunction containsNegation(text: string): boolean {\n const words = text.split(/\\s+/);\n return words.some((w) => NEGATION_WORDS.has(w));\n}\n\nfunction stripNegation(text: string): string {\n return text\n .replace(/\\b(not|don't|doesn't|isn't|aren't|won't|can't|never|no|none|neither|nor|nothing|nowhere)\\b/gi, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n// ── Memory loading ───────────────────────────────────────────────────────────\n\nfunction loadMemories(\n memoryDir: string,\n categories?: string[],\n maxLoad = 10000,\n): MemoryEntry[] {\n const result: MemoryEntry[] = [];\n const allCategories = categories ?? ALL_CATEGORY_DIRS;\n\n for (const category of allCategories) {\n if (result.length >= maxLoad) break;\n\n const dir = path.join(memoryDir, category);\n if (!fs.existsSync(dir)) continue;\n\n walkMdFiles(dir, (filePath) => {\n if (result.length >= maxLoad) return;\n\n const content = readFileSafe(filePath);\n if (!content) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id || !body) return;\n\n result.push({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? category.slice(0, -1),\n filePath,\n });\n });\n }\n\n return result;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nfunction readFileSafe(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction parseFrontmatter(content: string): Record<string, unknown> | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n fm[key] = value;\n }\n return fm;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction walkMdFiles(dir: string, callback: (filePath: string) => void): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkMdFiles(fullPath, callback);\n } else if (entry.name.endsWith(\".md\")) {\n callback(fullPath);\n }\n }\n}\n","/**\n * @remnic/core — Review Inbox\n *\n * Manages low-confidence memories and suggestions pending review.\n * Integrates with the existing review-queue system.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getCategoryDir, ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReviewItem {\n /** Memory ID */\n id: string;\n /** Content text */\n content: string;\n /** Category */\n category: string;\n /** Confidence score (0-1) */\n confidence: number;\n /** Confidence tier */\n confidenceTier: string;\n /** Source */\n source: string;\n /** File path if available */\n filePath?: string;\n /** Created date */\n created: string;\n /** Reason it's in review */\n reviewReason: \"low_confidence\" | \"suggestion\" | \"contradiction\" | \"duplicate\";\n /** Additional context */\n context?: string;\n}\n\nexport type ReviewAction = \"approve\" | \"dismiss\" | \"flag\";\n\nexport interface ReviewResult {\n /** Item acted upon */\n itemId: string;\n /** Action taken */\n action: ReviewAction;\n /** Updated file path (if modified) */\n updatedPath?: string;\n /** Status message */\n message: string;\n}\n\nexport interface ReviewListResult {\n /** Items pending review */\n items: ReviewItem[];\n /** Total count */\n total: number;\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface ReviewOptions {\n /** Memory root directory */\n memoryDir: string;\n /** Filter by reason */\n reason?: ReviewItem[\"reviewReason\"];\n /** Max items to return (default: 50) */\n limit?: number;\n /** Include items with confidence below this threshold (default: 0.7) */\n confidenceThreshold?: number;\n}\n\n// ── Main functions ───────────────────────────────────────────────────────────\n\n/**\n * List items pending review.\n */\nexport function listReviewItems(options: ReviewOptions): ReviewListResult {\n const startTime = Date.now();\n const {\n memoryDir,\n reason: filterReason,\n limit = 50,\n confidenceThreshold = 0.7,\n } = options;\n\n const items: ReviewItem[] = [];\n\n // Check suggestions directory\n const suggestionsDir = path.join(memoryDir, \"suggestions\");\n if (fs.existsSync(suggestionsDir)) {\n walkMd(suggestionsDir, (filePath, content) => {\n if (items.length >= limit) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id) return;\n\n items.push({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? \"suggestion\",\n confidence: parseConfidence(fm.confidence, 0.5),\n confidenceTier: (fm.confidenceTier as string) ?? \"low\",\n source: (fm.source as string) ?? \"unknown\",\n filePath,\n created: (fm.created as string) ?? new Date().toISOString(),\n reviewReason: \"suggestion\",\n });\n });\n }\n\n // Check review directory\n const reviewDir = path.join(memoryDir, \"review\");\n if (fs.existsSync(reviewDir)) {\n walkMd(reviewDir, (filePath, content) => {\n if (items.length >= limit) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id) return;\n\n items.push({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? \"review\",\n confidence: parseConfidence(fm.confidence, 0.5),\n confidenceTier: (fm.confidenceTier as string) ?? \"low\",\n source: (fm.source as string) ?? \"unknown\",\n filePath,\n created: (fm.created as string) ?? new Date().toISOString(),\n reviewReason: (fm.reviewReason as ReviewItem[\"reviewReason\"]) ?? \"low_confidence\",\n context: fm.context as string | undefined,\n });\n });\n }\n\n // Scan all categories for low-confidence items\n const categories = ALL_CATEGORY_DIRS;\n for (const category of categories) {\n if (items.length >= limit) break;\n\n const dir = path.join(memoryDir, category);\n if (!fs.existsSync(dir)) continue;\n\n walkMd(dir, (filePath, content) => {\n if (items.length >= limit) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id) return;\n\n const confidence = parseConfidence(fm.confidence, 1);\n if (confidence >= confidenceThreshold) return;\n\n // Skip if already in items\n if (items.some((i) => i.id === fm.id)) return;\n\n items.push({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? category.slice(0, -1),\n confidence,\n confidenceTier: (fm.confidenceTier as string) ?? \"low\",\n source: (fm.source as string) ?? \"unknown\",\n filePath,\n created: (fm.created as string) ?? new Date().toISOString(),\n reviewReason: \"low_confidence\",\n });\n });\n }\n\n // Filter by reason\n const filtered = filterReason\n ? items.filter((i) => i.reviewReason === filterReason)\n : items;\n\n return {\n items: filtered.slice(0, limit),\n total: filtered.length,\n durationMs: Date.now() - startTime,\n };\n}\n\n/**\n * Perform a review action on an item.\n */\nexport function performReview(\n memoryDir: string,\n itemId: string,\n action: ReviewAction,\n): ReviewResult {\n switch (action) {\n case \"approve\":\n return approveItem(memoryDir, itemId);\n case \"dismiss\":\n return dismissItem(memoryDir, itemId);\n case \"flag\":\n return flagItem(memoryDir, itemId);\n }\n}\n\n// ── Actions ──────────────────────────────────────────────────────────────────\n\nfunction approveItem(memoryDir: string, itemId: string): ReviewResult {\n // Find the item in suggestions/ or review/\n const locations = [\"suggestions\", \"review\"];\n for (const loc of locations) {\n const dir = path.join(memoryDir, loc);\n if (!fs.existsSync(dir)) continue;\n\n const found = findFileById(dir, itemId);\n if (!found) continue;\n\n const content = fs.readFileSync(found, \"utf8\");\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm) return { itemId, action: \"approve\", message: \"Could not parse frontmatter\" };\n\n // Promote to facts/ with boosted confidence\n const category = (fm.category as string) ?? \"fact\";\n const targetDir = getCategoryDir(memoryDir, category);\n const dateDir = new Date().toISOString().split(\"T\")[0];\n const outputPath = path.join(targetDir, dateDir, path.basename(found));\n\n // Update confidence in content\n const updatedContent = content\n .replace(/confidence: [\\d.]+/, \"confidence: 0.9\")\n .replace(/confidenceTier: \\w+/, \"confidenceTier: high\");\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, updatedContent);\n\n // Remove from review\n fs.unlinkSync(found);\n\n return {\n itemId,\n action: \"approve\",\n updatedPath: outputPath,\n message: `Promoted to ${category} with confidence 0.9`,\n };\n }\n\n return { itemId, action: \"approve\", message: \"Item not found\" };\n}\n\nfunction dismissItem(memoryDir: string, itemId: string): ReviewResult {\n const locations = [\"suggestions\", \"review\"];\n for (const loc of locations) {\n const dir = path.join(memoryDir, loc);\n if (!fs.existsSync(dir)) continue;\n\n const found = findFileById(dir, itemId);\n if (found) {\n fs.unlinkSync(found);\n return { itemId, action: \"dismiss\", message: \"Dismissed and removed\" };\n }\n }\n\n return { itemId, action: \"dismiss\", message: \"Item not found\" };\n}\n\nfunction flagItem(memoryDir: string, itemId: string): ReviewResult {\n const locations = [\"suggestions\", \"review\"];\n for (const loc of locations) {\n const dir = path.join(memoryDir, loc);\n if (!fs.existsSync(dir)) continue;\n\n const found = findFileById(dir, itemId);\n if (found) {\n // Add flagged marker to frontmatter\n const content = fs.readFileSync(found, \"utf8\");\n const fixed = content.replace(\n /^(---\\n)/,\n `---\\nflagged: true\\nflaggedAt: ${new Date().toISOString()}\\n`,\n );\n fs.writeFileSync(found, fixed);\n return { itemId, action: \"flag\", message: \"Flagged for further review\" };\n }\n }\n\n return { itemId, action: \"flag\", message: \"Item not found\" };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction findFileById(dir: string, id: string): string | null {\n const files = walkMdPaths(dir);\n for (const filePath of files) {\n const content = readFileSafe(filePath);\n if (!content) continue;\n const fm = parseFrontmatter(content);\n if (fm?.id === id) return filePath;\n }\n return null;\n}\n\nfunction parseConfidence(value: unknown, fallback: number): number {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : fallback;\n if (typeof value === \"string\") {\n const n = parseFloat(value);\n return Number.isFinite(n) ? n : fallback;\n }\n return fallback;\n}\n\nfunction readFileSafe(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction parseFrontmatter(content: string): Record<string, unknown> | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n fm[key] = value;\n }\n return fm;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction walkMd(dir: string, callback: (filePath: string, content: string) => void): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkMd(fullPath, callback);\n } else if (entry.name.endsWith(\".md\")) {\n const content = readFileSafe(fullPath);\n if (content) callback(fullPath, content);\n }\n }\n}\n\nfunction walkMdPaths(dir: string): string[] {\n const results: string[] = [];\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...walkMdPaths(fullPath));\n } else if (entry.name.endsWith(\".md\")) {\n results.push(fullPath);\n }\n }\n return results;\n}\n","/**\n * @remnic/core — Diff-Aware Sync\n *\n * Watches source files for changes and triggers re-ingestion\n * only for changed content. Uses file hashing to detect changes.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface SyncOptions {\n /** Source directory to watch */\n sourceDir: string;\n /** Memory root directory */\n memoryDir: string;\n /** State file path (stores hashes). Default: memoryDir/.sync-state.json */\n stateFile?: string;\n /** File extensions to watch (default: .md, .txt, .mdx) */\n extensions?: string[];\n /** Directories to exclude */\n excludeDirs?: string[];\n /** Whether to actually write changes (default: true) */\n dryRun?: boolean;\n}\n\nexport interface SyncResult {\n /** Files scanned */\n scanned: number;\n /** Files changed since last sync */\n changed: FileChange[];\n /** Files unchanged */\n unchanged: number;\n /** Files deleted since last sync */\n deleted: string[];\n /** Files newly added */\n added: string[];\n /** Duration in ms */\n durationMs: number;\n /** State file path */\n stateFile: string;\n}\n\nexport interface FileChange {\n /** Absolute file path */\n filePath: string;\n /** Relative path from source root */\n relativePath: string;\n /** Change type */\n type: \"added\" | \"modified\" | \"deleted\";\n /** Current content hash */\n currentHash: string;\n /** Previous content hash (if modified) */\n previousHash?: string;\n /** File size in bytes */\n size: number;\n}\n\nexport interface SyncState {\n /** Map of relative path → content hash */\n fileHashes: Record<string, string>;\n /** Last sync timestamp */\n lastSyncAt: string;\n /** Version of state format */\n version: number;\n}\n\n// ── Constants ────────────────────────────────────────────────────────────────\n\nconst DEFAULT_EXTENSIONS = new Set([\".md\", \".txt\", \".mdx\", \".rst\"]);\nconst DEFAULT_EXCLUDE = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".engram\",\n \"coverage\",\n]);\n\n// ── Main function ────────────────────────────────────────────────────────────\n\nexport function syncChanges(options: SyncOptions): SyncResult {\n const startTime = Date.now();\n const {\n sourceDir,\n memoryDir,\n extensions = [...DEFAULT_EXTENSIONS],\n excludeDirs = [],\n dryRun = false,\n } = options;\n\n const extSet = new Set(extensions);\n const excludeSet = new Set([...DEFAULT_EXCLUDE, ...excludeDirs]);\n const stateFilePath = options.stateFile ?? path.join(memoryDir, \".sync-state.json\");\n\n // Load previous state\n const prevState = loadState(stateFilePath);\n\n // Scan current files\n const currentFiles = scanFiles(sourceDir, extSet, excludeSet);\n\n // Compute diffs\n const changes = computeDiff(currentFiles, prevState.fileHashes, sourceDir);\n\n const added = changes.filter((c) => c.type === \"added\").map((c) => c.relativePath);\n const modified = changes.filter((c) => c.type === \"modified\");\n const deleted = changes\n .filter((c) => c.type === \"deleted\")\n .map((c) => c.relativePath);\n\n // Update state (even in dry run, we want to show what would change)\n if (!dryRun) {\n const newState: SyncState = {\n fileHashes: {},\n lastSyncAt: new Date().toISOString(),\n version: 1,\n };\n\n // Build new state from current files\n for (const [relPath, hash] of Object.entries(currentFiles)) {\n newState.fileHashes[relPath] = hash;\n }\n\n // Write state\n fs.mkdirSync(path.dirname(stateFilePath), { recursive: true });\n fs.writeFileSync(stateFilePath, JSON.stringify(newState, null, 2));\n }\n\n return {\n scanned: Object.keys(currentFiles).length,\n changed: changes,\n unchanged:\n Object.keys(currentFiles).length - changes.filter((c) => c.type !== \"deleted\").length,\n deleted,\n added,\n durationMs: Date.now() - startTime,\n stateFile: stateFilePath,\n };\n}\n\n/**\n * Watch for changes and call callback on file changes.\n * Returns a stop function.\n */\nexport function watchForChanges(\n options: SyncOptions,\n onChange: (changes: FileChange[]) => void,\n): { stop: () => void } {\n const { sourceDir, extensions, excludeDirs } = options;\n const extSet = new Set(extensions ?? DEFAULT_EXTENSIONS);\n const excludeSet = new Set([...DEFAULT_EXCLUDE, ...(excludeDirs ?? [])]);\n\n let lastHashes: Record<string, string> = {};\n\n // Initial scan\n const currentFiles = scanFiles(sourceDir, extSet, excludeSet);\n lastHashes = { ...currentFiles };\n\n // Poll interval (FSWatcher doesn't reliably work for all platforms)\n const interval = setInterval(() => {\n const nowFiles = scanFiles(sourceDir, extSet, excludeSet);\n const changes = computeDiff(nowFiles, lastHashes, sourceDir);\n\n if (changes.length > 0) {\n // Update hashes\n for (const change of changes) {\n if (change.type === \"deleted\") {\n delete lastHashes[change.relativePath];\n } else {\n lastHashes[change.relativePath] = change.currentHash;\n }\n }\n onChange(changes);\n }\n }, 5000);\n\n return {\n stop: () => clearInterval(interval),\n };\n}\n\n// ── File scanning ────────────────────────────────────────────────────────────\n\nfunction scanFiles(\n root: string,\n extensions: Set<string>,\n exclude: Set<string>,\n): Record<string, string> {\n const result: Record<string, string> = {};\n\n function walk(dir: string): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (exclude.has(entry.name)) continue;\n\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath);\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name).toLowerCase();\n if (!extensions.has(ext)) continue;\n\n const relPath = path.relative(root, fullPath);\n try {\n const content = fs.readFileSync(fullPath, \"utf8\");\n result[relPath] = hashContent(content);\n } catch {\n // Can't read — skip\n }\n }\n }\n }\n\n walk(root);\n return result;\n}\n\n// ── Diff computation ─────────────────────────────────────────────────────────\n\nfunction computeDiff(\n current: Record<string, string>,\n previous: Record<string, string>,\n sourceDir: string,\n): FileChange[] {\n const changes: FileChange[] = [];\n\n // Find added and modified\n for (const [relPath, hash] of Object.entries(current)) {\n const fullPath = path.join(sourceDir, relPath);\n\n if (!(relPath in previous)) {\n // Added\n let size = 0;\n try {\n size = fs.statSync(fullPath).size;\n } catch {\n // ignore\n }\n changes.push({\n filePath: fullPath,\n relativePath: relPath,\n type: \"added\",\n currentHash: hash,\n size,\n });\n } else if (previous[relPath] !== hash) {\n // Modified\n let size = 0;\n try {\n size = fs.statSync(fullPath).size;\n } catch {\n // ignore\n }\n changes.push({\n filePath: fullPath,\n relativePath: relPath,\n type: \"modified\",\n currentHash: hash,\n previousHash: previous[relPath],\n size,\n });\n }\n }\n\n // Find deleted\n for (const relPath of Object.keys(previous)) {\n if (!(relPath in current)) {\n changes.push({\n filePath: path.join(sourceDir, relPath),\n relativePath: relPath,\n type: \"deleted\",\n currentHash: \"\",\n size: 0,\n });\n }\n }\n\n return changes;\n}\n\n// ── State management ─────────────────────────────────────────────────────────\n\nfunction loadState(stateFilePath: string): SyncState {\n try {\n const raw = fs.readFileSync(stateFilePath, \"utf8\");\n return JSON.parse(raw);\n } catch {\n return {\n fileHashes: {},\n lastSyncAt: new Date(0).toISOString(),\n version: 1,\n };\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n","/**\n * @remnic/core — Connector Manager\n *\n * Metadata-driven registry for host adapters (Codex CLI, Claude Code, Cursor, etc.).\n * Manages connector lifecycle: install, remove, configure, health.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ConnectorManifest {\n /** Unique connector ID (e.g. \"claude-code\", \"codex-cli\") */\n id: string;\n /** Human-readable name */\n name: string;\n /** Version */\n version: string;\n /** Description */\n description: string;\n /** Capabilities */\n capabilities: ConnectorCapability;\n /** Required config fields */\n configSchema?: Record<string, string>;\n /** Whether currently installed */\n installed?: boolean;\n /** Homepage URL */\n homepage?: string;\n /** Author */\n author?: string;\n /** Repository URL */\n repository?: string;\n /** Tags */\n tags?: string[];\n}\n\nexport interface ConnectorCapability {\n /** Can observe conversations */\n observe: boolean;\n /** Can recall/query memories */\n recall: boolean;\n /** Can store memories */\n store: boolean;\n /** Can search */\n search: boolean;\n /** Can manage entities */\n entities: boolean;\n /** Supports real-time sync */\n realtimeSync: boolean;\n /** Supports batch operations */\n batch: boolean;\n /** Max memory budget in chars */\n maxBudgetChars?: number;\n /** Connection type */\n connectionType: \"mcp\" | \"http\" | \"cli\" | \"sdk\" | \"embedded\";\n}\n\nexport interface ConnectorInstance {\n /** Connector ID */\n connectorId: string;\n /** Resolved config */\n config: Record<string, unknown>;\n /** Status */\n status: \"installed\" | \"running\" | \"error\" | \"disabled\";\n /** Installed at timestamp */\n installedAt?: string;\n /** Error message if erro */\n error?: string;\n}\n\nexport interface ConnectorRegistry {\n /** Known connectors */\n connectors: ConnectorManifest[];\n /** Registry file path */\n registryPath: string;\n}\n\nexport interface InstallOptions {\n /** Connector ID to install */\n connectorId: string;\n /** Config values */\n config?: Record<string, unknown>;\n /** Memory directory */\n memoryDir?: string;\n /** Whether to force reinstall */\n force?: boolean;\n}\n\nexport interface InstallResult {\n /** Connector ID */\n connectorId: string;\n /** Status */\n status: \"installed\" | \"already_installed\" | \"config_required\" | \"error\";\n /** Config path */\n configPath?: string;\n /** Message */\n message: string;\n}\n\nexport interface RemoveResult {\n /** Connector ID */\n connectorId: string;\n /** Removed config path */\n configPath: string;\n /** Message */\n message: string;\n}\n\nexport interface DoctorResult {\n /** Connector ID */\n connectorId: string;\n /** Checks */\n checks: DoctorCheck[];\n /** All healthy */\n healthy: boolean;\n}\n\nexport interface DoctorCheck {\n /** Check name */\n name: string;\n /** Passed */\n ok: boolean;\n /** Detail */\n detail: string;\n}\n\n// ── Built-in connector definitions ─────────────────────────────────────────\n\nconst BUILTIN_CONNECTORS: ConnectorManifest[] = [\n {\n id: \"claude-code\",\n name: \"Claude Code\",\n version: \"1.0.0\",\n description: \"Anthropic's Claude Code CLI — direct memory access via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: true,\n entities: true,\n realtimeSync: true,\n batch: false,\n maxBudgetChars: 32000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace (default: 'default')\",\n },\n homepage: \"https://claude.ai/code\",\n author: \"Anthropic\",\n tags: [\"official\", \"ai\", \"claude\"],\n },\n {\n id: \"codex-cli\",\n name: \"Codex CLI\",\n version: \"1.0.0\",\n description: \"OpenAI Codex CLI — memory via MCP tool\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: false,\n entities: false,\n realtimeSync: false,\n batch: true,\n maxBudgetChars: 8000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace\",\n },\n homepage: \"https://openai.com/codex\",\n author: \"OpenAI\",\n tags: [\"official\", \"ai\", \"codex\"],\n },\n {\n id: \"cursor\",\n name: \"Cursor IDE\",\n version: \"1.0.0\",\n description: \"Cursor IDE — memory via config file + tool calls\",\n capabilities: {\n observe: false,\n recall: true,\n store: false,\n search: true,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 32000,\n connectionType: \"embedded\",\n },\n configSchema: {\n memoryDir: \"Path to Remnic memory directory\",\n },\n homepage: \"https://cursor.com\",\n author: \"Cursor Inc.\",\n tags: [\"official\", \"ide\"],\n },\n {\n id: \"cline\",\n name: \"Cline\",\n version: \"1.0.0\",\n description: \"VS Code Cline extension — memory via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: false,\n entities: false,\n realtimeSync: false,\n batch: true,\n maxBudgetChars: 8000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace\",\n },\n homepage: \"https://github.com/cline/cline\",\n author: \"Cline\",\n tags: [\"community\", \"vscode\"],\n },\n {\n id: \"github-copilot\",\n name: \"GitHub Copilot\",\n version: \"1.0.0\",\n description: \"GitHub Copilot — memory via MCP server\",\n capabilities: {\n observe: false,\n recall: true,\n store: false,\n search: true,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 16000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n },\n homepage: \"https://github.com/features/copilot\",\n author: \"GitHub\",\n tags: [\"official\", \"ai\", \"github\"],\n },\n {\n id: \"roo-code\",\n name: \"Roo Code\",\n version: \"1.0.0\",\n description: \"Roo Code — memory via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: false,\n entities: false,\n realtimeSync: false,\n batch: true,\n maxBudgetChars: 16000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace\",\n },\n homepage: \"https://roocode.com\",\n author: \"Roo Code\",\n tags: [\"community\", \"vscode\"],\n },\n {\n id: \"windsurf\",\n name: \"Windsurf\",\n version: \"1.0.0\",\n description: \"Windsurf IDE — memory via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: true,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 32000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n },\n homepage: \"https://windsurf.com\",\n author: \"Codeium\",\n tags: [\"official\", \"ide\"],\n },\n {\n id: \"amp\",\n name: \"Amp\",\n version: \"1.0.0\",\n description: \"Amp coding agent — memory via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: true,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 32000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n },\n homepage: \"https://ampcode.com\",\n author: \"Sourcegraph\",\n tags: [\"official\", \"ai\"],\n },\n {\n id: \"replit\",\n name: \"Replit Agent\",\n version: \"1.0.0\",\n description: \"Replit Agent — memory via HTTP API (reduced capabilities)\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: false,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 8000,\n connectionType: \"http\",\n },\n configSchema: {\n apiUrl: \"URL of the Remnic HTTP API\",\n authToken: \"Bearer token for authentication\",\n },\n homepage: \"https://replit.com\",\n author: \"Replit\",\n tags: [\"official\", \"cloud\"],\n },\n {\n id: \"generic-mcp\",\n name: \"Generic MCP Client\",\n version: \"1.0.0\",\n description: \"Any MCP-compatible client — connect via standard MCP protocol\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: true,\n entities: true,\n realtimeSync: true,\n batch: true,\n maxBudgetChars: 64000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace\",\n authToken: \"Bearer token for authentication\",\n },\n homepage: \"https://github.com/joshuaswarren/remnic\",\n author: \"Remnic\",\n tags: [\"generic\", \"mcp\"],\n },\n];\n\n// ── Registry management ───────────────────────────────────────────────────\n\nconst REGISTRY_DIR_NAME = \".engram-connectors\";\n\nexport function getRegistryPath(): string {\n const configDir = process.env.XDG_CONFIG_HOME\n ? path.join(process.env.XDG_CONFIG_HOME, \"engram\")\n : path.join(process.env.HOME ?? \"~\", \".config\", \"engram\");\n return path.join(configDir, REGISTRY_DIR_NAME, \"registry.json\");\n}\n\nexport function loadRegistry(): ConnectorRegistry {\n const regPath = getRegistryPath();\n\n if (!fs.existsSync(regPath)) {\n // First time — bootstrap with built-in connectors\n const registry: ConnectorRegistry = {\n connectors: BUILTIN_CONNECTORS,\n registryPath: regPath,\n };\n saveRegistry(registry);\n return registry;\n }\n\n const raw = fs.readFileSync(regPath, \"utf8\");\n try {\n const parsed = JSON.parse(raw);\n // Merge built-ins with any custom connectors\n const customIds = new Set((parsed.connectors ?? []).map((c: ConnectorManifest) => c.id));\n const merged = [\n ...BUILTIN_CONNECTORS.filter((b) => !customIds.has(b.id)),\n ...(parsed.connectors ?? []),\n ];\n return {\n connectors: merged,\n registryPath: regPath,\n };\n } catch {\n const registry: ConnectorRegistry = {\n connectors: BUILTIN_CONNECTORS,\n registryPath: regPath,\n };\n saveRegistry(registry);\n return registry;\n }\n}\n\nexport function saveRegistry(registry: ConnectorRegistry): void {\n const regPath = registry.registryPath;\n fs.mkdirSync(path.dirname(regPath), { recursive: true });\n fs.writeFileSync(regPath, JSON.stringify({ connectors: registry.connectors }, null, 2));\n}\n\n// ── List connectors ────────────────────────────────────────────────────────\n\nexport function listConnectors(): {\n installed: ConnectorInstance[];\n available: ConnectorManifest[];\n} {\n const registry = loadRegistry();\n const connectorsDir = getConnectorsDir();\n const installedIds = new Set<string>();\n\n // Find installed connectors\n if (fs.existsSync(connectorsDir)) {\n for (const entry of fs.readdirSync(connectorsDir)) {\n if (entry.endsWith(\".json\")) {\n try {\n const config = JSON.parse(\n fs.readFileSync(path.join(connectorsDir, entry), \"utf8\"),\n );\n installedIds.add(config.connectorId as string);\n } catch {\n // ignore malformed configs\n }\n }\n }\n }\n\n // Mark installed vs available\n const available: ConnectorManifest[] = registry.connectors.map((manifest) => ({\n ...manifest,\n installed: installedIds.has(manifest.id),\n }));\n\n // Build installed list\n const installed: ConnectorInstance[] = [];\n for (const id of installedIds) {\n const configPath = path.join(connectorsDir, `${id}.json`);\n try {\n const config = JSON.parse(fs.readFileSync(configPath, \"utf8\"));\n installed.push({\n connectorId: id,\n config,\n status: \"installed\",\n installedAt: config.installedAt as string | undefined,\n });\n } catch {\n // ignore\n }\n }\n\n return { installed, available };\n}\n\n// ── Install connector ───────────────────────────────────────────────────────\n\nexport function installConnector(options: InstallOptions): InstallResult {\n const registry = loadRegistry();\n const manifest = registry.connectors.find((c) => c.id === options.connectorId);\n\n if (!manifest) {\n return {\n connectorId: options.connectorId,\n status: \"error\",\n message: `Unknown connector: ${options.connectorId}`,\n };\n }\n\n // Check if already installed\n const existing = listConnectors().installed.find(\n (c) => c.connectorId === options.connectorId,\n );\n\n if (existing && !options.force) {\n return {\n connectorId: options.connectorId,\n status: \"already_installed\",\n message: \"Already installed. Use --force to reinstall.\",\n };\n }\n\n // Write config\n const configDir = getConnectorsDir();\n fs.mkdirSync(configDir, { recursive: true });\n\n const configPath = path.join(configDir, `${options.connectorId}.json`);\n\n // Build config from schema defaults + user overrides\n const resolvedConfig: Record<string, unknown> = {\n connectorId: options.connectorId,\n installedAt: new Date().toISOString(),\n ...options.config,\n };\n fs.writeFileSync(configPath, JSON.stringify(resolvedConfig, null, 2));\n\n return {\n connectorId: options.connectorId,\n status: \"installed\",\n configPath,\n message: `Installed ${manifest.name} v${manifest.version}`,\n };\n}\n\n// ── Remove connector ───────────────────────────────────────────────────────\n\nexport function removeConnector(connectorId: string): RemoveResult {\n const configDir = getConnectorsDir();\n const configPath = path.join(configDir, `${connectorId}.json`);\n\n if (!fs.existsSync(configPath)) {\n return {\n connectorId,\n configPath,\n message: \"Not installed\",\n };\n }\n\n fs.unlinkSync(configPath);\n return {\n connectorId,\n configPath,\n message: \"Removed\",\n };\n}\n\n// ── Doctor ────────────────────────────────────────────────────────────────────\n\nexport async function doctorConnector(connectorId: string): Promise<DoctorResult> {\n const installed = listConnectors().installed;\n const instance = installed.find((c) => c.connectorId === connectorId);\n\n if (!instance) {\n return {\n connectorId,\n checks: [{ name: \"Installed\", ok: false, detail: \"Not installed\" }],\n healthy: false,\n };\n }\n\n const configPath = path.join(getConnectorsDir(), `${connectorId}.json`);\n const checks: DoctorCheck[] = [];\n\n // Check config exists\n checks.push({\n name: \"Config file\",\n ok: fs.existsSync(configPath),\n detail: configPath,\n });\n\n // Check config is valid JSON\n try {\n const raw = fs.readFileSync(configPath, \"utf8\");\n JSON.parse(raw);\n checks.push({ name: \"Config valid\", ok: true, detail: \"OK\" });\n } catch (e) {\n checks.push({ name: \"Config valid\", ok: false, detail: String(e) });\n }\n\n // Check MCP server reachable (if applicable)\n const mcpUrl = instance.config.mcpServerUrl as string | undefined;\n if (mcpUrl) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 3000);\n const response = await fetch(mcpUrl, { signal: controller.signal });\n clearTimeout(timeoutId);\n checks.push({ name: \"MCP server\", ok: response.ok, detail: mcpUrl });\n } catch (e) {\n checks.push({\n name: \"MCP server\",\n ok: false,\n detail: `Cannot reach ${mcpUrl}: ${e instanceof Error ? e.message : \"unknown\"}`,\n });\n }\n }\n\n // Check memory dir (if applicable)\n const memoryDir = instance.config.memoryDir as string | undefined;\n if (memoryDir) {\n if (fs.existsSync(memoryDir)) {\n checks.push({ name: \"Memory directory\", ok: true, detail: memoryDir });\n } else {\n checks.push({ name: \"Memory directory\", ok: false, detail: `Not found: ${memoryDir}` });\n }\n }\n\n const healthy = checks.every((c) => c.ok);\n return { connectorId, checks, healthy };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction getConnectorsDir(): string {\n const configDir = process.env.XDG_CONFIG_HOME\n ? path.join(process.env.XDG_CONFIG_HOME, \"engram\")\n : path.join(process.env.HOME ?? \"~\", \".config\", \"engram\");\n return path.join(configDir, REGISTRY_DIR_NAME, \"connectors\");\n}\n","/**\n * @remnic/core — Spaces + Collaboration\n *\n * First-class memory spaces (personal, project, team) with merge/conflict\n * flows, promotion workflow, and audit trail.\n *\n * Each space is an isolated memory directory. Spaces can share memories\n * through push/pull and promotion workflows.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type SpaceKind = \"personal\" | \"project\" | \"team\";\n\nexport interface Space {\n /** Unique space ID */\n id: string;\n /** Human-readable name */\n name: string;\n /** Space type */\n kind: SpaceKind;\n /** Description */\n description?: string;\n /** Memory directory path (absolute) */\n memoryDir: string;\n /** Created at */\n createdAt: string;\n /** Updated at */\n updatedAt: string;\n /** Owner */\n owner?: string;\n /** Members (for team spaces) */\n members?: string[];\n /** Parent space (for promotion) */\n parentSpaceId?: string;\n}\n\nexport interface SpaceManifest {\n /** Current active space ID */\n activeSpaceId: string;\n /** All spaces */\n spaces: Space[];\n /** Manifest version */\n version: number;\n /** Last updated */\n updatedAt?: string;\n}\n\nexport interface SpaceSwitchResult {\n previousSpaceId: string;\n currentSpaceId: string;\n message: string;\n}\n\nexport interface SpacePushResult {\n sourceSpaceId: string;\n targetSpaceId: string;\n memoriesPushed: number;\n conflicts: ConflictEntry[];\n durationMs: number;\n}\n\nexport interface SpacePullResult {\n sourceSpaceId: string;\n targetSpaceId: string;\n memoriesPulled: number;\n conflicts: ConflictEntry[];\n durationMs: number;\n}\n\nexport interface SpaceShareResult {\n spaceId: string;\n sharedWith: string[];\n message: string;\n}\n\nexport interface SpacePromoteResult {\n sourceSpaceId: string;\n targetSpaceId: string;\n memoriesPromoted: number;\n conflicts: ConflictEntry[];\n durationMs: number;\n}\n\nexport interface ConflictEntry {\n /** Memory ID */\n memoryId: string;\n /** Source file path */\n sourcePath: string;\n /** Target file path */\n targetPath: string;\n /** Conflict type */\n conflictType: \"content_mismatch\" | \"metadata_mismatch\" | \"both\";\n /** Source content hash */\n sourceHash: string;\n /** Target content hash */\n targetHash: string;\n}\n\nexport interface MergeResult {\n merged: number;\n conflicts: ConflictEntry[];\n skipped: number;\n durationMs: number;\n}\n\nexport interface AuditEntry {\n id: string;\n timestamp: string;\n action: string;\n sourceSpaceId: string;\n targetSpaceId?: string;\n actor?: string;\n details: string;\n memoryIds?: string[];\n}\n\n// ── Manifest management ─────────────────────────────────────────────────────\n\nconst MANIFEST_VERSION = 1;\n\nexport function getSpacesDir(baseDir?: string): string {\n const homeDir = baseDir ?? process.env.HOME ?? \"~\";\n return path.join(homeDir, \".config\", \"engram\", \"spaces\");\n}\n\nexport function getManifestPath(baseDir?: string): string {\n return path.join(getSpacesDir(baseDir), \"manifest.json\");\n}\n\nexport function loadManifest(baseDir?: string, memoryDirOverride?: string): SpaceManifest {\n const manifestPath = getManifestPath(baseDir);\n\n if (!fs.existsSync(manifestPath)) {\n // Bootstrap with a personal space\n const personalSpace = createPersonalSpace(baseDir, memoryDirOverride);\n const manifest: SpaceManifest = {\n activeSpaceId: personalSpace.id,\n spaces: [personalSpace],\n version: MANIFEST_VERSION,\n };\n saveManifest(manifest, baseDir);\n return manifest;\n }\n\n const raw = JSON.parse(fs.readFileSync(manifestPath, \"utf8\"));\n return raw as SpaceManifest;\n}\n\nexport function saveManifest(manifest: SpaceManifest, baseDir?: string): void {\n const manifestPath = getManifestPath(baseDir);\n fs.mkdirSync(path.dirname(manifestPath), { recursive: true });\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + \"\\n\");\n}\n\nfunction createPersonalSpace(baseDir?: string, memoryDirOverride?: string): Space {\n const homeDir = baseDir ?? process.env.HOME ?? \"~\";\n // Priority: override > env var > existing standalone dir > existing OpenClaw dir > new standalone dir\n const standalonePath = path.join(homeDir, \".engram\", \"memory\");\n const openclawPath = path.join(homeDir, \".openclaw\", \"workspace\", \"memory\", \"local\");\n const memoryDir = memoryDirOverride\n ?? process.env.ENGRAM_MEMORY_DIR\n ?? (fs.existsSync(standalonePath) ? standalonePath\n : fs.existsSync(openclawPath) ? openclawPath\n : standalonePath);\n const now = new Date().toISOString();\n\n return {\n id: \"personal\",\n name: \"Personal\",\n kind: \"personal\",\n description: \"Default personal memory space\",\n memoryDir,\n createdAt: now,\n updatedAt: now,\n owner: process.env.USER,\n };\n}\n\n// ── Space CRUD ──────────────────────────────────────────────────────────────\n\nexport function listSpaces(baseDir?: string): Space[] {\n const manifest = loadManifest(baseDir);\n return manifest.spaces;\n}\n\nexport function getActiveSpace(baseDir?: string): Space {\n const manifest = loadManifest(baseDir);\n const space = manifest.spaces.find((s) => s.id === manifest.activeSpaceId);\n if (!space) throw new Error(`Active space ${manifest.activeSpaceId} not found`);\n return space;\n}\n\nexport function createSpace(options: {\n name: string;\n kind: SpaceKind;\n description?: string;\n memoryDir?: string;\n parentSpaceId?: string;\n baseDir?: string;\n}): Space {\n const manifest = loadManifest(options.baseDir);\n const id = options.name.toLowerCase().replace(/[^a-z0-9-]/g, \"-\").replace(/-+/g, \"-\");\n\n if (manifest.spaces.some((s) => s.id === id)) {\n throw new Error(`Space \"${id}\" already exists`);\n }\n\n // Validate parent space exists\n if (options.parentSpaceId && !manifest.spaces.some((s) => s.id === options.parentSpaceId)) {\n throw new Error(`Parent space \"${options.parentSpaceId}\" not found`);\n }\n\n const now = new Date().toISOString();\n const memoryDir = options.memoryDir ?? path.join(\n getSpacesDir(options.baseDir),\n id,\n \"memory\",\n );\n\n const space: Space = {\n id,\n name: options.name,\n kind: options.kind,\n description: options.description,\n memoryDir,\n createdAt: now,\n updatedAt: now,\n owner: process.env.USER,\n parentSpaceId: options.parentSpaceId,\n };\n\n // Ensure memory directory exists\n fs.mkdirSync(memoryDir, { recursive: true });\n\n manifest.spaces.push(space);\n manifest.updatedAt = now;\n saveManifest(manifest, options.baseDir);\n\n // Audit\n appendAudit({\n action: \"space.create\",\n sourceSpaceId: id,\n details: `Created ${options.kind} space \"${options.name}\"`,\n }, options.baseDir);\n\n return space;\n}\n\nexport function deleteSpace(spaceId: string, baseDir?: string): void {\n const manifest = loadManifest(baseDir);\n\n if (spaceId === \"personal\") {\n throw new Error(\"Cannot delete the personal space\");\n }\n\n const idx = manifest.spaces.findIndex((s) => s.id === spaceId);\n if (idx === -1) throw new Error(`Space \"${spaceId}\" not found`);\n\n // If deleting active space, switch to personal\n if (manifest.activeSpaceId === spaceId) {\n manifest.activeSpaceId = \"personal\";\n }\n\n // Clear parentSpaceId references from children\n for (const space of manifest.spaces) {\n if (space.parentSpaceId === spaceId) {\n space.parentSpaceId = undefined;\n }\n }\n\n manifest.spaces.splice(idx, 1);\n saveManifest(manifest, baseDir);\n\n appendAudit({\n action: \"space.delete\",\n sourceSpaceId: spaceId,\n details: `Deleted space \"${spaceId}\"`,\n }, baseDir);\n}\n\n// ── Switch ───────────────────────────────────────────────────────────────────\n\nexport function switchSpace(spaceId: string, baseDir?: string): SpaceSwitchResult {\n const manifest = loadManifest(baseDir);\n const space = manifest.spaces.find((s) => s.id === spaceId);\n\n if (!space) throw new Error(`Space \"${spaceId}\" not found`);\n\n const previousId = manifest.activeSpaceId;\n manifest.activeSpaceId = spaceId;\n saveManifest(manifest, baseDir);\n\n appendAudit({\n action: \"space.switch\",\n sourceSpaceId: previousId,\n targetSpaceId: spaceId,\n details: `Switched from \"${previousId}\" to \"${spaceId}\"`,\n }, baseDir);\n\n return {\n previousSpaceId: previousId,\n currentSpaceId: spaceId,\n message: `Switched to \"${space.name}\"`,\n };\n}\n\n// ── Push / Pull ─────────────────────────────────────────────────────────────\n\nexport function pushToSpace(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { memoryIds?: string[]; force?: boolean; baseDir?: string },\n): SpacePushResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n filterIds: options?.memoryIds,\n force: options?.force,\n });\n\n appendAudit({\n action: \"space.push\",\n sourceSpaceId,\n targetSpaceId,\n details: `Pushed ${result.merged} memories, ${result.conflicts.length} conflicts`,\n }, options?.baseDir);\n\n return {\n sourceSpaceId,\n targetSpaceId,\n memoriesPushed: result.merged,\n conflicts: result.conflicts,\n durationMs: Date.now() - startTime,\n };\n}\n\nexport function pullFromSpace(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { memoryIds?: string[]; force?: boolean; baseDir?: string },\n): SpacePullResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n filterIds: options?.memoryIds,\n force: options?.force,\n });\n\n appendAudit({\n action: \"space.pull\",\n sourceSpaceId,\n targetSpaceId,\n details: `Pulled ${result.merged} memories, ${result.conflicts.length} conflicts`,\n }, options?.baseDir);\n\n return {\n sourceSpaceId,\n targetSpaceId,\n memoriesPulled: result.merged,\n conflicts: result.conflicts,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Share ────────────────────────────────────────────────────────────────────\n\nexport function shareSpace(\n spaceId: string,\n members: string[],\n baseDir?: string,\n): SpaceShareResult {\n const manifest = loadManifest(baseDir);\n const space = manifest.spaces.find((s) => s.id === spaceId);\n\n if (!space) throw new Error(`Space \"${spaceId}\" not found`);\n if (space.kind === \"personal\") throw new Error(\"Cannot share personal space\");\n\n space.members = [...new Set([...(space.members ?? []), ...members])];\n space.updatedAt = new Date().toISOString();\n saveManifest(manifest, baseDir);\n\n appendAudit({\n action: \"space.share\",\n sourceSpaceId: spaceId,\n details: `Shared with: ${members.join(\", \")}`,\n }, baseDir);\n\n return {\n spaceId,\n sharedWith: members,\n message: `Shared \"${space.name}\" with ${members.length} member(s)`,\n };\n}\n\n// ── Promote ──────────────────────────────────────────────────────────────────\n\nexport function promoteSpace(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { memoryIds?: string[]; force?: boolean; forceOverwrite?: boolean; baseDir?: string },\n): SpacePromoteResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n // Promotion requires parent-child relationship or explicit force\n if (source.parentSpaceId !== targetSpaceId && target.parentSpaceId !== sourceSpaceId) {\n if (!options?.force) {\n throw new Error(\"Spaces must have a parent-child relationship for promotion. Use --force to override.\");\n }\n }\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n filterIds: options?.memoryIds,\n force: options?.forceOverwrite !== undefined ? options.forceOverwrite : (options?.force ?? false),\n });\n\n appendAudit({\n action: \"space.promote\",\n sourceSpaceId,\n targetSpaceId,\n details: `Promoted ${result.merged} memories from \"${source.name}\" to \"${target.name}\"`,\n }, options?.baseDir);\n\n return {\n sourceSpaceId,\n targetSpaceId,\n memoriesPromoted: result.merged,\n conflicts: result.conflicts,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Merge ────────────────────────────────────────────────────────────────────\n\nexport function mergeSpaces(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { force?: boolean; baseDir?: string },\n): MergeResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n force: options?.force,\n });\n\n appendAudit({\n action: \"space.merge\",\n sourceSpaceId,\n targetSpaceId,\n details: `Merged: ${result.merged} merged, ${result.conflicts.length} conflicts, ${result.skipped} skipped`,\n }, options?.baseDir);\n\n return {\n ...result,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Audit trail ─────────────────────────────────────────────────────────────\n\nexport function getAuditLog(baseDir?: string): AuditEntry[] {\n const auditPath = path.join(getSpacesDir(baseDir), \"audit.jsonl\");\n if (!fs.existsSync(auditPath)) return [];\n\n const lines = fs.readFileSync(auditPath, \"utf8\").trim().split(\"\\n\");\n return lines\n .filter((l) => l.trim())\n .map((l) => JSON.parse(l) as AuditEntry);\n}\n\nfunction appendAudit(entry: Omit<AuditEntry, \"id\" | \"timestamp\">, baseDir?: string): void {\n const auditPath = path.join(getSpacesDir(baseDir), \"audit.jsonl\");\n fs.mkdirSync(path.dirname(auditPath), { recursive: true });\n\n const full: AuditEntry = {\n id: crypto.randomUUID(),\n timestamp: new Date().toISOString(),\n ...entry,\n };\n\n fs.appendFileSync(auditPath, JSON.stringify(full) + \"\\n\");\n}\n\n// ── Internal helpers ─────────────────────────────────────────────────────────\n\ninterface CopyOptions {\n filterIds?: string[];\n force?: boolean;\n}\n\nfunction copyMemories(\n sourceDir: string,\n targetDir: string,\n options?: CopyOptions,\n): { merged: number; conflicts: ConflictEntry[]; skipped: number } {\n let merged = 0;\n const conflicts: ConflictEntry[] = [];\n let skipped = 0;\n\n if (!fs.existsSync(sourceDir)) {\n return { merged: 0, conflicts: [], skipped: 0 };\n }\n\n fs.mkdirSync(targetDir, { recursive: true });\n\n const sourceFiles = walkMd(sourceDir);\n for (const sourcePath of sourceFiles) {\n const content = fs.readFileSync(sourcePath, \"utf8\");\n const relativePath = path.relative(sourceDir, sourcePath);\n const targetPath = path.join(targetDir, relativePath);\n\n const sourceHash = hashContent(content);\n\n // Filter by IDs if specified\n if (options?.filterIds?.length) {\n const fm = parseSimpleFrontmatter(content);\n if (!fm?.id || !options.filterIds.includes(fm.id)) {\n skipped++;\n continue;\n }\n }\n\n // Check for conflict\n if (fs.existsSync(targetPath) && !options?.force) {\n const targetContent = fs.readFileSync(targetPath, \"utf8\");\n const targetHash = hashContent(targetContent);\n\n if (sourceHash !== targetHash) {\n conflicts.push({\n memoryId: parseSimpleFrontmatter(content)?.id ?? relativePath,\n sourcePath,\n targetPath,\n conflictType: \"content_mismatch\",\n sourceHash,\n targetHash,\n });\n continue;\n }\n\n // Same content — skip\n skipped++;\n continue;\n }\n\n // Copy file\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n fs.writeFileSync(targetPath, content);\n merged++;\n }\n\n return { merged, conflicts, skipped };\n}\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nfunction walkMd(dir: string): string[] {\n const results: string[] = [];\n\n function walk(d: string): void {\n for (const entry of fs.readdirSync(d, { withFileTypes: true })) {\n const fullPath = path.join(d, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath);\n } else if (entry.name.endsWith(\".md\")) {\n results.push(fullPath);\n }\n }\n }\n\n walk(dir);\n return results;\n}\n\ninterface SimpleFrontmatter {\n id?: string;\n [key: string]: string | undefined;\n}\n\nfunction parseSimpleFrontmatter(content: string): SimpleFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: SimpleFrontmatter = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n fm[key] = value;\n }\n return fm;\n}\n"],"mappings":"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","names":["path","path","fs","path","fs","path","fs","path","parseFrontmatter","extractBody","fs","path","crypto","hashContent","path","fs","readFileSafe","parseFrontmatter","extractBody","crypto","fs","path","path","fs","parseFrontmatter","extractBody","readFileSafe","fs","path","crypto","DEFAULT_EXCLUDE","hashContent","fs","path","fs","path","crypto","walkMd","hashContent"]}
1
+ {"version":3,"sources":["../src/projection/index.ts","../src/utils/category-dir.ts","../src/onboarding/index.ts","../src/curation/index.ts","../src/dedup/index.ts","../src/review/index.ts","../src/sync/index.ts","../src/connectors/index.ts","../src/spaces/index.ts"],"sourcesContent":["/**\n * @remnic/core — Workspace Tree Projection\n *\n * Generates a human-readable `.engram/context-tree/` from canonical memory.\n * Each node is a `.md` file with rich metadata, * (provenance, trust, confidence, source anchors).\n * Manual edits are preserved in fenced blocks.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getCategoryDir, ALL_CATEGORY_KEYS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface TreeNode {\n /** Relative path from context-tree root, e.g. \"entities/claude.md\" */\n path: string;\n /** Category from canonical memory */\n category: string;\n /** Human-readable title */\n title: string;\n /** File content (rendered markdown) */\n content: string;\n /** Source memory IDs that contributed to this node */\n sourceAnchors: string[];\n /** Confidence (0-1) */\n confidence: number;\n /** Trust zone classification */\n confidenceTier: string;\n /** When this node was generated */\n generatedAt: string;\n /** Provenance chain */\n provenance: ProvenanceEntry[];\n}\n\nexport interface ProvenanceEntry {\n memoryId: string;\n source: string;\n extracted: string;\n}\n\nexport interface GenerateOptions {\n /** Memory root directory (e.g. ~/.openclaw/workspace/memory/local) */\n memoryDir: string;\n /** Output directory (e.g. .engram/context-tree) */\n outputDir: string;\n /** Categories to include (default: all) */\n categories?: string[];\n /** Whether to include entity graph */\n includeEntities?: boolean;\n /** Whether to include orphaned questions */\n includeQuestions?: boolean;\n /** Max nodes per category (default: unlimited) */\n maxPerCategory?: number;\n /** Whether to watch for changes and regenerate incrementally */\n watch?: boolean;\n}\n\nexport interface GenerateResult {\n nodesGenerated: number;\n nodesSkipped: number;\n categories: Record<string, number>;\n durationMs: number;\n outputDir: string;\n}\n\n// ── Generation ──────────────────────────────────────────────────────────────\n\n/**\n * Generate a context tree from canonical memory.\n *\n * Reads memory `.md` files from the source directory, * and projects them into a clean, * human-readable tree structure at `outputDir`.\n */\nexport async function generateContextTree(options: GenerateOptions): Promise<GenerateResult> {\n const startTime = Date.now();\n const {\n memoryDir,\n outputDir,\n categories: filterCategories,\n includeEntities = true,\n includeQuestions = true,\n maxPerCategory = Infinity,\n } = options;\n\n let nodesGenerated = 0;\n let nodesSkipped = 0;\n const categoryCounts: Record<string, number> = {};\n\n // Ensure output directory exists\n fs.mkdirSync(outputDir, { recursive: true });\n\n // Process each category (exclude 'question' — handled by separate includeQuestions pass)\n const allCategories = filterCategories ?? ALL_CATEGORY_KEYS.filter((c) => c !== \"question\");\n\n for (const category of allCategories) {\n const categoryDir = getCategoryDir(memoryDir, category);\n if (!fs.existsSync(categoryDir)) continue;\n\n categoryCounts[category] = 0;\n const files = walkR(categoryDir);\n let count = 0;\n\n for (const filePath of files) {\n if (count >= maxPerCategory) {\n nodesSkipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const fm = parseFrontmatter(content);\n if (!fm) {\n nodesSkipped++;\n continue;\n }\n\n const node = projectNode(filePath, category, fm, content);\n if (!node) {\n nodesSkipped++;\n continue;\n }\n\n // Write node to output\n const outputPath = path.join(outputDir, node.path);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, node.content);\n\n nodesGenerated++;\n categoryCounts[category] = (categoryCounts[category] ?? 0) + 1;\n count++;\n }\n }\n\n // Process entities\n if (includeEntities) {\n const entitiesDir = path.join(memoryDir, \"entities\");\n if (fs.existsSync(entitiesDir)) {\n categoryCounts[\"entity\"] = 0;\n const entityFiles = walkR(entitiesDir);\n let count = 0;\n\n for (const filePath of entityFiles) {\n if (count >= maxPerCategory) {\n nodesSkipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const fileName = path.basename(filePath, \".md\");\n const node = projectEntityNode(fileName, content);\n\n const outputPath = path.join(outputDir, \"entities\", `${fileName}.md`);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, node.content);\n\n nodesGenerated++;\n categoryCounts[\"entity\"] = (categoryCounts[\"entity\"] ?? 0) + 1;\n count++;\n }\n }\n }\n\n // Process questions\n if (includeQuestions) {\n const questionsDir = path.join(memoryDir, \"questions\");\n if (fs.existsSync(questionsDir)) {\n categoryCounts[\"question\"] = 0;\n const qFiles = walkR(questionsDir);\n let count = 0;\n\n for (const filePath of qFiles) {\n if (count >= maxPerCategory) {\n nodesSkipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const fm = parseFrontmatter(content);\n if (!fm) {\n nodesSkipped++;\n continue;\n }\n\n const node = projectNode(filePath, \"question\", fm, content);\n if (!node) {\n nodesSkipped++;\n continue;\n }\n\n const outputPath = path.join(outputDir, node.path);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, node.content);\n\n nodesGenerated++;\n categoryCounts[\"question\"] = (categoryCounts[\"question\"] ?? 0) + 1;\n count++;\n }\n }\n }\n\n // Write index\n const index = generateIndex(categoryCounts, outputDir);\n fs.writeFileSync(path.join(outputDir, \"INDEX.md\"), index);\n\n return {\n nodesGenerated,\n nodesSkipped,\n categories: categoryCounts,\n durationMs: Date.now() - startTime,\n outputDir,\n };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n\nfunction walkR(dir: string): string[] {\n const results: string[] = [];\n function walk(directory: string): void {\n for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {\n const fullPath = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath);\n } else if (entry.name.endsWith(\".md\")) {\n results.push(fullPath);\n }\n }\n }\n walk(dir);\n return results;\n}\n\ninterface Frontmatter {\n id: string;\n category: string;\n created: string;\n updated: string;\n confidence: number;\n confidenceTier: string;\n tags: string[];\n source: string;\n entityRef?: string;\n lifecycleState?: string;\n}\n\nfunction parseFrontmatter(content: string): Frontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fmText = match[1];\n const fm: Record<string, unknown> = {};\n for (const line of fmText.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n if (key === \"tags\") {\n try {\n fm[key] = JSON.parse(value) as string[];\n } catch {\n fm[key] = [] as string[];\n }\n } else if (key === \"confidence\") {\n const parsed = parseFloat(value);\n fm[key] = Number.isFinite(parsed) ? parsed : 0;\n } else {\n fm[key] = value;\n }\n }\n return fm as unknown as Frontmatter;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction projectNode(\n filePath: string,\n category: string,\n fm: Frontmatter,\n rawContent: string,\n): TreeNode | null {\n const body = extractBody(rawContent);\n const fileName = path.basename(filePath, \".md\");\n const dateDir = path.basename(path.dirname(filePath));\n\n // Build relative path: category/date/file or just category/file\n let relPath: string;\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(dateDir)) {\n relPath = path.join(category, dateDir, `${fileName}.md`);\n } else {\n relPath = path.join(category, `${fileName}.md`);\n }\n\n const generatedAt = new Date().toISOString();\n\n const md = `# ${fm.id}\n\n> **Category:** ${fm.category}\n> **Created:** ${fm.created}\n> **Updated:** ${fm.updated ?? fm.created}\n> **Confidence:** ${fm.confidence} (${fm.confidenceTier}${fm.lifecycleState ? `, ${fm.lifecycleState}` : \"\"})\n${fm.tags?.length ? `\\n> **Tags:** ${fm.tags.join(\", \")}` : \"\"}\n${fm.entityRef ? `\\n> **Entity:** ${fm.entityRef}` : \"\"}\n> **Source:** ${fm.source ?? \"unknown\"}\n> **Projected:** ${generatedAt}\n\n---\n\n${body}\n`;\n\n return {\n path: relPath,\n category,\n title: fm.id,\n content: md,\n sourceAnchors: [fm.id],\n confidence: fm.confidence ?? 0,\n confidenceTier: fm.confidenceTier ?? \"unknown\",\n generatedAt,\n provenance: [{\n memoryId: fm.id,\n source: fm.source ?? \"unknown\",\n extracted: fm.created,\n }],\n };\n}\n\nfunction projectEntityNode(fileName: string, content: string): TreeNode {\n const generatedAt = new Date().toISOString();\n\n const md = `> **Projected:** ${generatedAt}\n> **Source:** canonical\n\n---\n\n${content}\n`;\n\n return {\n path: path.join(\"entities\", `${fileName}.md`),\n category: \"entity\",\n title: fileName,\n content: md,\n sourceAnchors: [fileName],\n confidence: 1,\n confidenceTier: \"explicit\",\n generatedAt,\n provenance: [{\n memoryId: fileName,\n source: \"canonical\",\n extracted: generatedAt,\n }],\n };\n}\n\nfunction generateIndex(\n categoryCounts: Record<string, number>,\n outputDir: string,\n): string {\n const lines = [\n \"# Context Tree Index\",\n \"\",\n `Generated: ${new Date().toISOString()}`,\n \"\",\n \"## Summary\",\n \"\",\n `| Category | Count |`,\n `|----------|-------|`,\n ];\n\n let total = 0;\n for (const [cat, count] of Object.entries(categoryCounts).sort()) {\n lines.push(`| ${cat} | ${count} |`);\n total += count;\n }\n\n lines.push(\"\");\n lines.push(`**Total:** ${total} nodes`);\n lines.push(\"\");\n lines.push(\"## Structure\");\n lines.push(\"\");\n lines.push(\"```\");\n lines.push(\"context-tree/\");\n lines.push(\"├── entities/ # Entity knowledge graph\");\n lines.push(\"├── fact/ # Factual memories (date-partitioned)\");\n lines.push(\"├── correction/ # Correction memories\");\n lines.push(\"├── decision/ # Decisions\");\n lines.push(\"├── moment/ # Notable moments\");\n lines.push(\"├── preference/ # Preferences\");\n lines.push(\"├── principle/ # Principles\");\n lines.push(\"├── question/ # Open questions\");\n lines.push(\"└── INDEX.md # This file\");\n lines.push(\"```\");\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","/**\n * @remnic/core — Category Directory Map\n *\n * Shared mapping of memory category names to directory names.\n * Single source of truth — import from here instead of copy-pasting.\n */\n\nimport path from \"node:path\";\n\nexport const CATEGORY_DIR_MAP: Record<string, string> = {\n correction: \"corrections\",\n question: \"questions\",\n preference: \"preferences\",\n decision: \"decisions\",\n moment: \"moments\",\n commitment: \"commitments\",\n principle: \"principles\",\n rule: \"rules\",\n skill: \"skills\",\n relationship: \"relationships\",\n};\n\n/** All directory names derived from CATEGORY_DIR_MAP, plus \"facts\" (the default). */\nexport const ALL_CATEGORY_DIRS: string[] = [\n \"facts\",\n ...Object.values(CATEGORY_DIR_MAP),\n];\n\n/** All category keys (singular form) — used when iterating categories and calling getCategoryDir. */\nexport const ALL_CATEGORY_KEYS: string[] = [\n \"fact\",\n ...Object.keys(CATEGORY_DIR_MAP),\n];\n\n/**\n * Resolve a category name to its directory path under memoryDir.\n * Falls back to `facts/` for unknown categories.\n */\nexport function getCategoryDir(memoryDir: string, category: string): string {\n const dir = CATEGORY_DIR_MAP[category];\n return dir ? path.join(memoryDir, dir) : path.join(memoryDir, \"facts\");\n}\n","/**\n * @remnic/core — Onboarding\n *\n * Detects project language, shape, and documentation to produce\n * an onboarding plan for memory ingestion.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface OnboardOptions {\n /** Directory to scan (defaults to cwd) */\n directory: string;\n /** Max depth to walk (default: 6) */\n maxDepth?: number;\n /** Directories to skip */\n excludeDirs?: string[];\n}\n\nexport interface LanguageInfo {\n /** Language name (e.g. \"TypeScript\", \"Python\") */\n language: string;\n /** Confidence in detection (0-1) */\n confidence: number;\n /** Evidence (e.g. [\"package.json\", \"tsconfig.json\", \"*.ts files\"]) */\n evidence: string[];\n}\n\nexport interface DocFile {\n /** Absolute path */\n path: string;\n /** Relative path from project root */\n relativePath: string;\n /** Estimated type */\n kind: \"readme\" | \"changelog\" | \"contributing\" | \"license\" | \"config\" | \"docs\" | \"other\";\n /** File size in bytes */\n size: number;\n}\n\nexport type ProjectShape = \"app\" | \"library\" | \"monorepo\" | \"workspace\" | \"script\" | \"unknown\";\n\nexport interface OnboardResult {\n /** Project root */\n directory: string;\n /** Detected languages (sorted by confidence) */\n languages: LanguageInfo[];\n /** Detected project shape */\n shape: ProjectShape;\n /** Shape evidence */\n shapeEvidence: string[];\n /** Discovered documentation files */\n docs: DocFile[];\n /** Total files scanned */\n totalFiles: number;\n /** Duration in ms */\n durationMs: number;\n /** Suggested ingestion plan */\n plan: IngestionPlan;\n}\n\nexport interface IngestionPlan {\n /** Priority files to ingest first */\n priorityFiles: DocFile[];\n /** Estimated total files to ingest */\n estimatedFiles: number;\n /** Recommended categories */\n categories: string[];\n /** Suggested memory namespace */\n suggestedNamespace: string;\n}\n\n// ── Language detection rules ─────────────────────────────────────────────────\n\ninterface LanguageRule {\n language: string;\n extensions: string[];\n manifests: string[];\n configFiles: string[];\n}\n\nconst LANGUAGE_RULES: LanguageRule[] = [\n {\n language: \"TypeScript\",\n extensions: [\".ts\", \".tsx\"],\n manifests: [\"package.json\"],\n configFiles: [\"tsconfig.json\", \"tsup.config.ts\"],\n },\n {\n language: \"JavaScript\",\n extensions: [\".js\", \".jsx\", \".mjs\", \".cjs\"],\n manifests: [\"package.json\"],\n configFiles: [\".eslintrc\", \".prettierrc\"],\n },\n {\n language: \"Python\",\n extensions: [\".py\", \".pyi\"],\n manifests: [\"pyproject.toml\", \"setup.py\", \"setup.cfg\", \"requirements.txt\"],\n configFiles: [\"mypy.ini\", \".flake8\", \"tox.ini\"],\n },\n {\n language: \"Go\",\n extensions: [\".go\"],\n manifests: [\"go.mod\", \"go.sum\"],\n configFiles: [],\n },\n {\n language: \"Rust\",\n extensions: [\".rs\"],\n manifests: [\"Cargo.toml\"],\n configFiles: [],\n },\n {\n language: \"Ruby\",\n extensions: [\".rb\"],\n manifests: [\"Gemfile\", \"*.gemspec\"],\n configFiles: [\".rubocop.yml\"],\n },\n {\n language: \"PHP\",\n extensions: [\".php\"],\n manifests: [\"composer.json\"],\n configFiles: [\"phpcs.xml\"],\n },\n {\n language: \"Java\",\n extensions: [\".java\", \".kt\"],\n manifests: [\"pom.xml\", \"build.gradle\", \"build.gradle.kts\"],\n configFiles: [],\n },\n {\n language: \"Swift\",\n extensions: [\".swift\"],\n manifests: [\"Package.swift\", \"Podfile\"],\n configFiles: [],\n },\n {\n language: \"C#\",\n extensions: [\".cs\"],\n manifests: [\"*.csproj\", \"*.sln\"],\n configFiles: [],\n },\n {\n language: \"Shell\",\n extensions: [\".sh\", \".bash\", \".zsh\"],\n manifests: [],\n configFiles: [],\n },\n {\n language: \"Dart\",\n extensions: [\".dart\"],\n manifests: [\"pubspec.yaml\"],\n configFiles: [],\n },\n {\n language: \"Elixir\",\n extensions: [\".ex\", \".exs\"],\n manifests: [\"mix.exs\"],\n configFiles: [],\n },\n];\n\nconst DEFAULT_EXCLUDE = new Set([\n \"node_modules\",\n \".git\",\n \"vendor\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n \"dist\",\n \"build\",\n \".next\",\n \".nuxt\",\n \"target\",\n \"coverage\",\n \".engram\",\n]);\n\n// ── Main function ────────────────────────────────────────────────────────────\n\nexport function onboard(options: OnboardOptions): OnboardResult {\n const startTime = Date.now();\n const {\n directory,\n maxDepth = 6,\n excludeDirs = [],\n } = options;\n\n const exclude = new Set([...DEFAULT_EXCLUDE, ...excludeDirs]);\n\n // Collect all files\n const files = walkDir(directory, exclude, maxDepth);\n\n // Detect languages\n const languages = detectLanguages(files, directory);\n\n // Detect shape\n const { shape, evidence: shapeEvidence } = detectShape(files, directory);\n\n // Discover docs\n const docs = discoverDocs(files, directory);\n\n // Build plan\n const plan = buildPlan(languages, shape, docs, directory);\n\n return {\n directory,\n languages,\n shape,\n shapeEvidence,\n docs,\n totalFiles: files.length,\n durationMs: Date.now() - startTime,\n plan,\n };\n}\n\n// ── Walk directory ───────────────────────────────────────────────────────────\n\nfunction walkDir(\n root: string,\n exclude: Set<string>,\n maxDepth: number,\n): string[] {\n const results: string[] = [];\n\n function walk(dir: string, depth: number): void {\n if (depth > maxDepth) return;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (exclude.has(entry.name)) continue;\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath, depth + 1);\n } else if (entry.isFile()) {\n results.push(fullPath);\n }\n }\n }\n\n walk(root, 0);\n return results;\n}\n\n// ── Language detection ───────────────────────────────────────────────────────\n\nfunction detectLanguages(files: string[], root: string): LanguageInfo[] {\n const results: LanguageInfo[] = [];\n\n // Count extensions\n const extCounts = new Map<string, number>();\n for (const f of files) {\n const ext = path.extname(f).toLowerCase();\n if (ext) extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);\n }\n\n // Check manifests at root level\n const rootFiles = new Set(\n files\n .filter((f) => path.dirname(f) === root)\n .map((f) => path.basename(f)),\n );\n\n for (const rule of LANGUAGE_RULES) {\n const evidence: string[] = [];\n let score = 0;\n\n // Extension matches\n let extMatch = 0;\n for (const ext of rule.extensions) {\n const count = extCounts.get(ext) ?? 0;\n if (count > 0) {\n extMatch += count;\n evidence.push(`${ext} files (${count})`);\n }\n }\n score += Math.min(extMatch * 0.05, 0.5);\n\n // Manifest matches\n for (const manifest of rule.manifests) {\n if (manifest.includes(\"*\")) {\n // Glob pattern — e.g. \"*.gemspec\" matches files ending with \".gemspec\"\n const suffix = manifest.replaceAll(/\\*/g, \"\");\n if ([...rootFiles].some((f) => f.endsWith(suffix))) {\n score += 0.2;\n evidence.push(manifest);\n }\n } else if (rootFiles.has(manifest)) {\n score += 0.2;\n evidence.push(manifest);\n }\n }\n\n // Config matches\n for (const cfg of rule.configFiles) {\n if (rootFiles.has(cfg)) {\n score += 0.1;\n evidence.push(cfg);\n }\n }\n\n if (score > 0) {\n results.push({\n language: rule.language,\n confidence: Math.min(score, 1),\n evidence,\n });\n }\n }\n\n return results.sort((a, b) => b.confidence - a.confidence);\n}\n\n// ── Shape detection ──────────────────────────────────────────────────────────\n\nfunction detectShape(\n files: string[],\n root: string,\n): { shape: ProjectShape; evidence: string[] } {\n const rootFiles = new Set(\n files\n .filter((f) => path.dirname(f) === root)\n .map((f) => path.basename(f)),\n );\n\n const rootDirs = new Set<string>();\n try {\n for (const entry of fs.readdirSync(root, { withFileTypes: true })) {\n if (entry.isDirectory()) rootDirs.add(entry.name);\n }\n } catch {\n // ignore\n }\n\n const evidence: string[] = [];\n\n // Monorepo: workspace packages/ or libs/ dirs + root package.json with workspaces\n if (rootFiles.has(\"package.json\")) {\n const pkg = readJsonSafe(path.join(root, \"package.json\"));\n if (pkg?.workspaces) {\n evidence.push(\"package.json has workspaces\");\n return { shape: \"monorepo\", evidence };\n }\n }\n\n if (rootDirs.has(\"packages\") || rootDirs.has(\"libs\")) {\n evidence.push(\"has packages/ or libs/ directory\");\n return { shape: \"monorepo\", evidence };\n }\n\n // Workspace: pnpm-workspace.yaml, Cargo workspace, go.work\n if (rootFiles.has(\"pnpm-workspace.yaml\") || rootFiles.has(\"go.work\")) {\n evidence.push(\"workspace manifest found\");\n return { shape: \"workspace\", evidence };\n }\n\n const cargoToml = readTomlWorkspace(path.join(root, \"Cargo.toml\"));\n if (cargoToml) {\n evidence.push(\"Cargo.toml has workspace\");\n return { shape: \"workspace\", evidence };\n }\n\n // Library: has lib/ or src/index.*, exports in package.json\n if (rootFiles.has(\"package.json\")) {\n const pkg = readJsonSafe(path.join(root, \"package.json\"));\n if (pkg?.exports || pkg?.main) {\n // If it also has \"bin\", it's more of an app\n if (pkg?.bin) {\n evidence.push(\"package.json has bin\");\n return { shape: \"app\", evidence };\n }\n evidence.push(\"package.json has exports/main\");\n return { shape: \"library\", evidence };\n }\n }\n\n // Check for app indicators\n if (\n rootFiles.has(\"Dockerfile\") ||\n rootFiles.has(\"docker-compose.yml\") ||\n rootFiles.has(\"docker-compose.yaml\") ||\n rootDirs.has(\"app\") ||\n rootDirs.has(\"src\") && rootDirs.has(\"public\")\n ) {\n evidence.push(\"app-like structure detected\");\n return { shape: \"app\", evidence };\n }\n\n // Script: few files, no package manifest\n if (files.length <= 5 && !rootFiles.has(\"package.json\") && !rootFiles.has(\"pyproject.toml\")) {\n evidence.push(\"few files, no manifest\");\n return { shape: \"script\", evidence };\n }\n\n return { shape: \"unknown\", evidence: [\"no strong shape signal\"] };\n}\n\n// ── Doc discovery ────────────────────────────────────────────────────────────\n\nfunction discoverDocs(files: string[], root: string): DocFile[] {\n const docs: DocFile[] = [];\n const docPatterns: Array<{ pattern: RegExp; kind: DocFile[\"kind\"] }> = [\n { pattern: /^readme(\\.\\w+)?$/i, kind: \"readme\" },\n { pattern: /^changelog(\\.\\w+)?$/i, kind: \"changelog\" },\n { pattern: /^changes(\\.\\w+)?$/i, kind: \"changelog\" },\n { pattern: /^contributing(\\.\\w+)?$/i, kind: \"contributing\" },\n { pattern: /^code[_-]of[_-]conduct(\\.\\w+)?$/i, kind: \"contributing\" },\n { pattern: /^license(\\.\\w+)?$/i, kind: \"license\" },\n { pattern: /^copying(\\.\\w+)?$/i, kind: \"license\" },\n { pattern: /^\\.env\\.example$/i, kind: \"config\" },\n { pattern: /^\\.editorconfig$/i, kind: \"config\" },\n ];\n\n for (const filePath of files) {\n const basename = path.basename(filePath).toLowerCase();\n const relPath = path.relative(root, filePath);\n let kind: DocFile[\"kind\"] | undefined;\n\n // Check against patterns\n for (const { pattern, kind: k } of docPatterns) {\n if (pattern.test(basename)) {\n kind = k;\n break;\n }\n }\n\n // Check docs/ directories\n if (!kind && isUnderDocsDir(relPath)) {\n kind = \"docs\";\n }\n\n // Check markdown files at root or in docs/\n if (!kind && (basename.endsWith(\".md\") || basename.endsWith(\".mdx\"))) {\n if (path.dirname(relPath) === \".\" || isUnderDocsDir(relPath)) {\n kind = \"docs\";\n }\n }\n\n if (kind) {\n let size = 0;\n try {\n size = fs.statSync(filePath).size;\n } catch {\n // ignore\n }\n docs.push({\n path: filePath,\n relativePath: relPath,\n kind,\n size,\n });\n }\n }\n\n return docs;\n}\n\nfunction isUnderDocsDir(relPath: string): boolean {\n const parts = relPath.split(path.sep);\n return parts[0] === \"docs\" || parts[0] === \"doc\" || parts[0] === \"documentation\";\n}\n\n// ── Plan generation ──────────────────────────────────────────────────────────\n\nfunction buildPlan(\n languages: LanguageInfo[],\n shape: ProjectShape,\n docs: DocFile[],\n _root: string,\n): IngestionPlan {\n // Priority: README, CONTRIBUTING, then other docs\n const priorityOrder: Record<DocFile[\"kind\"], number> = {\n readme: 0,\n contributing: 1,\n changelog: 2,\n license: 3,\n docs: 4,\n config: 5,\n other: 6,\n };\n\n const priorityFiles = [...docs]\n .filter((d) => d.size > 0)\n .sort((a, b) => priorityOrder[a.kind] - priorityOrder[b.kind]);\n\n // Recommended categories based on project shape\n const categories: string[] = [\"fact\", \"preference\", \"decision\", \"principle\"];\n if (shape === \"monorepo\" || shape === \"workspace\") {\n categories.push(\"entity\");\n }\n\n // Namespace suggestion from primary language\n const suggestedNamespace = languages.length > 0\n ? languages[0].language.toLowerCase()\n : \"project\";\n\n return {\n priorityFiles,\n estimatedFiles: docs.filter((d) => d.size > 0).length,\n categories,\n suggestedNamespace,\n };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction readJsonSafe(filePath: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(filePath, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction readTomlWorkspace(filePath: string): boolean {\n try {\n const content = fs.readFileSync(filePath, \"utf8\");\n return content.includes(\"[workspace]\");\n } catch {\n return false;\n }\n}\n","/**\n * @remnic/core — Curation\n *\n * Deliberate ingestion of files into memory with provenance tracking.\n * Supports statement-level extraction, dedup, and contradiction checks.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { getCategoryDir, ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface CurateOptions {\n /** File or directory path to curate */\n targetPath: string;\n /** Memory root directory for writing */\n memoryDir: string;\n /** Source label (e.g. \"manual\", \"docs\", \"onboarding\") */\n source?: string;\n /** Category override (default: auto-detect) */\n category?: string;\n /** Confidence to assign (default: 0.9 for curated items) */\n confidence?: number;\n /** Entity reference to attach */\n entityRef?: string;\n /** Tags to add */\n tags?: string[];\n /** Whether to perform dedup check against existing memories */\n checkDuplicates?: boolean;\n /** Whether to detect contradictions */\n checkContradictions?: boolean;\n /** Whether to write files (default: true). False = dry run */\n write?: boolean;\n}\n\nexport interface CuratedStatement {\n /** Unique ID for this statement */\n id: string;\n /** The extracted statement text */\n content: string;\n /** Category */\n category: string;\n /** Confidence */\n confidence: number;\n /** Provenance info */\n provenance: StatementProvenance;\n /** Hash of content for dedup */\n contentHash: string;\n /** Tags */\n tags: string[];\n /** Entity reference */\n entityRef?: string;\n}\n\nexport interface StatementProvenance {\n /** Source file path */\n sourcePath: string;\n /** Relative path from project root */\n relativePath: string;\n /** Source label */\n source: string;\n /** Line number if extractable (0 = unknown) */\n lineNumber: number;\n /** Timestamp of ingestion */\n ingestedAt: string;\n /** Hash of the source file for diff tracking */\n sourceFileHash: string;\n}\n\nexport interface CurateResult {\n /** Statements extracted */\n statements: CuratedStatement[];\n /** Files processed */\n filesProcessed: number;\n /** Files skipped (empty, binary, etc.) */\n filesSkipped: number;\n /** Duplicate statements found (if checkDuplicates) */\n duplicates: DuplicateResult[];\n /** Contradictions found (if checkContradictions) */\n contradictions: ContradictionResult[];\n /** Memory files written */\n written: string[];\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface DuplicateResult {\n /** New statement */\n newStatement: CuratedStatement;\n /** Existing memory ID that matches */\n existingId: string;\n /** Similarity score (0-1) */\n similarity: number;\n /** Recommended action */\n action: \"skip\" | \"merge\" | \"keep\";\n}\n\nexport interface ContradictionResult {\n /** New statement */\n newStatement: CuratedStatement;\n /** Conflicting memory ID */\n conflictingId: string;\n /** The conflicting content */\n conflictingContent: string;\n /** Severity */\n severity: \"high\" | \"medium\" | \"low\";\n}\n\n// ── Main function ────────────────────────────────────────────────────────────\n\nexport async function curate(options: CurateOptions): Promise<CurateResult> {\n const startTime = Date.now();\n const {\n targetPath,\n memoryDir,\n source = \"curation\",\n category: categoryOverride,\n confidence = 0.9,\n entityRef,\n tags = [],\n checkDuplicates = true,\n checkContradictions = false,\n write = true,\n } = options;\n\n const statements: CuratedStatement[] = [];\n const written: string[] = [];\n const duplicates: DuplicateResult[] = [];\n const contradictions: ContradictionResult[] = [];\n let filesProcessed = 0;\n let filesSkipped = 0;\n\n // Determine targets\n const targets = resolveTargets(targetPath);\n\n // Load existing memories for dedup/contradiction checks\n const existingMemories = checkDuplicates || checkContradictions\n ? loadExistingMemories(memoryDir)\n : new Map();\n\n // Process each file\n for (const filePath of targets) {\n const content = readFileSafe(filePath);\n if (!content) {\n filesSkipped++;\n continue;\n }\n\n if (isBinary(content)) {\n filesSkipped++;\n continue;\n }\n\n filesProcessed++;\n\n const sourceFileHash = hashContent(content);\n const fileStatements = extractStatements(\n content,\n filePath,\n targetPath,\n source,\n sourceFileHash,\n categoryOverride,\n confidence,\n entityRef,\n tags,\n );\n\n for (const stmt of fileStatements) {\n // Dedup check\n if (checkDuplicates) {\n const dup = findDuplicate(stmt, existingMemories);\n if (dup) {\n duplicates.push(dup);\n if (dup.action === \"skip\") continue;\n }\n }\n\n // Contradiction check\n if (checkContradictions) {\n const contra = findContradiction(stmt, existingMemories);\n if (contra) {\n contradictions.push(contra);\n }\n }\n\n statements.push(stmt);\n\n // Write to memory\n if (write) {\n const writtenPath = writeStatement(stmt, memoryDir);\n if (writtenPath) {\n written.push(writtenPath);\n existingMemories.set(stmt.contentHash, {\n id: stmt.id,\n content: stmt.content,\n category: stmt.category,\n });\n }\n }\n }\n }\n\n return {\n statements,\n filesProcessed,\n filesSkipped,\n duplicates,\n contradictions,\n written,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Target resolution ────────────────────────────────────────────────────────\n\nfunction resolveTargets(targetPath: string): string[] {\n const stat = fs.statSync(targetPath);\n if (stat.isFile()) return [targetPath];\n\n // Directory — walk for .md, .txt, .mdx\n const results: string[] = [];\n const extensions = new Set([\".md\", \".txt\", \".mdx\", \".rst\"]);\n\n function walk(dir: string): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== \"node_modules\" && entry.name !== \".git\") {\n walk(fullPath);\n }\n } else if (extensions.has(path.extname(entry.name).toLowerCase())) {\n results.push(fullPath);\n }\n }\n }\n\n walk(targetPath);\n return results;\n}\n\n// ── Statement extraction ─────────────────────────────────────────────────────\n\nfunction extractStatements(\n content: string,\n filePath: string,\n projectRoot: string,\n source: string,\n sourceFileHash: string,\n categoryOverride: string | undefined,\n confidence: number,\n entityRef: string | undefined,\n tags: string[],\n): CuratedStatement[] {\n const relativePath = path.relative(projectRoot, filePath);\n const statements: CuratedStatement[] = [];\n const now = new Date().toISOString();\n\n // Split content into paragraphs/lines and extract meaningful statements\n const paragraphs = content\n .split(/\\n{2,}/)\n .map((p) => p.trim())\n .filter((p) => p.length > 20 && p.length < 2000);\n\n // Also extract list items\n const listItems = content\n .split(\"\\n\")\n .filter((l) => /^\\s*[-*]\\s+/.test(l))\n .map((l) => l.replace(/^\\s*[-*]\\s+/, \"\").trim())\n .filter((l) => l.length > 10 && l.length < 500);\n\n const allItems = [...paragraphs, ...listItems];\n\n // Deduplicate within file\n const seen = new Set<string>();\n for (const item of allItems) {\n const hash = hashContent(item.toLowerCase());\n if (seen.has(hash)) continue;\n seen.add(hash);\n\n const id = generateId();\n const category = categoryOverride ?? detectCategory(item);\n\n statements.push({\n id,\n content: item,\n category,\n confidence,\n provenance: {\n sourcePath: filePath,\n relativePath,\n source,\n lineNumber: 0,\n ingestedAt: now,\n sourceFileHash,\n },\n contentHash: hash,\n tags: [...tags],\n entityRef,\n });\n }\n\n return statements;\n}\n\n// ── Category detection ───────────────────────────────────────────────────────\n\nfunction detectCategory(text: string): string {\n const lower = text.toLowerCase();\n\n if (/^(always|never|must|should|don't|avoid|ensure)/.test(lower)) return \"principle\";\n if (/^(we|team|project)\\s+(decided|chose|will|use)/.test(lower)) return \"decision\";\n if (/^(i|we)\\s+(prefer|like|want|hate|dislike)/.test(lower)) return \"preference\";\n if (/fix|bug|issue|broken|error/i.test(lower)) return \"correction\";\n if (/\\?.+$/.test(lower.trim())) return \"question\";\n\n return \"fact\";\n}\n\n// ── Dedup ────────────────────────────────────────────────────────────────────\n\ninterface ExistingMemory {\n id: string;\n content: string;\n category: string;\n}\n\nfunction findDuplicate(\n stmt: CuratedStatement,\n existing: Map<string, ExistingMemory>,\n): DuplicateResult | null {\n const stmtLower = stmt.content.toLowerCase();\n\n // Exact hash match\n const exactMatch = existing.get(stmt.contentHash);\n if (exactMatch) {\n return {\n newStatement: stmt,\n existingId: exactMatch.id,\n similarity: 1,\n action: \"skip\",\n };\n }\n\n // Fuzzy match — check substring containment\n for (const [_, mem] of existing) {\n const memLower = mem.content.toLowerCase();\n if (memLower.length > 50 && stmtLower.length > 50) {\n // Check if one contains the other\n if (memLower.includes(stmtLower.slice(0, 40)) || stmtLower.includes(memLower.slice(0, 40))) {\n return {\n newStatement: stmt,\n existingId: mem.id,\n similarity: 0.85,\n action: \"skip\",\n };\n }\n }\n }\n\n return null;\n}\n\n// ── Contradiction detection ──────────────────────────────────────────────────\n\nfunction findContradiction(\n stmt: CuratedStatement,\n existing: Map<string, ExistingMemory>,\n): ContradictionResult | null {\n const negationPatterns = [\n /\\b(not|don't|doesn't|isn't|aren't|won't|can't|never|no)\\b/i,\n ];\n\n const hasNegation = negationPatterns.some((p) => p.test(stmt.content));\n if (!hasNegation) return null;\n\n // Strip negation and look for positive version\n const stripped = stmt.content\n .toLowerCase()\n .replace(/\\b(not|don't|doesn't|isn't|aren't|won't|can't|never|no)\\b/gi, \"\")\n .trim();\n\n if (stripped.length < 20) return null;\n\n for (const [_, mem] of existing) {\n const memLower = mem.content.toLowerCase();\n // If an existing memory affirms what this statement negates\n if (memLower.includes(stripped.slice(0, Math.min(30, stripped.length)))) {\n return {\n newStatement: stmt,\n conflictingId: mem.id,\n conflictingContent: mem.content,\n severity: \"high\",\n };\n }\n }\n\n return null;\n}\n\n// ── Memory loading ───────────────────────────────────────────────────────────\n\nfunction loadExistingMemories(memoryDir: string): Map<string, ExistingMemory> {\n const result = new Map<string, ExistingMemory>();\n if (!fs.existsSync(memoryDir)) return result;\n\n // Walk all known category dirs for existing memories\n const dirs = ALL_CATEGORY_DIRS;\n for (const dir of dirs) {\n const fullDir = path.join(memoryDir, dir);\n if (!fs.existsSync(fullDir)) continue;\n\n walkFiles(fullDir, (filePath) => {\n const content = readFileSafe(filePath);\n if (!content) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id || !body) return;\n\n const hash = hashContent(body.toLowerCase());\n result.set(hash, {\n id: fm.id,\n content: body,\n category: fm.category ?? dir.slice(0, -1),\n });\n });\n }\n\n return result;\n}\n\n// ── Writing ──────────────────────────────────────────────────────────────────\n\nfunction writeStatement(stmt: CuratedStatement, memoryDir: string): string | null {\n const now = new Date();\n const dateDir = now.toISOString().split(\"T\")[0];\n const categoryDir = getCategoryDir(memoryDir, stmt.category);\n\n const dir = path.join(categoryDir, dateDir);\n fs.mkdirSync(dir, { recursive: true });\n\n const fileName = `${stmt.category}-${Date.now()}-${stmt.id.slice(0, 8)}.md`;\n const filePath = path.join(dir, fileName);\n\n const frontmatter = [\n \"---\",\n `id: ${stmt.id}`,\n `category: ${stmt.category}`,\n `created: ${stmt.provenance.ingestedAt}`,\n `updated: ${stmt.provenance.ingestedAt}`,\n `confidence: ${stmt.confidence}`,\n `confidenceTier: ${tierFromConfidence(stmt.confidence)}`,\n `source: ${stmt.provenance.source}`,\n `tags: ${JSON.stringify(stmt.tags)}`,\n stmt.entityRef ? `entityRef: ${stmt.entityRef}` : null,\n `provenanceFile: ${stmt.provenance.relativePath}`,\n `provenanceHash: ${stmt.provenance.sourceFileHash}`,\n \"---\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n\n const body = `${frontmatter}\\n\\n${stmt.content}\\n`;\n\n try {\n fs.writeFileSync(filePath, body);\n return filePath;\n } catch {\n return null;\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction generateId(): string {\n return crypto.randomUUID();\n}\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nfunction tierFromConfidence(confidence: number): string {\n if (confidence >= 0.95) return \"explicit\";\n if (confidence >= 0.8) return \"high\";\n if (confidence >= 0.5) return \"medium\";\n return \"low\";\n}\n\nfunction readFileSafe(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction isBinary(content: string): boolean {\n // Simple heuristic: if content has null bytes, it's binary\n for (let i = 0; i < Math.min(content.length, 8000); i++) {\n if (content.charCodeAt(i) === 0) return true;\n }\n return false;\n}\n\ninterface SimpleFrontmatter {\n id?: string;\n category?: string;\n [key: string]: unknown;\n}\n\nfunction parseFrontmatter(content: string): SimpleFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: SimpleFrontmatter = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n (fm as Record<string, unknown>)[key] = value;\n }\n return fm;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction walkFiles(dir: string, callback: (filePath: string) => void): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkFiles(fullPath, callback);\n } else if (entry.name.endsWith(\".md\")) {\n callback(fullPath);\n }\n }\n}\n","/**\n * @remnic/core — Dedup & Contradiction Detection\n *\n * Statement-level deduplication and contradiction detection\n * against existing memories. Can be used standalone or via curation.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MemoryEntry {\n /** Memory ID */\n id: string;\n /** Content text */\n content: string;\n /** Category */\n category: string;\n /** File path (if known) */\n filePath?: string;\n}\n\nexport interface DedupOptions {\n /** Memory root directory */\n memoryDir: string;\n /** Categories to scan (default: all) */\n categories?: string[];\n /** Similarity threshold for fuzzy matching (0-1, default: 0.85) */\n threshold?: number;\n /** Max memories to load (default: 10000) */\n maxLoad?: number;\n}\n\nexport interface DedupResult {\n /** Total memories scanned */\n scanned: number;\n /** Duplicate pairs found */\n duplicates: DuplicatePair[];\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface DuplicatePair {\n /** First memory */\n left: MemoryEntry;\n /** Second memory */\n right: MemoryEntry;\n /** Similarity score */\n similarity: number;\n /** Recommended action */\n action: \"merge\" | \"keep_left\" | \"keep_right\";\n}\n\nexport interface ContradictionOptions {\n /** Memory root directory */\n memoryDir: string;\n /** Categories to scan (default: all) */\n categories?: string[];\n /** Max memories to load (default: 10000) */\n maxLoad?: number;\n}\n\nexport interface ContradictionResult {\n /** Total memories scanned */\n scanned: number;\n /** Contradictions found */\n contradictions: ContradictionPair[];\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface ContradictionPair {\n /** First statement */\n left: MemoryEntry;\n /** Contradicting statement */\n right: MemoryEntry;\n /** Severity */\n severity: \"high\" | \"medium\" | \"low\";\n /** Reason */\n reason: string;\n}\n\n// ── Main functions ───────────────────────────────────────────────────────────\n\nexport function findDuplicates(options: DedupOptions): DedupResult {\n const startTime = Date.now();\n const { memoryDir, threshold = 0.85, maxLoad = 10000 } = options;\n\n const memories = loadMemories(memoryDir, options.categories, maxLoad);\n const duplicates: DuplicatePair[] = [];\n\n // Compare all pairs (O(n^2) but bounded by maxLoad)\n for (let i = 0; i < memories.length; i++) {\n for (let j = i + 1; j < memories.length; j++) {\n const sim = computeSimilarity(memories[i].content, memories[j].content);\n if (sim >= threshold) {\n duplicates.push({\n left: memories[i],\n right: memories[j],\n similarity: sim,\n action: sim >= 0.98 ? \"merge\" : sim >= 0.9 ? \"keep_right\" : \"keep_left\",\n });\n }\n }\n }\n\n return {\n scanned: memories.length,\n duplicates,\n durationMs: Date.now() - startTime,\n };\n}\n\nexport function findContradictions(options: ContradictionOptions): ContradictionResult {\n const startTime = Date.now();\n const { memoryDir, maxLoad = 10000 } = options;\n\n const memories = loadMemories(memoryDir, options.categories, maxLoad);\n const contradictions: ContradictionPair[] = [];\n\n for (let i = 0; i < memories.length; i++) {\n for (let j = i + 1; j < memories.length; j++) {\n const contra = detectContradiction(memories[i], memories[j]);\n if (contra) {\n contradictions.push(contra);\n }\n }\n }\n\n return {\n scanned: memories.length,\n contradictions,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Similarity computation ───────────────────────────────────────────────────\n\nfunction computeSimilarity(a: string, b: string): number {\n // Normalize\n const normA = normalize(a);\n const normB = normalize(b);\n\n // Exact match\n if (normA === normB) return 1;\n\n // Hash-based exact match\n if (hashContent(normA) === hashContent(normB)) return 0.99;\n\n // Substring containment\n if (normA.length > 50 && normB.length > 50) {\n if (normA.includes(normB.slice(0, 40)) || normB.includes(normA.slice(0, 40))) {\n return 0.9;\n }\n }\n\n // Word overlap (Jaccard)\n const wordsA = new Set(normA.split(/\\s+/));\n const wordsB = new Set(normB.split(/\\s+/));\n const intersection = new Set([...wordsA].filter((w) => wordsB.has(w)));\n const union = new Set([...wordsA, ...wordsB]);\n\n if (union.size === 0) return 0;\n return intersection.size / union.size;\n}\n\nfunction normalize(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s']/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n// ── Contradiction detection ──────────────────────────────────────────────────\n\nconst NEGATION_WORDS = new Set([\n \"not\", \"don't\", \"doesn't\", \"isn't\", \"aren't\", \"won't\", \"can't\",\n \"never\", \"no\", \"none\", \"neither\", \"nor\", \"nothing\", \"nowhere\",\n]);\n\nfunction detectContradiction(\n a: MemoryEntry,\n b: MemoryEntry,\n): ContradictionPair | null {\n const normA = normalize(a.content);\n const normB = normalize(b.content);\n\n // Check if one has negation and the other doesn't\n const aHasNegation = containsNegation(normA);\n const bHasNegation = containsNegation(normB);\n\n if (aHasNegation === bHasNegation) return null;\n\n // Strip negation and compare core content\n const strippedA = stripNegation(normA);\n const strippedB = stripNegation(normB);\n\n const sim = computeSimilarity(strippedA, strippedB);\n if (sim < 0.7) return null;\n\n // Check for opposite quantifiers\n const oppQuantifiers = [\n [\"always\", \"never\"],\n [\"all\", \"none\"],\n [\"every\", \"no\"],\n [\"must\", \"must not\"],\n [\"should\", \"should not\"],\n [\"can\", \"cannot\"],\n ];\n\n for (const [pos, neg] of oppQuantifiers) {\n if (\n (a.content.toLowerCase().includes(pos) && b.content.toLowerCase().includes(neg)) ||\n (a.content.toLowerCase().includes(neg) && b.content.toLowerCase().includes(pos))\n ) {\n return {\n left: a,\n right: b,\n severity: \"high\",\n reason: `Opposite quantifiers: \"${pos}\" vs \"${neg}\"`,\n };\n }\n }\n\n return {\n left: a,\n right: b,\n severity: sim >= 0.85 ? \"high\" : \"medium\",\n reason: \"Negated version of similar content\",\n };\n}\n\nfunction containsNegation(text: string): boolean {\n const words = text.split(/\\s+/);\n return words.some((w) => NEGATION_WORDS.has(w));\n}\n\nfunction stripNegation(text: string): string {\n return text\n .replace(/\\b(not|don't|doesn't|isn't|aren't|won't|can't|never|no|none|neither|nor|nothing|nowhere)\\b/gi, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n// ── Memory loading ───────────────────────────────────────────────────────────\n\nfunction loadMemories(\n memoryDir: string,\n categories?: string[],\n maxLoad = 10000,\n): MemoryEntry[] {\n const result: MemoryEntry[] = [];\n const allCategories = categories ?? ALL_CATEGORY_DIRS;\n\n for (const category of allCategories) {\n if (result.length >= maxLoad) break;\n\n const dir = path.join(memoryDir, category);\n if (!fs.existsSync(dir)) continue;\n\n walkMdFiles(dir, (filePath) => {\n if (result.length >= maxLoad) return;\n\n const content = readFileSafe(filePath);\n if (!content) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id || !body) return;\n\n result.push({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? category.slice(0, -1),\n filePath,\n });\n });\n }\n\n return result;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nfunction readFileSafe(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction parseFrontmatter(content: string): Record<string, unknown> | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n fm[key] = value;\n }\n return fm;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction walkMdFiles(dir: string, callback: (filePath: string) => void): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkMdFiles(fullPath, callback);\n } else if (entry.name.endsWith(\".md\")) {\n callback(fullPath);\n }\n }\n}\n","/**\n * @remnic/core — Review Inbox\n *\n * Manages low-confidence memories and suggestions pending review.\n * Integrates with the existing review-queue system.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getCategoryDir, ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReviewItem {\n /** Memory ID */\n id: string;\n /** Content text */\n content: string;\n /** Category */\n category: string;\n /** Confidence score (0-1) */\n confidence: number;\n /** Confidence tier */\n confidenceTier: string;\n /** Source */\n source: string;\n /** File path if available */\n filePath?: string;\n /** Created date */\n created: string;\n /** Reason it's in review */\n reviewReason: \"low_confidence\" | \"suggestion\" | \"contradiction\" | \"duplicate\";\n /** Additional context */\n context?: string;\n}\n\nexport type ReviewAction = \"approve\" | \"dismiss\" | \"flag\";\n\nexport interface ReviewResult {\n /** Item acted upon */\n itemId: string;\n /** Action taken */\n action: ReviewAction;\n /** Updated file path (if modified) */\n updatedPath?: string;\n /** Status message */\n message: string;\n}\n\nexport interface ReviewListResult {\n /** Items pending review */\n items: ReviewItem[];\n /** Total count */\n total: number;\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface ReviewOptions {\n /** Memory root directory */\n memoryDir: string;\n /** Filter by reason */\n reason?: ReviewItem[\"reviewReason\"];\n /** Max items to return (default: 50) */\n limit?: number;\n /** Include items with confidence below this threshold (default: 0.7) */\n confidenceThreshold?: number;\n}\n\n// ── Main functions ───────────────────────────────────────────────────────────\n\n/**\n * List items pending review.\n */\nexport function listReviewItems(options: ReviewOptions): ReviewListResult {\n const startTime = Date.now();\n const {\n memoryDir,\n reason: filterReason,\n limit = 50,\n confidenceThreshold = 0.7,\n } = options;\n\n const items: ReviewItem[] = [];\n\n // Check suggestions directory\n const suggestionsDir = path.join(memoryDir, \"suggestions\");\n if (fs.existsSync(suggestionsDir)) {\n walkMd(suggestionsDir, (filePath, content) => {\n if (items.length >= limit) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id) return;\n\n items.push({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? \"suggestion\",\n confidence: parseConfidence(fm.confidence, 0.5),\n confidenceTier: (fm.confidenceTier as string) ?? \"low\",\n source: (fm.source as string) ?? \"unknown\",\n filePath,\n created: (fm.created as string) ?? new Date().toISOString(),\n reviewReason: \"suggestion\",\n });\n });\n }\n\n // Check review directory\n const reviewDir = path.join(memoryDir, \"review\");\n if (fs.existsSync(reviewDir)) {\n walkMd(reviewDir, (filePath, content) => {\n if (items.length >= limit) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id) return;\n\n items.push({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? \"review\",\n confidence: parseConfidence(fm.confidence, 0.5),\n confidenceTier: (fm.confidenceTier as string) ?? \"low\",\n source: (fm.source as string) ?? \"unknown\",\n filePath,\n created: (fm.created as string) ?? new Date().toISOString(),\n reviewReason: (fm.reviewReason as ReviewItem[\"reviewReason\"]) ?? \"low_confidence\",\n context: fm.context as string | undefined,\n });\n });\n }\n\n // Scan all categories for low-confidence items\n const categories = ALL_CATEGORY_DIRS;\n for (const category of categories) {\n if (items.length >= limit) break;\n\n const dir = path.join(memoryDir, category);\n if (!fs.existsSync(dir)) continue;\n\n walkMd(dir, (filePath, content) => {\n if (items.length >= limit) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id) return;\n\n const confidence = parseConfidence(fm.confidence, 1);\n if (confidence >= confidenceThreshold) return;\n\n // Skip if already in items\n if (items.some((i) => i.id === fm.id)) return;\n\n items.push({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? category.slice(0, -1),\n confidence,\n confidenceTier: (fm.confidenceTier as string) ?? \"low\",\n source: (fm.source as string) ?? \"unknown\",\n filePath,\n created: (fm.created as string) ?? new Date().toISOString(),\n reviewReason: \"low_confidence\",\n });\n });\n }\n\n // Filter by reason\n const filtered = filterReason\n ? items.filter((i) => i.reviewReason === filterReason)\n : items;\n\n return {\n items: filtered.slice(0, limit),\n total: filtered.length,\n durationMs: Date.now() - startTime,\n };\n}\n\n/**\n * Perform a review action on an item.\n */\nexport function performReview(\n memoryDir: string,\n itemId: string,\n action: ReviewAction,\n): ReviewResult {\n switch (action) {\n case \"approve\":\n return approveItem(memoryDir, itemId);\n case \"dismiss\":\n return dismissItem(memoryDir, itemId);\n case \"flag\":\n return flagItem(memoryDir, itemId);\n }\n}\n\n// ── Actions ──────────────────────────────────────────────────────────────────\n\nfunction approveItem(memoryDir: string, itemId: string): ReviewResult {\n // Find the item in suggestions/ or review/\n const locations = [\"suggestions\", \"review\"];\n for (const loc of locations) {\n const dir = path.join(memoryDir, loc);\n if (!fs.existsSync(dir)) continue;\n\n const found = findFileById(dir, itemId);\n if (!found) continue;\n\n const content = fs.readFileSync(found, \"utf8\");\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm) return { itemId, action: \"approve\", message: \"Could not parse frontmatter\" };\n\n // Promote to facts/ with boosted confidence\n const category = (fm.category as string) ?? \"fact\";\n const targetDir = getCategoryDir(memoryDir, category);\n const dateDir = new Date().toISOString().split(\"T\")[0];\n const outputPath = path.join(targetDir, dateDir, path.basename(found));\n\n // Update confidence in content\n const updatedContent = content\n .replace(/confidence: [\\d.]+/, \"confidence: 0.9\")\n .replace(/confidenceTier: \\w+/, \"confidenceTier: high\");\n\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, updatedContent);\n\n // Remove from review\n fs.unlinkSync(found);\n\n return {\n itemId,\n action: \"approve\",\n updatedPath: outputPath,\n message: `Promoted to ${category} with confidence 0.9`,\n };\n }\n\n return { itemId, action: \"approve\", message: \"Item not found\" };\n}\n\nfunction dismissItem(memoryDir: string, itemId: string): ReviewResult {\n const locations = [\"suggestions\", \"review\"];\n for (const loc of locations) {\n const dir = path.join(memoryDir, loc);\n if (!fs.existsSync(dir)) continue;\n\n const found = findFileById(dir, itemId);\n if (found) {\n fs.unlinkSync(found);\n return { itemId, action: \"dismiss\", message: \"Dismissed and removed\" };\n }\n }\n\n return { itemId, action: \"dismiss\", message: \"Item not found\" };\n}\n\nfunction flagItem(memoryDir: string, itemId: string): ReviewResult {\n const locations = [\"suggestions\", \"review\"];\n for (const loc of locations) {\n const dir = path.join(memoryDir, loc);\n if (!fs.existsSync(dir)) continue;\n\n const found = findFileById(dir, itemId);\n if (found) {\n // Add flagged marker to frontmatter\n const content = fs.readFileSync(found, \"utf8\");\n const fixed = content.replace(\n /^(---\\n)/,\n `---\\nflagged: true\\nflaggedAt: ${new Date().toISOString()}\\n`,\n );\n fs.writeFileSync(found, fixed);\n return { itemId, action: \"flag\", message: \"Flagged for further review\" };\n }\n }\n\n return { itemId, action: \"flag\", message: \"Item not found\" };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction findFileById(dir: string, id: string): string | null {\n const files = walkMdPaths(dir);\n for (const filePath of files) {\n const content = readFileSafe(filePath);\n if (!content) continue;\n const fm = parseFrontmatter(content);\n if (fm?.id === id) return filePath;\n }\n return null;\n}\n\nfunction parseConfidence(value: unknown, fallback: number): number {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : fallback;\n if (typeof value === \"string\") {\n const n = parseFloat(value);\n return Number.isFinite(n) ? n : fallback;\n }\n return fallback;\n}\n\nfunction readFileSafe(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction parseFrontmatter(content: string): Record<string, unknown> | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n fm[key] = value;\n }\n return fm;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction walkMd(dir: string, callback: (filePath: string, content: string) => void): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkMd(fullPath, callback);\n } else if (entry.name.endsWith(\".md\")) {\n const content = readFileSafe(fullPath);\n if (content) callback(fullPath, content);\n }\n }\n}\n\nfunction walkMdPaths(dir: string): string[] {\n const results: string[] = [];\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...walkMdPaths(fullPath));\n } else if (entry.name.endsWith(\".md\")) {\n results.push(fullPath);\n }\n }\n return results;\n}\n","/**\n * @remnic/core — Diff-Aware Sync\n *\n * Watches source files for changes and triggers re-ingestion\n * only for changed content. Uses file hashing to detect changes.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface SyncOptions {\n /** Source directory to watch */\n sourceDir: string;\n /** Memory root directory */\n memoryDir: string;\n /** State file path (stores hashes). Default: memoryDir/.sync-state.json */\n stateFile?: string;\n /** File extensions to watch (default: .md, .txt, .mdx) */\n extensions?: string[];\n /** Directories to exclude */\n excludeDirs?: string[];\n /** Whether to actually write changes (default: true) */\n dryRun?: boolean;\n}\n\nexport interface SyncResult {\n /** Files scanned */\n scanned: number;\n /** Files changed since last sync */\n changed: FileChange[];\n /** Files unchanged */\n unchanged: number;\n /** Files deleted since last sync */\n deleted: string[];\n /** Files newly added */\n added: string[];\n /** Duration in ms */\n durationMs: number;\n /** State file path */\n stateFile: string;\n}\n\nexport interface FileChange {\n /** Absolute file path */\n filePath: string;\n /** Relative path from source root */\n relativePath: string;\n /** Change type */\n type: \"added\" | \"modified\" | \"deleted\";\n /** Current content hash */\n currentHash: string;\n /** Previous content hash (if modified) */\n previousHash?: string;\n /** File size in bytes */\n size: number;\n}\n\nexport interface SyncState {\n /** Map of relative path → content hash */\n fileHashes: Record<string, string>;\n /** Last sync timestamp */\n lastSyncAt: string;\n /** Version of state format */\n version: number;\n}\n\n// ── Constants ────────────────────────────────────────────────────────────────\n\nconst DEFAULT_EXTENSIONS = new Set([\".md\", \".txt\", \".mdx\", \".rst\"]);\nconst DEFAULT_EXCLUDE = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".engram\",\n \"coverage\",\n]);\n\n// ── Main function ────────────────────────────────────────────────────────────\n\nexport function syncChanges(options: SyncOptions): SyncResult {\n const startTime = Date.now();\n const {\n sourceDir,\n memoryDir,\n extensions = [...DEFAULT_EXTENSIONS],\n excludeDirs = [],\n dryRun = false,\n } = options;\n\n const extSet = new Set(extensions);\n const excludeSet = new Set([...DEFAULT_EXCLUDE, ...excludeDirs]);\n const stateFilePath = options.stateFile ?? path.join(memoryDir, \".sync-state.json\");\n\n // Load previous state\n const prevState = loadState(stateFilePath);\n\n // Scan current files\n const currentFiles = scanFiles(sourceDir, extSet, excludeSet);\n\n // Compute diffs\n const changes = computeDiff(currentFiles, prevState.fileHashes, sourceDir);\n\n const added = changes.filter((c) => c.type === \"added\").map((c) => c.relativePath);\n const modified = changes.filter((c) => c.type === \"modified\");\n const deleted = changes\n .filter((c) => c.type === \"deleted\")\n .map((c) => c.relativePath);\n\n // Update state (even in dry run, we want to show what would change)\n if (!dryRun) {\n const newState: SyncState = {\n fileHashes: {},\n lastSyncAt: new Date().toISOString(),\n version: 1,\n };\n\n // Build new state from current files\n for (const [relPath, hash] of Object.entries(currentFiles)) {\n newState.fileHashes[relPath] = hash;\n }\n\n // Write state\n fs.mkdirSync(path.dirname(stateFilePath), { recursive: true });\n fs.writeFileSync(stateFilePath, JSON.stringify(newState, null, 2));\n }\n\n return {\n scanned: Object.keys(currentFiles).length,\n changed: changes,\n unchanged:\n Object.keys(currentFiles).length - changes.filter((c) => c.type !== \"deleted\").length,\n deleted,\n added,\n durationMs: Date.now() - startTime,\n stateFile: stateFilePath,\n };\n}\n\n/**\n * Watch for changes and call callback on file changes.\n * Returns a stop function.\n */\nexport function watchForChanges(\n options: SyncOptions,\n onChange: (changes: FileChange[]) => void,\n): { stop: () => void } {\n const { sourceDir, extensions, excludeDirs } = options;\n const extSet = new Set(extensions ?? DEFAULT_EXTENSIONS);\n const excludeSet = new Set([...DEFAULT_EXCLUDE, ...(excludeDirs ?? [])]);\n\n let lastHashes: Record<string, string> = {};\n\n // Initial scan\n const currentFiles = scanFiles(sourceDir, extSet, excludeSet);\n lastHashes = { ...currentFiles };\n\n // Poll interval (FSWatcher doesn't reliably work for all platforms)\n const interval = setInterval(() => {\n const nowFiles = scanFiles(sourceDir, extSet, excludeSet);\n const changes = computeDiff(nowFiles, lastHashes, sourceDir);\n\n if (changes.length > 0) {\n // Update hashes\n for (const change of changes) {\n if (change.type === \"deleted\") {\n delete lastHashes[change.relativePath];\n } else {\n lastHashes[change.relativePath] = change.currentHash;\n }\n }\n onChange(changes);\n }\n }, 5000);\n\n return {\n stop: () => clearInterval(interval),\n };\n}\n\n// ── File scanning ────────────────────────────────────────────────────────────\n\nfunction scanFiles(\n root: string,\n extensions: Set<string>,\n exclude: Set<string>,\n): Record<string, string> {\n const result: Record<string, string> = {};\n\n function walk(dir: string): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (exclude.has(entry.name)) continue;\n\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath);\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name).toLowerCase();\n if (!extensions.has(ext)) continue;\n\n const relPath = path.relative(root, fullPath);\n try {\n const content = fs.readFileSync(fullPath, \"utf8\");\n result[relPath] = hashContent(content);\n } catch {\n // Can't read — skip\n }\n }\n }\n }\n\n walk(root);\n return result;\n}\n\n// ── Diff computation ─────────────────────────────────────────────────────────\n\nfunction computeDiff(\n current: Record<string, string>,\n previous: Record<string, string>,\n sourceDir: string,\n): FileChange[] {\n const changes: FileChange[] = [];\n\n // Find added and modified\n for (const [relPath, hash] of Object.entries(current)) {\n const fullPath = path.join(sourceDir, relPath);\n\n if (!(relPath in previous)) {\n // Added\n let size = 0;\n try {\n size = fs.statSync(fullPath).size;\n } catch {\n // ignore\n }\n changes.push({\n filePath: fullPath,\n relativePath: relPath,\n type: \"added\",\n currentHash: hash,\n size,\n });\n } else if (previous[relPath] !== hash) {\n // Modified\n let size = 0;\n try {\n size = fs.statSync(fullPath).size;\n } catch {\n // ignore\n }\n changes.push({\n filePath: fullPath,\n relativePath: relPath,\n type: \"modified\",\n currentHash: hash,\n previousHash: previous[relPath],\n size,\n });\n }\n }\n\n // Find deleted\n for (const relPath of Object.keys(previous)) {\n if (!(relPath in current)) {\n changes.push({\n filePath: path.join(sourceDir, relPath),\n relativePath: relPath,\n type: \"deleted\",\n currentHash: \"\",\n size: 0,\n });\n }\n }\n\n return changes;\n}\n\n// ── State management ─────────────────────────────────────────────────────────\n\nfunction loadState(stateFilePath: string): SyncState {\n try {\n const raw = fs.readFileSync(stateFilePath, \"utf8\");\n return JSON.parse(raw);\n } catch {\n return {\n fileHashes: {},\n lastSyncAt: new Date(0).toISOString(),\n version: 1,\n };\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n","/**\n * @remnic/core — Connector Manager\n *\n * Metadata-driven registry for host adapters (Codex CLI, Claude Code, Cursor, etc.).\n * Manages connector lifecycle: install, remove, configure, health.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ConnectorManifest {\n /** Unique connector ID (e.g. \"claude-code\", \"codex-cli\") */\n id: string;\n /** Human-readable name */\n name: string;\n /** Version */\n version: string;\n /** Description */\n description: string;\n /** Capabilities */\n capabilities: ConnectorCapability;\n /** Required config fields */\n configSchema?: Record<string, string>;\n /** Whether currently installed */\n installed?: boolean;\n /** Homepage URL */\n homepage?: string;\n /** Author */\n author?: string;\n /** Repository URL */\n repository?: string;\n /** Tags */\n tags?: string[];\n}\n\nexport interface ConnectorCapability {\n /** Can observe conversations */\n observe: boolean;\n /** Can recall/query memories */\n recall: boolean;\n /** Can store memories */\n store: boolean;\n /** Can search */\n search: boolean;\n /** Can manage entities */\n entities: boolean;\n /** Supports real-time sync */\n realtimeSync: boolean;\n /** Supports batch operations */\n batch: boolean;\n /** Max memory budget in chars */\n maxBudgetChars?: number;\n /** Connection type */\n connectionType: \"mcp\" | \"http\" | \"cli\" | \"sdk\" | \"embedded\";\n}\n\nexport interface ConnectorInstance {\n /** Connector ID */\n connectorId: string;\n /** Resolved config */\n config: Record<string, unknown>;\n /** Status */\n status: \"installed\" | \"running\" | \"error\" | \"disabled\";\n /** Installed at timestamp */\n installedAt?: string;\n /** Error message if erro */\n error?: string;\n}\n\nexport interface ConnectorRegistry {\n /** Known connectors */\n connectors: ConnectorManifest[];\n /** Registry file path */\n registryPath: string;\n}\n\nexport interface InstallOptions {\n /** Connector ID to install */\n connectorId: string;\n /** Config values */\n config?: Record<string, unknown>;\n /** Memory directory */\n memoryDir?: string;\n /** Whether to force reinstall */\n force?: boolean;\n}\n\nexport interface InstallResult {\n /** Connector ID */\n connectorId: string;\n /** Status */\n status: \"installed\" | \"already_installed\" | \"config_required\" | \"error\";\n /** Config path */\n configPath?: string;\n /** Message */\n message: string;\n}\n\nexport interface RemoveResult {\n /** Connector ID */\n connectorId: string;\n /** Removed config path */\n configPath: string;\n /** Message */\n message: string;\n}\n\nexport interface DoctorResult {\n /** Connector ID */\n connectorId: string;\n /** Checks */\n checks: DoctorCheck[];\n /** All healthy */\n healthy: boolean;\n}\n\nexport interface DoctorCheck {\n /** Check name */\n name: string;\n /** Passed */\n ok: boolean;\n /** Detail */\n detail: string;\n}\n\n// ── Built-in connector definitions ─────────────────────────────────────────\n\nconst BUILTIN_CONNECTORS: ConnectorManifest[] = [\n {\n id: \"claude-code\",\n name: \"Claude Code\",\n version: \"1.0.0\",\n description: \"Anthropic's Claude Code CLI — direct memory access via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: true,\n entities: true,\n realtimeSync: true,\n batch: false,\n maxBudgetChars: 32000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace (default: 'default')\",\n },\n homepage: \"https://claude.ai/code\",\n author: \"Anthropic\",\n tags: [\"official\", \"ai\", \"claude\"],\n },\n {\n id: \"codex-cli\",\n name: \"Codex CLI\",\n version: \"1.0.0\",\n description: \"OpenAI Codex CLI — memory via MCP tool\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: false,\n entities: false,\n realtimeSync: false,\n batch: true,\n maxBudgetChars: 8000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace\",\n },\n homepage: \"https://openai.com/codex\",\n author: \"OpenAI\",\n tags: [\"official\", \"ai\", \"codex\"],\n },\n {\n id: \"cursor\",\n name: \"Cursor IDE\",\n version: \"1.0.0\",\n description: \"Cursor IDE — memory via config file + tool calls\",\n capabilities: {\n observe: false,\n recall: true,\n store: false,\n search: true,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 32000,\n connectionType: \"embedded\",\n },\n configSchema: {\n memoryDir: \"Path to Remnic memory directory\",\n },\n homepage: \"https://cursor.com\",\n author: \"Cursor Inc.\",\n tags: [\"official\", \"ide\"],\n },\n {\n id: \"cline\",\n name: \"Cline\",\n version: \"1.0.0\",\n description: \"VS Code Cline extension — memory via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: false,\n entities: false,\n realtimeSync: false,\n batch: true,\n maxBudgetChars: 8000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace\",\n },\n homepage: \"https://github.com/cline/cline\",\n author: \"Cline\",\n tags: [\"community\", \"vscode\"],\n },\n {\n id: \"github-copilot\",\n name: \"GitHub Copilot\",\n version: \"1.0.0\",\n description: \"GitHub Copilot — memory via MCP server\",\n capabilities: {\n observe: false,\n recall: true,\n store: false,\n search: true,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 16000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n },\n homepage: \"https://github.com/features/copilot\",\n author: \"GitHub\",\n tags: [\"official\", \"ai\", \"github\"],\n },\n {\n id: \"roo-code\",\n name: \"Roo Code\",\n version: \"1.0.0\",\n description: \"Roo Code — memory via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: false,\n entities: false,\n realtimeSync: false,\n batch: true,\n maxBudgetChars: 16000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace\",\n },\n homepage: \"https://roocode.com\",\n author: \"Roo Code\",\n tags: [\"community\", \"vscode\"],\n },\n {\n id: \"windsurf\",\n name: \"Windsurf\",\n version: \"1.0.0\",\n description: \"Windsurf IDE — memory via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: true,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 32000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n },\n homepage: \"https://windsurf.com\",\n author: \"Codeium\",\n tags: [\"official\", \"ide\"],\n },\n {\n id: \"amp\",\n name: \"Amp\",\n version: \"1.0.0\",\n description: \"Amp coding agent — memory via MCP\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: true,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 32000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n },\n homepage: \"https://ampcode.com\",\n author: \"Sourcegraph\",\n tags: [\"official\", \"ai\"],\n },\n {\n id: \"replit\",\n name: \"Replit Agent\",\n version: \"1.0.0\",\n description: \"Replit Agent — memory via HTTP API (reduced capabilities)\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: false,\n entities: false,\n realtimeSync: false,\n batch: false,\n maxBudgetChars: 8000,\n connectionType: \"http\",\n },\n configSchema: {\n apiUrl: \"URL of the Remnic HTTP API\",\n authToken: \"Bearer token for authentication\",\n },\n homepage: \"https://replit.com\",\n author: \"Replit\",\n tags: [\"official\", \"cloud\"],\n },\n {\n id: \"generic-mcp\",\n name: \"Generic MCP Client\",\n version: \"1.0.0\",\n description: \"Any MCP-compatible client — connect via standard MCP protocol\",\n capabilities: {\n observe: true,\n recall: true,\n store: true,\n search: true,\n entities: true,\n realtimeSync: true,\n batch: true,\n maxBudgetChars: 64000,\n connectionType: \"mcp\",\n },\n configSchema: {\n mcpServerUrl: \"URL of the MCP Remnic server\",\n namespace: \"Optional namespace\",\n authToken: \"Bearer token for authentication\",\n },\n homepage: \"https://github.com/joshuaswarren/remnic\",\n author: \"Remnic\",\n tags: [\"generic\", \"mcp\"],\n },\n];\n\n// ── Registry management ───────────────────────────────────────────────────\n\nconst REGISTRY_DIR_NAME = \".engram-connectors\";\n\nexport function getRegistryPath(): string {\n const configDir = process.env.XDG_CONFIG_HOME\n ? path.join(process.env.XDG_CONFIG_HOME, \"engram\")\n : path.join(process.env.HOME ?? \"~\", \".config\", \"engram\");\n return path.join(configDir, REGISTRY_DIR_NAME, \"registry.json\");\n}\n\nexport function loadRegistry(): ConnectorRegistry {\n const regPath = getRegistryPath();\n\n if (!fs.existsSync(regPath)) {\n // First time — bootstrap with built-in connectors\n const registry: ConnectorRegistry = {\n connectors: BUILTIN_CONNECTORS,\n registryPath: regPath,\n };\n saveRegistry(registry);\n return registry;\n }\n\n const raw = fs.readFileSync(regPath, \"utf8\");\n try {\n const parsed = JSON.parse(raw);\n // Merge built-ins with any custom connectors\n const customIds = new Set((parsed.connectors ?? []).map((c: ConnectorManifest) => c.id));\n const merged = [\n ...BUILTIN_CONNECTORS.filter((b) => !customIds.has(b.id)),\n ...(parsed.connectors ?? []),\n ];\n return {\n connectors: merged,\n registryPath: regPath,\n };\n } catch {\n const registry: ConnectorRegistry = {\n connectors: BUILTIN_CONNECTORS,\n registryPath: regPath,\n };\n saveRegistry(registry);\n return registry;\n }\n}\n\nexport function saveRegistry(registry: ConnectorRegistry): void {\n const regPath = registry.registryPath;\n fs.mkdirSync(path.dirname(regPath), { recursive: true });\n fs.writeFileSync(regPath, JSON.stringify({ connectors: registry.connectors }, null, 2));\n}\n\n// ── List connectors ────────────────────────────────────────────────────────\n\nexport function listConnectors(): {\n installed: ConnectorInstance[];\n available: ConnectorManifest[];\n} {\n const registry = loadRegistry();\n const connectorsDir = getConnectorsDir();\n const installedIds = new Set<string>();\n\n // Find installed connectors\n if (fs.existsSync(connectorsDir)) {\n for (const entry of fs.readdirSync(connectorsDir)) {\n if (entry.endsWith(\".json\")) {\n try {\n const config = JSON.parse(\n fs.readFileSync(path.join(connectorsDir, entry), \"utf8\"),\n );\n installedIds.add(config.connectorId as string);\n } catch {\n // ignore malformed configs\n }\n }\n }\n }\n\n // Mark installed vs available\n const available: ConnectorManifest[] = registry.connectors.map((manifest) => ({\n ...manifest,\n installed: installedIds.has(manifest.id),\n }));\n\n // Build installed list\n const installed: ConnectorInstance[] = [];\n for (const id of installedIds) {\n const configPath = path.join(connectorsDir, `${id}.json`);\n try {\n const config = JSON.parse(fs.readFileSync(configPath, \"utf8\"));\n installed.push({\n connectorId: id,\n config,\n status: \"installed\",\n installedAt: config.installedAt as string | undefined,\n });\n } catch {\n // ignore\n }\n }\n\n return { installed, available };\n}\n\n// ── Install connector ───────────────────────────────────────────────────────\n\nexport function installConnector(options: InstallOptions): InstallResult {\n const registry = loadRegistry();\n const manifest = registry.connectors.find((c) => c.id === options.connectorId);\n\n if (!manifest) {\n return {\n connectorId: options.connectorId,\n status: \"error\",\n message: `Unknown connector: ${options.connectorId}`,\n };\n }\n\n // Check if already installed\n const existing = listConnectors().installed.find(\n (c) => c.connectorId === options.connectorId,\n );\n\n if (existing && !options.force) {\n return {\n connectorId: options.connectorId,\n status: \"already_installed\",\n message: \"Already installed. Use --force to reinstall.\",\n };\n }\n\n // Write config\n const configDir = getConnectorsDir();\n fs.mkdirSync(configDir, { recursive: true });\n\n const configPath = path.join(configDir, `${options.connectorId}.json`);\n\n // Build config from schema defaults + user overrides\n const resolvedConfig: Record<string, unknown> = {\n connectorId: options.connectorId,\n installedAt: new Date().toISOString(),\n ...options.config,\n };\n fs.writeFileSync(configPath, JSON.stringify(resolvedConfig, null, 2));\n\n return {\n connectorId: options.connectorId,\n status: \"installed\",\n configPath,\n message: `Installed ${manifest.name} v${manifest.version}`,\n };\n}\n\n// ── Remove connector ───────────────────────────────────────────────────────\n\nexport function removeConnector(connectorId: string): RemoveResult {\n const configDir = getConnectorsDir();\n const configPath = path.join(configDir, `${connectorId}.json`);\n\n if (!fs.existsSync(configPath)) {\n return {\n connectorId,\n configPath,\n message: \"Not installed\",\n };\n }\n\n fs.unlinkSync(configPath);\n return {\n connectorId,\n configPath,\n message: \"Removed\",\n };\n}\n\n// ── Doctor ────────────────────────────────────────────────────────────────────\n\nexport async function doctorConnector(connectorId: string): Promise<DoctorResult> {\n const installed = listConnectors().installed;\n const instance = installed.find((c) => c.connectorId === connectorId);\n\n if (!instance) {\n return {\n connectorId,\n checks: [{ name: \"Installed\", ok: false, detail: \"Not installed\" }],\n healthy: false,\n };\n }\n\n const configPath = path.join(getConnectorsDir(), `${connectorId}.json`);\n const checks: DoctorCheck[] = [];\n\n // Check config exists\n checks.push({\n name: \"Config file\",\n ok: fs.existsSync(configPath),\n detail: configPath,\n });\n\n // Check config is valid JSON\n try {\n const raw = fs.readFileSync(configPath, \"utf8\");\n JSON.parse(raw);\n checks.push({ name: \"Config valid\", ok: true, detail: \"OK\" });\n } catch (e) {\n checks.push({ name: \"Config valid\", ok: false, detail: String(e) });\n }\n\n // Check MCP server reachable (if applicable)\n const mcpUrl = instance.config.mcpServerUrl as string | undefined;\n if (mcpUrl) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 3000);\n const response = await fetch(mcpUrl, { signal: controller.signal });\n clearTimeout(timeoutId);\n checks.push({ name: \"MCP server\", ok: response.ok, detail: mcpUrl });\n } catch (e) {\n checks.push({\n name: \"MCP server\",\n ok: false,\n detail: `Cannot reach ${mcpUrl}: ${e instanceof Error ? e.message : \"unknown\"}`,\n });\n }\n }\n\n // Check memory dir (if applicable)\n const memoryDir = instance.config.memoryDir as string | undefined;\n if (memoryDir) {\n if (fs.existsSync(memoryDir)) {\n checks.push({ name: \"Memory directory\", ok: true, detail: memoryDir });\n } else {\n checks.push({ name: \"Memory directory\", ok: false, detail: `Not found: ${memoryDir}` });\n }\n }\n\n const healthy = checks.every((c) => c.ok);\n return { connectorId, checks, healthy };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction getConnectorsDir(): string {\n const configDir = process.env.XDG_CONFIG_HOME\n ? path.join(process.env.XDG_CONFIG_HOME, \"engram\")\n : path.join(process.env.HOME ?? \"~\", \".config\", \"engram\");\n return path.join(configDir, REGISTRY_DIR_NAME, \"connectors\");\n}\n","/**\n * @remnic/core — Spaces + Collaboration\n *\n * First-class memory spaces (personal, project, team) with merge/conflict\n * flows, promotion workflow, and audit trail.\n *\n * Each space is an isolated memory directory. Spaces can share memories\n * through push/pull and promotion workflows.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type SpaceKind = \"personal\" | \"project\" | \"team\";\n\nexport interface Space {\n /** Unique space ID */\n id: string;\n /** Human-readable name */\n name: string;\n /** Space type */\n kind: SpaceKind;\n /** Description */\n description?: string;\n /** Memory directory path (absolute) */\n memoryDir: string;\n /** Created at */\n createdAt: string;\n /** Updated at */\n updatedAt: string;\n /** Owner */\n owner?: string;\n /** Members (for team spaces) */\n members?: string[];\n /** Parent space (for promotion) */\n parentSpaceId?: string;\n}\n\nexport interface SpaceManifest {\n /** Current active space ID */\n activeSpaceId: string;\n /** All spaces */\n spaces: Space[];\n /** Manifest version */\n version: number;\n /** Last updated */\n updatedAt?: string;\n}\n\nexport interface SpaceSwitchResult {\n previousSpaceId: string;\n currentSpaceId: string;\n message: string;\n}\n\nexport interface SpacePushResult {\n sourceSpaceId: string;\n targetSpaceId: string;\n memoriesPushed: number;\n conflicts: ConflictEntry[];\n durationMs: number;\n}\n\nexport interface SpacePullResult {\n sourceSpaceId: string;\n targetSpaceId: string;\n memoriesPulled: number;\n conflicts: ConflictEntry[];\n durationMs: number;\n}\n\nexport interface SpaceShareResult {\n spaceId: string;\n sharedWith: string[];\n message: string;\n}\n\nexport interface SpacePromoteResult {\n sourceSpaceId: string;\n targetSpaceId: string;\n memoriesPromoted: number;\n conflicts: ConflictEntry[];\n durationMs: number;\n}\n\nexport interface ConflictEntry {\n /** Memory ID */\n memoryId: string;\n /** Source file path */\n sourcePath: string;\n /** Target file path */\n targetPath: string;\n /** Conflict type */\n conflictType: \"content_mismatch\" | \"metadata_mismatch\" | \"both\";\n /** Source content hash */\n sourceHash: string;\n /** Target content hash */\n targetHash: string;\n}\n\nexport interface MergeResult {\n merged: number;\n conflicts: ConflictEntry[];\n skipped: number;\n durationMs: number;\n}\n\nexport interface AuditEntry {\n id: string;\n timestamp: string;\n action: string;\n sourceSpaceId: string;\n targetSpaceId?: string;\n actor?: string;\n details: string;\n memoryIds?: string[];\n}\n\n// ── Manifest management ─────────────────────────────────────────────────────\n\nconst MANIFEST_VERSION = 1;\n\nexport function getSpacesDir(baseDir?: string): string {\n const homeDir = baseDir ?? process.env.HOME ?? \"~\";\n return path.join(homeDir, \".config\", \"engram\", \"spaces\");\n}\n\nexport function getManifestPath(baseDir?: string): string {\n return path.join(getSpacesDir(baseDir), \"manifest.json\");\n}\n\nexport function loadManifest(baseDir?: string, memoryDirOverride?: string): SpaceManifest {\n const manifestPath = getManifestPath(baseDir);\n\n if (!fs.existsSync(manifestPath)) {\n // Bootstrap with a personal space\n const personalSpace = createPersonalSpace(baseDir, memoryDirOverride);\n const manifest: SpaceManifest = {\n activeSpaceId: personalSpace.id,\n spaces: [personalSpace],\n version: MANIFEST_VERSION,\n };\n saveManifest(manifest, baseDir);\n return manifest;\n }\n\n const raw = JSON.parse(fs.readFileSync(manifestPath, \"utf8\"));\n return raw as SpaceManifest;\n}\n\nexport function saveManifest(manifest: SpaceManifest, baseDir?: string): void {\n const manifestPath = getManifestPath(baseDir);\n fs.mkdirSync(path.dirname(manifestPath), { recursive: true });\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + \"\\n\");\n}\n\nfunction createPersonalSpace(baseDir?: string, memoryDirOverride?: string): Space {\n const homeDir = baseDir ?? process.env.HOME ?? \"~\";\n // Priority: override > env var > existing standalone dir > existing OpenClaw dir > new standalone dir\n const standalonePath = path.join(homeDir, \".engram\", \"memory\");\n const openclawPath = path.join(homeDir, \".openclaw\", \"workspace\", \"memory\", \"local\");\n const memoryDir = memoryDirOverride\n ?? process.env.ENGRAM_MEMORY_DIR\n ?? (fs.existsSync(standalonePath) ? standalonePath\n : fs.existsSync(openclawPath) ? openclawPath\n : standalonePath);\n const now = new Date().toISOString();\n\n return {\n id: \"personal\",\n name: \"Personal\",\n kind: \"personal\",\n description: \"Default personal memory space\",\n memoryDir,\n createdAt: now,\n updatedAt: now,\n owner: process.env.USER,\n };\n}\n\n// ── Space CRUD ──────────────────────────────────────────────────────────────\n\nexport function listSpaces(baseDir?: string): Space[] {\n const manifest = loadManifest(baseDir);\n return manifest.spaces;\n}\n\nexport function getActiveSpace(baseDir?: string): Space {\n const manifest = loadManifest(baseDir);\n const space = manifest.spaces.find((s) => s.id === manifest.activeSpaceId);\n if (!space) throw new Error(`Active space ${manifest.activeSpaceId} not found`);\n return space;\n}\n\nexport function createSpace(options: {\n name: string;\n kind: SpaceKind;\n description?: string;\n memoryDir?: string;\n parentSpaceId?: string;\n baseDir?: string;\n}): Space {\n const manifest = loadManifest(options.baseDir);\n const id = options.name.toLowerCase().replace(/[^a-z0-9-]/g, \"-\").replace(/-+/g, \"-\");\n\n if (manifest.spaces.some((s) => s.id === id)) {\n throw new Error(`Space \"${id}\" already exists`);\n }\n\n // Validate parent space exists\n if (options.parentSpaceId && !manifest.spaces.some((s) => s.id === options.parentSpaceId)) {\n throw new Error(`Parent space \"${options.parentSpaceId}\" not found`);\n }\n\n const now = new Date().toISOString();\n const memoryDir = options.memoryDir ?? path.join(\n getSpacesDir(options.baseDir),\n id,\n \"memory\",\n );\n\n const space: Space = {\n id,\n name: options.name,\n kind: options.kind,\n description: options.description,\n memoryDir,\n createdAt: now,\n updatedAt: now,\n owner: process.env.USER,\n parentSpaceId: options.parentSpaceId,\n };\n\n // Ensure memory directory exists\n fs.mkdirSync(memoryDir, { recursive: true });\n\n manifest.spaces.push(space);\n manifest.updatedAt = now;\n saveManifest(manifest, options.baseDir);\n\n // Audit\n appendAudit({\n action: \"space.create\",\n sourceSpaceId: id,\n details: `Created ${options.kind} space \"${options.name}\"`,\n }, options.baseDir);\n\n return space;\n}\n\nexport function deleteSpace(spaceId: string, baseDir?: string): void {\n const manifest = loadManifest(baseDir);\n\n if (spaceId === \"personal\") {\n throw new Error(\"Cannot delete the personal space\");\n }\n\n const idx = manifest.spaces.findIndex((s) => s.id === spaceId);\n if (idx === -1) throw new Error(`Space \"${spaceId}\" not found`);\n\n // If deleting active space, switch to personal\n if (manifest.activeSpaceId === spaceId) {\n manifest.activeSpaceId = \"personal\";\n }\n\n // Clear parentSpaceId references from children\n for (const space of manifest.spaces) {\n if (space.parentSpaceId === spaceId) {\n space.parentSpaceId = undefined;\n }\n }\n\n manifest.spaces.splice(idx, 1);\n saveManifest(manifest, baseDir);\n\n appendAudit({\n action: \"space.delete\",\n sourceSpaceId: spaceId,\n details: `Deleted space \"${spaceId}\"`,\n }, baseDir);\n}\n\n// ── Switch ───────────────────────────────────────────────────────────────────\n\nexport function switchSpace(spaceId: string, baseDir?: string): SpaceSwitchResult {\n const manifest = loadManifest(baseDir);\n const space = manifest.spaces.find((s) => s.id === spaceId);\n\n if (!space) throw new Error(`Space \"${spaceId}\" not found`);\n\n const previousId = manifest.activeSpaceId;\n manifest.activeSpaceId = spaceId;\n saveManifest(manifest, baseDir);\n\n appendAudit({\n action: \"space.switch\",\n sourceSpaceId: previousId,\n targetSpaceId: spaceId,\n details: `Switched from \"${previousId}\" to \"${spaceId}\"`,\n }, baseDir);\n\n return {\n previousSpaceId: previousId,\n currentSpaceId: spaceId,\n message: `Switched to \"${space.name}\"`,\n };\n}\n\n// ── Push / Pull ─────────────────────────────────────────────────────────────\n\nexport function pushToSpace(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { memoryIds?: string[]; force?: boolean; baseDir?: string },\n): SpacePushResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n filterIds: options?.memoryIds,\n force: options?.force,\n });\n\n appendAudit({\n action: \"space.push\",\n sourceSpaceId,\n targetSpaceId,\n details: `Pushed ${result.merged} memories, ${result.conflicts.length} conflicts`,\n }, options?.baseDir);\n\n return {\n sourceSpaceId,\n targetSpaceId,\n memoriesPushed: result.merged,\n conflicts: result.conflicts,\n durationMs: Date.now() - startTime,\n };\n}\n\nexport function pullFromSpace(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { memoryIds?: string[]; force?: boolean; baseDir?: string },\n): SpacePullResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n filterIds: options?.memoryIds,\n force: options?.force,\n });\n\n appendAudit({\n action: \"space.pull\",\n sourceSpaceId,\n targetSpaceId,\n details: `Pulled ${result.merged} memories, ${result.conflicts.length} conflicts`,\n }, options?.baseDir);\n\n return {\n sourceSpaceId,\n targetSpaceId,\n memoriesPulled: result.merged,\n conflicts: result.conflicts,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Share ────────────────────────────────────────────────────────────────────\n\nexport function shareSpace(\n spaceId: string,\n members: string[],\n baseDir?: string,\n): SpaceShareResult {\n const manifest = loadManifest(baseDir);\n const space = manifest.spaces.find((s) => s.id === spaceId);\n\n if (!space) throw new Error(`Space \"${spaceId}\" not found`);\n if (space.kind === \"personal\") throw new Error(\"Cannot share personal space\");\n\n space.members = [...new Set([...(space.members ?? []), ...members])];\n space.updatedAt = new Date().toISOString();\n saveManifest(manifest, baseDir);\n\n appendAudit({\n action: \"space.share\",\n sourceSpaceId: spaceId,\n details: `Shared with: ${members.join(\", \")}`,\n }, baseDir);\n\n return {\n spaceId,\n sharedWith: members,\n message: `Shared \"${space.name}\" with ${members.length} member(s)`,\n };\n}\n\n// ── Promote ──────────────────────────────────────────────────────────────────\n\nexport function promoteSpace(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { memoryIds?: string[]; force?: boolean; forceOverwrite?: boolean; baseDir?: string },\n): SpacePromoteResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n // Promotion requires parent-child relationship or explicit force\n if (source.parentSpaceId !== targetSpaceId && target.parentSpaceId !== sourceSpaceId) {\n if (!options?.force) {\n throw new Error(\"Spaces must have a parent-child relationship for promotion. Use --force to override.\");\n }\n }\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n filterIds: options?.memoryIds,\n force: options?.forceOverwrite !== undefined ? options.forceOverwrite : (options?.force ?? false),\n });\n\n appendAudit({\n action: \"space.promote\",\n sourceSpaceId,\n targetSpaceId,\n details: `Promoted ${result.merged} memories from \"${source.name}\" to \"${target.name}\"`,\n }, options?.baseDir);\n\n return {\n sourceSpaceId,\n targetSpaceId,\n memoriesPromoted: result.merged,\n conflicts: result.conflicts,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Merge ────────────────────────────────────────────────────────────────────\n\nexport function mergeSpaces(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { force?: boolean; baseDir?: string },\n): MergeResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n force: options?.force,\n });\n\n appendAudit({\n action: \"space.merge\",\n sourceSpaceId,\n targetSpaceId,\n details: `Merged: ${result.merged} merged, ${result.conflicts.length} conflicts, ${result.skipped} skipped`,\n }, options?.baseDir);\n\n return {\n ...result,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Audit trail ─────────────────────────────────────────────────────────────\n\nexport function getAuditLog(baseDir?: string): AuditEntry[] {\n const auditPath = path.join(getSpacesDir(baseDir), \"audit.jsonl\");\n if (!fs.existsSync(auditPath)) return [];\n\n const lines = fs.readFileSync(auditPath, \"utf8\").trim().split(\"\\n\");\n return lines\n .filter((l) => l.trim())\n .map((l) => JSON.parse(l) as AuditEntry);\n}\n\nfunction appendAudit(entry: Omit<AuditEntry, \"id\" | \"timestamp\">, baseDir?: string): void {\n const auditPath = path.join(getSpacesDir(baseDir), \"audit.jsonl\");\n fs.mkdirSync(path.dirname(auditPath), { recursive: true });\n\n const full: AuditEntry = {\n id: crypto.randomUUID(),\n timestamp: new Date().toISOString(),\n ...entry,\n };\n\n fs.appendFileSync(auditPath, JSON.stringify(full) + \"\\n\");\n}\n\n// ── Internal helpers ─────────────────────────────────────────────────────────\n\ninterface CopyOptions {\n filterIds?: string[];\n force?: boolean;\n}\n\nfunction copyMemories(\n sourceDir: string,\n targetDir: string,\n options?: CopyOptions,\n): { merged: number; conflicts: ConflictEntry[]; skipped: number } {\n let merged = 0;\n const conflicts: ConflictEntry[] = [];\n let skipped = 0;\n\n if (!fs.existsSync(sourceDir)) {\n return { merged: 0, conflicts: [], skipped: 0 };\n }\n\n fs.mkdirSync(targetDir, { recursive: true });\n\n const sourceFiles = walkMd(sourceDir);\n for (const sourcePath of sourceFiles) {\n const content = fs.readFileSync(sourcePath, \"utf8\");\n const relativePath = path.relative(sourceDir, sourcePath);\n const targetPath = path.join(targetDir, relativePath);\n\n const sourceHash = hashContent(content);\n\n // Filter by IDs if specified\n if (options?.filterIds?.length) {\n const fm = parseSimpleFrontmatter(content);\n if (!fm?.id || !options.filterIds.includes(fm.id)) {\n skipped++;\n continue;\n }\n }\n\n // Check for conflict\n if (fs.existsSync(targetPath) && !options?.force) {\n const targetContent = fs.readFileSync(targetPath, \"utf8\");\n const targetHash = hashContent(targetContent);\n\n if (sourceHash !== targetHash) {\n conflicts.push({\n memoryId: parseSimpleFrontmatter(content)?.id ?? relativePath,\n sourcePath,\n targetPath,\n conflictType: \"content_mismatch\",\n sourceHash,\n targetHash,\n });\n continue;\n }\n\n // Same content — skip\n skipped++;\n continue;\n }\n\n // Copy file\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n fs.writeFileSync(targetPath, content);\n merged++;\n }\n\n return { merged, conflicts, skipped };\n}\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nfunction walkMd(dir: string): string[] {\n const results: string[] = [];\n\n function walk(d: string): void {\n for (const entry of fs.readdirSync(d, { withFileTypes: true })) {\n const fullPath = path.join(d, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath);\n } else if (entry.name.endsWith(\".md\")) {\n results.push(fullPath);\n }\n }\n }\n\n walk(dir);\n return results;\n}\n\ninterface SimpleFrontmatter {\n id?: string;\n [key: string]: string | undefined;\n}\n\nfunction parseSimpleFrontmatter(content: string): SimpleFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: SimpleFrontmatter = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n fm[key] = value;\n }\n return fm;\n}\n"],"mappings":"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","names":["path","path","fs","path","fs","path","fs","path","parseFrontmatter","extractBody","fs","path","crypto","hashContent","path","fs","readFileSafe","parseFrontmatter","extractBody","crypto","fs","path","path","fs","parseFrontmatter","extractBody","readFileSafe","fs","path","crypto","DEFAULT_EXCLUDE","hashContent","fs","path","fs","path","crypto","walkMd","hashContent"]}