cognitive-core 0.2.1 → 0.2.2

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 (331) hide show
  1. package/dist/atlas.d.ts +10 -0
  2. package/dist/atlas.d.ts.map +1 -1
  3. package/dist/atlas.js +65 -0
  4. package/dist/atlas.js.map +1 -1
  5. package/dist/learning/pipeline.d.ts +4 -31
  6. package/dist/learning/pipeline.d.ts.map +1 -1
  7. package/dist/learning/pipeline.js +12 -64
  8. package/dist/learning/pipeline.js.map +1 -1
  9. package/dist/memory/curated-loader.d.ts +21 -4
  10. package/dist/memory/curated-loader.d.ts.map +1 -1
  11. package/dist/memory/curated-loader.js +53 -16
  12. package/dist/memory/curated-loader.js.map +1 -1
  13. package/dist/memory/index.d.ts +2 -1
  14. package/dist/memory/index.d.ts.map +1 -1
  15. package/dist/memory/index.js +3 -1
  16. package/dist/memory/index.js.map +1 -1
  17. package/dist/memory/playbook.d.ts +6 -0
  18. package/dist/memory/playbook.d.ts.map +1 -1
  19. package/dist/memory/playbook.js +15 -0
  20. package/dist/memory/playbook.js.map +1 -1
  21. package/dist/memory/source-resolver.d.ts +120 -0
  22. package/dist/memory/source-resolver.d.ts.map +1 -0
  23. package/dist/memory/source-resolver.js +300 -0
  24. package/dist/memory/source-resolver.js.map +1 -0
  25. package/dist/types/config.d.ts +141 -0
  26. package/dist/types/config.d.ts.map +1 -1
  27. package/dist/types/config.js +40 -0
  28. package/dist/types/config.js.map +1 -1
  29. package/dist/types/index.d.ts +1 -1
  30. package/dist/types/index.d.ts.map +1 -1
  31. package/dist/types/index.js +1 -1
  32. package/dist/types/index.js.map +1 -1
  33. package/dist/workspace/types.d.ts +12 -54
  34. package/dist/workspace/types.d.ts.map +1 -1
  35. package/dist/workspace/types.js.map +1 -1
  36. package/package.json +2 -2
  37. package/playbooks/compound-engineering/adversarial-review.json +51 -0
  38. package/playbooks/compound-engineering/agent-native-architecture.json +59 -0
  39. package/playbooks/compound-engineering/agent-native-review.json +54 -0
  40. package/playbooks/compound-engineering/api-contract-review.json +52 -0
  41. package/playbooks/compound-engineering/brainstorm-requirements.json +55 -0
  42. package/playbooks/compound-engineering/bug-reproduction.json +62 -0
  43. package/playbooks/compound-engineering/confidence-calibration.json +49 -0
  44. package/playbooks/compound-engineering/correctness-review.json +49 -0
  45. package/playbooks/compound-engineering/data-migration-safety.json +59 -0
  46. package/playbooks/compound-engineering/deployment-verification.json +63 -0
  47. package/playbooks/compound-engineering/error-recovery-patterns.json +53 -0
  48. package/playbooks/compound-engineering/implementation-planning.json +64 -0
  49. package/playbooks/compound-engineering/issue-pattern-analysis.json +53 -0
  50. package/playbooks/compound-engineering/knowledge-compounding.json +63 -0
  51. package/playbooks/compound-engineering/learnings-research.json +54 -0
  52. package/playbooks/compound-engineering/maintainability-review.json +49 -0
  53. package/playbooks/compound-engineering/performance-review.json +54 -0
  54. package/playbooks/compound-engineering/plan-adversarial-review.json +56 -0
  55. package/playbooks/compound-engineering/plan-feasibility-review.json +56 -0
  56. package/playbooks/compound-engineering/project-standards-review.json +52 -0
  57. package/playbooks/compound-engineering/reliability-review.json +53 -0
  58. package/playbooks/compound-engineering/review-orchestration.json +64 -0
  59. package/playbooks/compound-engineering/security-review.json +54 -0
  60. package/playbooks/compound-engineering/systematic-execution.json +64 -0
  61. package/playbooks/compound-engineering/testing-review.json +50 -0
  62. package/src/atlas.ts +96 -0
  63. package/src/memory/curated-loader.ts +69 -16
  64. package/src/memory/index.ts +16 -0
  65. package/src/memory/playbook.ts +19 -0
  66. package/src/memory/source-resolver.ts +422 -0
  67. package/src/types/config.ts +46 -0
  68. package/src/types/index.ts +4 -0
  69. package/src/workspace/types.ts +22 -78
  70. package/tests/integration/curated-sources-e2e.test.ts +502 -0
  71. package/tests/memory/compound-engineering-seed.test.ts +338 -0
  72. package/tests/memory/curated-loader-extended.test.ts +225 -0
  73. package/tests/memory/playbook-quality-validation.test.ts +430 -0
  74. package/tests/memory/source-resolver.test.ts +700 -0
  75. package/.claude/settings.local.json +0 -11
  76. package/dist/learning/llm-extractor.d.ts +0 -88
  77. package/dist/learning/llm-extractor.d.ts.map +0 -1
  78. package/dist/learning/llm-extractor.js +0 -372
  79. package/dist/learning/llm-extractor.js.map +0 -1
  80. package/dist/learning/loop-coordinator.d.ts +0 -61
  81. package/dist/learning/loop-coordinator.d.ts.map +0 -1
  82. package/dist/learning/loop-coordinator.js +0 -96
  83. package/dist/learning/loop-coordinator.js.map +0 -1
  84. package/references/agent-workspace/CLAUDE.md +0 -74
  85. package/references/agent-workspace/README.md +0 -587
  86. package/references/agent-workspace/media/banner.png +0 -0
  87. package/references/agent-workspace/package-lock.json +0 -2061
  88. package/references/agent-workspace/package.json +0 -54
  89. package/references/agent-workspace/src/handle.ts +0 -122
  90. package/references/agent-workspace/src/index.ts +0 -32
  91. package/references/agent-workspace/src/manager.ts +0 -102
  92. package/references/agent-workspace/src/readers/json.ts +0 -71
  93. package/references/agent-workspace/src/readers/markdown.ts +0 -37
  94. package/references/agent-workspace/src/readers/raw.ts +0 -27
  95. package/references/agent-workspace/src/types.ts +0 -68
  96. package/references/agent-workspace/src/validation.ts +0 -93
  97. package/references/agent-workspace/src/writers/json.ts +0 -17
  98. package/references/agent-workspace/src/writers/markdown.ts +0 -27
  99. package/references/agent-workspace/src/writers/raw.ts +0 -22
  100. package/references/agent-workspace/tests/errors.test.ts +0 -652
  101. package/references/agent-workspace/tests/handle.test.ts +0 -144
  102. package/references/agent-workspace/tests/manager.test.ts +0 -124
  103. package/references/agent-workspace/tests/readers.test.ts +0 -205
  104. package/references/agent-workspace/tests/validation.test.ts +0 -196
  105. package/references/agent-workspace/tests/writers.test.ts +0 -108
  106. package/references/agent-workspace/tsconfig.json +0 -20
  107. package/references/agent-workspace/tsup.config.ts +0 -9
  108. package/references/minimem/.claude/settings.json +0 -7
  109. package/references/minimem/.sudocode/issues.jsonl +0 -18
  110. package/references/minimem/.sudocode/specs.jsonl +0 -1
  111. package/references/minimem/CLAUDE.md +0 -310
  112. package/references/minimem/README.md +0 -556
  113. package/references/minimem/claude-plugin/.claude-plugin/plugin.json +0 -10
  114. package/references/minimem/claude-plugin/.mcp.json +0 -7
  115. package/references/minimem/claude-plugin/README.md +0 -158
  116. package/references/minimem/claude-plugin/commands/recall.md +0 -47
  117. package/references/minimem/claude-plugin/commands/remember.md +0 -41
  118. package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +0 -272
  119. package/references/minimem/claude-plugin/hooks/hooks.json +0 -27
  120. package/references/minimem/claude-plugin/hooks/session-end.sh +0 -86
  121. package/references/minimem/claude-plugin/hooks/session-start.sh +0 -85
  122. package/references/minimem/claude-plugin/skills/memory/SKILL.md +0 -108
  123. package/references/minimem/package-lock.json +0 -5373
  124. package/references/minimem/package.json +0 -60
  125. package/references/minimem/scripts/postbuild.js +0 -35
  126. package/references/minimem/src/__tests__/edge-cases.test.ts +0 -371
  127. package/references/minimem/src/__tests__/errors.test.ts +0 -265
  128. package/references/minimem/src/__tests__/helpers.ts +0 -199
  129. package/references/minimem/src/__tests__/internal.test.ts +0 -407
  130. package/references/minimem/src/__tests__/knowledge.test.ts +0 -287
  131. package/references/minimem/src/__tests__/minimem.integration.test.ts +0 -1127
  132. package/references/minimem/src/__tests__/session.test.ts +0 -190
  133. package/references/minimem/src/cli/__tests__/commands.test.ts +0 -759
  134. package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +0 -141
  135. package/references/minimem/src/cli/commands/append.ts +0 -76
  136. package/references/minimem/src/cli/commands/config.ts +0 -262
  137. package/references/minimem/src/cli/commands/conflicts.ts +0 -413
  138. package/references/minimem/src/cli/commands/daemon.ts +0 -169
  139. package/references/minimem/src/cli/commands/index.ts +0 -12
  140. package/references/minimem/src/cli/commands/init.ts +0 -88
  141. package/references/minimem/src/cli/commands/mcp.ts +0 -177
  142. package/references/minimem/src/cli/commands/push-pull.ts +0 -213
  143. package/references/minimem/src/cli/commands/search.ts +0 -158
  144. package/references/minimem/src/cli/commands/status.ts +0 -84
  145. package/references/minimem/src/cli/commands/sync-init.ts +0 -290
  146. package/references/minimem/src/cli/commands/sync.ts +0 -70
  147. package/references/minimem/src/cli/commands/upsert.ts +0 -197
  148. package/references/minimem/src/cli/config.ts +0 -584
  149. package/references/minimem/src/cli/index.ts +0 -264
  150. package/references/minimem/src/cli/shared.ts +0 -161
  151. package/references/minimem/src/cli/sync/__tests__/central.test.ts +0 -152
  152. package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +0 -209
  153. package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +0 -118
  154. package/references/minimem/src/cli/sync/__tests__/detection.test.ts +0 -207
  155. package/references/minimem/src/cli/sync/__tests__/integration.test.ts +0 -476
  156. package/references/minimem/src/cli/sync/__tests__/registry.test.ts +0 -363
  157. package/references/minimem/src/cli/sync/__tests__/state.test.ts +0 -255
  158. package/references/minimem/src/cli/sync/__tests__/validation.test.ts +0 -193
  159. package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +0 -178
  160. package/references/minimem/src/cli/sync/central.ts +0 -292
  161. package/references/minimem/src/cli/sync/conflicts.ts +0 -204
  162. package/references/minimem/src/cli/sync/daemon.ts +0 -407
  163. package/references/minimem/src/cli/sync/detection.ts +0 -138
  164. package/references/minimem/src/cli/sync/index.ts +0 -107
  165. package/references/minimem/src/cli/sync/operations.ts +0 -373
  166. package/references/minimem/src/cli/sync/registry.ts +0 -279
  167. package/references/minimem/src/cli/sync/state.ts +0 -355
  168. package/references/minimem/src/cli/sync/validation.ts +0 -206
  169. package/references/minimem/src/cli/sync/watcher.ts +0 -234
  170. package/references/minimem/src/cli/version.ts +0 -34
  171. package/references/minimem/src/core/index.ts +0 -9
  172. package/references/minimem/src/core/indexer.ts +0 -628
  173. package/references/minimem/src/core/searcher.ts +0 -221
  174. package/references/minimem/src/db/schema.ts +0 -183
  175. package/references/minimem/src/db/sqlite-vec.ts +0 -24
  176. package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +0 -431
  177. package/references/minimem/src/embeddings/batch-gemini.ts +0 -392
  178. package/references/minimem/src/embeddings/batch-openai.ts +0 -409
  179. package/references/minimem/src/embeddings/embeddings.ts +0 -434
  180. package/references/minimem/src/index.ts +0 -109
  181. package/references/minimem/src/internal.ts +0 -299
  182. package/references/minimem/src/minimem.ts +0 -1276
  183. package/references/minimem/src/search/__tests__/hybrid.test.ts +0 -247
  184. package/references/minimem/src/search/graph.ts +0 -234
  185. package/references/minimem/src/search/hybrid.ts +0 -151
  186. package/references/minimem/src/search/search.ts +0 -256
  187. package/references/minimem/src/server/__tests__/mcp.test.ts +0 -341
  188. package/references/minimem/src/server/__tests__/tools.test.ts +0 -364
  189. package/references/minimem/src/server/mcp.ts +0 -326
  190. package/references/minimem/src/server/tools.ts +0 -720
  191. package/references/minimem/src/session.ts +0 -460
  192. package/references/minimem/tsconfig.json +0 -19
  193. package/references/minimem/tsup.config.ts +0 -26
  194. package/references/minimem/vitest.config.ts +0 -24
  195. package/references/sessionlog/.husky/pre-commit +0 -1
  196. package/references/sessionlog/.lintstagedrc.json +0 -4
  197. package/references/sessionlog/.prettierignore +0 -4
  198. package/references/sessionlog/.prettierrc.json +0 -11
  199. package/references/sessionlog/LICENSE +0 -21
  200. package/references/sessionlog/README.md +0 -453
  201. package/references/sessionlog/eslint.config.js +0 -58
  202. package/references/sessionlog/package-lock.json +0 -3672
  203. package/references/sessionlog/package.json +0 -65
  204. package/references/sessionlog/src/__tests__/agent-hooks.test.ts +0 -570
  205. package/references/sessionlog/src/__tests__/agent-registry.test.ts +0 -127
  206. package/references/sessionlog/src/__tests__/claude-code-hooks.test.ts +0 -225
  207. package/references/sessionlog/src/__tests__/claude-generator.test.ts +0 -46
  208. package/references/sessionlog/src/__tests__/commit-msg.test.ts +0 -86
  209. package/references/sessionlog/src/__tests__/cursor-agent.test.ts +0 -224
  210. package/references/sessionlog/src/__tests__/e2e-live.test.ts +0 -890
  211. package/references/sessionlog/src/__tests__/event-log.test.ts +0 -183
  212. package/references/sessionlog/src/__tests__/flush-sentinel.test.ts +0 -105
  213. package/references/sessionlog/src/__tests__/gemini-agent.test.ts +0 -375
  214. package/references/sessionlog/src/__tests__/git-hooks.test.ts +0 -78
  215. package/references/sessionlog/src/__tests__/hook-managers.test.ts +0 -121
  216. package/references/sessionlog/src/__tests__/lifecycle-tasks.test.ts +0 -759
  217. package/references/sessionlog/src/__tests__/opencode-agent.test.ts +0 -338
  218. package/references/sessionlog/src/__tests__/redaction.test.ts +0 -136
  219. package/references/sessionlog/src/__tests__/session-repo.test.ts +0 -353
  220. package/references/sessionlog/src/__tests__/session-store.test.ts +0 -166
  221. package/references/sessionlog/src/__tests__/setup-ccweb.test.ts +0 -466
  222. package/references/sessionlog/src/__tests__/skill-live.test.ts +0 -461
  223. package/references/sessionlog/src/__tests__/summarize.test.ts +0 -348
  224. package/references/sessionlog/src/__tests__/task-plan-e2e.test.ts +0 -610
  225. package/references/sessionlog/src/__tests__/task-plan-live.test.ts +0 -632
  226. package/references/sessionlog/src/__tests__/transcript-timestamp.test.ts +0 -121
  227. package/references/sessionlog/src/__tests__/types.test.ts +0 -166
  228. package/references/sessionlog/src/__tests__/utils.test.ts +0 -333
  229. package/references/sessionlog/src/__tests__/validation.test.ts +0 -103
  230. package/references/sessionlog/src/__tests__/worktree.test.ts +0 -57
  231. package/references/sessionlog/src/agent/agents/claude-code.ts +0 -1089
  232. package/references/sessionlog/src/agent/agents/cursor.ts +0 -361
  233. package/references/sessionlog/src/agent/agents/gemini-cli.ts +0 -632
  234. package/references/sessionlog/src/agent/agents/opencode.ts +0 -540
  235. package/references/sessionlog/src/agent/registry.ts +0 -143
  236. package/references/sessionlog/src/agent/session-types.ts +0 -113
  237. package/references/sessionlog/src/agent/types.ts +0 -220
  238. package/references/sessionlog/src/cli.ts +0 -597
  239. package/references/sessionlog/src/commands/clean.ts +0 -133
  240. package/references/sessionlog/src/commands/disable.ts +0 -84
  241. package/references/sessionlog/src/commands/doctor.ts +0 -145
  242. package/references/sessionlog/src/commands/enable.ts +0 -202
  243. package/references/sessionlog/src/commands/explain.ts +0 -261
  244. package/references/sessionlog/src/commands/reset.ts +0 -105
  245. package/references/sessionlog/src/commands/resume.ts +0 -180
  246. package/references/sessionlog/src/commands/rewind.ts +0 -195
  247. package/references/sessionlog/src/commands/setup-ccweb.ts +0 -275
  248. package/references/sessionlog/src/commands/status.ts +0 -172
  249. package/references/sessionlog/src/config.ts +0 -165
  250. package/references/sessionlog/src/events/event-log.ts +0 -126
  251. package/references/sessionlog/src/git-operations.ts +0 -558
  252. package/references/sessionlog/src/hooks/git-hooks.ts +0 -165
  253. package/references/sessionlog/src/hooks/lifecycle.ts +0 -391
  254. package/references/sessionlog/src/index.ts +0 -650
  255. package/references/sessionlog/src/security/redaction.ts +0 -283
  256. package/references/sessionlog/src/session/state-machine.ts +0 -452
  257. package/references/sessionlog/src/store/checkpoint-store.ts +0 -509
  258. package/references/sessionlog/src/store/native-store.ts +0 -173
  259. package/references/sessionlog/src/store/provider-types.ts +0 -99
  260. package/references/sessionlog/src/store/session-store.ts +0 -266
  261. package/references/sessionlog/src/strategy/attribution.ts +0 -296
  262. package/references/sessionlog/src/strategy/common.ts +0 -207
  263. package/references/sessionlog/src/strategy/content-overlap.ts +0 -228
  264. package/references/sessionlog/src/strategy/manual-commit.ts +0 -988
  265. package/references/sessionlog/src/strategy/types.ts +0 -279
  266. package/references/sessionlog/src/summarize/claude-generator.ts +0 -115
  267. package/references/sessionlog/src/summarize/summarize.ts +0 -432
  268. package/references/sessionlog/src/types.ts +0 -508
  269. package/references/sessionlog/src/utils/chunk-files.ts +0 -49
  270. package/references/sessionlog/src/utils/commit-message.ts +0 -65
  271. package/references/sessionlog/src/utils/detect-agent.ts +0 -36
  272. package/references/sessionlog/src/utils/hook-managers.ts +0 -125
  273. package/references/sessionlog/src/utils/ide-tags.ts +0 -32
  274. package/references/sessionlog/src/utils/paths.ts +0 -79
  275. package/references/sessionlog/src/utils/preview-rewind.ts +0 -80
  276. package/references/sessionlog/src/utils/rewind-conflict.ts +0 -121
  277. package/references/sessionlog/src/utils/shadow-branch.ts +0 -109
  278. package/references/sessionlog/src/utils/string-utils.ts +0 -46
  279. package/references/sessionlog/src/utils/todo-extract.ts +0 -188
  280. package/references/sessionlog/src/utils/trailers.ts +0 -187
  281. package/references/sessionlog/src/utils/transcript-parse.ts +0 -177
  282. package/references/sessionlog/src/utils/transcript-timestamp.ts +0 -59
  283. package/references/sessionlog/src/utils/tree-ops.ts +0 -219
  284. package/references/sessionlog/src/utils/tty.ts +0 -72
  285. package/references/sessionlog/src/utils/validation.ts +0 -65
  286. package/references/sessionlog/src/utils/worktree.ts +0 -58
  287. package/references/sessionlog/src/wire-types.ts +0 -59
  288. package/references/sessionlog/templates/setup-env.sh +0 -153
  289. package/references/sessionlog/tsconfig.json +0 -18
  290. package/references/sessionlog/vitest.config.ts +0 -12
  291. package/references/skill-tree/.claude/settings.json +0 -6
  292. package/references/skill-tree/.sudocode/issues.jsonl +0 -19
  293. package/references/skill-tree/.sudocode/specs.jsonl +0 -3
  294. package/references/skill-tree/CLAUDE.md +0 -126
  295. package/references/skill-tree/README.md +0 -372
  296. package/references/skill-tree/docs/GAPS_v1.md +0 -221
  297. package/references/skill-tree/docs/INTEGRATION_PLAN.md +0 -467
  298. package/references/skill-tree/docs/TODOS.md +0 -91
  299. package/references/skill-tree/docs/anthropic_skill_guide.md +0 -1364
  300. package/references/skill-tree/docs/design/federated-skill-trees.md +0 -524
  301. package/references/skill-tree/docs/design/multi-agent-sync.md +0 -759
  302. package/references/skill-tree/docs/scraper/BRAINSTORM.md +0 -583
  303. package/references/skill-tree/docs/scraper/POC_PLAN.md +0 -420
  304. package/references/skill-tree/docs/scraper/README.md +0 -170
  305. package/references/skill-tree/examples/basic-usage.ts +0 -164
  306. package/references/skill-tree/package-lock.json +0 -1852
  307. package/references/skill-tree/package.json +0 -66
  308. package/references/skill-tree/scraper/README.md +0 -123
  309. package/references/skill-tree/scraper/docs/DESIGN.md +0 -683
  310. package/references/skill-tree/scraper/docs/PLAN.md +0 -336
  311. package/references/skill-tree/scraper/drizzle.config.ts +0 -10
  312. package/references/skill-tree/scraper/package-lock.json +0 -6329
  313. package/references/skill-tree/scraper/package.json +0 -68
  314. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +0 -7
  315. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +0 -7
  316. package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +0 -27
  317. package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +0 -21
  318. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +0 -54
  319. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +0 -24
  320. package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +0 -93
  321. package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +0 -22
  322. package/references/skill-tree/scraper/tsup.config.ts +0 -14
  323. package/references/skill-tree/scraper/vitest.config.ts +0 -17
  324. package/references/skill-tree/scripts/convert-to-vitest.ts +0 -166
  325. package/references/skill-tree/skills/skill-writer/SKILL.md +0 -339
  326. package/references/skill-tree/skills/skill-writer/references/examples.md +0 -326
  327. package/references/skill-tree/skills/skill-writer/references/patterns.md +0 -210
  328. package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +0 -123
  329. package/references/skill-tree/test/run-all.ts +0 -106
  330. package/references/skill-tree/test/utils.ts +0 -128
  331. package/references/skill-tree/vitest.config.ts +0 -16
