akm-cli 0.9.0-rc.1 → 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 (587) hide show
  1. package/CHANGELOG.md +1190 -52
  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/stash-skeleton/README.md +38 -10
  26. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
  38. package/dist/assets/tasks/core/extract.yml +3 -2
  39. package/dist/assets/tasks/core/improve.yml +2 -1
  40. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  41. package/dist/assets/tasks/core/sync.yml +1 -0
  42. package/dist/assets/tasks/core/version-check.yml +2 -1
  43. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  44. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  45. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  46. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  47. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  48. package/dist/assets/templates/html/health.html +5 -4
  49. package/dist/assets/workflows/workflow-template.md +31 -15
  50. package/dist/cli/invocation.js +279 -0
  51. package/dist/cli/parse-args.js +5 -90
  52. package/dist/cli/retired-commands.js +78 -0
  53. package/dist/cli/shared.js +158 -48
  54. package/dist/cli-node.mjs +2 -1
  55. package/dist/cli.js +747 -293
  56. package/dist/commands/agent/agent-dispatch.js +19 -18
  57. package/dist/commands/agent/agent-support.js +0 -24
  58. package/dist/commands/agent/contribute-cli.js +43 -97
  59. package/dist/commands/completions.js +80 -23
  60. package/dist/commands/config-cli.js +44 -281
  61. package/dist/commands/env/env-binding.js +13 -9
  62. package/dist/commands/env/env-cli.js +76 -159
  63. package/dist/commands/env/env.js +12 -163
  64. package/dist/commands/env/marker-path.js +6 -0
  65. package/dist/commands/env/secret-cli.js +45 -61
  66. package/dist/commands/env/secret.js +32 -62
  67. package/dist/commands/feedback-cli.js +179 -85
  68. package/dist/commands/health/accept-rate.js +58 -0
  69. package/dist/commands/health/advisories.js +7 -8
  70. package/dist/commands/health/checks.js +279 -94
  71. package/dist/commands/health/html-report.js +197 -578
  72. package/dist/commands/health/improve-metrics.js +277 -246
  73. package/dist/commands/health/llm-usage.js +19 -19
  74. package/dist/commands/health/md-report.js +16 -7
  75. package/dist/commands/health/metrics.js +67 -32
  76. package/dist/commands/health/renderers.js +47 -0
  77. package/dist/commands/health/report-view-model.js +508 -0
  78. package/dist/commands/health/stash-exposure.js +1 -1
  79. package/dist/commands/health/surfaces.js +16 -56
  80. package/dist/commands/health/task-runs.js +3 -67
  81. package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
  82. package/dist/commands/health/types-improve.js +29 -0
  83. package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
  84. package/dist/commands/health/types-result.js +7 -0
  85. package/dist/commands/health/types-runs.js +4 -0
  86. package/dist/commands/health/types-session-log.js +4 -0
  87. package/dist/commands/health/types-windows.js +4 -0
  88. package/dist/commands/health/types.js +26 -21
  89. package/dist/commands/health/windows.js +2 -3
  90. package/dist/commands/health.js +296 -167
  91. package/dist/commands/improve/anti-collapse.js +5 -5
  92. package/dist/commands/improve/autonomy-gate.js +68 -0
  93. package/dist/commands/improve/collapse-detector.js +65 -52
  94. package/dist/commands/improve/consolidate/chunking.js +9 -7
  95. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  96. package/dist/commands/improve/consolidate/merge.js +4 -0
  97. package/dist/commands/improve/consolidate.js +454 -1354
  98. package/dist/commands/improve/content-hash.js +39 -0
  99. package/dist/commands/improve/distill/content-repair.js +4 -10
  100. package/dist/commands/improve/distill/promote-memory.js +89 -64
  101. package/dist/commands/improve/distill/quality-gate.js +118 -42
  102. package/dist/commands/improve/distill-guards.js +1 -1
  103. package/dist/commands/improve/distill-promotion-policy.js +33 -888
  104. package/dist/commands/improve/distill.js +607 -363
  105. package/dist/commands/improve/eligibility.js +165 -79
  106. package/dist/commands/improve/extract-cli.js +35 -126
  107. package/dist/commands/improve/extract-prompt.js +6 -35
  108. package/dist/commands/improve/extract.js +640 -391
  109. package/dist/commands/improve/feedback-valence.js +2 -12
  110. package/dist/commands/improve/improve-cli.js +134 -135
  111. package/dist/commands/improve/improve-result-file.js +30 -50
  112. package/dist/commands/improve/improve-run-types.js +4 -0
  113. package/dist/commands/improve/improve-strategies.js +135 -0
  114. package/dist/commands/improve/improve.js +904 -701
  115. package/dist/commands/improve/locks.js +64 -111
  116. package/dist/commands/improve/loop-stages.js +1110 -923
  117. package/dist/commands/improve/memory/derived-ref.js +124 -0
  118. package/dist/commands/improve/memory/memory-belief.js +79 -7
  119. package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
  120. package/dist/commands/improve/memory/memory-improve.js +25 -37
  121. package/dist/commands/improve/outcome-loop.js +25 -88
  122. package/dist/commands/improve/preparation.js +1034 -813
  123. package/dist/commands/improve/proactive-maintenance.js +34 -9
  124. package/dist/commands/improve/proposal-envelope.js +31 -0
  125. package/dist/commands/improve/reflect.js +983 -794
  126. package/dist/commands/improve/run-context.js +119 -0
  127. package/dist/commands/improve/salience.js +24 -127
  128. package/dist/commands/improve/session-asset.js +7 -3
  129. package/dist/commands/improve/shared.js +14 -34
  130. package/dist/commands/improve/source-identity.js +28 -0
  131. package/dist/commands/improve/triage.js +20 -17
  132. package/dist/commands/lint/base-linter.js +340 -313
  133. package/dist/commands/lint/env-key-rules.js +31 -47
  134. package/dist/commands/lint/index.js +185 -30
  135. package/dist/commands/{events.js → log.js} +28 -38
  136. package/dist/commands/migrate-cli.js +54 -0
  137. package/dist/commands/migration-tool.js +55 -0
  138. package/dist/commands/observability-cli.js +70 -208
  139. package/dist/commands/proposal/diff-format.js +50 -0
  140. package/dist/commands/proposal/drain-policies.js +0 -6
  141. package/dist/commands/proposal/drain.js +91 -40
  142. package/dist/commands/proposal/proposal-cli.js +134 -132
  143. package/dist/commands/proposal/proposal-types.js +56 -0
  144. package/dist/commands/proposal/proposal.js +83 -65
  145. package/dist/commands/proposal/propose-cli.js +88 -0
  146. package/dist/commands/proposal/propose.js +105 -88
  147. package/dist/commands/proposal/repository.js +1303 -278
  148. package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
  149. package/dist/commands/proposal/validators/proposal-validators.js +61 -12
  150. package/dist/commands/proposal/validators/proposals.js +6 -8
  151. package/dist/commands/read/curate.js +78 -73
  152. package/dist/commands/read/knowledge.js +510 -13
  153. package/dist/commands/read/registry-search.js +2 -2
  154. package/dist/commands/read/remember-cli.js +84 -15
  155. package/dist/commands/read/search-cli.js +203 -96
  156. package/dist/commands/read/search.js +126 -94
  157. package/dist/commands/read/show.js +226 -250
  158. package/dist/commands/registry-cli.js +34 -60
  159. package/dist/commands/remember.js +18 -57
  160. package/dist/commands/sources/add-cli.js +104 -49
  161. package/dist/commands/sources/bundle-cli.js +166 -0
  162. package/dist/commands/sources/bundle-config-ops.js +63 -0
  163. package/dist/commands/sources/info.js +27 -15
  164. package/dist/commands/sources/init.js +30 -40
  165. package/dist/commands/sources/installed-stashes.js +469 -172
  166. package/dist/commands/sources/schema-repair.js +10 -9
  167. package/dist/commands/sources/self-update.js +182 -121
  168. package/dist/commands/sources/source-add.js +169 -178
  169. package/dist/commands/sources/source-clone.js +144 -41
  170. package/dist/commands/sources/source-manage.js +94 -59
  171. package/dist/commands/sources/sources-cli.js +64 -205
  172. package/dist/commands/sources/stash-cli.js +91 -54
  173. package/dist/commands/sources/stash-skeleton.js +1 -1
  174. package/dist/commands/tasks/tasks-cli.js +106 -104
  175. package/dist/commands/tasks/tasks.js +445 -262
  176. package/dist/commands/workflow-cli.js +75 -228
  177. package/dist/core/action-contributors.js +1 -1
  178. package/dist/core/activation-policy.js +49 -0
  179. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  180. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  181. package/dist/core/adapter/adapters/akm-lint.js +392 -0
  182. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  183. package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
  184. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  185. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  186. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  187. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  188. package/dist/core/adapter/adapters/index.js +80 -0
  189. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  190. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  191. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  192. package/dist/core/adapter/adapters/shared.js +286 -0
  193. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  194. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  195. package/dist/core/adapter/bundle-adapter.js +4 -0
  196. package/dist/core/adapter/detect-adapter.js +17 -0
  197. package/dist/core/adapter/recognize-match.js +44 -0
  198. package/dist/core/adapter/registry.js +56 -0
  199. package/dist/core/adapter/types.js +4 -0
  200. package/dist/core/asset/akm-markdown.js +30 -0
  201. package/dist/core/asset/asset-placement.js +243 -0
  202. package/dist/core/asset/asset-ref.js +110 -79
  203. package/dist/core/asset/asset-serialize.js +20 -0
  204. package/dist/core/asset/frontmatter.js +28 -12
  205. package/dist/core/asset/markdown.js +40 -51
  206. package/dist/core/asset/resolve-ref.js +274 -0
  207. package/dist/core/asset/stash-meta.js +2 -2
  208. package/dist/core/bundle-id.js +51 -0
  209. package/dist/core/common.js +281 -86
  210. package/dist/core/config/config-io.js +42 -128
  211. package/dist/core/config/config-schema.js +233 -855
  212. package/dist/core/config/config-sources.js +162 -39
  213. package/dist/core/config/config-types.js +16 -11
  214. package/dist/core/config/config-version.js +29 -0
  215. package/dist/core/config/config-walker.js +126 -37
  216. package/dist/core/config/config.js +154 -331
  217. package/dist/core/config/deep-merge.js +41 -0
  218. package/dist/core/config/engine-semantics.js +28 -0
  219. package/dist/core/config/experimental.js +21 -0
  220. package/dist/core/config/schema/embedding.js +38 -0
  221. package/dist/core/config/schema/engines.js +116 -0
  222. package/dist/core/config/schema/experimental.js +47 -0
  223. package/dist/core/config/schema/feedback.js +31 -0
  224. package/dist/core/config/schema/improve-processes.js +389 -0
  225. package/dist/core/config/schema/improve.js +94 -0
  226. package/dist/core/config/schema/index-config.js +176 -0
  227. package/dist/core/config/schema/output.js +18 -0
  228. package/dist/core/config/schema/primitives.js +94 -0
  229. package/dist/core/config/schema/search.js +30 -0
  230. package/dist/core/config/schema/setup.js +18 -0
  231. package/dist/core/config/schema/sources-bundles.js +169 -0
  232. package/dist/core/config/schema/workflow.js +29 -0
  233. package/dist/core/env-secret-ref.js +155 -20
  234. package/dist/core/errors.js +17 -15
  235. package/dist/core/events-types.js +4 -0
  236. package/dist/core/events.js +46 -128
  237. package/dist/core/extra-params.js +62 -0
  238. package/dist/core/file-change.js +17 -0
  239. package/dist/core/file-lock.js +202 -57
  240. package/dist/core/fs-txn.js +392 -0
  241. package/dist/core/git-message.js +59 -0
  242. package/dist/core/improve-result.js +167 -0
  243. package/dist/core/lesson-lint.js +1 -17
  244. package/dist/core/logs-db.js +1 -1
  245. package/dist/core/maintenance-barrier.js +135 -0
  246. package/dist/core/migration-operation.js +44 -0
  247. package/dist/core/mutation-target.js +78 -0
  248. package/dist/core/paths.js +22 -25
  249. package/dist/core/platform.js +10 -0
  250. package/dist/core/recognition-util.js +128 -0
  251. package/dist/core/redaction.js +392 -0
  252. package/dist/core/standards/resolve-standards-context.js +36 -65
  253. package/dist/core/standards/resolve-stash-standards.js +2 -2
  254. package/dist/core/standards/resolve-type-conventions.js +5 -5
  255. package/dist/core/state/migrations.js +242 -11
  256. package/dist/core/state-db.js +98 -10
  257. package/dist/core/structured.js +1 -1
  258. package/dist/core/subprocess.js +303 -0
  259. package/dist/core/text-truncation.js +9 -5
  260. package/dist/core/time.js +20 -0
  261. package/dist/core/type-presentation.js +130 -0
  262. package/dist/core/warn.js +0 -3
  263. package/dist/core/write-source.js +834 -118
  264. package/dist/indexer/bundle-identity-guard.js +92 -0
  265. package/dist/indexer/db/graph-db.js +1 -25
  266. package/dist/indexer/db/llm-cache.js +1 -1
  267. package/dist/indexer/ensure-index.js +30 -9
  268. package/dist/indexer/graph/graph-boost.js +9 -30
  269. package/dist/indexer/graph/graph-extraction.js +41 -27
  270. package/dist/indexer/graph/graph-types.js +4 -0
  271. package/dist/indexer/index-writer-lock.js +93 -49
  272. package/dist/indexer/index-written-assets.js +100 -53
  273. package/dist/indexer/indexer.js +746 -329
  274. package/dist/indexer/init.js +18 -25
  275. package/dist/indexer/installations.js +142 -0
  276. package/dist/indexer/passes/dir-staleness.js +18 -10
  277. package/dist/indexer/passes/memory-inference.js +25 -15
  278. package/dist/indexer/passes/metadata.js +412 -243
  279. package/dist/indexer/scan/doc-to-entry.js +160 -0
  280. package/dist/indexer/scan/drain-dir.js +134 -0
  281. package/dist/indexer/search/db-search.js +292 -108
  282. package/dist/indexer/search/fts-query.js +64 -0
  283. package/dist/indexer/search/ranking-contributors.js +145 -25
  284. package/dist/indexer/search/ranking-types.js +4 -0
  285. package/dist/indexer/search/ranking.js +28 -71
  286. package/dist/indexer/search/search-attribution.js +67 -0
  287. package/dist/indexer/search/search-fields.js +18 -3
  288. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  289. package/dist/indexer/search/search-source.js +157 -111
  290. package/dist/indexer/search/semantic-status.js +4 -1
  291. package/dist/indexer/usage/usage-events.js +10 -30
  292. package/dist/indexer/walk/file-context.js +3 -45
  293. package/dist/indexer/walk/matchers.js +42 -73
  294. package/dist/indexer/walk/path-resolver.js +11 -5
  295. package/dist/indexer/walk/walker.js +42 -14
  296. package/dist/integrations/agent/builder-shared.js +7 -0
  297. package/dist/integrations/agent/builders.js +5 -58
  298. package/dist/integrations/agent/config.js +3 -143
  299. package/dist/integrations/agent/detect.js +17 -2
  300. package/dist/integrations/agent/engine-resolution.js +231 -0
  301. package/dist/integrations/agent/index.js +1 -2
  302. package/dist/integrations/agent/model-aliases.js +8 -3
  303. package/dist/integrations/agent/profiles.js +6 -99
  304. package/dist/integrations/agent/prompts.js +46 -18
  305. package/dist/integrations/agent/runner-dispatch.js +78 -13
  306. package/dist/integrations/agent/runner.js +76 -208
  307. package/dist/integrations/agent/spawn.js +48 -279
  308. package/dist/integrations/harnesses/aider/agent-builder.js +9 -8
  309. package/dist/integrations/harnesses/aider/index.js +2 -12
  310. package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -16
  311. package/dist/integrations/harnesses/amazonq/index.js +3 -17
  312. package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
  313. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  314. package/dist/integrations/harnesses/claude/index.js +1 -14
  315. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  316. package/dist/integrations/harnesses/codex/agent-builder.js +8 -7
  317. package/dist/integrations/harnesses/codex/index.js +2 -13
  318. package/dist/integrations/harnesses/copilot/agent-builder.js +9 -9
  319. package/dist/integrations/harnesses/copilot/index.js +1 -13
  320. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -9
  321. package/dist/integrations/harnesses/gemini/index.js +1 -13
  322. package/dist/integrations/harnesses/ids.js +24 -0
  323. package/dist/integrations/harnesses/index.js +31 -33
  324. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  325. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  326. package/dist/integrations/harnesses/opencode/index.js +1 -18
  327. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  328. package/dist/integrations/harnesses/opencode-sdk/harness.js +3 -17
  329. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +274 -191
  330. package/dist/integrations/harnesses/openhands/agent-builder.js +12 -10
  331. package/dist/integrations/harnesses/openhands/index.js +2 -12
  332. package/dist/integrations/harnesses/pi/agent-builder.js +11 -18
  333. package/dist/integrations/harnesses/pi/index.js +3 -16
  334. package/dist/integrations/harnesses/shared.js +17 -0
  335. package/dist/integrations/harnesses/types.js +38 -34
  336. package/dist/integrations/lockfile.js +211 -24
  337. package/dist/integrations/session-logs/index.js +24 -40
  338. package/dist/integrations/session-logs/provider-base.js +113 -0
  339. package/dist/llm/client.js +182 -110
  340. package/dist/llm/embedders/deterministic.js +2 -2
  341. package/dist/llm/embedders/remote.js +21 -9
  342. package/dist/llm/feature-gate.js +17 -57
  343. package/dist/llm/graph-extract.js +12 -13
  344. package/dist/llm/index-passes.js +8 -42
  345. package/dist/llm/memory-infer.js +144 -1
  346. package/dist/llm/metadata-enhance.js +45 -30
  347. package/dist/llm/structured-call.js +16 -8
  348. package/dist/llm/usage-persist.js +30 -5
  349. package/dist/llm/usage-telemetry.js +59 -6
  350. package/dist/output/cli-hints.js +1 -2
  351. package/dist/output/command-registry.js +27 -0
  352. package/dist/output/context.js +22 -7
  353. package/dist/output/format-exempt.js +80 -0
  354. package/dist/output/generic-render.js +251 -0
  355. package/dist/output/html-render.js +11 -16
  356. package/dist/output/render-registry.js +57 -0
  357. package/dist/output/renderers.js +15 -281
  358. package/dist/output/shapes/curate.js +10 -1
  359. package/dist/output/shapes/events.js +12 -7
  360. package/dist/output/shapes/helpers.js +58 -84
  361. package/dist/output/shapes/passthrough.js +8 -40
  362. package/dist/output/shapes/proposal/producer.js +15 -7
  363. package/dist/output/shapes/registry.js +12 -6
  364. package/dist/output/shapes.js +0 -9
  365. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  366. package/dist/output/text/bundle-show.js +7 -0
  367. package/dist/output/text/command-format.js +562 -0
  368. package/dist/output/text/env.js +1 -3
  369. package/dist/output/text/events.js +8 -7
  370. package/dist/output/text/helpers.js +15 -1375
  371. package/dist/output/text/proposal/producer.js +4 -2
  372. package/dist/output/text/proposal-format.js +202 -0
  373. package/dist/output/text/registry-commands.js +1 -2
  374. package/dist/output/text/registry.js +12 -6
  375. package/dist/output/text/show-directives.js +117 -0
  376. package/dist/output/text/show-format.js +103 -0
  377. package/dist/output/text/sync.js +5 -0
  378. package/dist/output/text/workflow-format.js +332 -0
  379. package/dist/output/text/workflow.js +1 -2
  380. package/dist/output/text.js +10 -19
  381. package/dist/registry/factory.js +4 -6
  382. package/dist/registry/origin-resolve.js +16 -27
  383. package/dist/registry/providers/skills-sh.js +3 -3
  384. package/dist/registry/providers/static-index.js +15 -25
  385. package/dist/registry/resolve.js +43 -94
  386. package/dist/registry/semver.js +43 -0
  387. package/dist/runtime.js +81 -12
  388. package/dist/scripts/akm-migrate.js +35529 -0
  389. package/dist/setup/detect.js +5 -7
  390. package/dist/setup/detected-engines.js +136 -0
  391. package/dist/setup/engine-config.js +100 -0
  392. package/dist/setup/registry-stash-loader.js +3 -3
  393. package/dist/setup/semantic-assets.js +12 -9
  394. package/dist/setup/setup.js +444 -208
  395. package/dist/setup/steps/connection-shared.js +120 -0
  396. package/dist/setup/steps/connection.js +108 -305
  397. package/dist/setup/steps/platforms.js +13 -12
  398. package/dist/setup/steps/semantic.js +15 -3
  399. package/dist/setup/steps/sources.js +21 -15
  400. package/dist/setup/steps/stashdir.js +6 -4
  401. package/dist/setup/steps/tasks.js +236 -119
  402. package/dist/setup/steps.js +3 -2
  403. package/dist/sources/freshness.js +39 -0
  404. package/dist/sources/provider-factory.js +11 -17
  405. package/dist/sources/providers/filesystem.js +2 -3
  406. package/dist/sources/providers/git-install.js +278 -34
  407. package/dist/sources/providers/git-provider.js +54 -56
  408. package/dist/sources/providers/git-stash.js +420 -91
  409. package/dist/sources/providers/git.js +2 -2
  410. package/dist/sources/providers/npm.js +16 -19
  411. package/dist/sources/providers/provider-utils.js +47 -22
  412. package/dist/sources/providers/sync-from-ref.js +3 -9
  413. package/dist/sources/providers/website.js +2 -2
  414. package/dist/sources/resolve.js +11 -10
  415. package/dist/sources/snapshot-fetchers/types.js +4 -0
  416. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
  417. package/dist/storage/database.js +60 -4
  418. package/dist/storage/engines/sqlite-migrations.js +156 -5
  419. package/dist/storage/locations.js +1 -2
  420. package/dist/storage/repositories/canaries-repository.js +1 -1
  421. package/dist/storage/repositories/events-repository.js +51 -11
  422. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  423. package/dist/storage/repositories/index-connection.js +79 -0
  424. package/dist/storage/repositories/index-db.js +4 -3
  425. package/dist/storage/repositories/index-entries-repository.js +863 -0
  426. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  427. package/dist/storage/repositories/index-entry-types.js +4 -0
  428. package/dist/storage/repositories/index-fts-repository.js +167 -0
  429. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  430. package/dist/storage/repositories/index-meta-repository.js +49 -0
  431. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  432. package/dist/storage/repositories/index-sql.js +12 -0
  433. package/dist/storage/repositories/index-utility-repository.js +356 -0
  434. package/dist/storage/repositories/index-vec-repository.js +250 -0
  435. package/dist/storage/repositories/outcome-repository.js +119 -0
  436. package/dist/storage/repositories/proposals-repository.js +317 -75
  437. package/dist/storage/repositories/registry-cache.js +1 -1
  438. package/dist/storage/repositories/salience-repository.js +172 -0
  439. package/dist/storage/repositories/task-history-repository.js +110 -3
  440. package/dist/storage/repositories/workflow-runs-repository.js +68 -35
  441. package/dist/tasks/backends/cron.js +169 -46
  442. package/dist/tasks/backends/exec-utils.js +76 -3
  443. package/dist/tasks/backends/index.js +6 -9
  444. package/dist/tasks/backends/launchd.js +292 -55
  445. package/dist/tasks/backends/schtasks.js +557 -70
  446. package/dist/tasks/backends/types.js +4 -0
  447. package/dist/tasks/command-executable.js +93 -0
  448. package/dist/tasks/embedded.js +56 -38
  449. package/dist/tasks/parser.js +156 -64
  450. package/dist/tasks/resolve-akm-bin.js +144 -51
  451. package/dist/tasks/runner.js +377 -209
  452. package/dist/tasks/schedule.js +108 -19
  453. package/dist/tasks/scheduler-invocation.js +296 -0
  454. package/dist/tasks/schema.js +1 -1
  455. package/dist/tasks/task-id.js +35 -0
  456. package/dist/tasks/validator.js +30 -16
  457. package/dist/workflows/authoring/authoring.js +96 -148
  458. package/dist/workflows/authoring/scope-key.js +1 -1
  459. package/dist/workflows/cli.js +0 -20
  460. package/dist/workflows/concurrency-policy.js +15 -0
  461. package/dist/workflows/exec/brief.js +25 -59
  462. package/dist/workflows/exec/frozen-judge.js +47 -0
  463. package/dist/workflows/exec/native-executor.js +157 -94
  464. package/dist/workflows/exec/report.js +365 -200
  465. package/dist/workflows/exec/run-workflow.js +46 -40
  466. package/dist/workflows/exec/scheduler.js +12 -41
  467. package/dist/workflows/exec/step-work.js +239 -205
  468. package/dist/workflows/exec/workflow-engine-gate.js +67 -0
  469. package/dist/workflows/ir/compile.js +141 -283
  470. package/dist/workflows/ir/freeze.js +233 -0
  471. package/dist/workflows/ir/plan-hash.js +40 -5
  472. package/dist/workflows/ir/schema.js +537 -1
  473. package/dist/workflows/parser.js +878 -306
  474. package/dist/workflows/program/expressions.js +20 -208
  475. package/dist/workflows/program/schema.js +7 -10
  476. package/dist/workflows/renderer.js +99 -121
  477. package/dist/workflows/resource-limits.js +22 -0
  478. package/dist/workflows/runtime/checkin.js +1 -1
  479. package/dist/workflows/runtime/plan-classifier.js +131 -0
  480. package/dist/workflows/runtime/runs.js +200 -113
  481. package/dist/workflows/runtime/unit-checkin.js +1 -1
  482. package/dist/workflows/runtime/unit-phases.js +20 -0
  483. package/dist/workflows/runtime/workflow-asset-loader.js +235 -97
  484. package/dist/workflows/schema.js +1 -11
  485. package/dist/workflows/validate-summary.js +4 -26
  486. package/dist/workflows/validator.js +52 -30
  487. package/docs/README.md +42 -78
  488. package/docs/migration/README.md +8 -0
  489. package/docs/migration/release-notes/0.6.0.md +1 -1
  490. package/docs/migration/release-notes/0.7.0.md +9 -8
  491. package/docs/migration/release-notes/0.9.0.md +158 -14
  492. package/docs/migration/v0.7-to-v0.8.md +46 -47
  493. package/docs/migration/v0.8-to-v0.9.md +844 -0
  494. package/docs/reference/README.md +12 -0
  495. package/docs/reference/data-and-telemetry.md +333 -0
  496. package/package.json +21 -17
  497. package/schemas/akm-asset-envelope.json +93 -0
  498. package/schemas/akm-config.json +4636 -0
  499. package/schemas/akm-task.json +87 -0
  500. package/{dist/schemas → schemas}/akm-workflow.json +127 -82
  501. package/dist/akm-migrate-storage +0 -38
  502. package/dist/assets/help/help-accept.md +0 -12
  503. package/dist/assets/help/help-improve.md +0 -84
  504. package/dist/assets/help/help-proposals.md +0 -17
  505. package/dist/assets/help/help-propose.md +0 -17
  506. package/dist/assets/help/help-reject.md +0 -11
  507. package/dist/assets/profiles/frequent.json +0 -13
  508. package/dist/assets/profiles/recombine-only.json +0 -21
  509. package/dist/assets/profiles/reflect-distill.json +0 -30
  510. package/dist/assets/profiles/synthesize.json +0 -15
  511. package/dist/assets/prompts/procedural-system.md +0 -44
  512. package/dist/assets/prompts/recombine-system.md +0 -40
  513. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  514. package/dist/assets/tasks/core/backup.yml +0 -4
  515. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  516. package/dist/assets/templates/html/default.html +0 -78
  517. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  518. package/dist/assets/wiki/index-template.md +0 -12
  519. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  520. package/dist/assets/wiki/log-template.md +0 -8
  521. package/dist/assets/wiki/schema-template.md +0 -61
  522. package/dist/cli/config-migrate.js +0 -150
  523. package/dist/cli/config-validate.js +0 -39
  524. package/dist/commands/graph/graph-cli.js +0 -124
  525. package/dist/commands/graph/graph.js +0 -487
  526. package/dist/commands/improve/calibration.js +0 -161
  527. package/dist/commands/improve/dedup.js +0 -482
  528. package/dist/commands/improve/extract-watch.js +0 -140
  529. package/dist/commands/improve/hot-probation.js +0 -45
  530. package/dist/commands/improve/improve-auto-accept.js +0 -276
  531. package/dist/commands/improve/improve-profiles.js +0 -168
  532. package/dist/commands/improve/procedural.js +0 -398
  533. package/dist/commands/improve/recombine.js +0 -818
  534. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  535. package/dist/commands/lint/agent-linter.js +0 -44
  536. package/dist/commands/lint/command-linter.js +0 -44
  537. package/dist/commands/lint/default-linter.js +0 -16
  538. package/dist/commands/lint/fact-linter.js +0 -39
  539. package/dist/commands/lint/knowledge-linter.js +0 -16
  540. package/dist/commands/lint/memory-linter.js +0 -61
  541. package/dist/commands/lint/registry.js +0 -41
  542. package/dist/commands/lint/skill-linter.js +0 -45
  543. package/dist/commands/lint/task-linter.js +0 -50
  544. package/dist/commands/lint/workflow-linter.js +0 -81
  545. package/dist/commands/proposal/legacy-import.js +0 -115
  546. package/dist/commands/sources/history.js +0 -196
  547. package/dist/commands/tasks/default-tasks.js +0 -186
  548. package/dist/commands/wiki-cli.js +0 -292
  549. package/dist/core/asset/asset-registry.js +0 -76
  550. package/dist/core/asset/asset-spec.js +0 -316
  551. package/dist/core/config/config-migration.js +0 -602
  552. package/dist/core/deep-merge.js +0 -38
  553. package/dist/core/eval/rank-metrics.js +0 -113
  554. package/dist/core/ripgrep/install.js +0 -163
  555. package/dist/core/ripgrep/resolve.js +0 -81
  556. package/dist/indexer/db/db.js +0 -1414
  557. package/dist/indexer/manifest.js +0 -170
  558. package/dist/indexer/passes/metadata-contributors.js +0 -31
  559. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  560. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
  561. package/dist/llm/call-ai.js +0 -62
  562. package/dist/llm/memory-infer-impl.js +0 -138
  563. package/dist/output/shapes/distill.js +0 -14
  564. package/dist/output/shapes/history.js +0 -11
  565. package/dist/output/text/distill.js +0 -6
  566. package/dist/output/text/enable-disable.js +0 -8
  567. package/dist/output/text/history.js +0 -6
  568. package/dist/output/text/wiki.js +0 -16
  569. package/dist/registry/build-index.js +0 -386
  570. package/dist/schemas/akm-config.json +0 -14225
  571. package/dist/scripts/migrate-storage.js +0 -13169
  572. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -10169
  573. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  574. package/dist/setup/legacy-config.js +0 -106
  575. package/dist/storage/repositories/consolidation-repository.js +0 -38
  576. package/dist/storage/repositories/recombine-repository.js +0 -213
  577. package/dist/wiki/wiki-templates.js +0 -15
  578. package/dist/wiki/wiki.js +0 -1012
  579. package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
  580. package/dist/workflows/db.js +0 -350
  581. package/dist/workflows/exec/watch.js +0 -116
  582. package/dist/workflows/program/parser.js +0 -760
  583. package/dist/workflows/program/project.js +0 -105
  584. package/docs/data-and-telemetry.md +0 -227
  585. package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
  586. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  587. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -1,36 +1,65 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ import { randomUUID } from "node:crypto";
