cognitive-core 0.2.1 → 0.2.3

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 (332) 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/bin/cognitive-core.js +0 -0
  6. package/dist/memory/curated-loader.d.ts +21 -4
  7. package/dist/memory/curated-loader.d.ts.map +1 -1
  8. package/dist/memory/curated-loader.js +53 -16
  9. package/dist/memory/curated-loader.js.map +1 -1
  10. package/dist/memory/index.d.ts +2 -1
  11. package/dist/memory/index.d.ts.map +1 -1
  12. package/dist/memory/index.js +3 -1
  13. package/dist/memory/index.js.map +1 -1
  14. package/dist/memory/playbook.d.ts +6 -0
  15. package/dist/memory/playbook.d.ts.map +1 -1
  16. package/dist/memory/playbook.js +15 -0
  17. package/dist/memory/playbook.js.map +1 -1
  18. package/dist/memory/source-resolver.d.ts +120 -0
  19. package/dist/memory/source-resolver.d.ts.map +1 -0
  20. package/dist/memory/source-resolver.js +300 -0
  21. package/dist/memory/source-resolver.js.map +1 -0
  22. package/dist/types/config.d.ts +141 -0
  23. package/dist/types/config.d.ts.map +1 -1
  24. package/dist/types/config.js +40 -0
  25. package/dist/types/config.js.map +1 -1
  26. package/dist/types/index.d.ts +1 -1
  27. package/dist/types/index.d.ts.map +1 -1
  28. package/dist/types/index.js +1 -1
  29. package/dist/types/index.js.map +1 -1
  30. package/dist/workspace/types.d.ts +12 -54
  31. package/dist/workspace/types.d.ts.map +1 -1
  32. package/dist/workspace/types.js.map +1 -1
  33. package/package.json +3 -3
  34. package/playbooks/compound-engineering/adversarial-review.json +51 -0
  35. package/playbooks/compound-engineering/agent-native-architecture.json +59 -0
  36. package/playbooks/compound-engineering/agent-native-review.json +54 -0
  37. package/playbooks/compound-engineering/api-contract-review.json +52 -0
  38. package/playbooks/compound-engineering/brainstorm-requirements.json +55 -0
  39. package/playbooks/compound-engineering/bug-reproduction.json +62 -0
  40. package/playbooks/compound-engineering/confidence-calibration.json +49 -0
  41. package/playbooks/compound-engineering/correctness-review.json +49 -0
  42. package/playbooks/compound-engineering/data-migration-safety.json +59 -0
  43. package/playbooks/compound-engineering/deployment-verification.json +63 -0
  44. package/playbooks/compound-engineering/error-recovery-patterns.json +53 -0
  45. package/playbooks/compound-engineering/implementation-planning.json +64 -0
  46. package/playbooks/compound-engineering/issue-pattern-analysis.json +53 -0
  47. package/playbooks/compound-engineering/knowledge-compounding.json +63 -0
  48. package/playbooks/compound-engineering/learnings-research.json +54 -0
  49. package/playbooks/compound-engineering/maintainability-review.json +49 -0
  50. package/playbooks/compound-engineering/performance-review.json +54 -0
  51. package/playbooks/compound-engineering/plan-adversarial-review.json +56 -0
  52. package/playbooks/compound-engineering/plan-feasibility-review.json +56 -0
  53. package/playbooks/compound-engineering/project-standards-review.json +52 -0
  54. package/playbooks/compound-engineering/reliability-review.json +53 -0
  55. package/playbooks/compound-engineering/review-orchestration.json +64 -0
  56. package/playbooks/compound-engineering/security-review.json +54 -0
  57. package/playbooks/compound-engineering/systematic-execution.json +64 -0
  58. package/playbooks/compound-engineering/testing-review.json +50 -0
  59. package/src/atlas.ts +96 -0
  60. package/src/memory/curated-loader.ts +69 -16
  61. package/src/memory/index.ts +16 -0
  62. package/src/memory/playbook.ts +19 -0
  63. package/src/memory/source-resolver.ts +422 -0
  64. package/src/types/config.ts +46 -0
  65. package/src/types/index.ts +4 -0
  66. package/src/workspace/types.ts +22 -78
  67. package/tests/integration/curated-sources-e2e.test.ts +502 -0
  68. package/tests/memory/compound-engineering-seed.test.ts +338 -0
  69. package/tests/memory/curated-loader-extended.test.ts +225 -0
  70. package/tests/memory/playbook-quality-validation.test.ts +430 -0
  71. package/tests/memory/source-resolver.test.ts +700 -0
  72. package/.claude/settings.local.json +0 -11
  73. package/dist/learning/llm-extractor.d.ts +0 -88
  74. package/dist/learning/llm-extractor.d.ts.map +0 -1
  75. package/dist/learning/llm-extractor.js +0 -372
  76. package/dist/learning/llm-extractor.js.map +0 -1
  77. package/dist/learning/loop-coordinator.d.ts +0 -61
  78. package/dist/learning/loop-coordinator.d.ts.map +0 -1
  79. package/dist/learning/loop-coordinator.js +0 -96
  80. package/dist/learning/loop-coordinator.js.map +0 -1
  81. package/dist/learning/pipeline.d.ts +0 -116
  82. package/dist/learning/pipeline.d.ts.map +0 -1
  83. package/dist/learning/pipeline.js +0 -288
  84. package/dist/learning/pipeline.js.map +0 -1
  85. package/references/agent-workspace/CLAUDE.md +0 -74
  86. package/references/agent-workspace/README.md +0 -587
  87. package/references/agent-workspace/media/banner.png +0 -0
  88. package/references/agent-workspace/package-lock.json +0 -2061
  89. package/references/agent-workspace/package.json +0 -54
  90. package/references/agent-workspace/src/handle.ts +0 -122
  91. package/references/agent-workspace/src/index.ts +0 -32
  92. package/references/agent-workspace/src/manager.ts +0 -102
  93. package/references/agent-workspace/src/readers/json.ts +0 -71
  94. package/references/agent-workspace/src/readers/markdown.ts +0 -37
  95. package/references/agent-workspace/src/readers/raw.ts +0 -27
  96. package/references/agent-workspace/src/types.ts +0 -68
  97. package/references/agent-workspace/src/validation.ts +0 -93
  98. package/references/agent-workspace/src/writers/json.ts +0 -17
  99. package/references/agent-workspace/src/writers/markdown.ts +0 -27
  100. package/references/agent-workspace/src/writers/raw.ts +0 -22
  101. package/references/agent-workspace/tests/errors.test.ts +0 -652
  102. package/references/agent-workspace/tests/handle.test.ts +0 -144
  103. package/references/agent-workspace/tests/manager.test.ts +0 -124
  104. package/references/agent-workspace/tests/readers.test.ts +0 -205
  105. package/references/agent-workspace/tests/validation.test.ts +0 -196
  106. package/references/agent-workspace/tests/writers.test.ts +0 -108
  107. package/references/agent-workspace/tsconfig.json +0 -20
  108. package/references/agent-workspace/tsup.config.ts +0 -9
  109. package/references/minimem/.claude/settings.json +0 -7
  110. package/references/minimem/.sudocode/issues.jsonl +0 -18
  111. package/references/minimem/.sudocode/specs.jsonl +0 -1
  112. package/references/minimem/CLAUDE.md +0 -310
  113. package/references/minimem/README.md +0 -556
  114. package/references/minimem/claude-plugin/.claude-plugin/plugin.json +0 -10
  115. package/references/minimem/claude-plugin/.mcp.json +0 -7
  116. package/references/minimem/claude-plugin/README.md +0 -158
  117. package/references/minimem/claude-plugin/commands/recall.md +0 -47
  118. package/references/minimem/claude-plugin/commands/remember.md +0 -41
  119. package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +0 -272
  120. package/references/minimem/claude-plugin/hooks/hooks.json +0 -27
  121. package/references/minimem/claude-plugin/hooks/session-end.sh +0 -86
  122. package/references/minimem/claude-plugin/hooks/session-start.sh +0 -85
  123. package/references/minimem/claude-plugin/skills/memory/SKILL.md +0 -108
  124. package/references/minimem/package-lock.json +0 -5373
  125. package/references/minimem/package.json +0 -60
  126. package/references/minimem/scripts/postbuild.js +0 -35
  127. package/references/minimem/src/__tests__/edge-cases.test.ts +0 -371
  128. package/references/minimem/src/__tests__/errors.test.ts +0 -265
  129. package/references/minimem/src/__tests__/helpers.ts +0 -199
  130. package/references/minimem/src/__tests__/internal.test.ts +0 -407
  131. package/references/minimem/src/__tests__/knowledge.test.ts +0 -287
  132. package/references/minimem/src/__tests__/minimem.integration.test.ts +0 -1127
  133. package/references/minimem/src/__tests__/session.test.ts +0 -190
  134. package/references/minimem/src/cli/__tests__/commands.test.ts +0 -759
  135. package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +0 -141
  136. package/references/minimem/src/cli/commands/append.ts +0 -76
  137. package/references/minimem/src/cli/commands/config.ts +0 -262
  138. package/references/minimem/src/cli/commands/conflicts.ts +0 -413
  139. package/references/minimem/src/cli/commands/daemon.ts +0 -169
  140. package/references/minimem/src/cli/commands/index.ts +0 -12
  141. package/references/minimem/src/cli/commands/init.ts +0 -88
  142. package/references/minimem/src/cli/commands/mcp.ts +0 -177
  143. package/references/minimem/src/cli/commands/push-pull.ts +0 -213
  144. package/references/minimem/src/cli/commands/search.ts +0 -158
  145. package/references/minimem/src/cli/commands/status.ts +0 -84
  146. package/references/minimem/src/cli/commands/sync-init.ts +0 -290
  147. package/references/minimem/src/cli/commands/sync.ts +0 -70
  148. package/references/minimem/src/cli/commands/upsert.ts +0 -197
  149. package/references/minimem/src/cli/config.ts +0 -584
  150. package/references/minimem/src/cli/index.ts +0 -264
  151. package/references/minimem/src/cli/shared.ts +0 -161
  152. package/references/minimem/src/cli/sync/__tests__/central.test.ts +0 -152
  153. package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +0 -209
  154. package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +0 -118
  155. package/references/minimem/src/cli/sync/__tests__/detection.test.ts +0 -207
  156. package/references/minimem/src/cli/sync/__tests__/integration.test.ts +0 -476
  157. package/references/minimem/src/cli/sync/__tests__/registry.test.ts +0 -363
  158. package/references/minimem/src/cli/sync/__tests__/state.test.ts +0 -255
  159. package/references/minimem/src/cli/sync/__tests__/validation.test.ts +0 -193
  160. package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +0 -178
  161. package/references/minimem/src/cli/sync/central.ts +0 -292
  162. package/references/minimem/src/cli/sync/conflicts.ts +0 -204
  163. package/references/minimem/src/cli/sync/daemon.ts +0 -407
  164. package/references/minimem/src/cli/sync/detection.ts +0 -138
  165. package/references/minimem/src/cli/sync/index.ts +0 -107
  166. package/references/minimem/src/cli/sync/operations.ts +0 -373
  167. package/references/minimem/src/cli/sync/registry.ts +0 -279
  168. package/references/minimem/src/cli/sync/state.ts +0 -355
  169. package/references/minimem/src/cli/sync/validation.ts +0 -206
  170. package/references/minimem/src/cli/sync/watcher.ts +0 -234
  171. package/references/minimem/src/cli/version.ts +0 -34
  172. package/references/minimem/src/core/index.ts +0 -9
  173. package/references/minimem/src/core/indexer.ts +0 -628
  174. package/references/minimem/src/core/searcher.ts +0 -221
  175. package/references/minimem/src/db/schema.ts +0 -183
  176. package/references/minimem/src/db/sqlite-vec.ts +0 -24
  177. package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +0 -431
  178. package/references/minimem/src/embeddings/batch-gemini.ts +0 -392
  179. package/references/minimem/src/embeddings/batch-openai.ts +0 -409
  180. package/references/minimem/src/embeddings/embeddings.ts +0 -434
  181. package/references/minimem/src/index.ts +0 -109
  182. package/references/minimem/src/internal.ts +0 -299
  183. package/references/minimem/src/minimem.ts +0 -1276
  184. package/references/minimem/src/search/__tests__/hybrid.test.ts +0 -247
  185. package/references/minimem/src/search/graph.ts +0 -234
  186. package/references/minimem/src/search/hybrid.ts +0 -151
  187. package/references/minimem/src/search/search.ts +0 -256
  188. package/references/minimem/src/server/__tests__/mcp.test.ts +0 -341
  189. package/references/minimem/src/server/__tests__/tools.test.ts +0 -364
  190. package/references/minimem/src/server/mcp.ts +0 -326
  191. package/references/minimem/src/server/tools.ts +0 -720
  192. package/references/minimem/src/session.ts +0 -460
  193. package/references/minimem/tsconfig.json +0 -19
  194. package/references/minimem/tsup.config.ts +0 -26
  195. package/references/minimem/vitest.config.ts +0 -24
  196. package/references/sessionlog/.husky/pre-commit +0 -1
  197. package/references/sessionlog/.lintstagedrc.json +0 -4
  198. package/references/sessionlog/.prettierignore +0 -4
  199. package/references/sessionlog/.prettierrc.json +0 -11
  200. package/references/sessionlog/LICENSE +0 -21
  201. package/references/sessionlog/README.md +0 -453
  202. package/references/sessionlog/eslint.config.js +0 -58
  203. package/references/sessionlog/package-lock.json +0 -3672
  204. package/references/sessionlog/package.json +0 -65
  205. package/references/sessionlog/src/__tests__/agent-hooks.test.ts +0 -570
  206. package/references/sessionlog/src/__tests__/agent-registry.test.ts +0 -127
  207. package/references/sessionlog/src/__tests__/claude-code-hooks.test.ts +0 -225
  208. package/references/sessionlog/src/__tests__/claude-generator.test.ts +0 -46
  209. package/references/sessionlog/src/__tests__/commit-msg.test.ts +0 -86
  210. package/references/sessionlog/src/__tests__/cursor-agent.test.ts +0 -224
  211. package/references/sessionlog/src/__tests__/e2e-live.test.ts +0 -890
  212. package/references/sessionlog/src/__tests__/event-log.test.ts +0 -183
  213. package/references/sessionlog/src/__tests__/flush-sentinel.test.ts +0 -105
  214. package/references/sessionlog/src/__tests__/gemini-agent.test.ts +0 -375
  215. package/references/sessionlog/src/__tests__/git-hooks.test.ts +0 -78
  216. package/references/sessionlog/src/__tests__/hook-managers.test.ts +0 -121
  217. package/references/sessionlog/src/__tests__/lifecycle-tasks.test.ts +0 -759
  218. package/references/sessionlog/src/__tests__/opencode-agent.test.ts +0 -338
  219. package/references/sessionlog/src/__tests__/redaction.test.ts +0 -136
  220. package/references/sessionlog/src/__tests__/session-repo.test.ts +0 -353
  221. package/references/sessionlog/src/__tests__/session-store.test.ts +0 -166
  222. package/references/sessionlog/src/__tests__/setup-ccweb.test.ts +0 -466
  223. package/references/sessionlog/src/__tests__/skill-live.test.ts +0 -461
  224. package/references/sessionlog/src/__tests__/summarize.test.ts +0 -348
  225. package/references/sessionlog/src/__tests__/task-plan-e2e.test.ts +0 -610
  226. package/references/sessionlog/src/__tests__/task-plan-live.test.ts +0 -632
  227. package/references/sessionlog/src/__tests__/transcript-timestamp.test.ts +0 -121
  228. package/references/sessionlog/src/__tests__/types.test.ts +0 -166
  229. package/references/sessionlog/src/__tests__/utils.test.ts +0 -333
  230. package/references/sessionlog/src/__tests__/validation.test.ts +0 -103
  231. package/references/sessionlog/src/__tests__/worktree.test.ts +0 -57
  232. package/references/sessionlog/src/agent/agents/claude-code.ts +0 -1089
  233. package/references/sessionlog/src/agent/agents/cursor.ts +0 -361
  234. package/references/sessionlog/src/agent/agents/gemini-cli.ts +0 -632
  235. package/references/sessionlog/src/agent/agents/opencode.ts +0 -540
  236. package/references/sessionlog/src/agent/registry.ts +0 -143
  237. package/references/sessionlog/src/agent/session-types.ts +0 -113
  238. package/references/sessionlog/src/agent/types.ts +0 -220
  239. package/references/sessionlog/src/cli.ts +0 -597
  240. package/references/sessionlog/src/commands/clean.ts +0 -133
  241. package/references/sessionlog/src/commands/disable.ts +0 -84
  242. package/references/sessionlog/src/commands/doctor.ts +0 -145
  243. package/references/sessionlog/src/commands/enable.ts +0 -202
  244. package/references/sessionlog/src/commands/explain.ts +0 -261
  245. package/references/sessionlog/src/commands/reset.ts +0 -105
  246. package/references/sessionlog/src/commands/resume.ts +0 -180
  247. package/references/sessionlog/src/commands/rewind.ts +0 -195
  248. package/references/sessionlog/src/commands/setup-ccweb.ts +0 -275
  249. package/references/sessionlog/src/commands/status.ts +0 -172
  250. package/references/sessionlog/src/config.ts +0 -165
  251. package/references/sessionlog/src/events/event-log.ts +0 -126
  252. package/references/sessionlog/src/git-operations.ts +0 -558
  253. package/references/sessionlog/src/hooks/git-hooks.ts +0 -165
  254. package/references/sessionlog/src/hooks/lifecycle.ts +0 -391
  255. package/references/sessionlog/src/index.ts +0 -650
  256. package/references/sessionlog/src/security/redaction.ts +0 -283
  257. package/references/sessionlog/src/session/state-machine.ts +0 -452
  258. package/references/sessionlog/src/store/checkpoint-store.ts +0 -509
  259. package/references/sessionlog/src/store/native-store.ts +0 -173
  260. package/references/sessionlog/src/store/provider-types.ts +0 -99
  261. package/references/sessionlog/src/store/session-store.ts +0 -266
  262. package/references/sessionlog/src/strategy/attribution.ts +0 -296
  263. package/references/sessionlog/src/strategy/common.ts +0 -207
  264. package/references/sessionlog/src/strategy/content-overlap.ts +0 -228
  265. package/references/sessionlog/src/strategy/manual-commit.ts +0 -988
  266. package/references/sessionlog/src/strategy/types.ts +0 -279
  267. package/references/sessionlog/src/summarize/claude-generator.ts +0 -115
  268. package/references/sessionlog/src/summarize/summarize.ts +0 -432
  269. package/references/sessionlog/src/types.ts +0 -508
  270. package/references/sessionlog/src/utils/chunk-files.ts +0 -49
  271. package/references/sessionlog/src/utils/commit-message.ts +0 -65
  272. package/references/sessionlog/src/utils/detect-agent.ts +0 -36
  273. package/references/sessionlog/src/utils/hook-managers.ts +0 -125
  274. package/references/sessionlog/src/utils/ide-tags.ts +0 -32
  275. package/references/sessionlog/src/utils/paths.ts +0 -79
  276. package/references/sessionlog/src/utils/preview-rewind.ts +0 -80
  277. package/references/sessionlog/src/utils/rewind-conflict.ts +0 -121
  278. package/references/sessionlog/src/utils/shadow-branch.ts +0 -109
  279. package/references/sessionlog/src/utils/string-utils.ts +0 -46
  280. package/references/sessionlog/src/utils/todo-extract.ts +0 -188
  281. package/references/sessionlog/src/utils/trailers.ts +0 -187
  282. package/references/sessionlog/src/utils/transcript-parse.ts +0 -177
  283. package/references/sessionlog/src/utils/transcript-timestamp.ts +0 -59
  284. package/references/sessionlog/src/utils/tree-ops.ts +0 -219
  285. package/references/sessionlog/src/utils/tty.ts +0 -72
  286. package/references/sessionlog/src/utils/validation.ts +0 -65
  287. package/references/sessionlog/src/utils/worktree.ts +0 -58
  288. package/references/sessionlog/src/wire-types.ts +0 -59
  289. package/references/sessionlog/templates/setup-env.sh +0 -153
  290. package/references/sessionlog/tsconfig.json +0 -18
  291. package/references/sessionlog/vitest.config.ts +0 -12
  292. package/references/skill-tree/.claude/settings.json +0 -6
  293. package/references/skill-tree/.sudocode/issues.jsonl +0 -19
  294. package/references/skill-tree/.sudocode/specs.jsonl +0 -3
  295. package/references/skill-tree/CLAUDE.md +0 -126
  296. package/references/skill-tree/README.md +0 -372
  297. package/references/skill-tree/docs/GAPS_v1.md +0 -221
  298. package/references/skill-tree/docs/INTEGRATION_PLAN.md +0 -467
  299. package/references/skill-tree/docs/TODOS.md +0 -91
  300. package/references/skill-tree/docs/anthropic_skill_guide.md +0 -1364
  301. package/references/skill-tree/docs/design/federated-skill-trees.md +0 -524
  302. package/references/skill-tree/docs/design/multi-agent-sync.md +0 -759
  303. package/references/skill-tree/docs/scraper/BRAINSTORM.md +0 -583
  304. package/references/skill-tree/docs/scraper/POC_PLAN.md +0 -420
  305. package/references/skill-tree/docs/scraper/README.md +0 -170
  306. package/references/skill-tree/examples/basic-usage.ts +0 -164
  307. package/references/skill-tree/package-lock.json +0 -1852
  308. package/references/skill-tree/package.json +0 -66
  309. package/references/skill-tree/scraper/README.md +0 -123
  310. package/references/skill-tree/scraper/docs/DESIGN.md +0 -683
  311. package/references/skill-tree/scraper/docs/PLAN.md +0 -336
  312. package/references/skill-tree/scraper/drizzle.config.ts +0 -10
  313. package/references/skill-tree/scraper/package-lock.json +0 -6329
  314. package/references/skill-tree/scraper/package.json +0 -68
  315. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +0 -7
  316. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +0 -7
  317. package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +0 -27
  318. package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +0 -21
  319. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +0 -54
  320. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +0 -24
  321. package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +0 -93
  322. package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +0 -22
  323. package/references/skill-tree/scraper/tsup.config.ts +0 -14
  324. package/references/skill-tree/scraper/vitest.config.ts +0 -17
  325. package/references/skill-tree/scripts/convert-to-vitest.ts +0 -166
  326. package/references/skill-tree/skills/skill-writer/SKILL.md +0 -339
  327. package/references/skill-tree/skills/skill-writer/references/examples.md +0 -326
  328. package/references/skill-tree/skills/skill-writer/references/patterns.md +0 -210
  329. package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +0 -123
  330. package/references/skill-tree/test/run-all.ts +0 -106
  331. package/references/skill-tree/test/utils.ts +0 -128
  332. package/references/skill-tree/vitest.config.ts +0 -16
