akm-cli 0.9.0-rc.0 → 0.9.0-rc.13

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 (598) hide show
  1. package/CHANGELOG.md +1283 -22
  2. package/README.md +62 -37
  3. package/SECURITY.md +46 -31
  4. package/dist/akm +162 -38
  5. package/dist/akm-migrate +44 -0
  6. package/dist/assets/backends/schtasks-template.xml +2 -1
  7. package/dist/assets/hints/cli-hints-full.md +268 -118
  8. package/dist/assets/hints/cli-hints-short.md +87 -24
  9. package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
  10. package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
  11. package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
  12. package/dist/assets/improve-strategies/frequent.json +15 -0
  13. package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
  14. package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
  15. package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
  16. package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
  17. package/dist/assets/improve-strategies/reflect-distill.json +30 -0
  18. package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
  19. package/dist/assets/prompts/consolidate-system.md +5 -5
  20. package/dist/assets/prompts/extract-session.md +2 -6
  21. package/dist/assets/prompts/memory-infer-user.md +2 -3
  22. package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
  23. package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
  24. package/dist/assets/prompts/reflect-output-repair.md +3 -0
  25. package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
  26. package/dist/assets/stash-skeleton/README.md +38 -10
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
  39. package/dist/assets/tasks/core/extract.yml +3 -2
  40. package/dist/assets/tasks/core/improve.yml +2 -1
  41. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  42. package/dist/assets/tasks/core/sync.yml +1 -0
  43. package/dist/assets/tasks/core/version-check.yml +2 -1
  44. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  45. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  46. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  47. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  48. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  49. package/dist/assets/templates/html/health.html +5 -4
  50. package/dist/assets/workflows/workflow-template.md +31 -15
  51. package/dist/cli/invocation.js +279 -0
  52. package/dist/cli/parse-args.js +5 -90
  53. package/dist/cli/retired-commands.js +78 -0
  54. package/dist/cli/shared.js +158 -48
  55. package/dist/cli-node.mjs +2 -1
  56. package/dist/cli.js +747 -293
  57. package/dist/commands/agent/agent-dispatch.js +19 -18
  58. package/dist/commands/agent/agent-support.js +0 -24
  59. package/dist/commands/agent/contribute-cli.js +43 -97
  60. package/dist/commands/completions.js +80 -23
  61. package/dist/commands/config-cli.js +44 -281
  62. package/dist/commands/env/env-binding.js +99 -0
  63. package/dist/commands/env/env-cli.js +84 -224
  64. package/dist/commands/env/env.js +12 -163
  65. package/dist/commands/env/marker-path.js +6 -0
  66. package/dist/commands/env/secret-cli.js +45 -61
  67. package/dist/commands/env/secret.js +32 -62
  68. package/dist/commands/feedback-cli.js +179 -85
  69. package/dist/commands/health/accept-rate.js +58 -0
  70. package/dist/commands/health/advisories.js +7 -8
  71. package/dist/commands/health/checks.js +279 -94
  72. package/dist/commands/health/html-report.js +197 -578
  73. package/dist/commands/health/improve-metrics.js +277 -246
  74. package/dist/commands/health/llm-usage.js +19 -19
  75. package/dist/commands/health/md-report.js +16 -7
  76. package/dist/commands/health/metrics.js +67 -32
  77. package/dist/commands/health/renderers.js +47 -0
  78. package/dist/commands/health/report-view-model.js +508 -0
  79. package/dist/commands/health/stash-exposure.js +1 -1
  80. package/dist/commands/health/surfaces.js +16 -56
  81. package/dist/commands/health/task-runs.js +3 -67
  82. package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
  83. package/dist/commands/health/types-improve.js +29 -0
  84. package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
  85. package/dist/commands/health/types-result.js +7 -0
  86. package/dist/commands/health/types-runs.js +4 -0
  87. package/dist/commands/health/types-session-log.js +4 -0
  88. package/dist/commands/health/types-windows.js +4 -0
  89. package/dist/commands/health/types.js +26 -21
  90. package/dist/commands/health/windows.js +2 -3
  91. package/dist/commands/health.js +296 -167
  92. package/dist/commands/improve/anti-collapse.js +5 -5
  93. package/dist/commands/improve/autonomy-gate.js +68 -0
  94. package/dist/commands/improve/collapse-detector.js +65 -52
  95. package/dist/commands/improve/consolidate/chunking.js +9 -7
  96. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  97. package/dist/commands/improve/consolidate/merge.js +4 -0
  98. package/dist/commands/improve/consolidate.js +454 -1354
  99. package/dist/commands/improve/content-hash.js +39 -0
  100. package/dist/commands/improve/distill/content-repair.js +4 -10
  101. package/dist/commands/improve/distill/promote-memory.js +89 -64
  102. package/dist/commands/improve/distill/quality-gate.js +118 -42
  103. package/dist/commands/improve/distill-guards.js +1 -1
  104. package/dist/commands/improve/distill-promotion-policy.js +33 -888
  105. package/dist/commands/improve/distill.js +607 -363
  106. package/dist/commands/improve/eligibility.js +165 -79
  107. package/dist/commands/improve/extract-cli.js +35 -126
  108. package/dist/commands/improve/extract-prompt.js +6 -35
  109. package/dist/commands/improve/extract.js +640 -391
  110. package/dist/commands/improve/feedback-valence.js +2 -12
  111. package/dist/commands/improve/improve-cli.js +134 -135
  112. package/dist/commands/improve/improve-result-file.js +30 -50
  113. package/dist/commands/improve/improve-run-types.js +4 -0
  114. package/dist/commands/improve/improve-strategies.js +135 -0
  115. package/dist/commands/improve/improve.js +904 -701
  116. package/dist/commands/improve/locks.js +64 -111
  117. package/dist/commands/improve/loop-stages.js +1110 -923
  118. package/dist/commands/improve/memory/derived-ref.js +124 -0
  119. package/dist/commands/improve/memory/memory-belief.js +79 -7
  120. package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
  121. package/dist/commands/improve/memory/memory-improve.js +25 -37
  122. package/dist/commands/improve/outcome-loop.js +25 -88
  123. package/dist/commands/improve/preparation.js +1034 -813
  124. package/dist/commands/improve/proactive-maintenance.js +34 -9
  125. package/dist/commands/improve/proposal-envelope.js +31 -0
  126. package/dist/commands/improve/reflect.js +983 -794
  127. package/dist/commands/improve/run-context.js +119 -0
  128. package/dist/commands/improve/salience.js +24 -127
  129. package/dist/commands/improve/session-asset.js +7 -3
  130. package/dist/commands/improve/shared.js +14 -34
  131. package/dist/commands/improve/source-identity.js +28 -0
  132. package/dist/commands/improve/triage.js +20 -17
  133. package/dist/commands/lint/base-linter.js +340 -313
  134. package/dist/commands/lint/env-key-rules.js +31 -47
  135. package/dist/commands/lint/index.js +185 -30
  136. package/dist/commands/{events.js → log.js} +28 -38
  137. package/dist/commands/migrate-cli.js +54 -0
  138. package/dist/commands/migration-tool.js +55 -0
  139. package/dist/commands/observability-cli.js +70 -208
  140. package/dist/commands/proposal/diff-format.js +50 -0
  141. package/dist/commands/proposal/drain-policies.js +0 -6
  142. package/dist/commands/proposal/drain.js +91 -40
  143. package/dist/commands/proposal/proposal-cli.js +134 -132
  144. package/dist/commands/proposal/proposal-types.js +56 -0
  145. package/dist/commands/proposal/proposal.js +83 -65
  146. package/dist/commands/proposal/propose-cli.js +88 -0
  147. package/dist/commands/proposal/propose.js +105 -88
  148. package/dist/commands/proposal/repository.js +1303 -278
  149. package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
  150. package/dist/commands/proposal/validators/proposal-validators.js +61 -12
  151. package/dist/commands/proposal/validators/proposals.js +6 -8
  152. package/dist/commands/read/curate.js +78 -73
  153. package/dist/commands/read/knowledge.js +510 -13
  154. package/dist/commands/read/registry-search.js +2 -2
  155. package/dist/commands/read/remember-cli.js +84 -15
  156. package/dist/commands/read/search-cli.js +203 -96
  157. package/dist/commands/read/search.js +126 -94
  158. package/dist/commands/read/show.js +226 -250
  159. package/dist/commands/registry-cli.js +34 -60
  160. package/dist/commands/remember.js +18 -57
  161. package/dist/commands/sources/add-cli.js +104 -49
  162. package/dist/commands/sources/bundle-cli.js +166 -0
  163. package/dist/commands/sources/bundle-config-ops.js +63 -0
  164. package/dist/commands/sources/info.js +27 -15
  165. package/dist/commands/sources/init.js +30 -40
  166. package/dist/commands/sources/installed-stashes.js +469 -172
  167. package/dist/commands/sources/migration-help.js +7 -4
  168. package/dist/commands/sources/schema-repair.js +10 -9
  169. package/dist/commands/sources/self-update.js +182 -121
  170. package/dist/commands/sources/source-add.js +169 -178
  171. package/dist/commands/sources/source-clone.js +144 -41
  172. package/dist/commands/sources/source-manage.js +94 -59
  173. package/dist/commands/sources/sources-cli.js +64 -205
  174. package/dist/commands/sources/stash-cli.js +91 -54
  175. package/dist/commands/sources/stash-skeleton.js +1 -1
  176. package/dist/commands/tasks/tasks-cli.js +106 -104
  177. package/dist/commands/tasks/tasks.js +445 -262
  178. package/dist/commands/workflow-cli.js +232 -121
  179. package/dist/core/action-contributors.js +1 -1
  180. package/dist/core/activation-policy.js +49 -0
  181. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  182. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  183. package/dist/core/adapter/adapters/akm-lint.js +392 -0
  184. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  185. package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
  186. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  187. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  188. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  189. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  190. package/dist/core/adapter/adapters/index.js +80 -0
  191. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  192. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  193. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  194. package/dist/core/adapter/adapters/shared.js +286 -0
  195. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  196. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  197. package/dist/core/adapter/bundle-adapter.js +4 -0
  198. package/dist/core/adapter/detect-adapter.js +17 -0
  199. package/dist/core/adapter/recognize-match.js +44 -0
  200. package/dist/core/adapter/registry.js +56 -0
  201. package/dist/core/adapter/types.js +4 -0
  202. package/dist/core/asset/akm-markdown.js +30 -0
  203. package/dist/core/asset/asset-placement.js +243 -0
  204. package/dist/core/asset/asset-ref.js +110 -79
  205. package/dist/core/asset/asset-serialize.js +20 -0
  206. package/dist/core/asset/frontmatter.js +28 -12
  207. package/dist/core/asset/markdown.js +40 -51
  208. package/dist/core/asset/resolve-ref.js +274 -0
  209. package/dist/core/asset/stash-meta.js +2 -2
  210. package/dist/core/bundle-id.js +51 -0
  211. package/dist/core/common.js +281 -86
  212. package/dist/core/config/config-io.js +42 -128
  213. package/dist/core/config/config-schema.js +233 -834
  214. package/dist/core/config/config-sources.js +162 -39
  215. package/dist/core/config/config-types.js +16 -11
  216. package/dist/core/config/config-version.js +29 -0
  217. package/dist/core/config/config-walker.js +126 -37
  218. package/dist/core/config/config.js +154 -331
  219. package/dist/core/config/deep-merge.js +41 -0
  220. package/dist/core/config/engine-semantics.js +28 -0
  221. package/dist/core/config/experimental.js +21 -0
  222. package/dist/core/config/schema/embedding.js +38 -0
  223. package/dist/core/config/schema/engines.js +116 -0
  224. package/dist/core/config/schema/experimental.js +47 -0
  225. package/dist/core/config/schema/feedback.js +31 -0
  226. package/dist/core/config/schema/improve-processes.js +389 -0
  227. package/dist/core/config/schema/improve.js +94 -0
  228. package/dist/core/config/schema/index-config.js +176 -0
  229. package/dist/core/config/schema/output.js +18 -0
  230. package/dist/core/config/schema/primitives.js +94 -0
  231. package/dist/core/config/schema/search.js +30 -0
  232. package/dist/core/config/schema/setup.js +18 -0
  233. package/dist/core/config/schema/sources-bundles.js +169 -0
  234. package/dist/core/config/schema/workflow.js +29 -0
  235. package/dist/core/env-secret-ref.js +155 -20
  236. package/dist/core/errors.js +17 -15
  237. package/dist/core/events-types.js +4 -0
  238. package/dist/core/events.js +46 -128
  239. package/dist/core/extra-params.js +62 -0
  240. package/dist/core/file-change.js +17 -0
  241. package/dist/core/file-lock.js +202 -57
  242. package/dist/core/fs-txn.js +392 -0
  243. package/dist/core/git-message.js +59 -0
  244. package/dist/core/improve-result.js +167 -0
  245. package/dist/core/json-schema.js +142 -0
  246. package/dist/core/lesson-lint.js +1 -17
  247. package/dist/core/logs-db.js +1 -1
  248. package/dist/core/maintenance-barrier.js +135 -0
  249. package/dist/core/migration-operation.js +44 -0
  250. package/dist/core/mutation-target.js +78 -0
  251. package/dist/core/paths.js +22 -25
  252. package/dist/core/platform.js +10 -0
  253. package/dist/core/recognition-util.js +128 -0
  254. package/dist/core/redaction.js +392 -0
  255. package/dist/core/standards/resolve-standards-context.js +36 -65
  256. package/dist/core/standards/resolve-stash-standards.js +2 -2
  257. package/dist/core/standards/resolve-type-conventions.js +5 -5
  258. package/dist/core/state/migrations.js +242 -11
  259. package/dist/core/state-db.js +98 -10
  260. package/dist/core/structured.js +1 -1
  261. package/dist/core/subprocess.js +303 -0
  262. package/dist/core/text-truncation.js +9 -5
  263. package/dist/core/time.js +20 -0
  264. package/dist/core/type-presentation.js +130 -0
  265. package/dist/core/warn.js +0 -3
  266. package/dist/core/write-source.js +834 -118
  267. package/dist/indexer/bundle-identity-guard.js +92 -0
  268. package/dist/indexer/db/graph-db.js +1 -25
  269. package/dist/indexer/db/llm-cache.js +1 -1
  270. package/dist/indexer/ensure-index.js +30 -9
  271. package/dist/indexer/graph/graph-boost.js +9 -30
  272. package/dist/indexer/graph/graph-extraction.js +41 -27
  273. package/dist/indexer/graph/graph-types.js +4 -0
  274. package/dist/indexer/index-writer-lock.js +93 -49
  275. package/dist/indexer/index-written-assets.js +100 -53
  276. package/dist/indexer/indexer.js +746 -329
  277. package/dist/indexer/init.js +18 -25
  278. package/dist/indexer/installations.js +142 -0
  279. package/dist/indexer/passes/dir-staleness.js +18 -10
  280. package/dist/indexer/passes/memory-inference.js +25 -15
  281. package/dist/indexer/passes/metadata.js +412 -243
  282. package/dist/indexer/scan/doc-to-entry.js +160 -0
  283. package/dist/indexer/scan/drain-dir.js +134 -0
  284. package/dist/indexer/search/db-search.js +292 -108
  285. package/dist/indexer/search/fts-query.js +64 -0
  286. package/dist/indexer/search/ranking-contributors.js +145 -25
  287. package/dist/indexer/search/ranking-types.js +4 -0
  288. package/dist/indexer/search/ranking.js +28 -71
  289. package/dist/indexer/search/search-attribution.js +67 -0
  290. package/dist/indexer/search/search-fields.js +18 -3
  291. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  292. package/dist/indexer/search/search-source.js +157 -111
  293. package/dist/indexer/search/semantic-status.js +4 -1
  294. package/dist/indexer/usage/usage-events.js +10 -30
  295. package/dist/indexer/walk/file-context.js +3 -45
  296. package/dist/indexer/walk/matchers.js +42 -34
  297. package/dist/indexer/walk/path-resolver.js +11 -5
  298. package/dist/indexer/walk/walker.js +42 -14
  299. package/dist/integrations/agent/builder-shared.js +7 -0
  300. package/dist/integrations/agent/builders.js +5 -56
  301. package/dist/integrations/agent/config.js +3 -143
  302. package/dist/integrations/agent/detect.js +17 -2
  303. package/dist/integrations/agent/engine-resolution.js +231 -0
  304. package/dist/integrations/agent/index.js +1 -2
  305. package/dist/integrations/agent/model-aliases.js +16 -2
  306. package/dist/integrations/agent/profiles.js +36 -62
  307. package/dist/integrations/agent/prompts.js +46 -18
  308. package/dist/integrations/agent/runner-dispatch.js +93 -4
  309. package/dist/integrations/agent/runner.js +76 -208
  310. package/dist/integrations/agent/spawn.js +88 -196
  311. package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
  312. package/dist/integrations/harnesses/aider/index.js +48 -0
  313. package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
  314. package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
  315. package/dist/integrations/harnesses/amazonq/index.js +45 -0
  316. package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
  317. package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
  318. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  319. package/dist/integrations/harnesses/claude/index.js +24 -35
  320. package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
  321. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  322. package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
  323. package/dist/integrations/harnesses/codex/index.js +52 -0
  324. package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
  325. package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
  326. package/dist/integrations/harnesses/copilot/index.js +48 -0
  327. package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
  328. package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
  329. package/dist/integrations/harnesses/gemini/index.js +48 -0
  330. package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
  331. package/dist/integrations/harnesses/ids.js +24 -0
  332. package/dist/integrations/harnesses/index.js +54 -34
  333. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  334. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  335. package/dist/integrations/harnesses/opencode/index.js +14 -32
  336. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  337. package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
  338. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
  339. package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
  340. package/dist/integrations/harnesses/openhands/index.js +48 -0
  341. package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
  342. package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
  343. package/dist/integrations/harnesses/pi/index.js +45 -0
  344. package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
  345. package/dist/integrations/harnesses/shared.js +17 -0
  346. package/dist/integrations/harnesses/types.js +43 -32
  347. package/dist/integrations/lockfile.js +211 -24
  348. package/dist/integrations/session-logs/index.js +36 -39
  349. package/dist/integrations/session-logs/provider-base.js +113 -0
  350. package/dist/llm/client.js +182 -110
  351. package/dist/llm/embedders/deterministic.js +2 -2
  352. package/dist/llm/embedders/remote.js +21 -9
  353. package/dist/llm/feature-gate.js +17 -57
  354. package/dist/llm/graph-extract.js +12 -13
  355. package/dist/llm/index-passes.js +8 -42
  356. package/dist/llm/memory-infer.js +144 -1
  357. package/dist/llm/metadata-enhance.js +45 -30
  358. package/dist/llm/structured-call.js +16 -8
  359. package/dist/llm/usage-persist.js +30 -5
  360. package/dist/llm/usage-telemetry.js +59 -6
  361. package/dist/output/cli-hints.js +1 -2
  362. package/dist/output/command-registry.js +27 -0
  363. package/dist/output/context.js +22 -7
  364. package/dist/output/format-exempt.js +80 -0
  365. package/dist/output/generic-render.js +251 -0
  366. package/dist/output/html-render.js +11 -16
  367. package/dist/output/render-registry.js +57 -0
  368. package/dist/output/renderers.js +14 -279
  369. package/dist/output/shapes/curate.js +10 -1
  370. package/dist/output/shapes/events.js +12 -7
  371. package/dist/output/shapes/helpers.js +58 -84
  372. package/dist/output/shapes/passthrough.js +11 -39
  373. package/dist/output/shapes/proposal/producer.js +15 -7
  374. package/dist/output/shapes/registry.js +12 -6
  375. package/dist/output/shapes.js +0 -9
  376. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  377. package/dist/output/text/bundle-show.js +7 -0
  378. package/dist/output/text/command-format.js +562 -0
  379. package/dist/output/text/env.js +1 -3
  380. package/dist/output/text/events.js +8 -7
  381. package/dist/output/text/helpers.js +15 -1164
  382. package/dist/output/text/proposal/producer.js +4 -2
  383. package/dist/output/text/proposal-format.js +202 -0
  384. package/dist/output/text/registry-commands.js +1 -2
  385. package/dist/output/text/registry.js +12 -6
  386. package/dist/output/text/show-directives.js +117 -0
  387. package/dist/output/text/show-format.js +103 -0
  388. package/dist/output/text/sync.js +5 -0
  389. package/dist/output/text/workflow-format.js +332 -0
  390. package/dist/output/text/workflow.js +3 -2
  391. package/dist/output/text.js +10 -19
  392. package/dist/registry/factory.js +4 -6
  393. package/dist/registry/origin-resolve.js +16 -27
  394. package/dist/registry/providers/skills-sh.js +3 -3
  395. package/dist/registry/providers/static-index.js +15 -25
  396. package/dist/registry/resolve.js +43 -94
  397. package/dist/registry/semver.js +43 -0
  398. package/dist/runtime.js +81 -12
  399. package/dist/scripts/akm-migrate.js +35529 -0
  400. package/dist/setup/detect.js +5 -7
  401. package/dist/setup/detected-engines.js +136 -0
  402. package/dist/setup/engine-config.js +100 -0
  403. package/dist/setup/registry-stash-loader.js +3 -3
  404. package/dist/setup/semantic-assets.js +12 -9
  405. package/dist/setup/setup.js +444 -208
  406. package/dist/setup/steps/connection-shared.js +120 -0
  407. package/dist/setup/steps/connection.js +108 -305
  408. package/dist/setup/steps/platforms.js +13 -12
  409. package/dist/setup/steps/semantic.js +15 -3
  410. package/dist/setup/steps/sources.js +21 -15
  411. package/dist/setup/steps/stashdir.js +6 -4
  412. package/dist/setup/steps/tasks.js +236 -119
  413. package/dist/setup/steps.js +3 -2
  414. package/dist/sources/freshness.js +39 -0
  415. package/dist/sources/provider-factory.js +11 -17
  416. package/dist/sources/providers/filesystem.js +2 -3
  417. package/dist/sources/providers/git-install.js +278 -34
  418. package/dist/sources/providers/git-provider.js +54 -56
  419. package/dist/sources/providers/git-stash.js +420 -91
  420. package/dist/sources/providers/git.js +2 -2
  421. package/dist/sources/providers/npm.js +16 -19
  422. package/dist/sources/providers/provider-utils.js +47 -22
  423. package/dist/sources/providers/sync-from-ref.js +3 -9
  424. package/dist/sources/providers/website.js +2 -2
  425. package/dist/sources/resolve.js +11 -10
  426. package/dist/sources/snapshot-fetchers/types.js +4 -0
  427. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
  428. package/dist/storage/database.js +60 -4
  429. package/dist/storage/engines/sqlite-migrations.js +156 -5
  430. package/dist/storage/locations.js +1 -2
  431. package/dist/storage/repositories/canaries-repository.js +1 -1
  432. package/dist/storage/repositories/events-repository.js +51 -11
  433. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  434. package/dist/storage/repositories/index-connection.js +79 -0
  435. package/dist/storage/repositories/index-db.js +4 -3
  436. package/dist/storage/repositories/index-entries-repository.js +863 -0
  437. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  438. package/dist/storage/repositories/index-entry-types.js +4 -0
  439. package/dist/storage/repositories/index-fts-repository.js +167 -0
  440. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  441. package/dist/storage/repositories/index-meta-repository.js +49 -0
  442. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  443. package/dist/storage/repositories/index-sql.js +12 -0
  444. package/dist/storage/repositories/index-utility-repository.js +356 -0
  445. package/dist/storage/repositories/index-vec-repository.js +250 -0
  446. package/dist/storage/repositories/outcome-repository.js +119 -0
  447. package/dist/storage/repositories/proposals-repository.js +317 -75
  448. package/dist/storage/repositories/registry-cache.js +1 -1
  449. package/dist/storage/repositories/salience-repository.js +172 -0
  450. package/dist/storage/repositories/task-history-repository.js +110 -3
  451. package/dist/storage/repositories/workflow-runs-repository.js +240 -19
  452. package/dist/tasks/backends/cron.js +169 -46
  453. package/dist/tasks/backends/exec-utils.js +76 -3
  454. package/dist/tasks/backends/index.js +6 -9
  455. package/dist/tasks/backends/launchd.js +292 -55
  456. package/dist/tasks/backends/schtasks.js +557 -70
  457. package/dist/tasks/backends/types.js +4 -0
  458. package/dist/tasks/command-executable.js +93 -0
  459. package/dist/tasks/embedded.js +56 -38
  460. package/dist/tasks/parser.js +156 -64
  461. package/dist/tasks/resolve-akm-bin.js +144 -51
  462. package/dist/tasks/runner.js +377 -209
  463. package/dist/tasks/schedule.js +108 -19
  464. package/dist/tasks/scheduler-invocation.js +296 -0
  465. package/dist/tasks/schema.js +1 -1
  466. package/dist/tasks/task-id.js +35 -0
  467. package/dist/tasks/validator.js +30 -16
  468. package/dist/text-import-hook.mjs +1 -1
  469. package/dist/workflows/authoring/authoring.js +104 -43
  470. package/dist/workflows/authoring/scope-key.js +1 -1
  471. package/dist/workflows/cli.js +0 -16
  472. package/dist/workflows/concurrency-policy.js +15 -0
  473. package/dist/workflows/exec/brief.js +450 -0
  474. package/dist/workflows/exec/frozen-judge.js +47 -0
  475. package/dist/workflows/exec/native-executor.js +1038 -0
  476. package/dist/workflows/exec/param-secrets.js +115 -0
  477. package/dist/workflows/exec/report.js +1460 -0
  478. package/dist/workflows/exec/run-workflow.js +602 -0
  479. package/dist/workflows/exec/scheduler.js +71 -0
  480. package/dist/workflows/exec/step-work.js +1190 -0
  481. package/dist/workflows/exec/unit-writer.js +23 -0
  482. package/dist/workflows/exec/workflow-engine-gate.js +67 -0
  483. package/dist/workflows/exec/worktree.js +171 -0
  484. package/dist/workflows/ir/compile.js +246 -0
  485. package/dist/workflows/ir/freeze.js +233 -0
  486. package/dist/workflows/ir/params.js +54 -0
  487. package/dist/workflows/ir/plan-hash.js +68 -0
  488. package/dist/workflows/ir/schema.js +540 -0
  489. package/dist/workflows/parser.js +878 -304
  490. package/dist/workflows/program/expressions.js +181 -0
  491. package/dist/workflows/program/schema.js +51 -0
  492. package/dist/workflows/renderer.js +100 -45
  493. package/dist/workflows/resource-limits.js +22 -0
  494. package/dist/workflows/runtime/agent-identity.js +59 -14
  495. package/dist/workflows/runtime/checkin.js +1 -1
  496. package/dist/workflows/runtime/plan-classifier.js +131 -0
  497. package/dist/workflows/runtime/runs.js +376 -119
  498. package/dist/workflows/runtime/unit-checkin.js +45 -0
  499. package/dist/workflows/runtime/unit-phases.js +20 -0
  500. package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
  501. package/dist/workflows/schema.js +1 -11
  502. package/dist/workflows/validate-summary.js +2 -3
  503. package/dist/workflows/validator.js +52 -30
  504. package/docs/README.md +42 -78
  505. package/docs/migration/README.md +8 -0
  506. package/docs/migration/release-notes/0.6.0.md +1 -1
  507. package/docs/migration/release-notes/0.7.0.md +9 -8
  508. package/docs/migration/release-notes/0.9.0.md +158 -14
  509. package/docs/migration/v0.7-to-v0.8.md +46 -47
  510. package/docs/migration/v0.8-to-v0.9.md +844 -0
  511. package/docs/reference/README.md +12 -0
  512. package/docs/reference/data-and-telemetry.md +333 -0
  513. package/package.json +21 -17
  514. package/schemas/akm-asset-envelope.json +93 -0
  515. package/schemas/akm-config.json +4636 -0
  516. package/schemas/akm-task.json +87 -0
  517. package/schemas/akm-workflow.json +373 -0
  518. package/dist/akm-migrate-storage +0 -38
  519. package/dist/assets/help/help-accept.md +0 -12
  520. package/dist/assets/help/help-improve.md +0 -84
  521. package/dist/assets/help/help-proposals.md +0 -17
  522. package/dist/assets/help/help-propose.md +0 -17
  523. package/dist/assets/help/help-reject.md +0 -11
  524. package/dist/assets/profiles/frequent.json +0 -13
  525. package/dist/assets/profiles/recombine-only.json +0 -21
  526. package/dist/assets/profiles/reflect-distill.json +0 -30
  527. package/dist/assets/profiles/synthesize.json +0 -15
  528. package/dist/assets/prompts/procedural-system.md +0 -44
  529. package/dist/assets/prompts/recombine-system.md +0 -40
  530. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  531. package/dist/assets/tasks/core/backup.yml +0 -4
  532. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  533. package/dist/assets/templates/html/default.html +0 -78
  534. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  535. package/dist/assets/wiki/index-template.md +0 -12
  536. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  537. package/dist/assets/wiki/log-template.md +0 -8
  538. package/dist/assets/wiki/schema-template.md +0 -61
  539. package/dist/cli/config-migrate.js +0 -150
  540. package/dist/cli/config-validate.js +0 -39
  541. package/dist/commands/graph/graph-cli.js +0 -124
  542. package/dist/commands/graph/graph.js +0 -487
  543. package/dist/commands/improve/calibration.js +0 -161
  544. package/dist/commands/improve/dedup.js +0 -482
  545. package/dist/commands/improve/extract-watch.js +0 -140
  546. package/dist/commands/improve/hot-probation.js +0 -45
  547. package/dist/commands/improve/improve-auto-accept.js +0 -276
  548. package/dist/commands/improve/improve-profiles.js +0 -168
  549. package/dist/commands/improve/procedural.js +0 -398
  550. package/dist/commands/improve/recombine.js +0 -818
  551. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  552. package/dist/commands/lint/agent-linter.js +0 -44
  553. package/dist/commands/lint/command-linter.js +0 -44
  554. package/dist/commands/lint/default-linter.js +0 -16
  555. package/dist/commands/lint/fact-linter.js +0 -39
  556. package/dist/commands/lint/knowledge-linter.js +0 -16
  557. package/dist/commands/lint/memory-linter.js +0 -61
  558. package/dist/commands/lint/registry.js +0 -41
  559. package/dist/commands/lint/skill-linter.js +0 -45
  560. package/dist/commands/lint/task-linter.js +0 -50
  561. package/dist/commands/lint/workflow-linter.js +0 -81
  562. package/dist/commands/proposal/legacy-import.js +0 -115
  563. package/dist/commands/sources/history.js +0 -196
  564. package/dist/commands/tasks/default-tasks.js +0 -186
  565. package/dist/commands/wiki-cli.js +0 -292
  566. package/dist/core/asset/asset-registry.js +0 -76
  567. package/dist/core/asset/asset-spec.js +0 -259
  568. package/dist/core/config/config-migration.js +0 -602
  569. package/dist/core/deep-merge.js +0 -38
  570. package/dist/core/eval/rank-metrics.js +0 -113
  571. package/dist/core/ripgrep/install.js +0 -163
  572. package/dist/core/ripgrep/resolve.js +0 -81
  573. package/dist/indexer/db/db.js +0 -1413
  574. package/dist/indexer/manifest.js +0 -170
  575. package/dist/indexer/passes/metadata-contributors.js +0 -31
  576. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  577. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
  578. package/dist/llm/call-ai.js +0 -62
  579. package/dist/llm/memory-infer-impl.js +0 -138
  580. package/dist/output/shapes/distill.js +0 -14
  581. package/dist/output/shapes/history.js +0 -11
  582. package/dist/output/text/distill.js +0 -6
  583. package/dist/output/text/enable-disable.js +0 -8
  584. package/dist/output/text/history.js +0 -6
  585. package/dist/output/text/wiki.js +0 -16
  586. package/dist/registry/build-index.js +0 -386
  587. package/dist/scripts/migrate-storage.js +0 -19108
  588. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
  589. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  590. package/dist/setup/legacy-config.js +0 -106
  591. package/dist/storage/repositories/consolidation-repository.js +0 -38
  592. package/dist/storage/repositories/recombine-repository.js +0 -213
  593. package/dist/wiki/wiki-templates.js +0 -15
  594. package/dist/wiki/wiki.js +0 -1012
  595. package/dist/workflows/db.js +0 -215
  596. package/docs/data-and-telemetry.md +0 -226
  597. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  598. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -3,118 +3,85 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
