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
@@ -4,13 +4,11 @@
4
4
  import { fetchWithRetry, jsonWithByteCap, toErrorMessage } from "../../core/common.js";
5
5
  import { asString } from "../../integrations/github.js";
6
6
  import { fetchCachedJson } from "../../storage/repositories/registry-cache.js";
7
- import { registerProvider } from "../factory.js";
7
+ import { registerRegistryProvider } from "../factory.js";
8
8
  import { buildInstallRef } from "../resolve.js";
9
9
  // ── Constants ───────────────────────────────────────────────────────────────
10
10
  /** Cache TTL in milliseconds (1 hour). */
11
11
  const CACHE_TTL_MS = 60 * 60 * 1000;
12
- /** Maximum age before cache is considered stale but still usable as fallback (7 days). */
13
- const CACHE_STALE_MS = 7 * 24 * 60 * 60 * 1000;
14
12
  // ── Provider class ──────────────────────────────────────────────────────────
15
13
  class StaticIndexProvider {
16
14
  type = "static-index";
@@ -20,25 +18,25 @@ class StaticIndexProvider {
20
18
  }
21
19
  async search(options) {
22
20
  const warnings = [];
23
- const allKits = await this.loadAllKits(warnings);
24
- const hits = scoreKits(allKits, options.query, options.limit);
21
+ const bundles = await this.loadBundles(warnings);
22
+ const hits = scoreBundles(bundles, options.query, options.limit);
25
23
  let assetHits;
26
24
  if (options.includeAssets) {
27
- const scored = scoreAssets(allKits, options.query, options.limit);
25
+ const scored = scoreAssets(bundles, options.query, options.limit);
28
26
  if (scored.length > 0)
29
27
  assetHits = scored;
30
28
  }
31
29
  return { hits, assetHits, warnings: warnings.length > 0 ? warnings : undefined };
32
30
  }
33
31
  // ── Internals ───────────────────────────────────────────────────────────
34
- async loadAllKits(warnings) {
35
- const allKits = [];
32
+ async loadBundles(warnings) {
33
+ const bundles = [];
36
34
  try {
37
35
  const index = await loadIndex(this.config);
38
36
  if (index) {
39
37
  const regName = this.config.name;
40
38
  for (const stash of index.stashes) {
41
- allKits.push({ stash, registryName: regName });
39
+ bundles.push({ stash, registryName: regName });
42
40
  }
43
41
  }
44
42
  }
@@ -46,18 +44,18 @@ class StaticIndexProvider {
46
44
  const label = this.config.name ? `${this.config.name} (${this.config.url})` : this.config.url;
47
45
  warnings.push(`Registry ${label}: ${toErrorMessage(err)}`);
48
46
  }
49
- return allKits;
47
+ return bundles;
50
48
  }
51
49
  }
52
50
  // ── Self-register ───────────────────────────────────────────────────────────
53
- registerProvider("static-index", (config) => new StaticIndexProvider(config));
51
+ registerRegistryProvider("static-index", (config) => new StaticIndexProvider(config));
54
52
  // ── Index loading with cache ────────────────────────────────────────────────
55
53
  async function loadIndex(entry) {
56
54
  return fetchCachedJson({
57
55
  cacheKey: entry.url,
58
56
  ttlMs: CACHE_TTL_MS,
59
57
  // Both the fresh hit and the stale fallback parse identically; a corrupt
60
- // cache row lets JSON.parse throw out of the load (legacy behaviour).
58
+ // cache row lets JSON.parse throw out of the load.
61
59
  parseCache: (json) => parseRegistryIndex(JSON.parse(json)) ?? undefined,
62
60
  fetchFresh: async () => {
63
61
  const response = await fetchWithRetry(entry.url, undefined, { timeout: 10_000 });
@@ -77,12 +75,6 @@ async function loadIndex(entry) {
77
75
  },
78
76
  });
79
77
  }
80
- export function isCacheExpired(mtimeMs) {
81
- return Date.now() - mtimeMs > CACHE_TTL_MS;
82
- }
83
- export function isCacheStale(mtimeMs) {
84
- return Date.now() - mtimeMs > CACHE_STALE_MS;
85
- }
86
78
  // ── Index parsing (exported for reuse) ──────────────────────────────────────
87
79
  export function parseRegistryIndex(data) {
88
80
  if (typeof data !== "object" || data === null || Array.isArray(data))
@@ -97,13 +89,13 @@ export function parseRegistryIndex(data) {
97
89
  if (!Array.isArray(obj.stashes))
98
90
  return null;
99
91
  const stashes = obj.stashes.flatMap((raw) => {
100
- const stash = parseStashEntry(raw);
92
+ const stash = parseBundleEntry(raw);
101
93
  return stash ? [stash] : [];
102
94
  });
103
95
  return { version: obj.version, updatedAt: obj.updatedAt, stashes };
104
96
  }
105
97
  // ── Stash entry parsing ───────────────────────────────────────────────────────
106
- function parseStashEntry(raw) {
98
+ function parseBundleEntry(raw) {
107
99
  if (typeof raw !== "object" || raw === null || Array.isArray(raw))
108
100
  return null;
109
101
  const obj = raw;
@@ -113,9 +105,7 @@ function parseStashEntry(raw) {
113
105
  const source = asSource(obj.source);
114
106
  if (!id || !name || !ref || !source)
115
107
  return null;
116
- // The legacy registry boolean `curated` is removed in v1. Legacy index JSON
117
- // containing a `curated` key parses normally; the key is silently ignored
118
- // (v1 spec §4.2, docs/migration/v1.md).
108
+ // Some published indexes include `curated`; it is intentionally ignored.
119
109
  return {
120
110
  id,
121
111
  name,
@@ -132,7 +122,7 @@ function parseStashEntry(raw) {
132
122
  };
133
123
  }
134
124
  // ── Scoring ─────────────────────────────────────────────────────────────────
135
- function scoreKits(stashes, query, limit) {
125
+ function scoreBundles(stashes, query, limit) {
136
126
  const tokens = query.toLowerCase().split(/\s+/).filter(Boolean);
137
127
  const scored = [];
138
128
  for (const { stash, registryName } of stashes) {
@@ -247,7 +237,7 @@ function scoreAssets(stashes, query, limit) {
247
237
  estimatedTokens: asset.estimatedTokens,
248
238
  stash: { id: stash.id, name: stash.name },
249
239
  registryName,
250
- action: `akm add ${installRef}`,
240
+ action: `akm bundle add ${installRef}`,
251
241
  score: Math.round(score * 1000) / 1000,
252
242
  },
253
243
  score,
@@ -9,6 +9,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
9
9
  import { fetchWithRetry, jsonWithByteCap } from "../core/common.js";
10
10
  import { NotFoundError, UsageError } from "../core/errors.js";
11
11
  import { asRecord, asString, GITHUB_API_BASE, githubHeaders } from "../integrations/github.js";
12
+ import { isExactSemver, isSemverRange, maxSatisfying } from "./semver.js";
12
13
  /**
13
14
  * Validate that a URL is safe to pass to git.
14
15
  * Allowlists https:, http:, ssh:, git: schemes and git@ SSH shorthand.
@@ -108,13 +109,13 @@ function detectRegistrySearchId(ref) {
108
109
  const suggestedRef = segments.length >= 2 ? `github:${segments[0]}/${segments[1]}` : undefined;
109
110
  const lines = [
110
111
  `"${ref}" looks like a registry search result ID, not an installable ref.`,
111
- `The "${prefix}:" prefix is a registry identifier and cannot be passed to \`akm add\`.`,
112
+ `The "${prefix}:" prefix is a registry identifier and cannot be passed to \`akm bundle add\`.`,
112
113
  "",
113
114
  ];
114
115
  if (suggestedRef) {
115
- lines.push(`Try installing the source repository directly:`, ` akm add ${suggestedRef}`, "");
116
+ lines.push(`Try installing the source repository directly:`, ` akm bundle add ${suggestedRef}`, "");
116
117
  }
117
- lines.push("Or search for the installable ref:", ` akm search "${segments.length > 2 ? segments[segments.length - 1] : rest}" --source registry`, "Then install using the installRef value from the result:", " akm add github:owner/repo", " akm add npm:package-name");
118
+ lines.push("Or search for the installable ref:", ` akm search "${segments.length > 2 ? segments[segments.length - 1] : rest}" --from registry`, "Then install using the installRef value from the result:", " akm bundle add github:owner/repo", " akm bundle add npm:package-name");
118
119
  return lines.join("\n");
119
120
  }
120
121
  export async function resolveRegistryArtifact(parsed) {
@@ -250,6 +251,16 @@ function isPathLikeRef(ref) {
250
251
  if (ref.startsWith("./") || ref.startsWith("../") || ref.startsWith(".\\") || ref.startsWith("..\\")) {
251
252
  return true;
252
253
  }
254
+ // R-007: a bare `owner/repo` (or `owner/repo#ref`) shorthand is ambiguous
255
+ // with a relative directory of the same shape, and is never an EXPLICIT
256
+ // local path the way `./owner/repo` is. Treating it as non-path here means
257
+ // `tryParseLocalRef` silently returns `undefined` (rather than throwing
258
+ // NotFoundError) when no such directory exists on disk, letting
259
+ // `parseRegistryRef`'s GitHub-shorthand fallback run instead. A directory
260
+ // that DOES exist with this shape is unaffected — `tryParseLocalRef`
261
+ // resolves it before the missing-path distinction ever matters.
262
+ if (looksLikeGithubOwnerRepo(ref))
263
+ return false;
253
264
  return ref.includes("/") || ref.includes("\\");
254
265
  }
255
266
  /** Default public npm registry host. */
@@ -317,9 +328,37 @@ export function validateNpmTarballUrl(tarballUrl, packageRef) {
317
328
  throw new UntrustedNpmTarballError(`npm package ${packageRef} returned a tarball URL on untrusted host "${host}" (allowed: ${allowed}).`);
318
329
  }
319
330
  }
331
+ /**
332
+ * Resolve the npm registry base URL used to fetch package METADATA.
333
+ *
334
+ * R-035: `AKM_NPM_REGISTRY` previously only widened the trusted-tarball-host
335
+ * allowlist (see {@link trustedNpmTarballHosts}) while the metadata endpoint
336
+ * stayed hardcoded to the public registry — so an operator-configured mirror
337
+ * was never actually consulted, making the `UntrustedNpmTarballError.hint()`
338
+ * text below false. Honoring the override here for metadata too makes the
339
+ * hint true: installs really do resolve entirely against the configured
340
+ * mirror when it is set, mirroring how a private npm registry replaces the
341
+ * default wholesale (like npm's own `--registry` flag) rather than being
342
+ * merged with it.
343
+ */
344
+ function npmMetadataRegistryBase() {
345
+ const override = process.env.AKM_NPM_REGISTRY?.trim();
346
+ if (override) {
347
+ try {
348
+ const url = new URL(override);
349
+ const base = `${url.origin}${url.pathname === "/" ? "" : url.pathname}`;
350
+ return base.replace(/\/+$/, "");
351
+ }
352
+ catch {
353
+ // Ignore unparseable overrides; fall back to the public registry.
354
+ }
355
+ }
356
+ return `https://${DEFAULT_NPM_REGISTRY_HOST}`;
357
+ }
320
358
  async function resolveNpmArtifact(parsed) {
321
359
  const encodedName = encodeURIComponent(parsed.packageName);
322
- const metadata = await fetchJson(`https://registry.npmjs.org/${encodedName}`);
360
+ const registryBase = npmMetadataRegistryBase();
361
+ const metadata = await fetchJson(`${registryBase}/${encodedName}`);
323
362
  const versions = asRecord(metadata.versions);
324
363
  const distTags = asRecord(metadata["dist-tags"]);
325
364
  const requested = parsed.requestedVersionOrTag;
@@ -560,96 +599,6 @@ function readGitValue(repoRoot, ...args) {
560
599
  const value = result.stdout.trim();
561
600
  return value || undefined;
562
601
  }
563
- function parseSemver(version) {
564
- const match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
565
- if (!match)
566
- return undefined;
567
- return {
568
- major: parseInt(match[1], 10),
569
- minor: parseInt(match[2], 10),
570
- patch: parseInt(match[3], 10),
571
- prerelease: match[4],
572
- };
573
- }
574
- function isExactSemver(version) {
575
- return /^\d+\.\d+\.\d+(?:-[a-zA-Z0-9.+-]+)?$/.test(version);
576
- }
577
- function isSemverRange(input) {
578
- return /^[~^>=<*]/.test(input) || /^\d+\.(\d+|\*)/.test(input);
579
- }
580
- function compareSemver(a, b) {
581
- if (a.major !== b.major)
582
- return a.major - b.major;
583
- if (a.minor !== b.minor)
584
- return a.minor - b.minor;
585
- if (a.patch !== b.patch)
586
- return a.patch - b.patch;
587
- // Versions with prerelease are lower than release
588
- if (a.prerelease && !b.prerelease)
589
- return -1;
590
- if (!a.prerelease && b.prerelease)
591
- return 1;
592
- return 0;
593
- }
594
- function semverGte(a, b) {
595
- return compareSemver(a, b) >= 0;
596
- }
597
- function satisfiesRange(version, range) {
598
- // Skip pre-release versions unless range specifically mentions one
599
- if (version.prerelease && !range.includes("-"))
600
- return false;
601
- // ^1.2.3 — compatible with version: same major, >= minor.patch
602
- const caretMatch = range.match(/^\^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
603
- if (caretMatch) {
604
- const rMajor = parseInt(caretMatch[1], 10);
605
- const rMinor = parseInt(caretMatch[2], 10);
606
- const rPatch = parseInt(caretMatch[3], 10);
607
- if (version.major !== rMajor)
608
- return false;
609
- // ^0.x has special behavior: ^0.2.3 means >=0.2.3 <0.3.0
610
- if (rMajor === 0) {
611
- if (version.minor !== rMinor)
612
- return false;
613
- return version.patch >= rPatch;
614
- }
615
- return semverGte(version, { major: rMajor, minor: rMinor, patch: rPatch });
616
- }
617
- // ~1.2.3 — same major.minor, patch >= specified
618
- const tildeMatch = range.match(/^~(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
619
- if (tildeMatch) {
620
- const rMajor = parseInt(tildeMatch[1], 10);
621
- const rMinor = parseInt(tildeMatch[2], 10);
622
- const rPatch = parseInt(tildeMatch[3], 10);
623
- return version.major === rMajor && version.minor === rMinor && version.patch >= rPatch;
624
- }
625
- // >=1.2.3
626
- const gteMatch = range.match(/^>=(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
627
- if (gteMatch) {
628
- const rMajor = parseInt(gteMatch[1], 10);
629
- const rMinor = parseInt(gteMatch[2], 10);
630
- const rPatch = parseInt(gteMatch[3], 10);
631
- return semverGte(version, { major: rMajor, minor: rMinor, patch: rPatch });
632
- }
633
- // * or latest
634
- if (range === "*" || range === "latest")
635
- return true;
636
- return false;
637
- }
638
- export function maxSatisfying(versions, range) {
639
- const candidates = [];
640
- for (const v of versions) {
641
- const parsed = parseSemver(v);
642
- if (!parsed)
643
- continue;
644
- if (satisfiesRange(parsed, range)) {
645
- candidates.push({ version: v, parsed });
646
- }
647
- }
648
- if (candidates.length === 0)
649
- return undefined;
650
- candidates.sort((a, b) => compareSemver(b.parsed, a.parsed));
651
- return candidates[0].version;
652
- }
653
602
  // Cap JSON responses at 10 MB — npm package manifests and GitHub API
654
603
  // responses are typically a few KB; a compromised registry streaming
655
604
  // tens of MB of JSON is a DoS surface, not a feature.
@@ -0,0 +1,43 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * Registry semver engine (§4.6 dedup, WI-9.3).
6
+ *
7
+ * R-068 #3: this used to be a hand-rolled parse/compare/range implementation
8
+ * (a verbatim move from `./resolve.ts`) that only understood exact versions,
9
+ * `^x.y.z`, `~x.y.z`, `>=x.y.z`, and `*`/`latest`. Every OTHER valid npm range
10
+ * form was silently REJECTED by `satisfiesRange` even though the looser
11
+ * `isSemverRange` classifier correctly recognized it as a range: `1.2.x`,
12
+ * `>1.0.0`, `<2.0.0`, compound ranges (`>=1.0.0 <2.0.0`), partial carets
13
+ * (`^1.2`), OR-ranges (`a || b`), hyphen ranges (`1.2.3 - 2.3.4`), and plain
14
+ * exact versions used as a range. A silently-empty `maxSatisfying` result for
15
+ * a genuinely satisfiable range meant `akm bundle add pkg@<range>` could fail to
16
+ * resolve a real, installable version.
17
+ *
18
+ * `semver` (the npm package) is already a runtime dependency
19
+ * (`package.json`) — it was simply never imported from `src/`. This module
20
+ * now delegates to it directly instead of re-deriving a subset of its
21
+ * behavior, so every range form `semver` itself understands is supported.
22
+ *
23
+ * NOTE: `src/runtime.ts` has its own `semverOrder` with a DIFFERENT
24
+ * contract (engine-version ordering, not range satisfaction) — the two are
25
+ * intentionally not unified.
26
+ */
27
+ import semver from "semver";
28
+ /** True when `version` is an exact, fully-specified semver (not a range, wildcard, or partial version). */
29
+ export function isExactSemver(version) {
30
+ return semver.valid(version) !== null;
31
+ }
32
+ /**
33
+ * True when `input` is a semver RANGE expression `maxSatisfying` can
34
+ * evaluate. Deliberately false for npm dist-tag conventions like `"latest"`
35
+ * — those are resolved via `dist-tags` lookup, not range satisfaction.
36
+ */
37
+ export function isSemverRange(input) {
38
+ return semver.validRange(input) !== null;
39
+ }
40
+ /** Highest version in `versions` that satisfies `range`, or `undefined` if none match. */
41
+ export function maxSatisfying(versions, range) {
42
+ return semver.maxSatisfying(versions, range) ?? undefined;
43
+ }
package/dist/runtime.js CHANGED
@@ -28,6 +28,7 @@ import path from "node:path";
28
28
  import { Readable } from "node:stream";
29
29
  import { pipeline } from "node:stream/promises";
30
30
  import { fileURLToPath } from "node:url";
31
+ import { ResponseTooLargeError, readChunkWithDeadline } from "./core/common.js";
31
32
  /** True when running under the Bun runtime. Computed once at module load. */
32
33
  const isBun = !!process.versions?.bun;
33
34
  /** A CommonJS-style require usable from this ESM module on both runtimes. */
@@ -136,22 +137,77 @@ function stdinIterator() {
136
137
  }
137
138
  // ── File write ──────────────────────────────────────────────────────────────
138
139
  /**
139
- * Stream a `Response` (or its body) to `filePath`. On Bun uses `Bun.write`,
140
- * which natively streams a `Response` to disk; on Node pipes the response body
141
- * through `stream/promises.pipeline` so the archive is never fully buffered.
140
+ * Defensive ceiling on a streamed-to-disk download (1 GiB).
142
141
  */
143
- export async function writeResponseToFile(filePath, res) {
144
- if (isBun) {
145
- await bunGlobal().write(filePath, res);
146
- return;
142
+ export const MAX_STREAMED_DOWNLOAD_BYTES = 1024 * 1024 * 1024;
143
+ /** Default overall wall-clock budget for streaming a download body (5 min). */
144
+ export const STREAMED_DOWNLOAD_BODY_TIMEOUT_MS = 5 * 60_000;
145
+ function writeStreamChunk(out, chunk) {
146
+ return new Promise((resolve, reject) => {
147
+ out.write(chunk, (err) => (err ? reject(err) : resolve()));
148
+ });
149
+ }
150
+ function endWriteStream(out) {
151
+ return new Promise((resolve, reject) => {
152
+ out.once("error", reject);
153
+ out.end(() => resolve());
154
+ });
155
+ }
156
+ /**
157
+ * Stream a `Response` body to `filePath` enforcing an explicit max-bytes cap
158
+ * and an overall body-read deadline.
159
+ *
160
+ * Refuses before reading when `Content-Length` exceeds the cap; otherwise
161
+ * streams chunk-by-chunk, aborting with {@link ResponseTooLargeError} the
162
+ * instant BYTES WRITTEN exceed the cap, or {@link BodyReadTimeoutError} when the
163
+ * body-read deadline passes. Uses the same runtime-agnostic reader loop on Bun
164
+ * and Node (correctness over the native `Bun.write` fast path, which offers no
165
+ * per-byte hook). On any failure the partial file is discarded and the stream
166
+ * cancelled.
167
+ */
168
+ export async function writeResponseToFileCapped(filePath, res, options) {
169
+ const maxBytes = options?.maxBytes ?? MAX_STREAMED_DOWNLOAD_BYTES;
170
+ const bodyTimeoutMs = options?.bodyTimeoutMs ?? STREAMED_DOWNLOAD_BODY_TIMEOUT_MS;
171
+ const url = res.url || filePath;
172
+ const declared = Number(res.headers.get("content-length"));
173
+ if (Number.isFinite(declared) && declared > maxBytes) {
174
+ await res.body?.cancel?.().catch(() => undefined);
175
+ throw new ResponseTooLargeError(url, maxBytes, declared);
147
176
  }
148
- if (res.body) {
149
- const readable = Readable.fromWeb(res.body);
150
- await pipeline(readable, createWriteStream(filePath));
177
+ const body = res.body;
178
+ if (!body) {
179
+ const buf = Buffer.from(await res.arrayBuffer());
180
+ if (buf.byteLength > maxBytes)
181
+ throw new ResponseTooLargeError(url, maxBytes, buf.byteLength);
182
+ await pipeline(Readable.from(buf), createWriteStream(filePath));
151
183
  return;
152
184
  }
153
- const buf = Buffer.from(await res.arrayBuffer());
154
- await pipeline(Readable.from(buf), createWriteStream(filePath));
185
+ const reader = body.getReader();
186
+ const out = createWriteStream(filePath);
187
+ const deadlineAt = Date.now() + bodyTimeoutMs;
188
+ let total = 0;
189
+ try {
190
+ while (true) {
191
+ const { done, value } = await readChunkWithDeadline(reader, deadlineAt, options?.signal, url, bodyTimeoutMs);
192
+ if (done)
193
+ break;
194
+ if (!value)
195
+ continue;
196
+ total += value.byteLength;
197
+ if (total > maxBytes)
198
+ throw new ResponseTooLargeError(url, maxBytes, total);
199
+ await writeStreamChunk(out, value);
200
+ }
201
+ await endWriteStream(out);
202
+ }
203
+ catch (err) {
204
+ out.destroy();
205
+ await reader.cancel().catch(() => undefined);
206
+ throw err;
207
+ }
208
+ finally {
209
+ reader.releaseLock?.();
210
+ }
155
211
  }
156
212
  // ── Hashing ─────────────────────────────────────────────────────────────────
157
213
  /**
@@ -237,6 +293,19 @@ export function sleepSync(ms) {
237
293
  }
238
294
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
239
295
  }
296
+ /**
297
+ * Request a synchronous garbage collection. On Bun runs `Bun.gc(true)`; on
298
+ * Node a no-op (no portable forced-GC without --expose-gc). Used by the
299
+ * migrate-apply WAL conversion to finalize any zombie-closed bun:sqlite
300
+ * connection (statements not finalized before close keep the connection and
301
+ * its WAL shared memory alive until GC — issue #720) before concluding that
302
+ * ANOTHER process holds the database.
303
+ */
304
+ export function requestGc() {
305
+ if (isBun) {
306
+ bunGlobal().gc(true);
307
+ }
308
+ }
240
309
  /** Async sleep for `ms`. On Bun uses `Bun.sleep`; on Node a `setTimeout` promise. */
241
310
  export function sleep(ms) {
242
311
  if (isBun) {