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
@@ -6,17 +6,30 @@
6
6
  * drop all curated playbooks and reload from source files without
7
7
  * losing extracted or imported playbooks.
8
8
  *
9
+ * Supports recursive directory scanning and source-prefix-based
10
+ * deletion for per-source recreate (multiple sources don't clobber
11
+ * each other).
12
+ *
9
13
  * Inspired by Dash's separation of curated knowledge (file-loaded)
10
14
  * vs learnings (runtime-discovered).
11
15
  */
12
16
 
13
- import { readFile, readdir, stat } from 'node:fs/promises';
14
- import { join, relative } from 'node:path';
17
+ import { readFile, readdir } from 'node:fs/promises';
18
+ import { join, relative, dirname } from 'node:path';
15
19
  import { existsSync } from 'node:fs';
20
+ import { fileURLToPath } from 'node:url';
16
21
  import type { PlaybookProvenance } from '../types/index.js';
17
22
  import { createPlaybook } from '../types/index.js';
18
23
  import type { PlaybookLibrary } from './playbook.js';
19
24
 
25
+ /**
26
+ * Path to the bundled compound-engineering seed pack shipped with cognitive-core.
27
+ * Resolves relative to this file's location in the package.
28
+ */
29
+ const __filename_curated = fileURLToPath(import.meta.url);
30
+ const __dirname_curated = dirname(__filename_curated);
31
+ export const BUNDLED_SEED_PACK_DIR = join(__dirname_curated, '../../playbooks/compound-engineering');
32
+
20
33
  /**
21
34
  * Schema for a curated playbook JSON file
22
35
  */
@@ -55,17 +68,49 @@ export interface CuratedLoadResult {
55
68
  recreated: boolean;
56
69
  }
57
70
 
71
+ /**
72
+ * Options for loadCuratedPlaybooks
73
+ */
74
+ export interface CuratedLoadOptions {
75
+ /** If true, delete existing curated playbooks before loading */
76
+ recreate?: boolean;
77
+ /**
78
+ * Source identifier for provenance tracking.
79
+ * Used as prefix in provenance.sourceFile for per-source recreate.
80
+ * If provided and recreate is true, only playbooks from this source are deleted.
81
+ */
82
+ sourceId?: string;
83
+ }
84
+
85
+ /**
86
+ * Recursively find all JSON files in a directory tree.
87
+ */
88
+ async function findJsonFiles(dir: string): Promise<string[]> {
89
+ const entries = await readdir(dir, { withFileTypes: true });
90
+ const files: string[] = [];
91
+ for (const entry of entries) {
92
+ const fullPath = join(dir, entry.name);
93
+ if (entry.isDirectory()) {
94
+ files.push(...await findJsonFiles(fullPath));
95
+ } else if (entry.name.endsWith('.json')) {
96
+ files.push(fullPath);
97
+ }
98
+ }
99
+ return files;
100
+ }
101
+
58
102
  /**
59
103
  * Load curated playbooks from a directory of JSON files into the library.
104
+ * Supports recursive directory scanning.
60
105
  *
61
106
  * @param curatedDir - Directory containing curated playbook JSON files
62
107
  * @param library - PlaybookLibrary to load into
63
- * @param options.recreate - If true, delete existing curated playbooks before loading
108
+ * @param options - Load options (recreate, sourceId)
64
109
  */