+ import { detectAdapterId } from "../../core/adapter/detect-adapter.js";
7
+ import { isBundleSlug } from "../../core/asset/asset-ref.js";
6
8
  import { isHttpUrl, resolveStashDir } from "../../core/common.js";
7
- import { getSources, loadConfig, loadUserConfig, saveConfig } from "../../core/config/config.js";
9
+ import { bundleEntryToSourceEntry, getSources, installedSourceDescriptor, loadConfig, mutateConfig, } from "../../core/config/config.js";
8
10
  import { ConfigError, UsageError } from "../../core/errors.js";
9
11
  import { akmIndex } from "../../indexer/indexer.js";
10
- import { upsertLockEntry } from "../../integrations/lockfile.js";
12
+ import { deriveBundleId } from "../../indexer/installations.js";
13
+ import { readLockfile, removeLockEntry, upsertLockEntry } from "../../integrations/lockfile.js";
11
14
  import { parseRegistryRef } from "../../registry/resolve.js";
12
15
  import { detectStashRoot } from "../../sources/providers/provider-utils.js";
13
16
  import { syncFromRef } from "../../sources/providers/sync-from-ref.js";
14
- import { ensureWebsiteMirror, shouldAllowPrivateWebsiteUrlForTests, validateWebsiteInputUrl, } from "../../sources/website-ingest.js";
15
- import { ensureWikiNameAvailable, validateWikiName } from "../../wiki/wiki.js";
16
- const VALID_OVERRIDE_TYPES = new Set(["wiki"]);
17
+ import { ensureWebsiteMirror, shouldAllowPrivateWebsiteUrlForTests, validateWebsiteInputUrl, } from "../../sources/snapshot-fetchers/website-ingest.js";
18
+ import { bundleKeyForPath, bundleKeyForUrl, nextBundleKey } from "./bundle-config-ops.js";
17
19
  export async function akmAdd(input) {
18
20
  const ref = input.ref.trim();
19
21
  if (!ref)
20
22
  throw new UsageError("Install ref or local directory is required. " +
21
- "Examples: `akm add @scope/stash`, `akm add github:owner/repo`, `akm add ./local/path`");
22
- // Validate and resolve wiki name when --type wiki is used
23
- let wikiName;
24
- if (input.overrideType) {
25
- if (!VALID_OVERRIDE_TYPES.has(input.overrideType)) {
26
- throw new UsageError(`Invalid --type value: "${input.overrideType}". Supported types: ${[...VALID_OVERRIDE_TYPES].join(", ")}`);
27
- }
28
- if (input.overrideType === "wiki") {
29
- const derived = input.name ?? deriveWikiNameFromRef(ref);
30
- validateWikiName(derived);
31
- wikiName = derived;
32
- }
33
- }
23
+ "Examples: `akm bundle add @scope/stash`, `akm bundle add github:owner/repo`, `akm bundle add ./local/path`");
34
24
  const stashDir = resolveStashDir();