@@ -1,108 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import * as fs from 'fs/promises';
3
- import * as path from 'path';
4
- import * as os from 'os';
5
- import { writeJson, writeJsonl, writeMarkdown, writeRaw, copyDir, symlink } from '../src/index.js';
6
-
7
- describe('Writers', () => {
8
- let dir: string;
9
-
10
- beforeEach(async () => {
11
- dir = await fs.mkdtemp(path.join(os.tmpdir(), 'ws-writers-'));
12
- });
13
-
14
- afterEach(async () => {
15
- await fs.rm(dir, { recursive: true, force: true });
16
- });
17
-
18
- describe('writeJson', () => {
19
- it('writes pretty-printed JSON with trailing newline', async () => {
20
- await writeJson(dir, 'data.json', { foo: 'bar', num: 42 });
21
- const content = await fs.readFile(path.join(dir, 'data.json'), 'utf-8');
22
- expect(content).toBe('{\n "foo": "bar",\n "num": 42\n}\n');
23
- });
24
-
25
- it('creates subdirectories as needed', async () => {
26
- await writeJson(dir, 'nested/deep/data.json', { ok: true });
27
- const content = await fs.readFile(path.join(dir, 'nested/deep/data.json'), 'utf-8');
28
- expect(JSON.parse(content)).toEqual({ ok: true });
29
- });
30
- });
31
-
32
- describe('writeJsonl', () => {
33
- it('writes one JSON object per line', async () => {
34
- const items = [{ a: 1 }, { b: 2 }, { c: 3 }];
35
- await writeJsonl(dir, 'data.jsonl', items);
36
- const content = await fs.readFile(path.join(dir, 'data.jsonl'), 'utf-8');
37
- const lines = content.trimEnd().split('\n');
38
- expect(lines).toHaveLength(3);
39
- expect(JSON.parse(lines[0])).toEqual({ a: 1 });
40
- expect(JSON.parse(lines[2])).toEqual({ c: 3 });
41
- });
42
- });
43
-
44
- describe('writeMarkdown', () => {
45
- it('writes markdown with YAML frontmatter', async () => {
46
- await writeMarkdown(dir, 'doc.md', {
47
- frontmatter: { title: 'Hello', tags: ['a', 'b'] },
48
- body: '# Content\n\nSome text.',
49
- });
50
- const content = await fs.readFile(path.join(dir, 'doc.md'), 'utf-8');
51
- expect(content).toContain('---\n');
52
- expect(content).toContain('title: Hello');
53
- expect(content).toContain('# Content');
54
- });
55
-
56
- it('writes markdown without frontmatter when empty', async () => {
57
- await writeMarkdown(dir, 'plain.md', {
58
- frontmatter: {},
59
- body: '# Just body',
60
- });
61
- const content = await fs.readFile(path.join(dir, 'plain.md'), 'utf-8');
62
- expect(content).not.toContain('---');
63
- expect(content).toBe('# Just body\n');
64
- });
65
- });
66
-
67
- describe('writeRaw', () => {
68
- it('writes raw string content', async () => {
69
- await writeRaw(dir, 'data.csv', 'a,b,c\n1,2,3\n');
70
- const content = await fs.readFile(path.join(dir, 'data.csv'), 'utf-8');
71
- expect(content).toBe('a,b,c\n1,2,3\n');
72
- });
73
- });
74
-
75
- describe('copyDir', () => {
76
- it('copies a directory tree', async () => {
77
- // Create a source directory
78
- const src = path.join(dir, '_src');
79
- await fs.mkdir(path.join(src, 'sub'), { recursive: true });
80
- await fs.writeFile(path.join(src, 'a.txt'), 'hello');
81
- await fs.writeFile(path.join(src, 'sub', 'b.txt'), 'world');
82
-
83
- const dest = path.join(dir, 'dest');
84
- await fs.mkdir(dest, { recursive: true });
85
- await copyDir(dest, 'copied', src);
86
-
87
- const a = await fs.readFile(path.join(dest, 'copied', 'a.txt'), 'utf-8');
88
- const b = await fs.readFile(path.join(dest, 'copied', 'sub', 'b.txt'), 'utf-8');
89
- expect(a).toBe('hello');
90
- expect(b).toBe('world');
91
- });
92
- });
93
-
94
- describe('symlink', () => {
95
- it('creates a symlink to a target', async () => {
96
- const target = path.join(dir, 'target.txt');
97
- await fs.writeFile(target, 'symlinked');
98
-
99
- await symlink(dir, 'link.txt', target);
100
-
101
- const content = await fs.readFile(path.join(dir, 'link.txt'), 'utf-8');
102
- expect(content).toBe('symlinked');
103
-
104
- const stat = await fs.lstat(path.join(dir, 'link.txt'));
105
- expect(stat.isSymbolicLink()).toBe(true);
106
- });
107
- });
108
- });
@@ -1,20 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "declaration": true,
7
- "declarationMap": true,
8
- "sourceMap": true,
9
- "outDir": "dist",
10
- "rootDir": "src",
11
- "strict": true,
12
- "esModuleInterop": true,
13
- "skipLibCheck": true,
14
- "forceConsistentCasingInFileNames": true,
15
- "resolveJsonModule": true,
16
- "isolatedModules": true
17
- },
18
- "include": ["src"],
19
- "exclude": ["node_modules", "dist", "tests"]
20
- }
@@ -1,9 +0,0 @@
1
- import { defineConfig } from 'tsup';
2
-
3
- export default defineConfig({
4
- entry: ['src/index.ts'],
5
- format: ['esm', 'cjs'],
6
- dts: true,
7
- clean: true,
8
- sourcemap: true,
9
- });
@@ -1,7 +0,0 @@
1
- {
2
- "attribution":
3
- {
4
- "commit": "",
5
- "pr": ""
6
- }
7
- }
@@ -1,18 +0,0 @@
1
- {"id":"i-7edu","uuid":"d7e8cb3b-73c5-4ac8-b0c3-75d30b3af857","title":"Implement global and per-directory config system for sync","content":"## Overview\nExtend the existing config system to support sync-related configuration at both global and per-directory levels.\n\n## Acceptance Criteria\n- [ ] Global config at `~/.config/minimem/config.json` supports:\n - `centralRepo`: path to central repository\n - `sync.conflictStrategy`: default merge strategy\n - `sync.autoSync`: boolean for daemon auto-sync\n - `sync.autoCommit`: boolean for auto-committing\n- [ ] Per-directory config at `.minimem/config.json` supports:\n - `sync.enabled`: boolean\n - `sync.path`: path in central repo\n - `sync.include`: glob patterns for files to sync\n - `sync.exclude`: glob patterns to exclude\n- [ ] Default include pattern: `[\"MEMORY.md\", \"memory/**/*.md\"]`\n- [ ] Config loading merges global defaults with per-directory overrides\n- [ ] `minimem config set` and `minimem config get` work for sync settings\n\n## Technical Notes\n- Extend existing `src/cli/config.ts`\n- Use JSON schema validation for config\n- Handle `~` expansion in paths\n\n## Implements\n[[s-2wx5]] - Config system requirement","status":"closed","priority":0,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:55:58","updated_at":"2026-02-03 05:36:54","closed_at":"2026-02-03 05:36:54","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-7edu","from_type":"issue","to":"i-1ce6","to_type":"issue","type":"blocks"},{"from":"i-7edu","from_type":"issue","to":"i-1tlk","to_type":"issue","type":"blocks"},{"from":"i-7edu","from_type":"issue","to":"i-8gam","to_type":"issue","type":"blocks"},{"from":"i-7edu","from_type":"issue","to":"i-dvoe","to_type":"issue","type":"blocks"},{"from":"i-7edu","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["cli","config","foundation"],"feedback":[{"id":"a8f202b4-f0a8-4455-816d-78bbb53e06f5","from_id":"i-7edu","to_id":"s-2wx5","feedback_type":"comment","content":"Implemented config system for sync with:\n- Extended CliConfig with sync section (enabled, path, include, exclude)\n- Added GlobalConfig type for XDG config (~/.config/minimem/config.json)\n- Added centralRepo, machineId, and sync settings to global config\n- Added expandPath utility for ~ expansion\n- Added loadXdgConfig, saveXdgConfig functions\n- Added getMachineId function (generates hostname-{random4hex})\n- Added getSyncConfig to merge local + global with defaults\n- Updated config command to display sync settings\n- Added --xdg-global flag to config command\n- All 39 tests pass","agent":"alexngai","anchor":null,"dismissed":false,"created_at":"2026-02-03T05:36:54.045Z","updated_at":"2026-02-03T05:36:54.045Z"}]}
2
- {"id":"i-1tlk","uuid":"855b8770-3183-4956-8b80-d9b7b26b173f","title":"Implement directory type auto-detection","content":"## Overview\nDetect which of the four directory types a memory directory is: project-bound, standalone, hybrid, or unmanaged.\n\n## Acceptance Criteria\n- [ ] `detectDirectoryType(dir: string)` function returns one of:\n - `project-bound`: inside git repo, no sync config\n - `standalone`: has sync config, not inside git repo\n - `hybrid`: inside git repo AND has sync config\n - `unmanaged`: no git repo, no sync config\n- [ ] Detection checks for `.git` in parent directories\n- [ ] Detection reads `.minimem/config.json` for sync config\n- [ ] Exported for use by other commands (sync, push, pull, daemon)\n- [ ] Unit tests for all four detection cases\n\n## Technical Notes\n- Walk up directory tree looking for `.git`\n- Check for `sync.enabled` in local config\n- Consider caching result per session\n\n## Implements\n[[s-2wx5]] - Auto-detection requirement","status":"closed","priority":0,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:06","updated_at":"2026-02-03 05:37:57","closed_at":"2026-02-03 05:37:57","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-1tlk","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["detection","foundation"]}
3
- {"id":"i-31u0","uuid":"900cf512-3ed8-47d7-a6bb-3ea7e8668e43","title":"Implement machine ID generation and storage","content":"## Overview\nGenerate a unique machine identifier for registry tracking, stored in global config.\n\n## Acceptance Criteria\n- [ ] `getMachineId()` returns consistent ID for this machine\n- [ ] ID format: `{hostname}-{random-suffix}` (e.g., `macbook-pro-a1b2`)\n- [ ] Generated once on first use, stored in global config\n- [ ] Random suffix is 4 hex characters\n- [ ] Function is idempotent (same ID on repeated calls)\n\n## Technical Notes\n- Use `os.hostname()` for hostname\n- Use `crypto.randomBytes(2).toString('hex')` for suffix\n- Store in `~/.config/minimem/config.json` as `machineId`\n\n## Implements\n[[s-2wx5]] - Machine ID for registry","status":"closed","priority":0,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:10","updated_at":"2026-02-03 05:36:54","closed_at":"2026-02-03 05:36:54","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-31u0","from_type":"issue","to":"i-dvoe","to_type":"issue","type":"blocks"},{"from":"i-31u0","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["config","foundation"]}
4
- {"id":"i-1ce6","uuid":"ec0bde24-9cb6-4545-88bb-87f7c552d028","title":"Implement central repo initialization (sync init-central)","content":"## Overview\nCreate a new central repository for syncing memories, or configure an existing repo as central.\n\n## Acceptance Criteria\n- [ ] `minimem sync init-central <path>` creates new central repo:\n - Initializes git repo if not exists\n - Creates `.gitignore` (ignores `*.db`, `staging/`, `conflicts/`)\n - Creates empty `.minimem-registry.json`\n - Creates README.md explaining the repo\n- [ ] If path is existing git repo, adds registry file if missing\n- [ ] Warns if existing repo has unusual structure\n- [ ] Sets `centralRepo` in global config after creation\n- [ ] Validates path is writable\n\n## Technical Notes\n- Use `simple-git` for git operations\n- Create directory structure atomically\n\n## Implements\n[[s-2wx5]] - Bootstrap Flow A","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:17","updated_at":"2026-02-03 05:40:19","closed_at":"2026-02-03 05:40:19","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-1ce6","from_type":"issue","to":"i-1ll7","to_type":"issue","type":"blocks"},{"from":"i-1ce6","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["bootstrap","central-repo","cli"]}
5
- {"id":"i-dvoe","uuid":"ad511324-6191-4e0c-bbf4-5be94f92a63e","title":"Implement registry system for path collision prevention","content":"## Overview\nManage the `.minimem-registry.json` file in central repo to track all sync mappings and prevent path collisions.\n\n## Acceptance Criteria\n- [ ] Registry schema with mappings array:\n - `path`: central repo path\n - `localPath`: local directory path\n - `machineId`: machine identifier\n - `lastSync`: ISO timestamp\n- [ ] `readRegistry(centralRepo)` loads registry\n- [ ] `writeRegistry(centralRepo, registry)` saves registry\n- [ ] `checkCollision(registry, path, localPath, machineId)` returns:\n - `none`: path is free\n - `same-machine`: can remap (update)\n - `collision`: different machine has this path\n- [ ] `addMapping(registry, mapping)` adds/updates entry\n- [ ] `removeMapping(registry, path, machineId)` removes entry\n- [ ] Registry file is created if missing\n\n## Technical Notes\n- Atomic writes (write to temp, rename)\n- Handle concurrent access gracefully\n\n## Implements\n[[s-2wx5]] - Central Repo Registry","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:22","updated_at":"2026-02-03 05:40:20","closed_at":"2026-02-03 05:40:20","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-dvoe","from_type":"issue","to":"i-1ll7","to_type":"issue","type":"blocks"},{"from":"i-dvoe","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["central-repo","registry"]}
6
- {"id":"i-1ll7","uuid":"9ea75ed5-2fa2-430b-87d1-4f7a7f518d4a","title":"Implement sync init command with collision validation","content":"## Overview\nInitialize sync for a memory directory, mapping it to a path in the central repo with collision checking.\n\n## Acceptance Criteria\n- [ ] `minimem sync init --path <central-path>` for current directory\n- [ ] `minimem sync init --local <dir> --path <central-path>` for explicit directory\n- [ ] Validates central repo is configured\n- [ ] Checks registry for path collisions, blocks if collision detected\n- [ ] Creates `.minimem/config.json` with sync settings\n- [ ] Registers mapping in central repo registry\n- [ ] Performs initial sync (pull if central has content, push if local-only)\n- [ ] Shows clear error messages for:\n - Central repo not configured\n - Path already mapped by different directory\n - Local directory doesn't exist\n\n## Technical Notes\n- Requires: config system, registry system, machine ID\n- Initial sync direction based on which side has content\n\n## Implements\n[[s-2wx5]] - Bootstrap Flow C","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:29","updated_at":"2026-02-03 05:42:51","closed_at":"2026-02-03 05:42:51","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-1ll7","from_type":"issue","to":"i-7gne","to_type":"issue","type":"blocks"},{"from":"i-1ll7","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["cli","sync-setup"]}
7
- {"id":"i-7gne","uuid":"b793a113-8ab4-4921-82e7-273f16320a0a","title":"Implement sync list and sync remove commands","content":"## Overview\nCommands to view all sync mappings and remove a directory from sync.\n\n## Acceptance Criteria\n- [ ] `minimem sync list` shows all mappings from registry:\n - Central path\n - Local path\n - Machine ID\n - Last sync time\n - Highlights current machine's mappings\n- [ ] `minimem sync remove` removes current directory from sync:\n - Removes from local `.minimem/config.json`\n - Removes from central repo registry\n - Does NOT delete synced files (just unlinks)\n- [ ] `minimem sync remove --local <dir>` for explicit directory\n- [ ] Confirms before removing\n\n## Technical Notes\n- Read registry from central repo\n- Format output as table\n\n## Implements\n[[s-2wx5]] - CLI commands for sync management","status":"closed","priority":2,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:33","updated_at":"2026-02-03 05:42:57","closed_at":"2026-02-03 05:42:57","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-7gne","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["cli","sync-setup"]}
8
- {"id":"i-8gam","uuid":"4450c802-d293-45e1-8a6b-76c476764814","title":"Implement sync state tracking with content hashing","content":"## Overview\nTrack the sync state of files using content hashes to detect changes and conflicts.\n\n## Acceptance Criteria\n- [ ] Sync state stored in `.minimem/sync-state.json`:\n - `lastSync`: ISO timestamp\n - `files`: map of filename to hash info\n- [ ] Each file entry has:\n - `localHash`: SHA-256 of local content\n - `remoteHash`: SHA-256 of remote content\n - `lastSyncedHash`: hash at last successful sync\n- [ ] `computeFileHash(filePath)` returns SHA-256 hex\n- [ ] `loadSyncState(dir)` reads state file\n- [ ] `saveSyncState(dir, state)` writes state file\n- [ ] `updateSyncState(dir, files)` updates hashes after sync\n- [ ] Handles missing state file (first sync)\n\n## Technical Notes\n- Use `crypto.createHash('sha256')`\n- Atomic writes for state file\n- Only track files matching include/exclude patterns\n\n## Implements\n[[s-2wx5]] - Conflict Detection (Hash + Shadow)","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:41","updated_at":"2026-02-03 05:42:50","closed_at":"2026-02-03 05:42:50","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-8gam","from_type":"issue","to":"i-3jn4","to_type":"issue","type":"blocks"},{"from":"i-8gam","from_type":"issue","to":"i-5ooa","to_type":"issue","type":"blocks"},{"from":"i-8gam","from_type":"issue","to":"i-9fm3","to_type":"issue","type":"blocks"},{"from":"i-8gam","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["core-sync","state"]}
9
- {"id":"i-5ooa","uuid":"17bc44e4-1373-4fde-8114-06320d27b71e","title":"Implement push command","content":"## Overview\nPush local memory files to the central repository.\n\n## Acceptance Criteria\n- [ ] `minimem push` syncs current directory to central repo\n- [ ] `minimem push --dir <path>` for explicit directory\n- [ ] Only pushes files matching include/exclude patterns\n- [ ] Uses atomic staging:\n 1. Copy to `.minimem/staging/{timestamp}/`\n 2. Validate all files copied\n 3. Move to central repo path\n 4. Clean up staging\n- [ ] Updates sync state after successful push\n- [ ] Updates registry `lastSync` timestamp\n- [ ] Detects conflicts (both sides changed) and delegates to conflict handler\n- [ ] Shows summary: files pushed, conflicts found, errors\n\n## Technical Notes\n- Requires: sync state, config, registry\n- Use conflict detection before overwriting\n\n## Implements\n[[s-2wx5]] - Push command","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:46","updated_at":"2026-02-03 05:45:16","closed_at":"2026-02-03 05:45:16","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-5ooa","from_type":"issue","to":"i-25ys","to_type":"issue","type":"blocks"},{"from":"i-5ooa","from_type":"issue","to":"i-7l8f","to_type":"issue","type":"blocks"},{"from":"i-5ooa","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["cli","core-sync"]}
10
- {"id":"i-3jn4","uuid":"5c9b07bf-718d-47b2-bc32-5b19b9087d33","title":"Implement pull command","content":"## Overview\nPull memory files from the central repository to local directory.\n\n## Acceptance Criteria\n- [ ] `minimem pull` syncs central repo to current directory\n- [ ] `minimem pull --dir <path>` for explicit directory\n- [ ] Only pulls files matching include/exclude patterns\n- [ ] Uses atomic staging:\n 1. Copy from central to `.minimem/staging/{timestamp}/`\n 2. Validate all files copied\n 3. Move to local directory\n 4. Clean up staging\n- [ ] Updates sync state after successful pull\n- [ ] Detects conflicts (both sides changed) and delegates to conflict handler\n- [ ] Shows summary: files pulled, conflicts found, errors\n- [ ] Creates local directories as needed\n\n## Technical Notes\n- Requires: sync state, config, registry\n- Mirror of push logic but reversed direction\n\n## Implements\n[[s-2wx5]] - Pull command","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:48","updated_at":"2026-02-03 05:45:16","closed_at":"2026-02-03 05:45:16","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-3jn4","from_type":"issue","to":"i-25ys","to_type":"issue","type":"blocks"},{"from":"i-3jn4","from_type":"issue","to":"i-7l8f","to_type":"issue","type":"blocks"},{"from":"i-3jn4","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["cli","core-sync"]}
11
- {"id":"i-9fm3","uuid":"f5cb95c3-ba65-4ffe-a863-da414d6dc801","title":"Implement conflict detection algorithm","content":"## Overview\nDetect when both local and remote have changed since last sync, requiring conflict resolution.\n\n## Acceptance Criteria\n- [ ] `detectConflicts(dir, centralRepo)` returns list of:\n - `file`: filename\n - `status`: `no-change` | `local-only` | `remote-only` | `conflict`\n - `localHash`, `remoteHash`, `baseHash`\n- [ ] Algorithm per file:\n - If localHash == remoteHash → `no-change`\n - If localHash == baseHash → `remote-only` (pull)\n - If remoteHash == baseHash → `local-only` (push)\n - Else → `conflict`\n- [ ] Creates shadow copy for conflicts:\n - `.minimem/shadows/{filename}.base` from lastSyncedHash content\n- [ ] Handles new files (no base hash)\n- [ ] Handles deleted files\n\n## Technical Notes\n- Shadow copies needed for 3-way merge\n- Consider file renames (future enhancement)\n\n## Implements\n[[s-2wx5]] - Conflict Detection Algorithm","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:56:56","updated_at":"2026-02-03 05:45:12","closed_at":"2026-02-03 05:45:12","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-9fm3","from_type":"issue","to":"i-3jn4","to_type":"issue","type":"blocks"},{"from":"i-9fm3","from_type":"issue","to":"i-5ooa","to_type":"issue","type":"blocks"},{"from":"i-9fm3","from_type":"issue","to":"i-8t0z","to_type":"issue","type":"blocks"},{"from":"i-9fm3","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["conflict","core-sync"]}
12
- {"id":"i-8t0z","uuid":"f4a413ac-3349-4d99-9c24-b6ba0cbe982e","title":"Implement merge resolution strategies","content":"## Overview\nApply configured merge strategy when conflicts are detected.\n\n## Acceptance Criteria\n- [ ] `resolveConflict(file, strategy, options)` applies strategy:\n - `keep-both`: Append both with conflict markers and timestamps\n - `merge`: Git-style 3-way merge using diff3\n - `manual`: Move to quarantine, fail sync for this file\n - `last-write-wins`: Use file with later mtime\n- [ ] Keep-both format:\n ```\n <<<<<<< LOCAL (2024-01-15 10:30)\n local content\n =======\n remote content\n >>>>>>> REMOTE (2024-01-15 09:45)\n ```\n- [ ] Merge resolver hook support:\n - If `mergeResolver` configured, spawn external tool\n - Wait for tool to exit\n - Read merged result\n- [ ] Returns: `resolved` | `quarantined` | `failed`\n\n## Technical Notes\n- Use `diff3` or similar for 3-way merge\n- External tools get paths: base, local, remote, output\n\n## Implements\n[[s-2wx5]] - Merge Resolution Strategies","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:57:02","updated_at":"2026-02-03 05:45:17","closed_at":"2026-02-03 05:45:17","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-8t0z","from_type":"issue","to":"i-9a8e","to_type":"issue","type":"blocks"},{"from":"i-8t0z","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["conflict","merge"]}
13
- {"id":"i-9a8e","uuid":"57a30353-f397-4bce-9478-3b429da858ee","title":"Implement quarantine and recovery system","content":"## Overview\nQuarantine conflicted files and provide recovery commands for failed syncs.\n\n## Acceptance Criteria\n- [ ] Quarantine structure:\n ```\n .minimem/conflicts/{timestamp}/\n ├── {filename}.local\n ├── {filename}.remote\n └── {filename}.base\n ```\n- [ ] `quarantineConflict(file, local, remote, base)` saves copies\n- [ ] `minimem sync conflicts` lists all quarantined conflicts:\n - Timestamp, filename, local/remote timestamps\n- [ ] `minimem sync resolve <file>` opens merge tool for manual resolution\n- [ ] `minimem sync recover` retries last failed sync\n- [ ] Sync log at `.minimem/sync.log`:\n - Timestamp, operation, result, errors\n- [ ] Cleanup old quarantine (configurable retention)\n\n## Technical Notes\n- Quarantine preserves all versions for safety\n- Recovery reads from staging if present\n\n## Implements\n[[s-2wx5]] - Sync Failure Recovery","status":"closed","priority":2,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:57:08","updated_at":"2026-02-03 07:24:05","closed_at":"2026-02-03 07:24:05","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-9a8e","from_type":"issue","to":"i-65zj","to_type":"issue","type":"blocks"},{"from":"i-9a8e","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["cli","conflict","recovery"],"feedback":[{"id":"c65a26ed-b934-4357-89e3-05ab096f6ced","from_id":"i-9a8e","to_id":"s-2wx5","feedback_type":"comment","content":"Implemented quarantine and recovery system:\n- Quarantine structure in `.minimem/conflicts/{timestamp}/` with `.local`, `.remote`, `.base` files\n- `quarantineConflict()` and `listQuarantinedConflicts()` in conflicts.ts\n- CLI commands: `sync:conflicts`, `sync:resolve <timestamp>`, `sync:cleanup`\n- Sync log at `.minimem/sync.log` with JSONL format\n- `sync:log` command to view history\n- Auto-detects merge tools (code, meld, kdiff3, vimdiff)\n- Cleanup supports --days and --dry-run options","agent":"alexngai","anchor":null,"dismissed":false,"created_at":"2026-02-03T07:24:04.899Z","updated_at":"2026-02-03T07:24:04.899Z"}]}
14
- {"id":"i-7l8f","uuid":"95c7277b-dfb0-47c0-8092-51116a648069","title":"Implement file watcher with debouncing","content":"## Overview\nWatch memory directories for file changes with debouncing to avoid rapid-fire syncs.\n\n## Acceptance Criteria\n- [ ] `createFileWatcher(dir, options)` returns watcher instance\n- [ ] Watches files matching include/exclude patterns\n- [ ] Debounces changes (default 2 seconds):\n - Multiple rapid changes trigger single callback\n - Configurable debounce interval\n- [ ] Emits events: `change`, `add`, `unlink`\n- [ ] Ignores `.minimem/` directory (staging, conflicts, db)\n- [ ] `watcher.close()` cleans up\n- [ ] Works cross-platform (macOS, Linux, Windows)\n\n## Technical Notes\n- Use `chokidar` for cross-platform watching\n- Debounce per-file or batch all changes\n- Consider `usePolling` fallback for network drives\n\n## Implements\n[[s-2wx5]] - Daemon file watching","status":"closed","priority":2,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:57:15","updated_at":"2026-02-03 07:30:17","closed_at":"2026-02-03 07:30:17","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-7l8f","from_type":"issue","to":"i-3ko0","to_type":"issue","type":"blocks"},{"from":"i-7l8f","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["daemon","watcher"],"feedback":[{"id":"9ec16de1-c190-4de5-871d-80cd5eebdf1d","from_id":"i-7l8f","to_id":"s-2wx5","feedback_type":"comment","content":"Implemented file watcher with debouncing in src/cli/sync/watcher.ts:\n- `createFileWatcher(dir, options)` returns watcher instance\n- Watches files matching include/exclude patterns (default: MEMORY.md, memory/*.md)\n- Debounces changes (default 2 seconds, configurable)\n- Emits batched 'changes' events with event type (add, change, unlink)\n- Ignores .minimem/ directory automatically\n- `createMultiDirWatcher()` for watching multiple directories\n- Uses chokidar for cross-platform support\n- Supports usePolling option for network drives\n- `watcher.close()` cleans up resources","agent":"alexngai","anchor":null,"dismissed":false,"created_at":"2026-02-03T07:30:17.354Z","updated_at":"2026-02-03T07:30:17.354Z"}]}
15
- {"id":"i-3ko0","uuid":"d113f827-40c7-4072-9c1e-d7b95c10c661","title":"Implement daemon core with auto-sync","content":"## Overview\nBackground daemon that watches configured directories and syncs automatically.\n\n## Acceptance Criteria\n- [ ] `minimem daemon` starts daemon in foreground\n- [ ] `minimem daemon --background` detaches (writes PID file)\n- [ ] `minimem daemon stop` stops running daemon\n- [ ] `minimem daemon status` shows daemon state\n- [ ] Daemon behavior:\n - Reads all directories with sync config from registry\n - Starts file watcher for each\n - On local change: triggers push (if autoSync enabled)\n - Watches central repo for changes (polling or git hooks)\n - On central change: triggers pull to affected directories\n- [ ] Respects `autoCommit` setting (stage only vs commit)\n- [ ] Logs activity to `.minimem/daemon.log`\n- [ ] Graceful shutdown on SIGTERM/SIGINT\n\n## Technical Notes\n- Use PID file for singleton daemon\n- Consider systemd/launchd integration later\n\n## Implements\n[[s-2wx5]] - Daemon Architecture","status":"closed","priority":2,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:57:21","updated_at":"2026-02-03 07:32:36","closed_at":"2026-02-03 07:32:36","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-3ko0","from_type":"issue","to":"i-5skx","to_type":"issue","type":"blocks"},{"from":"i-3ko0","from_type":"issue","to":"i-65zj","to_type":"issue","type":"blocks"},{"from":"i-3ko0","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["auto-sync","daemon"],"feedback":[{"id":"a6defc05-2fc0-4c4c-ba67-33e9a311330e","from_id":"i-3ko0","to_id":"s-2wx5","feedback_type":"comment","content":"Implemented daemon core in src/cli/sync/daemon.ts and src/cli/commands/daemon.ts:\n- `minimem daemon` starts daemon in foreground\n- `minimem daemon --background` detaches with PID file\n- `minimem daemon:stop` stops running daemon\n- `minimem daemon:status` shows daemon state\n- `minimem daemon:logs` shows daemon log with -f/--follow option\n- Daemon reads sync-enabled directories from registry\n- Auto-syncs on local changes when autoSync is enabled\n- Polls central repo for remote changes\n- Logs activity to ~/.minimem/daemon.log with rotation\n- Graceful shutdown on SIGTERM/SIGINT","agent":"alexngai","anchor":null,"dismissed":false,"created_at":"2026-02-03T07:32:36.150Z","updated_at":"2026-02-03T07:32:36.150Z"}]}
16
- {"id":"i-5skx","uuid":"66e3932f-7064-4d65-a2f5-8c40dd69ed76","title":"Implement registry validation in daemon","content":"## Overview\nDaemon periodically validates registry for path collisions and warns users.\n\n## Acceptance Criteria\n- [ ] Daemon checks registry on startup\n- [ ] Periodic validation (configurable interval, default 5 minutes)\n- [ ] Detects invalid states:\n - Same path mapped by multiple machines\n - Stale mappings (machine not seen in X days)\n - Local directory no longer exists\n- [ ] Warnings logged and optionally shown to user\n- [ ] Does not auto-fix, just warns\n- [ ] `minimem sync validate` manual validation command\n\n## Technical Notes\n- Avoid spamming warnings (once per issue per session)\n- Consider notification system integration\n\n## Implements\n[[s-2wx5]] - Daemon validates registry","status":"closed","priority":3,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:57:25","updated_at":"2026-02-03 07:35:11","closed_at":"2026-02-03 07:35:11","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-5skx","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["daemon","registry","validation"],"feedback":[{"id":"7235dfb2-ab25-4b72-b673-e9472ae54bdf","from_id":"i-5skx","to_id":"s-2wx5","feedback_type":"comment","content":"Implemented registry validation in src/cli/sync/validation.ts:\n- Detects path collisions (same path mapped by different machines)\n- Detects stale mappings (not synced in 30+ days)\n- Detects missing local directories (for current machine only)\n- `minimem sync:validate` CLI command with JSON output option\n- Daemon validates registry on startup and periodically (every 5 minutes)\n- Warnings logged to daemon.log without spamming","agent":"alexngai","anchor":null,"dismissed":false,"created_at":"2026-02-03T07:35:11.209Z","updated_at":"2026-02-03T07:35:11.209Z"}]}
17
- {"id":"i-25ys","uuid":"93fdc287-ae2b-49fa-905f-d109eb12da84","title":"Implement sync status command","content":"## Overview\nShow sync status across all configured directories.\n\n## Acceptance Criteria\n- [ ] `minimem sync status` shows for each synced directory:\n - Local path\n - Central repo path\n - Last sync time\n - Status: `synced` | `local-changes` | `remote-changes` | `conflicts`\n - Number of pending changes\n- [ ] `minimem sync status --dir <path>` for specific directory\n- [ ] Color-coded output (green=synced, yellow=changes, red=conflicts)\n- [ ] Shows daemon status (running/stopped)\n- [ ] Quick summary line at end\n\n## Technical Notes\n- Reads sync state files\n- Compares current hashes to detect pending changes\n- Does not perform sync, just reports\n\n## Implements\n[[s-2wx5]] - Status command (nice to have)","status":"closed","priority":3,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:57:32","updated_at":"2026-02-03 07:20:56","closed_at":"2026-02-03 07:20:56","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-25ys","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["cli","status"],"feedback":[{"id":"b06307fd-5ecc-4c1c-ad85-bce61065228e","from_id":"i-25ys","to_id":"s-2wx5","feedback_type":"comment","content":"Implemented sync:status command in src/cli/commands/push-pull.ts. Shows sync status with counts for unchanged, local changes, remote changes, new files, deleted files, and conflicts. Color-coding deferred to future enhancement. Daemon status will be added when daemon is implemented.","agent":"alexngai","anchor":null,"dismissed":false,"created_at":"2026-02-03T07:20:56.704Z","updated_at":"2026-02-03T07:20:56.704Z"}]}
18
- {"id":"i-65zj","uuid":"3f63eb98-b13e-4ba9-8a97-7e2b28d019ce","title":"Write integration tests for git sync system","content":"## Overview\nEnd-to-end tests for the complete sync workflow.\n\n## Acceptance Criteria\n- [ ] Test bootstrap flows:\n - Fresh central repo creation\n - Existing repo as central\n - Directory sync init\n - Clone setup on \"new machine\" (simulated)\n- [ ] Test sync operations:\n - Push local changes\n - Pull remote changes\n - Bidirectional sync\n- [ ] Test conflict scenarios:\n - Both sides changed, keep-both resolution\n - Conflict quarantine\n - Recovery from failed sync\n- [ ] Test collision prevention:\n - Block duplicate path mapping\n - Allow same-machine remap\n- [ ] Test daemon (if feasible):\n - Auto-sync on file change\n - Registry validation warnings\n- [ ] Use temp directories, no real git remotes\n\n## Technical Notes\n- Mock git operations or use real local repos\n- Clean up temp directories after tests\n- Consider test isolation\n\n## Implements\n[[s-2wx5]] - Success Criteria validation","status":"closed","priority":3,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-02 23:57:37","updated_at":"2026-02-03 18:40:36","closed_at":"2026-02-03 18:40:36","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-65zj","from_type":"issue","to":"s-2wx5","to_type":"spec","type":"implements"}],"tags":["integration","testing"],"feedback":[{"id":"ee25b64f-eaa8-4f55-ae5f-73863958c6a6","from_id":"i-65zj","to_id":"s-2wx5","feedback_type":"comment","content":"Implemented comprehensive integration tests in src/cli/sync/__tests__/integration.test.ts:\n\n**Bootstrap Flows:**\n- Fresh central repo creation and validation\n- XDG config setup with central repo path\n- Directory sync initialization\n- Clone setup simulation on \"new machine\"\n\n**Sync Operations:**\n- Push local changes to central\n- Pull remote changes to local\n- Bidirectional sync\n\n**Conflict Scenarios:**\n- Detect conflicts when both sides changed\n- Keep-both strategy for conflict resolution\n- Quarantine conflicts for manual resolution\n\n**Collision Prevention:**\n- Block duplicate path mapping from different machines\n- Allow same machine to remap path\n- Allow different paths for different machines\n- Detect collisions in validation\n\n**Full Workflow Test:**\n- Complete end-to-end sync workflow covering all components\n\nTotal: 133 tests across 10 test files, all passing.","agent":"alexngai","anchor":null,"dismissed":false,"created_at":"2026-02-03T18:40:35.831Z","updated_at":"2026-02-03T18:40:35.831Z"}]}
@@ -1 +0,0 @@
1
- {"id":"s-2wx5","uuid":"f2e6f765-0ff1-40ee-b93c-4ea832231e94","title":"Git Sync System for Memory Directories","file_path":"specs/s-2wx5_git_sync_system_for_memory_directories.md","content":"# Git Sync System for Memory Directories\n\n## Context\n\nminimem stores memories as plain Markdown files which are inherently git-friendly. However, users need a way to sync memories across machines and collaborate with others. The SQLite database with embeddings is **not** the source of truth and should never be committed—it's rebuilt locally via `minimem sync`.\n\nUsers have two distinct use cases:\n1. **Project-bound memories** - embedded directly in code repos alongside source code\n2. **Standalone memories** - scattered directories that should sync to a central repository\n3. **Hybrid** - project memories that are ALSO synced to a central repo for aggregation\n\n## Out of Scope\n\n- Real-time collaborative editing (not Google Docs)\n- Full git client replacement (we use git, not replace it)\n- Remote repository hosting (user provides their own)\n- Encryption at rest (use git-crypt or similar if needed)\n\n## Requirements\n\n### Must Have\n\n- [ ] CLI commands to configure sync mappings between local directories and central repo paths\n- [ ] Auto-detection of directory type (project-bound, standalone, hybrid)\n- [ ] Push/pull commands to sync directories with central repo\n- [ ] Configurable merge resolution strategies\n- [ ] Support for multiple directories syncing to one central repo\n- [ ] Path collision validation on init\n- [ ] Graceful sync failure recovery with atomic operations\n\n### Should Have\n\n- [ ] Daemon for automatic sync with file watching\n- [ ] Git hooks integration in central repo (post-pull triggers local sync)\n- [ ] Merge resolver hook for custom conflict resolution tools\n- [ ] Sync state registry in central repo to detect collisions\n\n### Nice to Have\n\n- [ ] Integration with MCP server (daemon runs alongside)\n- [ ] Periodic sync fallback when file watching unavailable\n- [ ] Status command showing sync state across all configured directories\n\n## Design\n\n### Directory Types\n\n| Type | Detection | Git Management | Sync Behavior |\n|------|-----------|----------------|---------------|\n| **Project-bound** | Inside git repo, no sync config | User handles git | No sync |\n| **Standalone** | Has sync config, not in project git | minimem manages | Full sync |\n| **Hybrid** | Inside git repo AND has sync config | User handles project git | Also syncs to central |\n| **Unmanaged** | No git repo, no sync config | None | Prompt to set up |\n\n### Auto-Detection Logic\n\n```\nIs there a sync config in .minimem/config.json?\n├─ Yes: \n│ └─ Is directory inside a git repo?\n│ ├─ Yes → Hybrid (user manages project git, minimem syncs to central)\n│ └─ No → Standalone (minimem manages sync)\n└─ No:\n └─ Is directory inside a git repo?\n ├─ Yes → Project-bound (user manages everything)\n └─ No → Unmanaged (prompt to set up sync?)\n```\n\n### Configuration\n\n**Global config** (`~/.config/minimem/config.json`):\n```json\n{\n \"centralRepo\": \"~/memories-repo\",\n \"sync\": {\n \"conflictStrategy\": \"keep-both\",\n \"autoSync\": true,\n \"autoCommit\": false\n }\n}\n```\n\n**Per-directory config** (`.minimem/config.json`):\n```json\n{\n \"sync\": {\n \"enabled\": true,\n \"path\": \"global/\",\n \"include\": [\"MEMORY.md\", \"memory/**/*.md\"],\n \"exclude\": [\"memory/drafts/**\"]\n }\n}\n```\n\n**Default sync scope:** `MEMORY.md` + `memory/**/*.md`\n\n### Central Repo Registry\n\nThe central repo maintains a registry to prevent path collisions:\n\n**`.minimem-registry.json`** (in central repo root):\n```json\n{\n \"mappings\": [\n {\n \"path\": \"global/\",\n \"localPath\": \"~/.minimem\",\n \"machineId\": \"macbook-pro-a1b2\",\n \"lastSync\": \"2024-01-15T10:30:00Z\"\n },\n {\n \"path\": \"work/\",\n \"localPath\": \"~/work/memories\",\n \"machineId\": \"macbook-pro-a1b2\",\n \"lastSync\": \"2024-01-15T10:30:00Z\"\n }\n ]\n}\n```\n\n**Collision detection:**\n- On `sync init`: check registry, block if path already mapped by different local path\n- Daemon: periodically validate registry, warn on conflicts\n- Same machine can remap (update), different machine with same path = collision\n\n### CLI Commands\n\n```bash\n# === Central Repo Setup ===\n\n# Use existing repo as central\nminimem config set centralRepo ~/existing-memories-repo\n\n# Initialize new central repo\nminimem sync init-central ~/new-memories-repo\n# Creates repo structure, .gitignore, registry file\n\n# === Directory Sync Setup ===\n\n# Initialize sync for current directory\nminimem sync init --path global/\n# Validates path not already mapped, updates registry\n\n# Explicit paths\nminimem sync init --local ~/work/memories --path work/\n\n# List all sync mappings (from registry)\nminimem sync list\n\n# Remove mapping\nminimem sync remove\n# Removes from local config and registry\n\n# === Sync Operations ===\n\nminimem push # local → central repo\nminimem pull # central repo → local\nminimem sync status # show sync state for all directories\n```\n\n### Conflict Detection (Hybrid: Hash + Shadow)\n\n**Sync state tracking** (`.minimem/sync-state.json`):\n```json\n{\n \"lastSync\": \"2024-01-15T10:30:00Z\",\n \"files\": {\n \"MEMORY.md\": {\n \"localHash\": \"abc123\",\n \"remoteHash\": \"abc123\",\n \"lastSyncedHash\": \"abc123\"\n },\n \"memory/2024-01-15.md\": {\n \"localHash\": \"def456\",\n \"remoteHash\": \"def456\",\n \"lastSyncedHash\": \"def456\"\n }\n }\n}\n```\n\n**Detection algorithm:**\n```\nFor each file:\n localHash = hash(local file)\n remoteHash = hash(central repo file)\n baseHash = lastSyncedHash from sync-state.json\n \n if localHash == remoteHash:\n → No change, skip\n elif localHash == baseHash:\n → Only remote changed, pull\n elif remoteHash == baseHash:\n → Only local changed, push\n else:\n → Both changed, CONFLICT\n → Create shadow copy for 3-way merge\n → Apply merge strategy\n```\n\n**Shadow copies** (created only on conflict):\n- `.minimem/shadows/{filename}.base` - last synced version\n- Used as merge base for 3-way merge\n- Cleaned up after resolution\n\n### Merge Resolution Strategies\n\n| Strategy | Behavior | Use Case |\n|----------|----------|----------|\n| `merge` | Git-style 3-way merge | Technical content |\n| `keep-both` | Append both versions with separator | **Default for memories** |\n| `manual` | Fail, open in merge tool | Critical content |\n| `last-write-wins` | Overwrite with latest timestamp | Low-stakes |\n\n**Keep-both format:**\n```markdown\n<<<<<<< LOCAL (2024-01-15 10:30)\nLocal version of content\n=======\nRemote version of content\n>>>>>>> REMOTE (2024-01-15 09:45)\n```\n\nMerge resolver hook:\n```json\n{\n \"sync\": {\n \"conflictStrategy\": \"manual\",\n \"mergeResolver\": \"code --wait --merge\"\n }\n}\n```\n\n### Sync Failure Recovery (Atomic + Quarantine)\n\n**Atomic sync process:**\n```\n1. Create staging: .minimem/staging/{timestamp}/\n2. Copy files to staging\n3. Validate all files copied successfully\n4. On success: move staging → final destination\n5. On failure: \n - Leave staging intact\n - Log error to .minimem/sync.log\n - Notify user\n```\n\n**Quarantine for conflicts:**\n```\n.minimem/\n├── conflicts/\n│ └── 2024-01-15T10-30-00/\n│ ├── MEMORY.md.local\n│ ├── MEMORY.md.remote\n│ └── MEMORY.md.base\n└── staging/\n └── {in-progress sync files}\n```\n\n**Recovery commands:**\n```bash\nminimem sync recover # retry failed sync\nminimem sync conflicts # list unresolved conflicts\nminimem sync resolve <file> # manually resolve conflict\n```\n\n### Daemon Architecture\n\n```\n ┌─────────────────┐\n │ Daemon │\n └────────┬────────┘\n │\n ┌───────────────────┼───────────────────┐\n │ │ │\n ▼ ▼ ▼\n Watch local dirs Watch central repo Validate registry\n (file changes) (git pull detected) (detect collisions)\n │ │ │\n ▼ ▼ ▼\n Debounce + Push Pull to local dirs Warn on conflicts\n```\n\n**Daemon responsibilities:**\n- Watch configured directories for file changes\n- Debounce rapid changes (e.g., 2 second delay)\n- Trigger push on local changes (if autoSync enabled)\n- Watch central repo for pulls (git hooks or polling)\n- Periodically validate registry for path collisions\n- Stage changes only by default (autoCommit: false)\n\nDaemon modes:\n- Standalone: `minimem daemon`\n- Integrated: runs with MCP server\n- System service: launchd/systemd\n\n### Bootstrap Flows\n\n**Flow A: Fresh central repo**\n```bash\nminimem sync init-central ~/memories-repo\n# Creates:\n# ~/memories-repo/\n# ├── .git/\n# ├── .gitignore # ignores *.db, staging/, conflicts/\n# ├── .minimem-registry.json\n# └── README.md\n\nminimem config set centralRepo ~/memories-repo\n```\n\n**Flow B: Existing repo as central**\n```bash\nminimem config set centralRepo ~/existing-repo\n# Validates repo exists\n# Creates .minimem-registry.json if missing\n# Warns if structure looks unusual\n```\n\n**Flow C: Add directory to sync**\n```bash\ncd ~/.minimem\nminimem sync init --path global/\n# Checks registry for collision\n# Updates .minimem/config.json\n# Registers in central repo\n# Initial sync (pull or push based on state)\n```\n\n**Flow D: Clone setup on new machine**\n```bash\ngit clone <central-repo> ~/memories-repo\nminimem config set centralRepo ~/memories-repo\nminimem sync list # shows all registered paths\nminimem sync init --local ~/.minimem --path global/\n# Links local directory to existing central path\n# Updates registry with new machine ID\n# Pulls content from central\n```\n\n### Central Repo Structure\n\n```\nmemories-repo/ # git repo\n├── .git/\n├── .gitignore\n├── .minimem-registry.json # path collision prevention\n├── global/ # maps to ~/.minimem/\n│ ├── MEMORY.md\n│ └── memory/\n├── work/ # maps to ~/work/memories/\n│ ├── MEMORY.md\n│ └── memory/\n└── projects/\n └── projectA/ # hybrid: also in project repo\n ├── MEMORY.md\n └── memory/\n```\n\n## Success Criteria\n\n- [ ] User can configure a central repo and map multiple directories to it\n- [ ] `minimem push/pull` correctly syncs files between local and central\n- [ ] Conflicts are detected using hash comparison and resolved with keep-both strategy\n- [ ] Path collisions are prevented via registry validation on init\n- [ ] Auto-detection correctly identifies all four directory types\n- [ ] Sync failures are recoverable via atomic operations and quarantine\n- [ ] Daemon watches for changes and syncs automatically when enabled\n- [ ] Daemon detects and warns about registry conflicts\n\n## Technical Considerations\n\n- Use `chokidar` for cross-platform file watching\n- Git operations via `simple-git` library\n- Debounce file changes (2 second default) before sync\n- Content hashing with SHA-256 for conflict detection\n- Machine ID from `os.hostname()` + random suffix on first run\n- Store machine ID in global config\n- Central repo only contains `.md` files, registry, and gitignore\n\n## Decisions Made\n\n| Question | Decision | Rationale |\n|----------|----------|-----------|\n| Daemon auto-commit? | Configurable, default off | User controls when to commit |\n| Conflict strategy default? | `keep-both` | Never lose memory data |\n| Lock mechanism? | Atomic staging | Simpler than locks, same safety |\n| Path collision handling? | Registry + validation on init | Prevent rather than recover |\n","priority":1,"archived":0,"archived_at":null,"created_at":"2026-02-02 06:36:19","updated_at":"2026-02-02 23:50:18","parent_id":null,"parent_uuid":null,"relationships":[],"tags":["cli","daemon","git","sync"]}
@@ -1,310 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides context for AI agents working on the minimem codebase.
4
-
5
- ## Project Overview
6
-
7
- **minimem** is a file-based memory system with vector search for AI agents. It lets users store memories as Markdown files and search them semantically using embeddings.
8
-
9
- **Key value props:**
10
- - Plain Markdown files (git-friendly, human-readable)
11
- - Semantic search via embeddings (OpenAI, Gemini, or local)
12
- - Hybrid search combining vectors + full-text (BM25)
13
- - MCP server for Claude Desktop/Cursor integration
14
- - CLI for command-line usage
15
-
16
- ## Architecture
17
-
18
- ```
19
- src/
20
- ├── minimem.ts # Main Minimem class - core logic
21
- ├── internal.ts # Utilities: chunking, hashing, file listing
22
- ├── index.ts # Public exports
23
- ├── cli/ # CLI implementation
24
- │ ├── index.ts # Entry point, command registration
25
- │ ├── config.ts # Config loading, directory resolution
26
- │ └── commands/ # Individual command implementations
27
- ├── db/ # Database layer
28
- │ ├── schema.ts # SQLite schema creation (v4)
29
- │ └── sqlite-vec.ts # Vector extension loading
30
- ├── embeddings/ # Embedding providers
31
- │ ├── embeddings.ts # Provider factory and interfaces
32
- │ ├── batch-openai.ts # OpenAI batch embedding
33
- │ └── batch-gemini.ts # Gemini batch embedding
34
- ├── search/ # Search implementation
35
- │ ├── hybrid.ts # Hybrid vector+FTS search, BM25
36
- │ ├── search.ts # Knowledge-filtered search helpers
37
- │ └── graph.ts # Knowledge graph traversal (BFS)
38
- └── server/ # MCP server
39
- ├── mcp.ts # MCP protocol implementation
40
- └── tools.ts # Tool definitions for LLM integration
41
- ```
42
-
43
- ## Key Files
44
-
45
- | File | Purpose |
46
- |------|---------|
47
- | `src/minimem.ts` | Core class with search, sync, append, knowledge methods |
48
- | `src/internal.ts` | `chunkMarkdown()`, `hashText()`, `listMemoryFiles()` |
49
- | `src/session.ts` | Frontmatter parsing/serialization (incl. knowledge fields) |
50
- | `src/cli/commands/search.ts` | Multi-directory search implementation |
51
- | `src/embeddings/embeddings.ts` | `createEmbeddingProvider()` factory |
52
- | `src/search/hybrid.ts` | `mergeHybridResults()`, BM25 scoring |
53
- | `src/search/search.ts` | `buildKnowledgeFilterSql()` for metadata filtering |
54
- | `src/search/graph.ts` | `getLinksFrom()`, `getLinksTo()`, `getNeighbors()`, `getPathBetween()` |
55
- | `src/server/mcp.ts` | MCP server for Claude Desktop integration |
56
- | `src/server/tools.ts` | MCP tool definitions (memory + knowledge) |
57
-
58
- ## Development Commands
59
-
60
- ```bash
61
- npm run build # Build library and CLI
62
- npm run dev # Watch mode
63
- npm run test # Unit tests (vitest)
64
- npm run test:cli # CLI command tests
65
- npm run test:integration # E2E integration tests
66
- npm run test:all # All tests
67
- ```
68
-
69
- ## Testing
70
-
71
- Tests are in `__tests__/` directories alongside source:
72
-
73
- - `src/__tests__/minimem.integration.test.ts` - Full E2E with mock embeddings
74
- - `src/__tests__/knowledge.test.ts` - Knowledge frontmatter parsing + graph traversal
75
- - `src/cli/__tests__/commands.test.ts` - CLI command tests
76
- - `src/embeddings/__tests__/` - Embedding provider tests
77
- - `src/search/__tests__/` - Hybrid search tests
78
- - `src/server/__tests__/` - MCP server + knowledge tool tests
79
-
80
- **Mock embeddings:** Tests use deterministic embeddings based on keyword presence (no API calls needed). See `createDeterministicEmbedding()` in test files.
81
-
82
- ## Build System
83
-
84
- - **tsup** for bundling (ESM only, Node 22+)
85
- - Library: `dist/index.js` with types
86
- - CLI: `dist/cli/index.js` (bundled with shebang)
87
- - **postbuild** script fixes `node:sqlite` import (esbuild strips `node:` prefix)
88
-
89
- ## Important Patterns
90
-
91
- ### Memory Path Validation
92
- Only `MEMORY.md` and `memory/*.md` files are indexed. The `validateMemoryPath()` method enforces this.
93
-
94
- ### Embedding Cache
95
- Embeddings are cached by content hash in SQLite. Same content = same embedding, even across files.
96
-
97
- ### Hybrid Search
98
- Default weights: 70% vector similarity, 30% BM25 text search. Configurable via `hybrid.vectorWeight` and `hybrid.textWeight`.
99
-
100
- ### Multi-Directory Search
101
- The search command can query multiple directories:
102
- ```bash
103
- minimem search "query" --dir ~/a --dir ~/b --global
104
- ```
105
- Results are merged and sorted by score.
106
-
107
- ## Common Tasks
108
-
109
- ### Adding a new CLI command
110
-
111
- 1. Create `src/cli/commands/newcmd.ts`:
112
- ```typescript
113
- export type NewCmdOptions = { dir?: string; global?: boolean; };
114
-
115
- export async function newcmd(options: NewCmdOptions): Promise<void> {
116
- const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });
117
- // ... implementation
118
- }
119
- ```
120
-
121
- 2. Export from `src/cli/commands/index.ts`
122
-
123
- 3. Register in `src/cli/index.ts`:
124
- ```typescript
125
- program
126
- .command("newcmd")
127
- .description("Description")
128
- .option("-d, --dir <path>", "Memory directory")
129
- .action(newcmd);
130
- ```
131
-
132
- 4. Add tests in `src/cli/__tests__/commands.test.ts`
133
-
134
- ### Adding a new embedding provider
135
-
136
- 1. Add provider type to `EmbeddingProviderOptions` in `src/embeddings/embeddings.ts`
137
- 2. Implement in `createEmbeddingProvider()` switch statement
138
- 3. Add batch function in `src/embeddings/batch-{provider}.ts` if needed
139
- 4. Update `auto` provider detection logic
140
-
141
- ### Modifying the database schema
142
-
143
- 1. Update `createSchema()` in `src/db/schema.ts` (currently at SCHEMA_VERSION 4)
144
- 2. Consider migration strategy (currently: recreate on schema change)
145
- 3. Update relevant queries in `src/minimem.ts`
146
- 4. If adding knowledge-related columns, update `indexKnowledgeMetadata()` in `src/minimem.ts`
147
-
148
- ## Gotchas
149
-
150
- 1. **node:sqlite is experimental** - Requires Node 22+, shows warning on every run
151
- 2. **sqlite-vec may not load** - Falls back to FTS-only search if extension fails
152
- 3. **CLI bundle strips node: prefix** - postbuild script fixes this
153
- 4. **Commander.js is CJS** - Must be external in CLI bundle, not inlined
154
-
155
- ## Environment Variables
156
-
157
- | Variable | Purpose |
158
- |----------|---------|
159
- | `OPENAI_API_KEY` | OpenAI embeddings |
160
- | `GOOGLE_API_KEY` | Gemini embeddings |
161
- | `GEMINI_API_KEY` | Alternative Gemini key |
162
- | `MEMORY_DIR` | Default memory directory |
163
-
164
- ## File Structure Convention
165
-
166
- ```
167
- project/
168
- ├── MEMORY.md # Main memory (required for init)
169
- ├── memory/ # Additional memories
170
- │ ├── YYYY-MM-DD.md # Daily logs (from append)
171
- │ └── *.md # Topic files
172
- └── .minimem/
173
- ├── config.json # User config
174
- ├── index.db # SQLite with vectors
175
- └── .gitignore # Ignores index.db
176
- ```
177
-
178
- ## MCP Integration
179
-
180
- The MCP server exposes 5 tools over stdio, compatible with Claude Desktop and Cursor:
181
-
182
- | Tool | Purpose |
183
- |------|---------|
184
- | `memory_search` | General semantic search across all memory files |
185
- | `memory_get_details` | Retrieve full content of a specific memory file |
186
- | `knowledge_search` | Search knowledge notes with domain/entity/confidence/type filters |
187
- | `knowledge_graph` | Traverse knowledge graph relationships from a note |
188
- | `knowledge_path` | Find shortest path between two knowledge notes via graph links |
189
-
190
- The 3 `knowledge_*` tools are additive — they only return results when knowledge-formatted notes (with the frontmatter convention below) are present. Without knowledge notes, they return empty results.
191
-
192
- Config location for Claude Desktop:
193
- - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
194
- - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
195
-
196
- ## Claude Code Plugin
197
-
198
- The `claude-plugin/` directory contains a ready-to-use Claude Code plugin:
199
-
200
- ```
201
- claude-plugin/
202
- ├── .claude-plugin/
203
- │ └── plugin.json # Plugin manifest
204
- ├── .mcp.json # MCP server definition (uses npx minimem mcp)
205
- ├── skills/
206
- │ └── memory/
207
- │ └── SKILL.md # Auto-invoked memory skill
208
- └── commands/
209
- ├── remember.md # /minimem:remember command
210
- └── recall.md # /minimem:recall command
211
- ```
212
-
213
- ### Testing the Plugin
214
-
215
- ```bash
216
- claude --plugin-dir ./claude-plugin
217
- ```
218
-
219
- ### Plugin Commands
220
-
221
- - `/minimem:remember <text>` - Store information in memory
222
- - `/minimem:recall <query>` - Search for stored memories
223
-
224
- ## Knowledge Frontmatter Convention
225
-
226
- minimem can index structured knowledge notes produced by external systems (e.g., cognitive-core). This is a **file-format convention only** — minimem does not import or depend on any external package.
227
-
228
- When a memory file's YAML frontmatter contains knowledge-specific fields, minimem parses them and populates metadata columns in the `chunks` table and edges in the `knowledge_links` table.
229
-
230
- ### Supported fields
231
-
232
- All fields are optional. If absent, the file is treated as a regular memory note.
233
-
234
- ```yaml
235
- ---
236
- id: k-abc123 # Unique knowledge node ID
237
- type: observation # observation | entity | domain-summary
238
- domain: [database, devops] # Domain tags
239
- entities: [prisma, postgres] # Referenced entities
240
- confidence: 0.85 # Confidence score (0.0–1.0)
241
- source: # Provenance metadata
242
- origin: extracted # extracted | agent-authored
243
- trajectories: [t-001, t-002] # Source trajectory IDs
244
- agentId: agent-v1 # Authoring agent
245
- links: # Graph edges to other knowledge nodes
246
- - target: k-other
247
- relation: related-to # related-to | depends-on | supports | etc.
248
- layer: semantic # semantic | temporal | causal | entity
249
- - target: k-dep
250
- relation: depends-on
251
- created: 2025-01-15T10:00:00Z
252
- updated: 2025-01-15T12:00:00Z
253
- supersedes: k-old # ID of note this replaces
254
- tags: [migration, patterns]
255
- ---
256
- # Note Title
257
-
258
- Body content in Markdown.
259
- ```
260
-
261
- ### How it works
262
-
263
- 1. **Indexing** (`indexFile()`): When a file is indexed, frontmatter is parsed via `parseFrontmatter()`. If `type` is present, the chunk row gets `knowledge_type`, `knowledge_id`, `domains` (JSON), `entities` (JSON), and `confidence` populated. If `links` is present, rows are upserted into `knowledge_links`.
264
-
265
- 2. **Filtered search** (`knowledgeSearch()`): Accepts `domain`, `entities`, `minConfidence`, and `knowledgeType` filters. Uses `json_each()` SQL for array column matching. Falls back to regular search when no filters are provided.
266
-
267
- 3. **Graph traversal** (`src/search/graph.ts`): Operates on the `knowledge_links` table. Supports outgoing/incoming edge queries, BFS neighbor discovery (configurable depth), and shortest-path finding.
268
-
269
- 4. **Re-indexing**: When a file changes, old `knowledge_links` for that file are deleted before new ones are inserted, keeping the graph consistent.
270
-
271
- ### Independence guarantee
272
-
273
- - minimem defines its own types (`KnowledgeSource`, `KnowledgeLink`, `MemoryFrontmatter`) locally in `src/session.ts`
274
- - Zero imports from cognitive-core or any external knowledge system
275
- - All knowledge columns are nullable — regular memory files index without them
276
- - The `knowledge_links` table only gets rows when frontmatter contains `links`
277
- - All knowledge MCP tools (`knowledge_search`, `knowledge_graph`, `knowledge_path`) are additive alongside existing tools
278
-
279
- ### Database schema (v4)
280
-
281
- Knowledge-related additions to the schema:
282
-
283
- ```sql
284
- -- Added columns on chunks table (all nullable)
285
- knowledge_type TEXT -- 'observation', 'entity', 'domain-summary'
286
- knowledge_id TEXT -- Note ID from frontmatter
287
- domains TEXT -- JSON array of domain strings
288
- entities TEXT -- JSON array of entity strings
289
- confidence REAL -- 0.0–1.0
290
-
291
- -- New table for graph edges
292
- CREATE TABLE knowledge_links (
293
- from_id TEXT NOT NULL,
294
- to_id TEXT NOT NULL,
295
- relation TEXT NOT NULL,
296
- layer TEXT, -- semantic, temporal, causal, entity
297
- weight REAL DEFAULT 0.5,
298
- source_path TEXT,
299
- created_at INTEGER DEFAULT (unixepoch()),
300
- PRIMARY KEY (from_id, to_id, relation)
301
- );
302
- ```
303
-
304
- ## Code Style
305
-
306
- - TypeScript with strict mode
307
- - ESM modules (no CommonJS)
308
- - Async/await for all I/O
309
- - Types exported alongside implementations
310
- - Tests use Node.js native test runner (not vitest) for integration tests