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
@@ -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) {