35
25
  if (shouldAddAsWebsiteUrl(ref)) {
36
- return addWebsiteSource(ref, stashDir, input.name ?? wikiName, input.options, wikiName);
26
+ return addWebsiteSource(ref, stashDir, input.name, input.options);
37
27
  }
38
28
  // Detect local directory refs and route them to stashes[] instead of installed[]
39
29
  try {
40
30
  const parsed = parseRegistryRef(ref);
41
31
  if (parsed.source === "local") {
42
- return addLocalSource(ref, parsed.sourcePath, stashDir, wikiName, input.name);
32
+ return addLocalSource(ref, parsed.sourcePath, stashDir, input.name);
43
33
  }
44
34
  }
45
35
  catch {
46
36
  // Not a local ref — fall through to registry install
47
37
  }
48
- return addRegistryStash(ref, stashDir, input.writable, wikiName);
49
- }
50
- export async function registerWikiSource(input) {
51
- const stashDir = resolveStashDir();
52
- const name = input.name ?? deriveWikiNameFromRef(input.ref);
53
- validateWikiName(name);
54
- ensureWikiNameAvailable(stashDir, name);
55
- return akmAdd({
56
- ref: input.ref,
57
- name,
58
- overrideType: "wiki",
59
- options: input.options,
60
- writable: input.writable,
61
- });
38
+ return addRegistryStash(ref, stashDir, input.writable);
62
39
  }