65
110
  export async function loadCuratedPlaybooks(
66
111
  curatedDir: string,
67
112
  library: PlaybookLibrary,
68
- options?: { recreate?: boolean }
113
+ options?: CuratedLoadOptions
69
114
  ): Promise<CuratedLoadResult> {
70
115
  const result: CuratedLoadResult = {
71
116
  loaded: 0,
@@ -78,20 +123,23 @@ export async function loadCuratedPlaybooks(
78
123
  return result;
79
124
  }
80
125
 
81
- // Recreate: drop all curated playbooks first
126
+ // Recreate: drop curated playbooks before loading
82
127
  if (options?.recreate) {
83
- await library.deleteByOrigin('curated');
128
+ if (options.sourceId) {
129
+ // Per-source recreate: only delete playbooks from this source
130
+ await library.deleteByCuratedSource(options.sourceId);
131
+ } else {
132
+ // Global recreate: delete all curated playbooks
133
+ await library.deleteByOrigin('curated');
134
+ }
84
135
  result.recreated = true;
85
136
  }
86
137
 
87
- // Find all JSON files in the directory (non-recursive)
88
- const files = await readdir(curatedDir);
89
- const jsonFiles = files.filter((f) => f.endsWith('.json'));
138
+ // Find all JSON files recursively
139
+ const jsonFiles = await findJsonFiles(curatedDir);
90
140
 
91
- for (const file of jsonFiles) {
92
- const filePath = join(curatedDir, file);
93
- const fileStat = await stat(filePath);
94
- if (!fileStat.isFile()) continue;
141
+ for (const filePath of jsonFiles) {
142
+ const relativeToDir = relative(curatedDir, filePath);
95
143
 
96
144
  try {
97
145
  const content = await readFile(filePath, 'utf-8');
@@ -100,7 +148,7 @@ export async function loadCuratedPlaybooks(
100
148
  // Validate required fields
101
149
  if (!parsed.name || !parsed.applicability || !parsed.guidance) {
102
150
  result.errors.push({
103
- file,
151
+ file: relativeToDir,
104
152
  error: 'Missing required fields: name, applicability, guidance',
105
153
  });
106
154
  continue;
@@ -113,10 +161,15 @@ export async function loadCuratedPlaybooks(
113
161
  continue;
114
162
  }
115
163
 
164
+ // Build sourceFile with optional source prefix
116
165
  const relativePath = relative(process.cwd(), filePath);
166
+ const sourceFile = options?.sourceId
167
+ ? `${options.sourceId}:${relativeToDir}`
168
+ : relativePath;
169
+
117
170
  const provenance: PlaybookProvenance = {
118
171
  origin: 'curated',
119
- sourceFile: relativePath,
172
+ sourceFile,
120
173
  curatedBy: parsed.curatedBy,
121
174
  recordedAt: new Date(),
122
175
  };
@@ -150,7 +203,7 @@ export async function loadCuratedPlaybooks(
150
203
  result.loaded++;
151
204
  } catch (error) {
152
205
  result.errors.push({
153
- file,
206
+ file: relativeToDir,
154
207
  error: error instanceof Error ? error.message : String(error),
155
208
  });
156
209
  }
@@ -99,10 +99,26 @@ export type { SqlitePersistenceConfig } from '../persistence/index.js';
99
99
  // Curated playbook loading
100
100
  export {
101
101
  loadCuratedPlaybooks,
102
+ BUNDLED_SEED_PACK_DIR,
102
103
  type CuratedPlaybookFile,
103
104
  type CuratedLoadResult,
105
+ type CuratedLoadOptions,
104
106
  } from './curated-loader.js';
105
107
 
108
+ // Source resolver (git + local path resolution for curated sources)
109
+ export {
110
+ resolvePlaybookSource,
111
+ isGitSource,
112
+ parseGitSource,
113
+ discoverPlaybookDir,
114
+ sourceStateKey,
115
+ type ParsedGitSource,
116
+ type PlaybookManifest,
117
+ type SourceState,
118
+ type ResolveResult,
119
+ type ResolveOptions,
120
+ } from './source-resolver.js';
121
+
106
122
  // Skill export (compile playbooks → Open Agent Skills format)
107
123
  export {
108
124
  compilePlaybookToSkill,
@@ -616,6 +616,25 @@ export class PlaybookLibrary {
616
616
  return toDelete.length;
617
617
  }
618
618
 
619
+ /**
620
+ * Delete curated playbooks whose provenance.sourceFile starts with the given prefix.
621
+ * Used by the source resolver to recreate playbooks from a specific source
622
+ * without affecting other curated sources.
623
+ */
624
+ async deleteByCuratedSource(sourcePrefix: string): Promise<number> {
625
+ await this.init();
626
+ const toDelete = this.getAllSync().filter(
627
+ (p) =>
628
+ p.provenance?.origin === 'curated' &&
629
+ p.provenance.sourceFile?.startsWith(sourcePrefix),
630
+ );
631
+ for (const playbook of toDelete) {
632
+ this.persistence.deletePlaybook(playbook.id);
633
+ this._index.remove(playbook.id);
634
+ }
635
+ return toDelete.length;
636
+ }
637
+
619
638
  /**
620
639
  * Get provenance summary across all playbooks
621
640
  */
@@ -0,0 +1,422 @@
1
+ /**
2
+ * Source Resolver — Normalizes playbook sources (local paths, git URLs, shorthands)
3
+ * into local directory paths for the curated loader.
4
+ *
5
+ * Supports:
6
+ * - Local filesystem paths (pass-through)
7
+ * - Git URLs: "git:https://github.com/org/repo" or "git:https://github.com/org/repo#ref"
8
+ * - GitHub shorthand: "github:org/repo" or "github:org/repo#ref"
9
+ *
10
+ * Cloned repos are cached in a configurable directory (default: .atlas/curated-cache/).
11
+ * Cache freshness is controlled by maxAgeMs. Stale caches are refreshed on next resolve.
12
+ */
13
+
14
+ import { execFile as execFileCb } from 'node:child_process';
15
+ import { existsSync, statSync, rmSync } from 'node:fs';
16
+ import { join } from 'node:path';
17
+ import { mkdir, readFile, readdir } from 'node:fs/promises';
18
+ import { promisify } from 'node:util';
19
+
20
+ const execFile = promisify(execFileCb);
21
+
22
+ // ============================================================================
23
+ // Types
24
+ // ============================================================================
25
+
26
+ /**
27
+ * Parsed git source components
28
+ */
29
+ export interface ParsedGitSource {
30
+ url: string;
31
+ ref?: string;
32
+ cacheKey: string;
33
+ }
34
+
35
+ /**
36
+ * Manifest file (cognitive-core.json) at repo root
37
+ */
38
+ export interface PlaybookManifest {
39
+ /** Relative path to playbook directory within the repo */
40
+ playbooks: string;
41
+ /** Optional version label */
42
+ version?: string;
43
+ /** Optional display name */
44
+ name?: string;
45
+ /** Optional description */
46
+ description?: string;
47
+ }
48
+
49
+ /**
50
+ * State persisted per resolved source (stored in system_state)
51
+ */
52
+ export interface SourceState {
53
+ /** Original config source string */
54
+ source: string;
55
+ /** Resolved git URL (empty for local paths) */
56
+ url: string;
57
+ /** Requested ref (branch/tag/commit) */
58
+ ref: string;
59
+ /** Actual commit SHA loaded */
60
+ commitSha: string;
61
+ /** Local cache path */
62
+ cachePath: string;
63
+ /** Discovered playbook directory within cache */
64
+ playbookDir: string;
65
+ /** ISO timestamp of last successful load */
66
+ loadedAt: string;
67
+ /** Number of playbooks loaded from this source */
68
+ playbookCount: number;
69
+ }
70
+
71
+ /**
72
+ * Result of resolving a source
73
+ */
74
+ export interface ResolveResult {
75
+ /** Local directory path containing playbook JSON files */
76
+ playbookDir: string;
77
+ /** Whether this is a git source */
78
+ isGit: boolean;
79
+ /** Commit SHA (only for git sources) */
80
+ commitSha?: string;
81
+ /** Whether the source was freshly cloned/updated */
82
+ updated: boolean;
83
+ /** Source identifier for provenance tracking */
84
+ sourceId: string;
85
+ }
86
+
87
+ /**
88
+ * Options for source resolution
89
+ */
90
+ export interface ResolveOptions {
91
+ /** Cache directory (default: .atlas/curated-cache) */
92
+ cacheDir: string;
93
+ /** Maximum cache age in milliseconds before refreshing (default: 24h) */
94
+ maxAgeMs: number;
95
+ /** Force update regardless of cache age */
96
+ forceUpdate?: boolean;
97
+ /** Callback for loading/saving source state */
98
+ getSourceState?: (source: string) => SourceState | undefined;
99
+ setSourceState?: (source: string, state: SourceState) => void;
100
+ }
101
+
102
+ // ============================================================================
103
+ // Public API
104
+ // ============================================================================
105
+
106
+ /**
107
+ * Check if a source string is a git source (not a local path).
108
+ */
109
+ export function isGitSource(source: string): boolean {
110
+ return (
111
+ source.startsWith('git:') ||
112
+ source.startsWith('github:') ||
113
+ source.startsWith('git@') ||
114
+ source.startsWith('git+')
115
+ );
116
+ }
117
+
118
+ /**
119
+ * Parse a git source string into URL and optional ref components.
120
+ *
121
+ * Supported formats:
122
+ * - "git:https://github.com/org/repo"
123
+ * - "git:https://github.com/org/repo#v1.0.0"
124
+ * - "github:org/repo"
125
+ * - "github:org/repo#branch"
126
+ */
127
+ export function parseGitSource(source: string): ParsedGitSource {
128
+ let raw = source;
129
+
130
+ // Strip prefix
131
+ if (raw.startsWith('git:')) {
132
+ raw = raw.slice(4);
133
+ } else if (raw.startsWith('git+')) {
134
+ raw = raw.slice(4);
135
+ } else if (raw.startsWith('github:')) {
136
+ const rest = raw.slice(7); // "org/repo" or "org/repo#ref"
137
+ const [path, ref] = rest.split('#', 2);
138
+ const url = `https://github.com/${path}.git`;
139
+ const cacheKey = `github.com/${path}`;
140
+ return { url, ref, cacheKey };
141
+ }
142
+
143
+ // Parse ref from fragment
144
+ const hashIdx = raw.indexOf('#');
145
+ let url: string;
146
+ let ref: string | undefined;
147
+
148
+ if (hashIdx !== -1) {
149
+ url = raw.slice(0, hashIdx);
150
+ ref = raw.slice(hashIdx + 1);
151
+ } else {
152
+ url = raw;
153
+ }
154
+
155
+ // Ensure .git suffix for HTTPS URLs
156
+ if (url.startsWith('https://') && !url.endsWith('.git')) {
157
+ url += '.git';
158
+ }
159
+
160
+ // Build cache key from URL (strip protocol + .git suffix)
161
+ const cacheKey = url
162
+ .replace(/^https?:\/\//, '')
163
+ .replace(/\.git$/, '');
164
+
165
+ return { url, ref, cacheKey };
166
+ }
167
+
168
+ /**
169
+ * Resolve a playbook source to a local directory path.
170
+ *
171
+ * For local paths, returns the path as-is (after verifying it exists).
172
+ * For git sources, clones/updates to a cache directory and discovers
173
+ * the playbook directory within the repo.
174
+ */
175
+ export async function resolvePlaybookSource(
176
+ source: string,
177
+ options: ResolveOptions,
178
+ ): Promise<ResolveResult | null> {
179
+ // Local path — pass through
180
+ if (!isGitSource(source)) {
181
+ if (!existsSync(source)) {
182
+ console.warn(`[source-resolver] Local path does not exist: ${source}`);
183
+ return null;
184
+ }
185
+ return {
186
+ playbookDir: source,
187
+ isGit: false,
188
+ updated: false,
189
+ sourceId: source,
190
+ };
191
+ }
192
+
193
+ // Git source — parse, clone/update, discover
194
+ const parsed = parseGitSource(source);
195
+ const cachePath = join(options.cacheDir, parsed.cacheKey);
196
+
197
+ try {
198
+ // Ensure cache parent dir exists
199
+ await mkdir(cachePath, { recursive: true });
200
+
201
+ const isCloned = existsSync(join(cachePath, '.git'));
202
+
203
+ if (!isCloned) {
204
+ // First-time clone
205
+ await gitClone(parsed.url, parsed.ref, cachePath);
206
+ } else if (shouldUpdate(source, options)) {
207
+ // Update existing cache
208
+ await gitUpdate(parsed.ref, cachePath);
209
+ }
210
+
211
+ // Get current commit SHA
212
+ const commitSha = await gitRevParse(cachePath);
213
+
214
+ // Check if we already loaded this exact SHA
215
+ const prevState = options.getSourceState?.(source);
216
+ if (prevState && prevState.commitSha === commitSha && !options.forceUpdate) {
217
+ return {
218
+ playbookDir: prevState.playbookDir,
219
+ isGit: true,
220
+ commitSha,
221
+ updated: false,
222
+ sourceId: source,
223
+ };
224
+ }
225
+
226
+ // Discover playbook directory
227
+ const playbookDir = await discoverPlaybookDir(cachePath);
228
+ if (!playbookDir) {
229
+ console.warn(`[source-resolver] No playbook directory found in ${source}`);
230
+ return null;
231
+ }
232
+
233
+ // Persist source state
234
+ const state: SourceState = {
235
+ source,
236
+ url: parsed.url,
237
+ ref: parsed.ref ?? '',
238
+ commitSha,
239
+ cachePath,
240
+ playbookDir,
241
+ loadedAt: new Date().toISOString(),
242
+ playbookCount: 0, // Updated by caller after loading
243
+ };
244
+ options.setSourceState?.(source, state);
245
+
246
+ return {
247
+ playbookDir,
248
+ isGit: true,
249
+ commitSha,
250
+ updated: true,
251
+ sourceId: source,
252
+ };
253
+ } catch (error) {
254
+ // If we have a cached version, use it despite the error
255
+ if (existsSync(join(cachePath, '.git'))) {
256
+ console.warn(
257
+ `[source-resolver] Failed to update ${source}, using cached version:`,
258
+ error instanceof Error ? error.message : String(error),
259
+ );
260
+ const prevState = options.getSourceState?.(source);
261
+ if (prevState) {
262
+ return {
263
+ playbookDir: prevState.playbookDir,
264
+ isGit: true,
265
+ commitSha: prevState.commitSha,
266
+ updated: false,
267
+ sourceId: source,
268
+ };
269
+ }
270
+ // Try to discover even without state
271
+ const playbookDir = await discoverPlaybookDir(cachePath);
272
+ if (playbookDir) {
273
+ return {
274
+ playbookDir,
275
+ isGit: true,
276
+ updated: false,
277
+ sourceId: source,
278
+ };
279
+ }
280
+ }
281
+
282
+ console.warn(
283
+ `[source-resolver] Failed to resolve ${source}, skipping:`,
284
+ error instanceof Error ? error.message : String(error),
285
+ );
286
+ return null;
287
+ }
288
+ }
289
+
290
+ // ============================================================================
291
+ // Git operations
292
+ // ============================================================================
293
+
294
+ async function gitClone(url: string, ref: string | undefined, dest: string): Promise<void> {
295
+ // Remove the directory first since mkdir already created it
296
+ rmSync(dest, { recursive: true, force: true });
297
+
298
+ const args = ['clone', '--depth', '1', '--single-branch'];
299
+ if (ref) {
300
+ args.push('--branch', ref);
301
+ }
302
+ args.push(url, dest);
303
+
304
+ await execFile('git', args, { timeout: 60_000 });
305
+ }
306
+
307
+ async function gitUpdate(ref: string | undefined, cachePath: string): Promise<void> {
308
+ const fetchArgs = ['fetch', 'origin'];
309
+ if (ref) {
310
+ fetchArgs.push(ref);
311
+ }
312
+ await execFile('git', fetchArgs, { cwd: cachePath, timeout: 30_000 });
313
+
314
+ // Always use FETCH_HEAD — works for branches, tags, and commits.
315
+ // Using origin/${ref} would break for tags (refs/tags/*, not refs/remotes/origin/*).
316
+ await execFile('git', ['reset', '--hard', 'FETCH_HEAD'], {
317
+ cwd: cachePath,
318
+ timeout: 10_000,
319
+ });
320
+ }
321
+
322
+ async function gitRevParse(cachePath: string): Promise<string> {
323
+ const { stdout } = await execFile('git', ['rev-parse', 'HEAD'], {
324
+ cwd: cachePath,
325
+ timeout: 5_000,
326
+ });
327
+ return stdout.trim();
328
+ }
329
+
330
+ // ============================================================================
331
+ // Playbook directory discovery
332
+ // ============================================================================
333
+
334
+ /**
335
+ * Discover the playbook directory within a cloned repo.
336
+ *
337
+ * Search order:
338
+ * 1. Manifest file (cognitive-core.json) at repo root
339
+ * 2. Convention: playbooks/ directory
340
+ * 3. Convention: curated-playbooks/ directory
341
+ * 4. Root directory if it contains .json files matching schema
342
+ */
343
+ export async function discoverPlaybookDir(repoRoot: string): Promise<string | null> {
344
+ // 1. Check for manifest
345
+ const manifestPath = join(repoRoot, 'cognitive-core.json');
346
+ if (existsSync(manifestPath)) {
347
+ try {
348
+ const content = await readFile(manifestPath, 'utf-8');
349
+ const manifest = JSON.parse(content) as PlaybookManifest;
350
+ if (manifest.playbooks) {
351
+ const dir = join(repoRoot, manifest.playbooks);
352
+ if (existsSync(dir)) {
353
+ return dir;
354
+ }
355
+ }
356
+ } catch {
357
+ // Invalid manifest, fall through to convention
358
+ }
359
+ }
360
+
361
+ // 2. Convention: playbooks/
362
+ const playbooksDir = join(repoRoot, 'playbooks');
363
+ if (existsSync(playbooksDir) && statSync(playbooksDir).isDirectory()) {
364
+ return playbooksDir;
365
+ }
366
+
367
+ // 3. Convention: curated-playbooks/
368
+ const curatedDir = join(repoRoot, 'curated-playbooks');
369
+ if (existsSync(curatedDir) && statSync(curatedDir).isDirectory()) {
370
+ return curatedDir;
371
+ }
372
+
373
+ // 4. Check if root has JSON files that look like playbooks
374
+ if (await hasPlaybookJsonFiles(repoRoot)) {
375
+ return repoRoot;
376
+ }
377
+
378
+ return null;
379
+ }
380
+
381
+ /**
382
+ * Check if a directory contains at least one JSON file that looks like a playbook.
383
+ */
384
+ async function hasPlaybookJsonFiles(dir: string): Promise<boolean> {
385
+ try {
386
+ const files = await readdir(dir);
387
+ const jsonFiles = files.filter(f => f.endsWith('.json'));
388
+ if (jsonFiles.length === 0) return false;
389
+
390
+ // Check first JSON file for required playbook fields
391
+ const content = await readFile(join(dir, jsonFiles[0]), 'utf-8');
392
+ const parsed = JSON.parse(content);
393
+ return !!(parsed.name && parsed.applicability && parsed.guidance);
394
+ } catch {
395
+ return false;
396
+ }
397
+ }
398
+
399
+ // ============================================================================
400
+ // Cache management
401
+ // ============================================================================
402
+
403
+ /**
404
+ * Determine whether a cached source should be updated.
405
+ */
406
+ function shouldUpdate(source: string, options: ResolveOptions): boolean {
407
+ if (options.forceUpdate) return true;
408
+
409
+ const state = options.getSourceState?.(source);
410
+ if (!state) return true; // No previous state, always update
411
+
412
+ const loadedAt = new Date(state.loadedAt).getTime();
413
+ const age = Date.now() - loadedAt;
414
+ return age > options.maxAgeMs;
415
+ }
416
+
417
+ /**
418
+ * Generate the system_state key for a source.
419
+ */
420
+ export function sourceStateKey(source: string): string {
421
+ return `curated-source:${source}`;
422
+ }
@@ -513,6 +513,45 @@ export const SkillTreeConfigSchema = z.object({
513
513
  dbPath: z.string().default('skills.db'),
514
514
  });
515
515
 
516
+ /**
517
+ * Curated playbook cache configuration (for git sources)
518
+ */
519
+ export const CuratedCacheConfigSchema = z.object({
520
+ /** Cache directory for cloned repos (relative to storage.baseDir, default: curated-cache) */
521
+ dir: z.string().default('curated-cache'),
522
+ /** Maximum cache age in milliseconds before refreshing (default: 24h) */
523
+ maxAgeMs: z.number().default(24 * 60 * 60 * 1000),
524
+ });
525
+
526
+ export type CuratedCacheConfig = z.infer<typeof CuratedCacheConfigSchema>;
527
+
528
+ /**
529
+ * Curated playbook configuration
530
+ */
531
+ export const CuratedPlaybooksConfigSchema = z.object({
532
+ /** Load the bundled compound-engineering seed pack on init */
533
+ loadBundledSeedPack: z.boolean().default(false),
534
+ /** Additional directories to load curated playbooks from (backward compat) */
535
+ additionalDirs: z.array(z.string()).default([]),
536
+ /**
537
+ * Playbook sources — local paths or git URIs.
538
+ *
539
+ * Supported formats:
540
+ * - Local path: "/path/to/playbooks"
541
+ * - Git URL: "git:https://github.com/org/repo" or "git:https://github.com/org/repo#v1.0.0"
542
+ * - GitHub shorthand: "github:org/repo" or "github:org/repo#branch"
543
+ *
544
+ * Git sources are cloned to a local cache and refreshed based on cache.maxAgeMs.
545
+ */
546
+ sources: z.array(z.string()).default([]),
547
+ /** Cache configuration for git-based sources */
548
+ cache: CuratedCacheConfigSchema.default({}),
549
+ /** Re-create curated playbooks on each init (useful when updating seed files) */
550
+ recreateOnInit: z.boolean().default(false),
551
+ });
552
+
553
+ export type CuratedPlaybooksConfig = z.infer<typeof CuratedPlaybooksConfigSchema>;
554
+
516
555
  export type SkillTreeConfig = z.infer<typeof SkillTreeConfigSchema>;
517
556
 
518
557
  /**
@@ -570,6 +609,8 @@ export const AtlasConfigSchema = z.object({
570
609
  knowledgeBank: KnowledgeBankConfigSchema.default({}),
571
610
  /** Skill-tree storage configuration */
572
611
  skillTree: SkillTreeConfigSchema.default({}),
612
+ /** Curated playbook seeding configuration */
613
+ curatedPlaybooks: CuratedPlaybooksConfigSchema.default({}),
573
614
  /** Session bank configuration (Entire CLI integration) */
574
615
  sessionBank: SessionBankConfigSchema.default({}),
575
616
  /** Feature toggles for ruvector-inspired subsystems */
@@ -609,6 +650,11 @@ export function mergeConfig(
609
650
  teamLearning: { ...base.teamLearning, ...overrides.teamLearning },
610
651
  knowledgeBank: { ...base.knowledgeBank, ...overrides.knowledgeBank },
611
652
  skillTree: { ...base.skillTree, ...overrides.skillTree },
653
+ curatedPlaybooks: {
654
+ ...base.curatedPlaybooks,
655
+ ...overrides.curatedPlaybooks,
656
+ cache: { ...base.curatedPlaybooks.cache, ...overrides.curatedPlaybooks?.cache },
657
+ },
612
658
  sessionBank: { ...base.sessionBank, ...overrides.sessionBank },
613
659
  features: { ...base.features, ...overrides.features },
614
660
  });