@@ -1,279 +0,0 @@
1
- /**
2
- * Registry system for sync path collision prevention
3
- *
4
- * The registry is stored in the central repo as .minimem-registry.json
5
- * and tracks which local directories are mapped to which paths.
6
- */
7
-
8
- import fs from "node:fs/promises";
9
- import path from "node:path";
10
- import os from "node:os";
11
- import crypto from "node:crypto";
12
-
13
- const REGISTRY_FILENAME = ".minimem-registry.json";
14
-
15
- export type RegistryMapping = {
16
- /** Path in central repo (e.g., "global/", "work/") */
17
- path: string;
18
- /** Local directory path (with ~ for home) */
19
- localPath: string;
20
- /** Machine identifier */
21
- machineId: string;
22
- /** Last sync timestamp (ISO format) */
23
- lastSync: string;
24
- };
25
-
26
- export type Registry = {
27
- version: number;
28
- mappings: RegistryMapping[];
29
- };
30
-
31
- export type CollisionCheckResult = "none" | "same-machine" | "collision";
32
-
33
- /**
34
- * Get the registry file path for a central repo
35
- */
36
- export function getRegistryPath(centralRepo: string): string {
37
- return path.join(centralRepo, REGISTRY_FILENAME);
38
- }
39
-
40
- /**
41
- * Create an empty registry
42
- */
43
- export function createEmptyRegistry(): Registry {
44
- return {
45
- version: 1,
46
- mappings: [],
47
- };
48
- }
49
-
50
- /**
51
- * Read registry from central repo
52
- * Returns empty registry if file doesn't exist
53
- */
54
- export async function readRegistry(centralRepo: string): Promise<Registry> {
55
- const registryPath = getRegistryPath(centralRepo);
56
-
57
- try {
58
- const content = await fs.readFile(registryPath, "utf-8");
59
- const registry = JSON.parse(content) as Registry;
60
-
61
- // Validate basic structure
62
- if (!registry.mappings || !Array.isArray(registry.mappings)) {
63
- return createEmptyRegistry();
64
- }
65
-
66
- return registry;
67
- } catch (error) {
68
- // File doesn't exist or is invalid
69
- return createEmptyRegistry();
70
- }
71
- }
72
-
73
- /**
74
- * Write registry to central repo atomically
75
- * Writes to temp file then renames to avoid corruption
76
- */
77
- export async function writeRegistry(
78
- centralRepo: string,
79
- registry: Registry
80
- ): Promise<void> {
81
- const registryPath = getRegistryPath(centralRepo);
82
- const tempPath = `${registryPath}.${crypto.randomBytes(4).toString("hex")}.tmp`;
83
-
84
- // Ensure version is set
85
- registry.version = registry.version || 1;
86
-
87
- // Write to temp file
88
- await fs.writeFile(tempPath, JSON.stringify(registry, null, 2), "utf-8");
89
-
90
- // Atomic rename
91
- await fs.rename(tempPath, registryPath);
92
- }
93
-
94
- /**
95
- * Normalize a path for comparison
96
- * Expands ~ and resolves to absolute path
97
- */
98
- export function normalizePath(filePath: string): string {
99
- if (filePath.startsWith("~/")) {
100
- return path.resolve(os.homedir(), filePath.slice(2));
101
- }
102
- if (filePath === "~") {
103
- return os.homedir();
104
- }
105
- return path.resolve(filePath);
106
- }
107
-
108
- /**
109
- * Compress a path for storage
110
- * Replaces home directory with ~
111
- */
112
- export function compressPath(filePath: string): string {
113
- const home = os.homedir();
114
- const resolved = path.resolve(filePath);
115
- if (resolved.startsWith(home)) {
116
- return "~" + resolved.slice(home.length);
117
- }
118
- return resolved;
119
- }
120
-
121
- /**
122
- * Normalize central repo path (remove trailing slash, etc.)
123
- */
124
- export function normalizeRepoPath(repoPath: string): string {
125
- // Remove trailing slashes but keep at least one char
126
- let normalized = repoPath.replace(/\/+$/, "");
127
- if (normalized === "") {
128
- normalized = "/";
129
- }
130
- // Ensure it ends with / for directory paths (except root)
131
- if (!normalized.endsWith("/") && normalized !== "/") {
132
- normalized += "/";
133
- }
134
- return normalized;
135
- }
136
-
137
- /**
138
- * Check if a path mapping would collide with existing mappings
139
- *
140
- * Returns:
141
- * - "none": path is free, can be used
142
- * - "same-machine": same machine already has this path, can update
143
- * - "collision": different machine has this path, blocked
144
- */
145
- export function checkCollision(
146
- registry: Registry,
147
- centralPath: string,
148
- localPath: string,
149
- machineId: string
150
- ): CollisionCheckResult {
151
- const normalizedCentralPath = normalizeRepoPath(centralPath);
152
- const normalizedLocalPath = normalizePath(localPath);
153
-
154
- for (const mapping of registry.mappings) {
155
- const mappingCentralPath = normalizeRepoPath(mapping.path);
156
- const mappingLocalPath = normalizePath(mapping.localPath);
157
-
158
- // Check if central path matches
159
- if (mappingCentralPath === normalizedCentralPath) {
160
- // Same machine, same or different local path - can update
161
- if (mapping.machineId === machineId) {
162
- return "same-machine";
163
- }
164
-
165
- // Different machine - collision
166
- return "collision";
167
- }
168
- }
169
-
170
- return "none";
171
- }
172
-
173
- /**
174
- * Add or update a mapping in the registry
175
- */
176
- export function addMapping(
177
- registry: Registry,
178
- mapping: RegistryMapping
179
- ): Registry {
180
- const normalizedPath = normalizeRepoPath(mapping.path);
181
- const normalizedLocalPath = compressPath(mapping.localPath);
182
-
183
- // Remove existing mapping for this path+machine combination
184
- const filteredMappings = registry.mappings.filter(
185
- (m) =>
186
- !(
187
- normalizeRepoPath(m.path) === normalizedPath &&
188
- m.machineId === mapping.machineId
189
- )
190
- );
191
-
192
- // Add new mapping
193
- filteredMappings.push({
194
- ...mapping,
195
- path: normalizedPath,
196
- localPath: normalizedLocalPath,
197
- });
198
-
199
- return {
200
- ...registry,
201
- mappings: filteredMappings,
202
- };
203
- }
204
-
205
- /**
206
- * Remove a mapping from the registry
207
- */
208
- export function removeMapping(
209
- registry: Registry,
210
- centralPath: string,
211
- machineId: string
212
- ): Registry {
213
- const normalizedPath = normalizeRepoPath(centralPath);
214
-
215
- const filteredMappings = registry.mappings.filter(
216
- (m) =>
217
- !(normalizeRepoPath(m.path) === normalizedPath && m.machineId === machineId)
218
- );
219
-
220
- return {
221
- ...registry,
222
- mappings: filteredMappings,
223
- };
224
- }
225
-
226
- /**
227
- * Find a mapping by central path and machine ID
228
- */
229
- export function findMapping(
230
- registry: Registry,
231
- centralPath: string,
232
- machineId: string
233
- ): RegistryMapping | undefined {
234
- const normalizedPath = normalizeRepoPath(centralPath);
235
-
236
- return registry.mappings.find(
237
- (m) =>
238
- normalizeRepoPath(m.path) === normalizedPath && m.machineId === machineId
239
- );
240
- }
241
-
242
- /**
243
- * Get all mappings for a specific machine
244
- */
245
- export function getMachineMappings(
246
- registry: Registry,
247
- machineId: string
248
- ): RegistryMapping[] {
249
- return registry.mappings.filter((m) => m.machineId === machineId);
250
- }
251
-
252
- /**
253
- * Update the lastSync timestamp for a mapping
254
- */
255
- export function updateLastSync(
256
- registry: Registry,
257
- centralPath: string,
258
- machineId: string
259
- ): Registry {
260
- const normalizedPath = normalizeRepoPath(centralPath);
261
-
262
- const mappings = registry.mappings.map((m) => {
263
- if (
264
- normalizeRepoPath(m.path) === normalizedPath &&
265
- m.machineId === machineId
266
- ) {
267
- return {
268
- ...m,
269
- lastSync: new Date().toISOString(),
270
- };
271
- }
272
- return m;
273
- });
274
-
275
- return {
276
- ...registry,
277
- mappings,
278
- };
279
- }
@@ -1,355 +0,0 @@
1
- /**
2
- * Sync state tracking with content hashing
3
- *
4
- * Tracks file hashes to detect changes between local directories
5
- * and the central repository. Uses 2-way comparison (local vs remote).
6
- *
7
- * Conflict resolution: Last-write-wins
8
- * - Push: local overwrites remote
9
- * - Pull: remote overwrites local
10
- */
11
-
12
- import fs from "node:fs/promises";
13
- import path from "node:path";
14
- import crypto from "node:crypto";
15
- import { minimatch } from "minimatch";
16
-
17
- const STATE_FILENAME = "sync-state.json";
18
- const STATE_DIR = ".minimem";
19
-
20
- export type FileHashInfo = {
21
- /** SHA-256 hash of local file content */
22
- localHash: string;
23
- /** SHA-256 hash of remote file content */
24
- remoteHash: string;
25
- /** Last modified timestamp (ISO) */
26
- lastModified: string;
27
- };
28
-
29
- export type SyncState = {
30
- /** Version for future migrations */
31
- version: number;
32
- /** Last sync timestamp (ISO) */
33
- lastSync: string | null;
34
- /** Central repo path this directory syncs to */
35
- centralPath: string;
36
- /** File hashes keyed by relative path */
37
- files: Record<string, FileHashInfo>;
38
- };
39
-
40
- /**
41
- * Get the sync state file path for a directory
42
- */
43
- export function getSyncStatePath(dir: string): string {
44
- return path.join(dir, STATE_DIR, STATE_FILENAME);
45
- }
46
-
47
- /**
48
- * Create an empty sync state
49
- */
50
- export function createEmptySyncState(centralPath: string): SyncState {
51
- return {
52
- version: 2, // Bumped version for simplified state
53
- lastSync: null,
54
- centralPath,
55
- files: {},
56
- };
57
- }
58
-
59
- /**
60
- * Load sync state from a directory
61
- * Returns empty state if file doesn't exist
62
- */
63
- export async function loadSyncState(
64
- dir: string,
65
- centralPath: string
66
- ): Promise<SyncState> {
67
- const statePath = getSyncStatePath(dir);
68
-
69
- try {
70
- const content = await fs.readFile(statePath, "utf-8");
71
- const state = JSON.parse(content) as SyncState;
72
-
73
- // Validate basic structure
74
- if (!state.files || typeof state.files !== "object") {
75
- return createEmptySyncState(centralPath);
76
- }
77
-
78
- // Update centralPath if it changed
79
- state.centralPath = centralPath;
80
-
81
- // Migrate v1 state (remove lastSyncedHash if present)
82
- if (state.version === 1) {
83
- for (const file of Object.keys(state.files)) {
84
- const entry = state.files[file] as FileHashInfo & { lastSyncedHash?: string };
85
- delete entry.lastSyncedHash;
86
- }
87
- state.version = 2;
88
- }
89
-
90
- return state;
91
- } catch {
92
- return createEmptySyncState(centralPath);
93
- }
94
- }
95
-
96
- /**
97
- * Save sync state atomically
98
- */
99
- export async function saveSyncState(
100
- dir: string,
101
- state: SyncState
102
- ): Promise<void> {
103
- const statePath = getSyncStatePath(dir);
104
- const stateDir = path.dirname(statePath);
105
- const tempPath = `${statePath}.${crypto.randomBytes(4).toString("hex")}.tmp`;
106
-
107
- // Ensure directory exists
108
- await fs.mkdir(stateDir, { recursive: true });
109
-
110
- // Ensure version is set
111
- state.version = state.version || 2;
112
-
113
- // Write to temp file
114
- await fs.writeFile(tempPath, JSON.stringify(state, null, 2), "utf-8");
115
-
116
- // Atomic rename
117
- await fs.rename(tempPath, statePath);
118
- }
119
-
120
- /**
121
- * Compute SHA-256 hash of a file's content
122
- */
123
- export async function computeFileHash(filePath: string): Promise<string> {
124
- const content = await fs.readFile(filePath);
125
- return crypto.createHash("sha256").update(content).digest("hex");
126
- }
127
-
128
- /**
129
- * Compute hash of string content
130
- */
131
- export function computeContentHash(content: string | Buffer): string {
132
- return crypto.createHash("sha256").update(content).digest("hex");
133
- }
134
-
135
- /**
136
- * List files matching include/exclude patterns
137
- */
138
- export async function listSyncableFiles(
139
- dir: string,
140
- include: string[],
141
- exclude: string[]
142
- ): Promise<string[]> {
143
- const files: string[] = [];
144
-
145
- async function walkDir(currentDir: string, relativePath: string = "") {
146
- const entries = await fs.readdir(currentDir, { withFileTypes: true });
147
-
148
- for (const entry of entries) {
149
- const entryPath = path.join(currentDir, entry.name);
150
- const relPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
151
-
152
- // Skip .minimem directory
153
- if (entry.name === ".minimem") continue;
154
-
155
- if (entry.isDirectory()) {
156
- await walkDir(entryPath, relPath);
157
- } else if (entry.isFile()) {
158
- // Check include patterns
159
- const matchesInclude = include.some((pattern) =>
160
- minimatch(relPath, pattern)
161
- );
162
-
163
- // Check exclude patterns
164
- const matchesExclude = exclude.some((pattern) =>
165
- minimatch(relPath, pattern)
166
- );
167
-
168
- if (matchesInclude && !matchesExclude) {
169
- files.push(relPath);
170
- }
171
- }
172
- }
173
- }
174
-
175
- try {
176
- await walkDir(dir);
177
- } catch (error) {
178
- // Directory might not exist yet
179
- if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
180
- throw error;
181
- }
182
- }
183
-
184
- return files.sort();
185
- }
186
-
187
- /**
188
- * Get file hash info, computing hash if file exists
189
- */
190
- export async function getFileHashInfo(
191
- filePath: string
192
- ): Promise<{ exists: boolean; hash?: string; mtime?: string }> {
193
- try {
194
- const stat = await fs.stat(filePath);
195
- const hash = await computeFileHash(filePath);
196
- return {
197
- exists: true,
198
- hash,
199
- mtime: stat.mtime.toISOString(),
200
- };
201
- } catch {
202
- return { exists: false };
203
- }
204
- }
205
-
206
- /**
207
- * Sync status for a file (2-way comparison)
208
- *
209
- * With last-write-wins, there are no conflicts:
210
- * - Push operations: local changes overwrite remote
211
- * - Pull operations: remote changes overwrite local
212
- */
213
- export type FileSyncStatus =
214
- | "unchanged" // Both same
215
- | "local-modified" // Local differs from remote (push will overwrite remote)
216
- | "remote-modified"// Remote differs from local (pull will overwrite local)
217
- | "local-only" // File exists only locally
218
- | "remote-only"; // File exists only on remote
219
-
220
- /**
221
- * Compare local and remote files to determine sync status
222
- * Simple 2-way comparison (no 3-way merge needed with last-write-wins)
223
- */
224
- export function getFileSyncStatus(
225
- localHash: string | null,
226
- remoteHash: string | null
227
- ): FileSyncStatus {
228
- // Both exist and are the same
229
- if (localHash && remoteHash && localHash === remoteHash) {
230
- return "unchanged";
231
- }
232
-
233
- // File exists in both but differs
234
- if (localHash && remoteHash && localHash !== remoteHash) {
235
- // With last-write-wins, caller decides direction
236
- // Return "local-modified" to indicate a difference
237
- return "local-modified";
238
- }
239
-
240
- // File only exists locally
241
- if (localHash && !remoteHash) {
242
- return "local-only";
243
- }
244
-
245
- // File only exists on remote
246
- if (!localHash && remoteHash) {
247
- return "remote-only";
248
- }
249
-
250
- return "unchanged";
251
- }
252
-
253
- /**
254
- * Update sync state after a successful sync
255
- */
256
- export function updateSyncStateAfterSync(
257
- state: SyncState,
258
- filePath: string,
259
- hash: string
260
- ): SyncState {
261
- return {
262
- ...state,
263
- lastSync: new Date().toISOString(),
264
- files: {
265
- ...state.files,
266
- [filePath]: {
267
- localHash: hash,
268
- remoteHash: hash,
269
- lastModified: new Date().toISOString(),
270
- },
271
- },
272
- };
273
- }
274
-
275
- /**
276
- * Remove a file from sync state
277
- */
278
- export function removeFileFromSyncState(
279
- state: SyncState,
280
- filePath: string
281
- ): SyncState {
282
- const { [filePath]: _, ...remainingFiles } = state.files;
283
- return {
284
- ...state,
285
- files: remainingFiles,
286
- };
287
- }
288
-
289
- /**
290
- * Build a complete sync state by scanning files
291
- */
292
- export async function buildSyncState(
293
- localDir: string,
294
- remoteDir: string,
295
- centralPath: string,
296
- include: string[],
297
- exclude: string[]
298
- ): Promise<{
299
- state: SyncState;
300
- changes: Array<{
301
- file: string;
302
- status: FileSyncStatus;
303
- localHash: string | null;
304
- remoteHash: string | null;
305
- }>;
306
- }> {
307
- const state = createEmptySyncState(centralPath);
308
- const changes: Array<{
309
- file: string;
310
- status: FileSyncStatus;
311
- localHash: string | null;
312
- remoteHash: string | null;
313
- }> = [];
314
-
315
- // Get all files from both sides
316
- const [localFiles, remoteFiles] = await Promise.all([
317
- listSyncableFiles(localDir, include, exclude),
318
- listSyncableFiles(remoteDir, include, exclude),
319
- ]);
320
-
321
- const allFiles = new Set([...localFiles, ...remoteFiles]);
322
-
323
- for (const file of allFiles) {
324
- const localPath = path.join(localDir, file);
325
- const remotePath = path.join(remoteDir, file);
326
-
327
- const [localInfo, remoteInfo] = await Promise.all([
328
- getFileHashInfo(localPath),
329
- getFileHashInfo(remotePath),
330
- ]);
331
-
332
- const status = getFileSyncStatus(
333
- localInfo.hash ?? null,
334
- remoteInfo.hash ?? null
335
- );
336
-
337
- if (status !== "unchanged") {
338
- changes.push({
339
- file,
340
- status,
341
- localHash: localInfo.hash ?? null,
342
- remoteHash: remoteInfo.hash ?? null,
343
- });
344
- }
345
-
346
- // Update state with current hashes
347
- state.files[file] = {
348
- localHash: localInfo.hash ?? "",
349
- remoteHash: remoteInfo.hash ?? "",
350
- lastModified: localInfo.mtime ?? remoteInfo.mtime ?? new Date().toISOString(),
351
- };
352
- }
353
-
354
- return { state, changes };
355
- }