63
40
  /**
64
- * Add a local directory as a filesystem stash source.
65
- * Creates a stashes[] entry instead of an installed[] entry.
41
+ * Add a local directory as a filesystem bundle (spec §10.1) — replaces the
42
+ * retired `sources[]` filesystem entry.
66
43
  */
67
- async function addLocalSource(ref, sourcePath, stashDir, wikiName, explicitName) {
44
+ async function addLocalSource(ref, sourcePath, stashDir, explicitName) {
68
45
  const stashRoot = detectStashRoot(sourcePath);
69
46
  const resolvedPath = path.resolve(stashRoot);
70
- const config = loadUserConfig();
71
- // Derive the canonical name: explicit --name wins, then wiki name, then readable path.
72
- const derivedName = explicitName ?? wikiName ?? toReadableId(resolvedPath);
73
- // Check for duplicates in sources[]
74
- const sources = [...getSources(config)];
75
- const existing = sources.find((s) => s.type === "filesystem" && s.path && path.resolve(s.path) === resolvedPath);
76
- let persistedEntry;
77
- if (!existing) {
78
- persistedEntry = {
79
- type: "filesystem",
47
+ let bundleKey = explicitName ?? toReadableId(resolvedPath);
48
+ mutateConfig((config) => {
49
+ const existing = bundleKeyForPath(config, resolvedPath);
50
+ if (existing) {
51
+ bundleKey = existing;
52
+ const current = config.bundles?.[existing];
53
+ if (current?.components)
54
+ return config;
55
+ const bundles = { ...(config.bundles ?? {}) };
56
+ bundles[existing] = {
57
+ ...current,
58
+ path: resolvedPath,
59
+ components: { main: { root: ".", adapter: detectAdapterId(resolvedPath) } },
60
+ };
61
+ return { ...config, bundles };
62
+ }
63
+ const bundles = { ...(config.bundles ?? {}) };
64
+ bundleKey = nextBundleKey(bundles, explicitName, resolvedPath);
65
+ bundles[bundleKey] = {
80
66
  path: resolvedPath,
81
- name: derivedName,
82
- ...(wikiName ? { wikiName } : {}),
67
+ components: { main: { root: ".", adapter: detectAdapterId(resolvedPath) } },
83
68
  };
84
- sources.push(persistedEntry);
85
- saveConfig({ ...config, sources });
86
- }
87
- else {
88
- let changed = false;
89
- // If --name was explicitly supplied, update the persisted name.
90
- if (explicitName && existing.name !== explicitName) {
91
- existing.name = explicitName;
92
- changed = true;
93
- }
94
- if (wikiName && existing.wikiName !== wikiName) {
95
- existing.wikiName = wikiName;
96
- changed = true;
97
- }
98
- if (changed)
99
- saveConfig({ ...config, sources });
100
- persistedEntry = existing;
101
- }
69
+ return { ...config, bundles };
70
+ });
102
71
  const index = await akmIndex({ stashDir });
103
72
  const updatedConfig = loadConfig();
104
73
  return {
105
74
  schemaVersion: 1,
106
- stashDir,
107
- ref: wikiName ?? ref,
75
+ bundleDir: stashDir,
76
+ ref,
108
77
  sourceAdded: {
109
78
  type: "filesystem",
110
79
  path: resolvedPath,
111
- name: persistedEntry.name ?? toReadableId(resolvedPath),
80
+ name: bundleKey,
112
81
  stashRoot: resolvedPath,
113
- ...(persistedEntry.wikiName ? { wiki: persistedEntry.wikiName } : {}),
114
82
  },
115
83
  config: {
116
84
  sourceCount: getSources(updatedConfig).length,
117
- installedKitCount: updatedConfig.installed?.length ?? 0,
118
85
  },
119
86
  index: {
120
87
  mode: index.mode,
@@ -125,36 +92,29 @@ async function addLocalSource(ref, sourcePath, stashDir, wikiName, explicitName)
125
92
  },
126
93
  };
127
94
  }
128
- async function addWebsiteSource(ref, stashDir, name, options, wikiName) {
95
+ async function addWebsiteSource(ref, stashDir, name, options) {
129
96
  const allowPrivateHosts = shouldAllowPrivateWebsiteUrlForTests(ref);
130
97
  const normalizedUrl = validateWebsiteInputUrl(ref, { allowPrivateHosts });
131
- const config = loadUserConfig();
132
- const sources = [...getSources(config)];
133
- let entry = sources.find((stash) => stash.type === "website" && stash.url === normalizedUrl);
134
- if (!entry) {
135
- entry = {
136
- type: "website",
137
- url: normalizedUrl,
138
- name: name ?? toWebsiteName(normalizedUrl),
139
- ...(options && Object.keys(options).length > 0 ? { options } : {}),
140
- ...(wikiName ? { wikiName } : {}),
98
+ const maxPages = typeof options?.maxPages === "number" ? options.maxPages : undefined;
99
+ let entry;
100
+ mutateConfig((config) => {
101
+ const bundles = { ...(config.bundles ?? {}) };
102
+ const existingKey = bundleKeyForUrl(config, normalizedUrl);
103
+ const key = existingKey ?? nextBundleKey(bundles, name ?? toWebsiteName(normalizedUrl), normalizedUrl);
104
+ const website = { url: normalizedUrl, ...(maxPages !== undefined ? { maxPages } : {}) };
105
+ const nextBundle = {
106
+ ...(existingKey ? bundles[key] : {}),
107
+ website,
108
+ components: { main: { root: ".", adapter: "website-snapshot", writable: false } },
141
109
  };
142
- sources.push(entry);
143
- saveConfig({ ...config, sources });
144
- }
145
- else {
146
- let changed = false;
147
- if (options && Object.keys(options).length > 0) {
148
- entry.options = { ...entry.options, ...options };
149
- changed = true;
150
- }
151
- if (wikiName && entry.wikiName !== wikiName) {
152
- entry.wikiName = wikiName;
153
- changed = true;
110
+ if (JSON.stringify(bundles[key]) === JSON.stringify(nextBundle)) {
111
+ entry = bundleEntryToSourceEntry(key, bundles[key]);
112
+ return config;
154
113
  }
155
- if (changed)
156
- saveConfig({ ...config, sources });
157
- }
114
+ bundles[key] = nextBundle;
115
+ entry = bundleEntryToSourceEntry(key, nextBundle);
116
+ return { ...config, bundles };
117
+ });
158
118
  const cachePaths = await ensureWebsiteMirror(entry, {
159
119
  requireStashDir: true,
160
120
  ...(allowPrivateHosts ? { allowPrivateHosts: true } : {}),
@@ -163,18 +123,16 @@ async function addWebsiteSource(ref, stashDir, name, options, wikiName) {
163
123
  const updatedConfig = loadConfig();
164
124
  return {
165
125
  schemaVersion: 1,
166
- stashDir,
167
- ref: wikiName ?? ref,
126
+ bundleDir: stashDir,
127
+ ref,
168
128
  sourceAdded: {
169
129
  type: "website",
170
130
  url: normalizedUrl,
171
- name: entry.name,
131
+ name: entry?.name,
172
132
  stashRoot: cachePaths.stashDir,
173
- ...(entry.wikiName ? { wiki: entry.wikiName } : {}),
174
133
  },
175
134
  config: {
176
135
  sourceCount: getSources(updatedConfig).length,
177
- installedKitCount: updatedConfig.installed?.length ?? 0,
178
136
  },
179
137
  index: {
180
138
  mode: index.mode,
@@ -189,14 +147,26 @@ async function addWebsiteSource(ref, stashDir, name, options, wikiName) {
189
147
  * Install a stash from a registry (npm, github, git) by dispatching to the
190
148
  * matching syncable provider and persisting the lock entry.
191
149
  */
192
- async function addRegistryStash(ref, stashDir, writable, wikiName) {
150
+ async function addRegistryStash(ref, stashDir, writable) {
193
151
  const parsedRef = parseRegistryRef(ref);
194
- if (writable === true && parsedRef.source !== "git") {
152
+ if (writable === true && parsedRef.source !== "git" && parsedRef.source !== "github") {
195
153
  throw new ConfigError("writable: true is only supported on filesystem and git sources", "INVALID_CONFIG_FILE");
196
154
  }
197
- const synced = await syncFromRef(ref, { writable });
198
- const replaced = (loadConfig().installed ?? []).find((entry) => entry.id === synced.id);
199
- const updatedConfig = upsertInstalledRegistryEntry({
155
+ const currentConfig = loadConfig();
156
+ const existingBundleKey = findInstalledBundleKey(currentConfig.bundles ?? {}, parsedRef.id);
157
+ const existingBundle = existingBundleKey ? currentConfig.bundles?.[existingBundleKey] : undefined;
158
+ const priorLock = existingBundleKey ? readLockfile().find((entry) => entry.id === existingBundleKey) : undefined;
159
+ const existingWritable = Object.values(existingBundle?.components ?? {})[0]?.writable ?? existingBundle?.writable === true;
160
+ const effectiveWritable = writable === true || existingWritable;
161
+ const requiredRoots = priorLock?.localRoot
162
+ ? Object.values(existingBundle?.components ?? {}).map((component) => path.resolve(priorLock.localRoot, component.root ?? "."))
163
+ : [];
164
+ const synced = await syncFromRef(ref, {
165
+ writable: effectiveWritable,
166
+ ...(effectiveWritable && priorLock?.localRoot ? { writableRoot: priorLock.localRoot } : {}),
167
+ ...(requiredRoots.length > 0 ? { writableRequiredRoots: requiredRoots } : {}),
168
+ });
169
+ const { config: updatedConfig, bundleId } = upsertInstalledRegistryEntry({
200
170
  id: synced.id,
201
171
  source: synced.source,
202
172
  ref: synced.ref,
@@ -207,20 +177,25 @@ async function addRegistryStash(ref, stashDir, writable, wikiName) {
207
177
  cacheDir: synced.cacheDir,
208
178
  installedAt: synced.syncedAt,
209
179
  writable: synced.writable,
210
- ...(wikiName ? { wikiName } : {}),
211
180
  });
181
+ // The prior materialized root (if this is a re-install) — read BEFORE the lock
182
+ // upsert overwrites it, so a moved cache root can be cleaned afterwards.
183
+ const priorLocalRoot = priorLock?.localRoot;
212
184
  await upsertLockEntry({
213
- id: synced.id,
185
+ id: bundleId,
214
186
  source: synced.source,
215
187
  ref: synced.ref,
216
188
  resolvedVersion: synced.resolvedVersion,
217
189
  resolvedRevision: synced.resolvedRevision,
218
190
  integrity: synced.integrity,
191
+ // §10.2 resolved lock state the install flow has on hand.
192
+ localRoot: synced.contentDir,
193
+ installedAt: synced.syncedAt,
219
194
  });
220
- // Clean up old cache directory on re-install
221
- if (replaced && replaced.cacheDir !== synced.cacheDir) {
195
+ // Clean up the old materialized root on re-install (moved cache).
196
+ if (!effectiveWritable && priorLocalRoot && path.resolve(priorLocalRoot) !== path.resolve(synced.contentDir)) {
222
197
  try {
223
- fs.rmSync(replaced.cacheDir, { recursive: true, force: true });
198
+ fs.rmSync(priorLocalRoot, { recursive: true, force: true });
224
199
  }
225
200
  catch {
226
201
  // Best-effort cleanup only.
@@ -229,7 +204,7 @@ async function addRegistryStash(ref, stashDir, writable, wikiName) {
229
204
  const index = await akmIndex({ stashDir });
230
205
  return {
231
206
  schemaVersion: 1,
232
- stashDir,
207
+ bundleDir: stashDir,
233
208
  ref,
234
209
  installed: {
235
210
  id: synced.id,
@@ -245,7 +220,6 @@ async function addRegistryStash(ref, stashDir, writable, wikiName) {
245
220
  },
246
221
  config: {
247
222
  sourceCount: getSources(updatedConfig).length,
248
- installedKitCount: updatedConfig.installed?.length ?? 0,
249
223
  },
250
224
  index: {
251
225
  mode: index.mode,
@@ -256,34 +230,89 @@ async function addRegistryStash(ref, stashDir, writable, wikiName) {
256
230
  },
257
231
  };
258
232
  }
259
- /** Persist or replace an installed stash entry in the user config. */
233
+ /**
234
+ * Persist or replace a registry-installed source as a 0.9.0 `bundles` entry
235
+ * (spec §10.1 / §10.2 desired/resolved split). The bundle carries ONLY the
236
+ * desired descriptor (git/npm locator + preserved `registryId` + `writable`);
237
+ * the resolved cache root belongs exclusively in the lock (written by callers
238
+ * via {@link upsertLockEntry} with the returned `bundleId`). Returns the config
239
+ * plus the derived bundle id so the caller keys its lock entry identically.
240
+ */
260
241
  export function upsertInstalledRegistryEntry(entry) {
261
- const current = loadUserConfig();
262
- const currentInstalled = current.installed ?? [];
263
- const withoutExisting = currentInstalled.filter((item) => item.id !== entry.id);
264
- const nextInstalled = [...withoutExisting, normalizeInstalledEntry(entry)];
265
- const nextConfig = { ...current, installed: nextInstalled };
266
- saveConfig(nextConfig);
267
- return nextConfig;
242
+ let bundleId = entry.id;
243
+ const config = mutateConfig((current) => {
244
+ const bundles = { ...(current.bundles ?? {}) };
245
+ bundleId = resolveInstalledBundleKey(bundles, entry.id, entry.stashRoot);
246
+ const existingComponents = bundles[bundleId]?.components;
247
+ const components = existingComponents
248
+ ? Object.fromEntries(Object.entries(existingComponents).map(([id, component]) => [
249
+ id,
250
+ { ...component, writable: entry.writable === true },
251
+ ]))
252
+ : {
253
+ main: {
254
+ root: ".",
255
+ adapter: detectAdapterId(path.resolve(entry.stashRoot)),
256
+ writable: entry.writable === true,
257
+ },
258
+ };
259
+ const descriptor = installedSourceDescriptor(entry.source, entry.ref, path.resolve(entry.stashRoot));
260
+ bundles[bundleId] = {
261
+ ...descriptor,
262
+ ...(entry.writable === true ? { writable: true } : {}),
263
+ ...(entry.id !== bundleId ? { registryId: entry.id } : {}),
264
+ components: components,
265
+ };
266
+ return { ...current, bundles };
267
+ }).config;
268
+ return { config, bundleId };
268
269
  }
269
- /** Remove an installed stash entry from the user config. */
270
- export function removeInstalledRegistryEntry(id) {
271
- const current = loadUserConfig();
272
- const currentInstalled = current.installed ?? [];
273
- const nextInstalled = currentInstalled.filter((item) => item.id !== id);
274
- const nextConfig = {
275
- ...current,
276
- installed: nextInstalled.length > 0 ? nextInstalled : undefined,
277
- };
278
- saveConfig(nextConfig);
279
- return nextConfig;
270
+ /**
271
+ * Remove a registry-installed source: delete its `bundles` entry and its lock
272
+ * entry (spec §10.2). Matches the bundle by preserved `registryId` or by a
273
+ * slug-legal install id used verbatim as the key. Idempotent.
274
+ */
275
+ export async function removeInstalledRegistryEntry(id) {
276
+ let removedKey;
277
+ const config = mutateConfig((current) => {
278
+ const bundles = { ...(current.bundles ?? {}) };
279
+ const key = findInstalledBundleKey(bundles, id);
280
+ if (!key)
281
+ return current;
282
+ removedKey = key;
283
+ delete bundles[key];
284
+ return { ...current, bundles: Object.keys(bundles).length > 0 ? bundles : undefined };
285
+ }).config;
286
+ if (removedKey)
287
+ await removeLockEntry(removedKey);
288
+ return config;
280
289
  }
281
- function normalizeInstalledEntry(entry) {
282
- return {
283
- ...entry,
284
- stashRoot: path.resolve(entry.stashRoot),
285
- cacheDir: path.resolve(entry.cacheDir),
286
- };
290
+ /**
291
+ * The bundle key that maps to a registry install id, or `undefined` when no
292
+ * bundle currently represents it. A non-slug-legal install id (e.g.
293
+ * `github:owner/repo`) is preserved verbatim on the bundle's `registryId`; a
294
+ * slug-legal id is used directly as the key.
295
+ */
296
+ function findInstalledBundleKey(bundles, installId) {
297
+ for (const [key, bundle] of Object.entries(bundles)) {
298
+ if (bundle.registryId === installId)
299
+ return key;
300
+ }
301
+ if (isBundleSlug(installId) && installId in bundles)
302
+ return installId;
303
+ return undefined;
304
+ }
305
+ /**
306
+ * The stable bundle key for a registry install: reuse the existing bundle for
307
+ * this install id (so re-installs keep the same key), otherwise derive a
308
+ * batch-unique key via the shared {@link deriveBundleId} (D-R5), unique against
309
+ * the currently-configured bundle keys.
310
+ */
311
+ function resolveInstalledBundleKey(bundles, installId, stashRoot) {
312
+ const existing = findInstalledBundleKey(bundles, installId);
313
+ if (existing)
314
+ return existing;
315
+ return deriveBundleId(installId, path.resolve(stashRoot), new Set(Object.keys(bundles)));
287
316
  }
288
317
  function toReadableId(resolvedPath) {
289
318
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
@@ -315,41 +344,3 @@ function toWebsiteName(siteUrl) {
315
344
  return siteUrl;
316
345
  }
317
346
  }
318
- /**
319
- * Derive a wiki name from a ref string when --name is not provided.
320
- * Lowercases and slugifies the most meaningful identifier segment.
321
- */
322
- export function deriveWikiNameFromRef(ref) {
323
- let candidate = ref;
324
- // github:owner/repo or github:owner/repo@ref
325
- if (/^github:/i.test(ref)) {
326
- const repoPath = ref.replace(/^github:/i, "").split("@")[0];
327
- candidate = repoPath.split("/").pop() ?? repoPath;
328
- }
329
- // npm:pkg or @scope/pkg
330
- else if (/^npm:/i.test(ref) || ref.startsWith("@")) {
331
- candidate = ref
332
- .replace(/^npm:/i, "")
333
- .replace(/^@[^/]+\//, "")
334
- .split("@")[0];
335
- }
336
- // git URLs or HTTPS git URLs
337
- else if (/^(git:|https?:\/\/)/.test(ref)) {
338
- try {
339
- candidate = new URL(ref).pathname.split("/").pop() ?? candidate;
340
- }
341
- catch {
342
- candidate = ref.split("/").pop() ?? ref;
343
- }
344
- candidate = candidate.replace(/\.git$/, "");
345
- }
346
- // Local paths
347
- else {
348
- candidate = path.basename(ref.replace(/\/+$/, ""));
349
- }
350
- return candidate
351
- .toLowerCase()
352
- .replace(/[^a-z0-9]+/g, "-")
353
- .replace(/^-+|-+$/g, "")
354
- .slice(0, 64);
355
- }