4
5
  import fs from "node:fs";
5
6
  import path from "node:path";
6
- import { makeAssetRef, parseAssetRef } from "../../core/asset/asset-ref.js";
7
- import { TYPE_DIRS } from "../../core/asset/asset-spec.js";
8
- import { NotFoundError, UsageError } from "../../core/errors.js";
9
- import { findSourceForPath, getPrimarySource, resolveSourceEntries, } from "../../indexer/search/search-source.js";
10
- import { isRemoteOrigin, resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
7
+ import { stashDirFor } from "../../core/asset/asset-placement.js";
8
+ import { isBundleSlug } from "../../core/asset/asset-ref.js";
9
+ import { displayRef, parseQualifiedRefInput } from "../../core/asset/resolve-ref.js";
10
+ import { loadConfig } from "../../core/config/config.js";
11
+ import { ConfigError, NotFoundError, UsageError } from "../../core/errors.js";
12
+ import { defaultBundleForTarget } from "../../core/mutation-target.js";
13
+ import { warn } from "../../core/warn.js";
14
+ import { commitWriteTargetBoundary, prepareWriteTargetForMutation, resolveWriteTarget, } from "../../core/write-source.js";
15
+ import { withAssetMutationLease } from "../../indexer/index-writer-lock.js";
16
+ import { indexWrittenAssets } from "../../indexer/index-written-assets.js";
17
+ import { findSourceForPath, resolveSourceEntries } from "../../indexer/search/search-source.js";
18
+ import { isRemoteOrigin, resolveSourcesForLocator, resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
11
19
  import { syncFromRef } from "../../sources/providers/sync-from-ref.js";
12
20
  import { resolveAssetPath } from "../../sources/resolve.js";
21
+ function destinationRef(config, target, type, name) {
22
+ if (!config || !target)
23
+ return undefined;
24
+ return displayRef({ type, name, bundleId: target.source.name }, defaultBundleForTarget(config));
25
+ }
13
26
  export async function akmClone(options) {
14
- const parsed = parseAssetRef(options.sourceRef);
15
- // When --dest is provided, the working stash is optional
27
+ const unmanagedDest = options.dest;
28
+ const hasUnmanagedDest = unmanagedDest !== undefined;
29
+ if (hasUnmanagedDest && options.target !== undefined) {
30
+ throw new UsageError("--dest and --bundle cannot be used together; choose an unmanaged path or a managed bundle.");
31
+ }
32
+ // F1b/F4b: accept the 0.9.0 conceptId spelling (`akm clone scripts/deploy.sh`).
33
+ // F5 origin split (parseQualifiedRefInput): `akm clone` also accepts a NON-slug
34
+ // clone SOURCE as the `origin//conceptId` prefix — a registry ref
35
+ // (`npm:@scope/pkg`), a bare path, or a URL — resolved by
36
+ // resolveSourcesForOrigin's registry-id / path matching + the remote-fetch
37
+ // fallback below (the strict new-grammar parser rejects such origins as they
38
+ // are not bundle slugs).
39
+ const parsed = parseQualifiedRefInput(options.sourceRef);
40
+ const config = hasUnmanagedDest ? undefined : loadConfig();
41
+ const resolvedWriteTarget = config ? resolveWriteTarget(config, options.target) : undefined;
42
+ const writeTarget = resolvedWriteTarget ? prepareWriteTargetForMutation(resolvedWriteTarget) : undefined;
43
+ // An unmanaged --dest does not require any configured write target.
16
44
  let allSources;
17
45
  try {
18
46
  allSources = resolveSourceEntries();
19
47
  }
20
48
  catch (err) {
21
- if (options.dest) {
49
+ if (hasUnmanagedDest) {
22
50
  allSources = [];
23
51
  }
24
52
  else {
25
53
  throw err;
26
54
  }
27
55
  }
28
- const primarySource = getPrimarySource(allSources);
29
- const destRoot = options.dest ? path.resolve(options.dest) : primarySource?.path;
56
+ const destRoot = unmanagedDest !== undefined ? path.resolve(unmanagedDest) : writeTarget?.source.path;
30
57
  if (!destRoot) {
31
- throw new Error("No working stash configured and no --dest provided. Run `akm init` or pass --dest.");
58
+ throw new ConfigError("No writable source configured and no --dest provided. Run `akm bundle create` or pass --dest.", "STASH_DIR_NOT_FOUND");
32
59
  }
33
- let searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
60
+ let searchSources = parsed.origin && !isBundleSlug(parsed.origin)
61
+ ? resolveSourcesForLocator(parsed.origin, allSources)
62
+ : resolveSourcesForOrigin(parsed.origin, allSources);
34
63
  // Remote fetch fallback: if no local source matched and origin looks remote, fetch it
35
64
  let remoteFetched;
36
65
  if (searchSources.length === 0 && parsed.origin && isRemoteOrigin(parsed.origin, allSources)) {
@@ -66,9 +95,9 @@ export async function akmClone(options) {
66
95
  }
67
96
  const sourceSource = findSourceForPath(sourcePath, allSources);
68
97
  const destName = options.newName ?? parsed.name;
69
- const typeDir = TYPE_DIRS[parsed.type];
98
+ const typeDir = stashDirFor(parsed.type);
70
99
  // Validate destName to prevent path traversal (parsed.name is already
71
- // validated by parseAssetRef, but newName comes directly from user input).
100
+ // validated by the ref parser, but newName comes directly from user input).
72
101
  // Run whenever newName is provided, including empty string.
73
102
  if (options.newName !== undefined) {
74
103
  if (destName === "") {
@@ -92,7 +121,11 @@ export async function akmClone(options) {
92
121
  throw new UsageError(`Unsafe clone name "${destName}": resolves outside the target type directory.`);
93
122
  }
94
123
  }
95
- const destLabel = options.dest ? "at destination" : "in working stash";
124
+ const destLabel = hasUnmanagedDest
125
+ ? "at destination"
126
+ : writeTarget?.selector
127
+ ? `in target "${writeTarget.selector}"`
128
+ : "in working stash";
96
129
  // Guard against self-clone
97
130
  if (parsed.type === "skill") {
98
131
  const sourceSkillDir = path.resolve(path.dirname(sourcePath));
@@ -110,39 +143,109 @@ export async function akmClone(options) {
110
143
  throw new Error(`Source and destination are the same path. Use --name to provide a new name for the clone.`);
111
144
  }
112
145
  }
113
- let destPath;
114
- if (parsed.type === "skill") {
115
- const sourceSkillDir = path.dirname(sourcePath);
116
- const destSkillDir = path.join(destRoot, typeDir, destName);
117
- const overwritten = fs.existsSync(destSkillDir);
118
- if (overwritten && !options.force) {
119
- throw new Error(`Asset already exists ${destLabel}: ${destSkillDir}. Use --force to overwrite.`);
146
+ return withAssetMutationLease("clone", async () => {
147
+ let destPath;
148
+ let overwritten;
149
+ let operationPaths;
150
+ if (parsed.type === "skill") {
151
+ const sourceSkillDir = path.dirname(sourcePath);
152
+ const destSkillDir = path.join(destRoot, typeDir, destName);
153
+ assertNoDestinationSymlinkParent(destRoot, destSkillDir);
154
+ const existing = lstatIfExists(destSkillDir);
155
+ overwritten = existing !== undefined;
156
+ if (overwritten && !options.force) {
157
+ throw new UsageError(`Asset already exists ${destLabel}: ${destSkillDir}. Use --force to overwrite.`, "RESOURCE_ALREADY_EXISTS");
158
+ }
159
+ const replacedPaths = existing?.isDirectory() && !existing.isSymbolicLink() ? listTreeFiles(destSkillDir) : [];
160
+ // Stage first so a failed source copy leaves the old entry untouched. A
161
+ // final symlink is removed as an entry, never traversed.
162
+ const stagingDir = `${destSkillDir}.tmp-${randomUUID()}`;
163
+ try {
164
+ fs.cpSync(sourceSkillDir, stagingDir, { recursive: true, errorOnExist: true, force: false });
165
+ if (overwritten)
166
+ fs.rmSync(destSkillDir, { recursive: true, force: true });
167
+ fs.renameSync(stagingDir, destSkillDir);
168
+ }
169
+ catch (err) {
170
+ fs.rmSync(stagingDir, { recursive: true, force: true });
171
+ throw err;
172
+ }
173
+ destPath = path.join(destSkillDir, "SKILL.md");
174
+ operationPaths = [...new Set([...replacedPaths, ...listTreeFiles(destSkillDir)])];
120
175
  }
121
- if (overwritten) {
122
- fs.rmSync(destSkillDir, { recursive: true, force: true });
176
+ else {
177
+ destPath = path.join(destRoot, typeDir, destName);
178
+ assertNoDestinationSymlinkParent(destRoot, destPath);
179
+ const existing = lstatIfExists(destPath);
180
+ overwritten = existing !== undefined;
181
+ if (overwritten && !options.force) {
182
+ throw new UsageError(`Asset already exists ${destLabel}: ${destPath}. Use --force to overwrite.`, "RESOURCE_ALREADY_EXISTS");
183
+ }
184
+ fs.mkdirSync(path.dirname(destPath), { recursive: true });
185
+ const stagingPath = `${destPath}.tmp-${randomUUID()}`;
186
+ try {
187
+ fs.copyFileSync(sourcePath, stagingPath, fs.constants.COPYFILE_EXCL);
188
+ if (overwritten)
189
+ fs.rmSync(destPath, { recursive: true, force: true });
190
+ fs.renameSync(stagingPath, destPath);
191
+ }
192
+ catch (err) {
193
+ fs.rmSync(stagingPath, { force: true });
194
+ throw err;
195
+ }
196
+ operationPaths = [destPath];
197
+ }
198
+ const ref = destinationRef(config, writeTarget, parsed.type, destName);
199
+ if (writeTarget) {
200
+ const commitRoot = writeTarget.source.repoPath ?? writeTarget.source.path;
201
+ const commitPaths = operationPaths.map((filePath) => path.relative(commitRoot, filePath).replaceAll(path.sep, "/"));
202
+ commitWriteTargetBoundary(writeTarget, `Clone ${ref}`, { paths: commitPaths });
203
+ if (!(await indexWrittenAssets(writeTarget.source.path, [destPath], { bundleId: writeTarget.source.name }))) {
204
+ warn(`Clone ${ref} succeeded, but its targeted index update failed; run \`akm index\` to refresh it.`);
205
+ }
123
206
  }
124
- fs.cpSync(sourceSkillDir, destSkillDir, { recursive: true });
125
- destPath = path.join(destSkillDir, "SKILL.md");
126
- const ref = makeAssetRef(parsed.type, destName, "local");
127
207
  return {
128
208
  source: { path: sourcePath, registryId: sourceSource?.registryId },
129
- destination: { path: destPath, ref },
209
+ destination: { path: destPath, ...(ref ? { ref } : {}) },
130
210
  overwritten,
131
211
  ...(remoteFetched ? { remoteFetched } : {}),
132
212
  };
213
+ });
214
+ }
215
+ function lstatIfExists(filePath) {
216
+ try {
217
+ return fs.lstatSync(filePath);
133
218
  }
134
- destPath = path.join(destRoot, typeDir, destName);
135
- const overwritten = fs.existsSync(destPath);
136
- if (overwritten && !options.force) {
137
- throw new Error(`Asset already exists ${destLabel}: ${destPath}. Use --force to overwrite.`);
219
+ catch (error) {
220
+ if (error.code === "ENOENT")
221
+ return undefined;
222
+ throw error;
223
+ }
224
+ }
225
+ function assertNoDestinationSymlinkParent(root, destination) {
226
+ const resolvedRoot = path.resolve(root);
227
+ const relativeParent = path.relative(resolvedRoot, path.dirname(path.resolve(destination)));
228
+ if (relativeParent === "" || relativeParent === ".")
229
+ return;
230
+ if (relativeParent.startsWith("..") || path.isAbsolute(relativeParent)) {
231
+ throw new UsageError(`Clone destination escapes the selected target: ${destination}.`, "PATH_ESCAPE_VIOLATION");
232
+ }
233
+ let current = resolvedRoot;
234
+ for (const segment of relativeParent.split(path.sep)) {
235
+ current = path.join(current, segment);
236
+ if (lstatIfExists(current)?.isSymbolicLink()) {
237
+ throw new UsageError(`Clone destination has a symbolic-link parent outside the selected target boundary: ${current}.`, "PATH_ESCAPE_VIOLATION");
238
+ }
239
+ }
240
+ }
241
+ function listTreeFiles(root) {
242
+ const files = [];
243
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
244
+ const entryPath = path.join(root, entry.name);
245
+ if (entry.isDirectory())
246
+ files.push(...listTreeFiles(entryPath));
247
+ else
248
+ files.push(entryPath);
138
249
  }
139
- fs.mkdirSync(path.dirname(destPath), { recursive: true });
140
- fs.copyFileSync(sourcePath, destPath);
141
- const ref = makeAssetRef(parsed.type, destName, "local");
142
- return {
143
- source: { path: sourcePath, registryId: sourceSource?.registryId },
144
- destination: { path: destPath, ref },
145
- overwritten,
146
- ...(remoteFetched ? { remoteFetched } : {}),
147
- };
250
+ return files;
148
251
  }
@@ -2,10 +2,11 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import path from "node:path";
5
+ import { detectAdapterId } from "../../core/adapter/detect-adapter.js";
5
6
  import { isRemoteUrl } from "../../core/common.js";
6
- import { getSources, loadConfig, loadUserConfig, saveConfig } from "../../core/config/config.js";
7
+ import { bundleEntryToSourceEntry, bundlesToSourceEntries, getSources, mutateConfig } from "../../core/config/config.js";
7
8
  import { ConfigError, UsageError } from "../../core/errors.js";
8
- import { resolveSourceEntries } from "../../indexer/search/search-source.js";
9
+ import { bundleKeyForPath, bundleKeyForUrl, nextBundleKey } from "./bundle-config-ops.js";
9
10
  // ── Operations ──────────────────────────────────────────────────────────────
10
11
  /**
11
12
  * Add a stash source (filesystem path or remote provider URL) to config.
@@ -22,72 +23,106 @@ export function addStash(opts) {
22
23
  if (writable === true && providerType && providerType !== "filesystem" && providerType !== "git") {
23
24
  throw new ConfigError("writable: true is only supported on filesystem and git sources", "INVALID_CONFIG_FILE");
24
25
  }
25
- const config = loadUserConfig();
26
- const sources = [...getSources(config)];
27
- let entry;
28
- if (isRemoteUrl(target)) {
29
- if (!providerType) {
30
- throw new UsageError("--provider is required for URL sources (e.g. --provider git --provider website)");
31
- }
32
- // Deduplicate by URL
33
- if (sources.some((s) => s.url === target)) {
34
- return { sources, added: false, message: "Source URL already configured" };
35
- }
36
- entry = { type: providerType, url: target };
37
- if (name)
38
- entry.name = name;
39
- if (writable)
40
- entry.writable = true;
41
- if (providerOptions)
42
- entry.options = providerOptions;
26
+ let result;
27
+ const targetIsUrl = isRemoteUrl(target);
28
+ if (targetIsUrl && !providerType) {
29
+ throw new UsageError("--provider is required for URL sources (e.g. --provider git --provider website)");
43
30
  }
44
- else {
45
- // Filesystem path
46
- const resolvedPath = path.resolve(target);
47
- if (sources.some((s) => s.path && path.resolve(s.path) === resolvedPath)) {
48
- return { sources, added: false, message: "Source path already configured" };
31
+ // R-013: `--provider npm` names an npm package SPEC (e.g. "lodash",
32
+ // "@scope/pkg@^2"), never a URL — a tarball URL is not installable as a
33
+ // package spec and would only fail much later, at first sync, with a
34
+ // confusing "Invalid npm package name" error. Reject it loudly here instead.
35
+ if (providerType === "npm" && targetIsUrl) {
36
+ throw new UsageError(`--provider npm expects a package spec (e.g. "lodash" or "@scope/pkg@^2"), not a URL: "${target}". ` +
37
+ "Drop --provider npm and re-run `akm bundle add <package>` to add an npm source.");
38
+ }
39
+ // A bare (non-URL) target with --provider npm is a declarative npm source
40
+ // add — the same "locator, not a URL" descriptor path used for git/website
41
+ // URL sources below. Without this, a non-URL target fell through to the
42
+ // filesystem branch below and `--provider npm` was silently ignored,
43
+ // creating a bogus filesystem bundle for the current working directory
44
+ // (R-013).
45
+ const useDescriptorPath = targetIsUrl || providerType === "npm";
46
+ mutateConfig((config) => {
47
+ const bundles = { ...(config.bundles ?? {}) };
48
+ let key;
49
+ if (useDescriptorPath) {
50
+ if (bundleKeyForUrl(config, target)) {
51
+ const already = targetIsUrl ? "Source URL already configured" : "Source already configured";
52
+ result = { sources: getSources(config), added: false, message: already };
53
+ return config;
54
+ }
55
+ key = nextBundleKey(bundles, name, target);
56
+ bundles[key] = urlBundleDescriptor(providerType, target, providerOptions, writable === true);
57
+ }
58
+ else {
59
+ const resolvedPath = path.resolve(target);
60
+ if (bundleKeyForPath(config, resolvedPath)) {
61
+ result = { sources: getSources(config), added: false, message: "Source path already configured" };
62
+ return config;
63
+ }
64
+ key = nextBundleKey(bundles, name, resolvedPath);
65
+ bundles[key] = {
66
+ path: resolvedPath,
67
+ ...(writable === true ? { writable: true } : {}),
68
+ components: {
69
+ main: { root: ".", adapter: detectAdapterId(resolvedPath), writable: writable ?? true },
70
+ },
71
+ };
49
72
  }
50
- entry = { type: "filesystem", path: resolvedPath };
51
- if (name)
52
- entry.name = name;
73
+ const next = { ...config, bundles };
74
+ const entry = bundleEntryToSourceEntry(key, bundles[key]);
75
+ result = { sources: bundlesToSourceEntries(next) ?? [], added: true, entry };
76
+ return next;
77
+ });
78
+ return result;
79
+ }
80
+ /**
81
+ * Build the 0.9.0 bundle descriptor for a declarative (non-filesystem) source
82
+ * (spec §10.1). `locator` is a URL for git/website; for npm it is a bare
83
+ * package spec (e.g. "lodash", "@scope/pkg@^2") — never a URL (R-013,
84
+ * rejected earlier in {@link addStash}).
85
+ */
86
+ function urlBundleDescriptor(providerType, locator, options, writable) {
87
+ if (providerType === "website") {
88
+ // Website provider options ride on the (passthrough) website descriptor and
89
+ // round-trip back to `entry.options` via bundleEntryToSourceEntry.
90
+ return {
91
+ website: { url: locator, ...(options ?? {}) },
92
+ components: { main: { root: ".", adapter: "website-snapshot", writable: false } },
93
+ };
53
94
  }
54
- sources.push(entry);
55
- saveConfig({ ...config, sources });
56
- return { sources, added: true, entry };
95
+ if (providerType === "npm")
96
+ return { npm: locator };
97
+ if (providerType === "git")
98
+ return { git: locator, ...(writable ? { writable: true } : {}) };
99
+ throw new ConfigError(`unsupported source type "${providerType}"; expected filesystem, git, website, or npm`, "INVALID_CONFIG_FILE");
57
100
  }
58
101
  /**
59
102
  * Remove a stash source by URL, path, or name.
60
103
  * Match priority: URL > path > name (most specific first).
61
104
  */
62
105
  export function removeStash(target) {
63
- const config = loadUserConfig();
64
- const sources = [...getSources(config)];
65
106
  const isUrlTarget = isRemoteUrl(target);
66
107
  const resolvedPath = !isUrlTarget ? path.resolve(target) : undefined;
67
- // Try URL match first, then path, then name (most specific → least specific)
68
- let idx = -1;
69
- if (isUrlTarget) {
70
- idx = sources.findIndex((s) => s.url === target);
71
- }
72
- if (idx === -1 && resolvedPath) {
73
- idx = sources.findIndex((s) => s.path && path.resolve(s.path) === resolvedPath);
74
- }
75
- if (idx === -1) {
76
- idx = sources.findIndex((s) => s.name === target);
77
- }
78
- if (idx === -1) {
79
- return { sources, removed: false, message: "No matching source found" };
80
- }
81
- const removed = sources.splice(idx, 1)[0];
82
- saveConfig({ ...config, sources });
83
- return { sources, removed: true, entry: removed };
84
- }
85
- /**
86
- * List all stash sources (local filesystem + configured stashes).
87
- */
88
- export function listStashes() {
89
- const config = loadConfig();
90
- const localSources = resolveSourceEntries();
91
- const sources = getSources(config);
92
- return { localSources, sources };
108
+ let result;
109
+ mutateConfig((config) => {
110
+ const bundles = { ...(config.bundles ?? {}) };
111
+ // Match priority: URL > path > bundle key (name).
112
+ let key = isUrlTarget ? bundleKeyForUrl(config, target) : undefined;
113
+ if (!key && resolvedPath)
114
+ key = bundleKeyForPath(config, resolvedPath);
115
+ if (!key && target in bundles)
116
+ key = target;
117
+ if (!key) {
118
+ result = { sources: getSources(config), removed: false, message: "No matching source found" };
119
+ return config;
120
+ }
121
+ const removed = bundleEntryToSourceEntry(key, bundles[key]);
122
+ delete bundles[key];
123
+ const next = { ...config, bundles: Object.keys(bundles).length > 0 ? bundles : undefined };
124
+ result = { sources: bundlesToSourceEntries(next) ?? [], removed: true, entry: removed };
125
+ return next;
126
+ });
127
+ return result;
93
128
  }