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
@@ -3,16 +3,152 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
5
  * Runtime helpers that derive {@link ConfiguredSource} values from the
6
- * persisted {@link SourceConfigEntry} / {@link InstalledStashEntry} shapes
6
+ * persisted {@link SourceConfigEntry} / {@link InstalledBundle} shapes
7
7
  * in an {@link AkmConfig}.
8
8
  */
9
9
  import { createHash } from "node:crypto";
10
+ import path from "node:path";
11
+ import { ConfigError } from "../errors.js";
12
+ /** The current one-component-per-bundle configuration entry, if present. */
13
+ export function bundleComponentConfig(bundle) {
14
+ if (!bundle?.components)
15
+ return undefined;
16
+ const components = Object.values(bundle.components);
17
+ if (components.length !== 1) {
18
+ throw new ConfigError("A bundle components map must contain exactly one component.", "INVALID_CONFIG_FILE");
19
+ }
20
+ return components[0];
21
+ }
22
+ /**
23
+ * Convert a `bundles` map (0.9.0 config-shape cutover, spec §10.1 / D-R5) into
24
+ * the ordered {@link SourceConfigEntry} list the transitional runtime source
25
+ * resolvers already consume — `defaultBundle` first (primary), then map
26
+ * insertion order (preserving today's installation-priority semantics, on which
27
+ * D-R4 short-ref resolution depends). Each entry's `name` IS its bundle key, so
28
+ * `deriveInstallations` re-derives the exact same installation id (D-R5 rule 1).
29
+ *
30
+ * Returns `undefined` for an old-shape config (no `bundles`), so callers fall
31
+ * back to the pre-cutover `stashDir`/`sources[]`/`installed[]` resolution.
32
+ */
33
+ /**
34
+ * The resolved primary stash path — the `defaultBundle`'s filesystem `path`
35
+ * (spec §10.1) — or `undefined` when no filesystem primary is configured.
36
+ */
37
+ export function primaryBundlePath(config) {
38
+ const bundles = config.bundles;
39
+ const key = config.defaultBundle;
40
+ if (!bundles || !key)
41
+ return undefined;
42
+ const entry = bundles[key];
43
+ if (!entry || typeof entry.path !== "string" || entry.path.length === 0)
44
+ return undefined;
45
+ const componentRoot = bundleComponentConfig(entry)?.root;
46
+ if (!componentRoot || componentRoot === ".")
47
+ return entry.path;
48
+ const bundleRoot = path.resolve(entry.path);
49
+ const resolved = path.resolve(bundleRoot, componentRoot);
50
+ const relative = path.relative(bundleRoot, resolved);
51
+ if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
52
+ throw new ConfigError(`Component root "${componentRoot}" escapes bundle "${key}".`, "INVALID_CONFIG_FILE");
53
+ }
54
+ return resolved;
55
+ }
56
+ export function bundlesToSourceEntries(config) {
57
+ const bundles = config.bundles;
58
+ if (!bundles)
59
+ return undefined;
60
+ const keys = Object.keys(bundles);
61
+ const defaultKey = config.defaultBundle && config.defaultBundle in bundles ? config.defaultBundle : undefined;
62
+ const ordered = defaultKey ? [defaultKey, ...keys.filter((k) => k !== defaultKey)] : keys;
63
+ const entries = [];
64
+ for (const key of ordered) {
65
+ const entry = bundleEntryToSourceEntry(key, bundles[key], key === defaultKey);
66
+ if (entry)
67
+ entries.push(entry);
68
+ }
69
+ return entries;
70
+ }
71
+ /** Map one `bundles.<key>` entry to a runtime {@link SourceConfigEntry}. */
72
+ export function bundleEntryToSourceEntry(key, bundle, isPrimary = false) {
73
+ const base = {
74
+ name: key,
75
+ ...(bundle.writable !== undefined ? { writable: bundle.writable } : {}),
76
+ ...(bundle.enabled !== undefined ? { enabled: bundle.enabled } : {}),
77
+ ...(isPrimary ? { primary: true } : {}),
78
+ };
79
+ if (typeof bundle.path === "string" && bundle.path.length > 0) {
80
+ return { type: "filesystem", path: bundle.path, ...base };
81
+ }
82
+ if (typeof bundle.git === "string" && bundle.git.length > 0) {
83
+ return { type: "git", url: normalizeInstalledGitRef("", bundle.git), ...base };
84
+ }
85
+ if (bundle.website && typeof bundle.website.url === "string") {
86
+ // All non-`url` website-descriptor keys (maxPages/refresh/maxDepth + any
87
+ // passthrough provider options) round-trip back to the runtime entry's
88
+ // `options` bag, mirroring the pre-cutover `sources[].options` shape.
89
+ const { url, ...rest } = bundle.website;
90
+ return {
91
+ type: "website",
92
+ url,
93
+ ...(Object.keys(rest).length > 0 ? { options: rest } : {}),
94
+ ...base,
95
+ };
96
+ }
97
+ if (typeof bundle.npm === "string" && bundle.npm.length > 0) {
98
+ // Today's npm source carries the package spec in `path` (see parseSourceSpec).
99
+ return { type: "npm", path: bundle.npm, ...base };
100
+ }
101
+ return undefined;
102
+ }
103
+ /**
104
+ * Desired 0.9.0 bundle descriptor for a registry-installed source (spec §10.1).
105
+ * Maps the install source kind onto the ONE source descriptor a bundle entry
106
+ * carries: git/github → a provider-ready clone URL, npm → `{ npm: ref }`,
107
+ * everything else (local/filesystem) → `{ path: stashRoot }`.
108
+ *
109
+ * CRITICAL (spec §10.2:453): the materialized cache root NEVER appears in the
110
+ * descriptor for a git/npm bundle — the desired config carries only the source
111
+ * descriptor; the install locator stays in `registryId` and the resolved root
112
+ * belongs exclusively in the lock's `localRoot`. Callers layer
113
+ * `registryId`/`writable` onto the result.
114
+ */
115
+ export function installedSourceDescriptor(source, ref, stashRoot) {
116
+ switch (source) {
117
+ case "git":
118
+ case "github":
119
+ if (ref)
120
+ return { git: normalizeInstalledGitRef(source, ref) };
121
+ break;
122
+ case "npm":
123
+ if (ref)
124
+ return { npm: ref };
125
+ break;
126
+ default:
127
+ break;
128
+ }
129
+ // local/filesystem installs reference a real on-disk path (no package-manager
130
+ // cache to re-materialize), so the resolved root IS the desired path.
131
+ return { path: stashRoot };
132
+ }
133
+ function normalizeInstalledGitRef(source, ref) {
134
+ if (ref.startsWith("git+"))
135
+ return ref.slice(4);
136
+ const isGithubShorthand = ref.startsWith("github:") || (source === "github" && /^[^/:#]+\/[^/#]+(?:#.+)?$/.test(ref));
137
+ if (!isGithubShorthand)
138
+ return ref;
139
+ const body = ref.startsWith("github:") ? ref.slice("github:".length) : ref;
140
+ const fragmentAt = body.indexOf("#");
141
+ const repository = fragmentAt >= 0 ? body.slice(0, fragmentAt) : body;
142
+ const requestedRef = fragmentAt >= 0 ? body.slice(fragmentAt + 1) : "";
143
+ const cloneUrl = `https://github.com/${repository.replace(/\.git$/i, "")}`;
144
+ return requestedRef ? `${cloneUrl}/tree/${requestedRef}` : cloneUrl;
145
+ }
10
146
  /**
11
147
  * Synthesize a stable identifier when a {@link SourceConfigEntry} omits its
12
148
  * `name`. Uses a short hash of the discriminating fields so two equivalent
13
149
  * entries collapse to the same generated name.
14
150
  */
15
- function deriveStashEntryName(entry) {
151
+ function deriveBundleName(entry) {
16
152
  if (entry.name)
17
153
  return entry.name;
18
154
  const seed = JSON.stringify({
@@ -46,63 +182,50 @@ export function parseSourceSpec(entry) {
46
182
  case "npm":
47
183
  return entry.path ? { type: "npm", package: entry.path } : undefined;
48
184
  default:
49
- // Unknown provider — best-effort fallback so callers still get something.
50
- return entry.path ? { type: "filesystem", path: entry.path } : undefined;
185
+ return undefined;
51
186
  }
52
187
  }
53
188
  /**
54
- * Build the full ordered list of runtime {@link ConfiguredSource} values from
55
- * a loaded {@link AkmConfig}:
56
- * 1. The entry marked `primary: true` (or a synthetic entry from `stashDir`).
57
- * 2. Remaining `sources[]` entries in declared order.
58
- * 3. Legacy `installed[]` entries, mapped into runtime entries.
189
+ * Build the full ordered list of runtime {@link ConfiguredSource} values from a
190
+ * loaded {@link AkmConfig}, resolved from `bundles` + `defaultBundle` (spec
191
+ * §10.1): the `defaultBundle` (primary) first, then map insertion order. The
192
+ * retired `stashDir`/`sources[]`/`installed[]` trio is no longer read here — a
193
+ * pre-cutover config is normalized to bundles by the migrator before it loads.
59
194
  *
60
195
  * Entries with `enabled: false` are still emitted — callers decide whether to
61
196
  * honour the flag. Entries that fail {@link parseSourceSpec} drop silently.
197
+ * Returns `[]` when no bundles are configured.
62
198
  */
63
199
  export function resolveConfiguredSources(config) {
64
- const entries = [];
65
- const sources = config.sources ?? [];
66
- let primary = sources.find((entry) => entry.primary === true);
67
- if (!primary && config.stashDir) {
68
- primary = { type: "filesystem", path: config.stashDir, primary: true };
200
+ const bundleEntries = bundlesToSourceEntries(config);
201
+ if (!bundleEntries)
202
+ return [];
203
+ const out = [];
204
+ for (const persisted of bundleEntries) {
205
+ const runtime = toConfiguredSource(persisted, persisted.primary === true);
206
+ if (runtime) {
207
+ const component = bundleComponentConfig(config.bundles?.[persisted.name ?? ""]);
208
+ out.push({
209
+ ...runtime,
210
+ ...(component?.adapter ? { adapterId: component.adapter } : {}),
211
+ ...(component?.root ? { componentRoot: component.root } : {}),
212
+ ...(component?.writable !== undefined ? { writable: component.writable } : {}),
213
+ });
214
+ }
69
215
  }
70
- if (primary) {
71
- const runtime = toConfiguredSource(primary, true);
72
- if (runtime)
73
- entries.push(runtime);
74
- }
75
- for (const entry of sources) {
76
- if (entry === primary)
77
- continue;
78
- const runtime = toConfiguredSource(entry, false);
79
- if (runtime)
80
- entries.push(runtime);
81
- }
82
- for (const installed of config.installed ?? []) {
83
- entries.push({
84
- name: installed.id,
85
- type: "filesystem",
86
- source: { type: "filesystem", path: installed.stashRoot },
87
- enabled: true,
88
- writable: installed.writable,
89
- ...(installed.wikiName ? { wikiName: installed.wikiName } : {}),
90
- });
91
- }
92
- return entries;
216
+ return out;
93
217
  }
94
218
  function toConfiguredSource(persisted, isPrimary) {
95
219
  const source = parseSourceSpec(persisted);
96
220
  if (!source)
97
221
  return undefined;
98
222
  return {
99
- name: deriveStashEntryName(persisted),
223
+ name: deriveBundleName(persisted),
100
224
  type: persisted.type,
101
225
  source,
102
226
  ...(persisted.enabled !== undefined ? { enabled: persisted.enabled } : {}),
103
227
  ...(persisted.writable !== undefined ? { writable: persisted.writable } : {}),
104
228
  ...(isPrimary || persisted.primary ? { primary: true } : {}),
105
229
  ...(persisted.options ? { options: persisted.options } : {}),
106
- ...(persisted.wikiName ? { wikiName: persisted.wikiName } : {}),
107
230
  };
108
231
  }
@@ -1,16 +1,21 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- // VALID_HARNESS_IDS now derives from the unified HARNESS_REGISTRY (#562), which
5
- // is the single source of truth replacing the previously-disconnected
6
- // registries. config ← harnesses is the only import direction (harnesses/ is a
7
- // dependency-graph leaf), so there is no cycle.
8
- import { VALID_HARNESS_IDS } from "../../integrations/harnesses/index.js";
4
+ // VALID_HARNESS_IDS / HARNESS_AGENT_DISPATCH_IDS derive from the dependency-free
5
+ // harnesses/ids.ts leaf (WI-9.8 KILL 3), NOT the full HARNESS_REGISTRY barrel
6
+ // (`../../integrations/harnesses`) — that barrel transitively pulls in every
7
+ // harness's agent-builder and the agent runtime, which is what fused config
8
+ // into the same import-cycle SCC as `integrations/agent/*`. `harnesses/index.ts`
9
+ // asserts at construction time that its registry matches this leaf, so the two
10
+ // cannot silently drift (see `tests/harnesses-registry.test.ts` for the
11
+ // value-level pin). config ← harnesses/ids is the only import direction (the
12
+ // leaf imports nothing), so there is no cycle.
13
+ import { HARNESS_AGENT_DISPATCH_IDS, VALID_HARNESS_IDS } from "../../integrations/harnesses/ids.js";
9
14
  /**
10
- * Canonical list of valid agent harness / platform ids. Re-exported from the
11
- * unified harness registry (#562) so the Zod `AgentPlatformSchema` enum, the
12
- * `AgentProfileConfig` platform union, and setup's `DetectedHarness` union all
13
- * derive from one place and cannot drift. Add a harness in
14
- * `src/integrations/harnesses/index.ts`.
15
+ * Canonical list of valid agent harness / platform ids. Derived from the
16
+ * dependency-free harness-id leaf (#562/WI-9.8) so the Zod `AgentPlatformSchema`
17
+ * enum, the agent-engine platform union, and setup's `DetectedHarness` union
18
+ * all derive from one place and cannot drift. Add a harness in
19
+ * `src/integrations/harnesses/index.ts` (and its `ids.ts` mirror entry).
15
20
  */
16
- export { VALID_HARNESS_IDS };
21
+ export { HARNESS_AGENT_DISPATCH_IDS, VALID_HARNESS_IDS };
@@ -0,0 +1,29 @@
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
+ /** Compare legacy numeric or semver-like config versions for diagnostics only. */
5
+ export function compareConfigVersion(a, b) {
6
+ const left = normalize(a);
7
+ const right = normalize(b);
8
+ if (!left || !right)
9
+ return undefined;
10
+ for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
11
+ const l = left[index] ?? 0;
12
+ const r = right[index] ?? 0;
13
+ if (l < r)
14
+ return -1;
15
+ if (l > r)
16
+ return 1;
17
+ }
18
+ return 0;
19
+ }
20
+ function normalize(value) {
21
+ if (typeof value === "number" && Number.isFinite(value))
22
+ return [0, Math.trunc(value), 0];
23
+ if (typeof value !== "string" || !value.trim())
24
+ return undefined;
25
+ const parts = value.trim().replace(/^v/i, "").split(/[-+]/, 1)[0].split(".");
26
+ if (parts.some((part) => !/^\d+$/.test(part)))
27
+ return undefined;
28
+ return parts.map(Number);
29
+ }
@@ -22,7 +22,8 @@
22
22
  */
23
23
  import { z } from "zod";
24
24
  import { UsageError } from "../errors.js";
25
- import { AkmConfigBaseSchema, listTopLevelConfigKeys } from "./config-schema.js";
25
+ import { AkmConfigBaseSchema, EngineConfigSchema, listTopLevelConfigKeys } from "./config-schema.js";
26
+ import { deepMergeConfig } from "./deep-merge.js";
26
27
  /**
27
28
  * Parse a dotted path into segments. Empty segments are rejected. Bracket
28
29
  * notation (e.g. `sources[0]`) is NOT supported — arrays are set as JSON.
@@ -73,9 +74,10 @@ function unwrap(schema) {
73
74
  * AkmConfig schema. Returns `undefined` if any path segment doesn't match a
74
75
  * known schema field.
75
76
  */
76
- function resolveSchemaAt(path) {
77
+ function resolveSchemaAt(path, config, raw) {
77
78
  let schema = AkmConfigBaseSchema;
78
- for (const segment of path) {
79
+ let existing = config;
80
+ for (const [index, segment] of path.entries()) {
79
81
  schema = unwrap(schema);
80
82
  if (schema instanceof z.ZodObject) {
81
83
  const next = schema.shape[segment];
@@ -84,23 +86,56 @@ function resolveSchemaAt(path) {
84
86
  const catchall = schema._def.catchall;
85
87
  if (catchall && !(catchall instanceof z.ZodNever)) {
86
88
  schema = catchall;
87
- continue;
88
89
  }
89
- return undefined;
90
+ else {
91
+ return undefined;
92
+ }
93
+ }
94
+ else {
95
+ schema = next;
90
96
  }
91
- schema = next;
92
97
  }
93
98
  else if (schema instanceof z.ZodRecord) {
94
- // Records (profiles.llm, profiles.agent, profiles.improve, sources, etc.)
99
+ // Named records (engines, improve.strategies, sources, etc.)
95
100
  // accept any string key — descend into the value schema.
96
101
  schema = schema._def.valueType;
97
102
  }
103
+ else if (schema instanceof z.ZodUnion) {
104
+ const option = selectUnionObjectOption(schema._def.options, segment, existing, index === path.length - 1 ? raw : undefined);
105
+ if (!option)
106
+ return undefined;
107
+ schema = option.shape[segment];
108
+ }
98
109
  else {
99
110
  // Cannot descend into a non-object schema.
100
111
  return undefined;
101
112
  }
113
+ existing = isPlainObject(existing) ? existing[segment] : undefined;
102
114
  }
103
- return unwrap(schema);
115
+ // Preserve leaf refinements/transforms for validation. Traversal unwraps at
116
+ // the start of each loop iteration, while coercion unwraps independently.
117
+ return schema;
118
+ }
119
+ function selectUnionObjectOption(candidates, segment, existing, raw) {
120
+ const options = candidates
121
+ .map((candidate) => unwrap(candidate))
122
+ .filter((candidate) => candidate instanceof z.ZodObject);
123
+ if (raw !== undefined) {
124
+ const requested = options.find((option) => {
125
+ const leaf = option.shape[segment];
126
+ if (!leaf || !(unwrap(leaf) instanceof z.ZodLiteral))
127
+ return false;
128
+ return leaf.safeParse(coerceForSchema(leaf, raw, segment)).success;
129
+ });
130
+ if (requested)
131
+ return requested;
132
+ }
133
+ if (isPlainObject(existing)) {
134
+ const selected = options.find((option) => Object.entries(option.shape).some(([key, field]) => key in existing && unwrap(field) instanceof z.ZodLiteral && field.safeParse(existing[key]).success));
135
+ if (selected)
136
+ return segment in selected.shape ? selected : undefined;
137
+ }
138
+ return options.find((option) => segment in option.shape);
104
139
  }
105
140
  /**
106
141
  * Get the value at the dotted path from a config-shaped object. Returns
@@ -109,7 +144,7 @@ function resolveSchemaAt(path) {
109
144
  */
110
145
  export function configGet(config, dotted) {
111
146
  const path = parsePath(dotted);
112
- const schema = resolveSchemaAt(path);
147
+ const schema = resolveSchemaAt(path, config);
113
148
  if (!schema) {
114
149
  throw new UsageError(`Unknown config key: ${dotted}`, "INVALID_FLAG_VALUE", unknownKeyHint(dotted));
115
150
  }
@@ -129,23 +164,38 @@ export function configGet(config, dotted) {
129
164
  *
130
165
  * Throws {@link UsageError} on:
131
166
  * - unknown path
132
- * - apiKey paths (#454)
167
+ * - invalid apiKey paths
133
168
  * - coercion failure
134
169
  */
135
170
  export function configSet(config, dotted, raw) {
136
171
  const path = parsePath(dotted);
172
+ if (path.length === 1 && path[0] === "configVersion") {
173
+ throw new UsageError("configVersion cannot be changed through config set.", "INVALID_FLAG_VALUE");
174
+ }
137
175
  // #454: apiKey paths are not persistable. Throw at set time.
138
176
  rejectApiKeyPath(path, dotted);
139
- const schema = resolveSchemaAt(path);
140
- if (!schema) {
177
+ const schema = resolveSchemaAt(path, config, raw);
178
+ const symbolicApiKey = (path[0] === "engines" && path[2] === "apiKey") ||
179
+ (path[0] === "embedding" && path.length === 2 && path[1] === "apiKey");
180
+ if (!schema && !symbolicApiKey) {
141
181
  throw new UsageError(`Unknown config key: ${dotted}`, "INVALID_FLAG_VALUE", unknownKeyHint(dotted));
142
182
  }
143
- const value = coerceForSchema(schema, raw, dotted);
183
+ const value = path[0] === "engines" && path.length === 2
184
+ ? parseObjectPatch(raw, dotted)
185
+ : symbolicApiKey
186
+ ? raw
187
+ : coerceForSchema(schema, raw, dotted);
144
188
  // Validate the coerced value against the leaf schema. This catches enum
145
189
  // mismatches, out-of-range numbers, schema-level shape errors (writable
146
190
  // npm/website sources via .superRefine, strict-mode unknown keys in nested
147
191
  // objects, etc.) BEFORE we apply the patch.
148
- const parsed = schema.safeParse(value);
192
+ const parsed = path[0] === "engines" && path.length === 2
193
+ ? EngineConfigSchema.safeParse(value)
194
+ : symbolicApiKey
195
+ ? /^\$[A-Za-z_][A-Za-z0-9_]*$|^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(raw)
196
+ ? { success: true, data: value }
197
+ : { success: false, error: { issues: [{ path: [], message: `apiKey must be $VAR or \${VAR}` }] } }
198
+ : schema.safeParse(value);
149
199
  if (!parsed.success) {
150
200
  const lines = parsed.error.issues
151
201
  .map((i) => {
@@ -155,16 +205,20 @@ export function configSet(config, dotted, raw) {
155
205
  .join("\n");
156
206
  throw new UsageError(`Invalid value for ${dotted}:\n${lines}`, "INVALID_FLAG_VALUE");
157
207
  }
158
- const next = setPath(config, path, parsed.data);
159
- // Targeted invariant: defaultWriteTarget must point at a configured source
208
+ const existing = path.reduce((value, key) => {
209
+ if (value && typeof value === "object")
210
+ return value[key];
211
+ return undefined;
212
+ }, config);
213
+ const next = setPath(config, path, isPlainObject(existing) && isPlainObject(parsed.data) ? deepMergeConfig(existing, parsed.data) : parsed.data);
214
+ // Targeted invariant: defaultWriteTarget must point at a configured bundle
160
215
  // (#464.a). Whole-config validation happens at save time; this check fires
161
- // at set time so the user sees the typo immediately. Empty-sources case is
162
- // accepted here (legacy behaviour) — saveConfig will reject if it persists.
216
+ // at set time so the user sees the typo immediately.
163
217
  if (dotted === "defaultWriteTarget" && typeof value === "string") {
164
- const sources = next.sources ?? [];
165
- const knownNames = sources.map((s) => s.name).filter((n) => typeof n === "string" && n.length > 0);
166
- if (knownNames.length > 0 && !knownNames.includes(value)) {
167
- throw new UsageError(`Unknown source name "${value}" for defaultWriteTarget; configured source names: ${knownNames.map((n) => `"${n}"`).join(", ")}.`, "INVALID_FLAG_VALUE");
218
+ const bundles = next.bundles && typeof next.bundles === "object" ? next.bundles : {};
219
+ const knownNames = Object.keys(bundles);
220
+ if (!knownNames.includes(value)) {
221
+ throw new UsageError(`Unknown bundle "${value}" for defaultWriteTarget; configured bundles: ${knownNames.map((n) => `"${n}"`).join(", ") || "none"}.`, "INVALID_FLAG_VALUE");
168
222
  }
169
223
  }
170
224
  return next;
@@ -175,8 +229,11 @@ export function configSet(config, dotted, raw) {
175
229
  */
176
230
  export function configUnset(config, dotted) {
177
231
  const path = parsePath(dotted);
232
+ if (path.length === 1 && path[0] === "configVersion") {
233
+ throw new UsageError("configVersion cannot be removed through config unset.", "INVALID_FLAG_VALUE");
234
+ }
178
235
  // Validate the path resolves to a real schema field (so typos don't no-op).
179
- const schema = resolveSchemaAt(path);
236
+ const schema = resolveSchemaAt(path, config);
180
237
  if (!schema) {
181
238
  throw new UsageError(`Unknown config key: ${dotted}`, "INVALID_FLAG_VALUE", unknownKeyHint(dotted));
182
239
  }
@@ -184,12 +241,14 @@ export function configUnset(config, dotted) {
184
241
  }
185
242
  // ── apiKey rejection (#454) ─────────────────────────────────────────────────
186
243
  /**
187
- * Reject any attempt to persist an apiKey via `akm config set`. Matches:
188
- * - `llm.apiKey` (legacy alias mapped to default LLM profile)
189
- * - `embedding.apiKey`
190
- * - `profiles.llm.<name>.apiKey`
244
+ * Embedding credentials are never persisted. Engine credentials are symbolic
245
+ * configuration and are validated by the engine schema below.
191
246
  */
192
247
  function rejectApiKeyPath(path, dotted) {
248
+ if (path[0] === "engines" && path[2] === "apiKey")
249
+ return;
250
+ if (path[0] === "embedding" && path.length === 2 && path[1] === "apiKey")
251
+ return;
193
252
  const last = path[path.length - 1];
194
253
  if (last !== "apiKey")
195
254
  return;
@@ -197,14 +256,25 @@ function rejectApiKeyPath(path, dotted) {
197
256
  throw new UsageError(`apiKey cannot be persisted in config; export ${recipe} instead. (key: ${dotted})`, "INVALID_FLAG_VALUE", "Storing API keys in config.json leaks them through backups, logs, and version control. " +
198
257
  "Use the corresponding environment variable. AKM reads it at request time.");
199
258
  }
259
+ function parseObjectPatch(raw, key) {
260
+ try {
261
+ const value = JSON.parse(raw);
262
+ if (!isPlainObject(value))
263
+ throw new Error("expected an object");
264
+ return value;
265
+ }
266
+ catch (err) {
267
+ throw new UsageError(`Invalid JSON object for ${key}: ${err instanceof Error ? err.message : String(err)}`, "INVALID_JSON_CONFIG_VALUE");
268
+ }
269
+ }
270
+ function isPlainObject(value) {
271
+ return value !== null && typeof value === "object" && !Array.isArray(value);
272
+ }
200
273
  function recipeForApiKey(path, _dotted) {
201
274
  if (path[0] === "embedding")
202
275
  return "AKM_EMBED_API_KEY";
203
- if (path[0] === "llm")
204
- return "AKM_LLM_API_KEY";
205
- if (path[0] === "profiles" && path[1] === "llm" && typeof path[2] === "string") {
206
- const upper = path[2].toUpperCase().replace(/-/g, "_");
207
- return `AKM_PROFILE_${upper}_API_KEY (or AKM_LLM_API_KEY for the default profile)`;
276
+ if (path[0] === "engines" && typeof path[1] === "string") {
277
+ return `AKM_ENGINE_${path[1].toUpperCase().replaceAll("-", "_")}_API_KEY`;
208
278
  }
209
279
  return "AKM_LLM_API_KEY / AKM_EMBED_API_KEY";
210
280
  }
@@ -237,7 +307,7 @@ function coerceForSchema(schema, raw, key) {
237
307
  return raw;
238
308
  }
239
309
  if (target instanceof z.ZodLiteral) {
240
- return target._def.value;
310
+ return typeof target._def.value === "string" ? raw : target._def.value;
241
311
  }
242
312
  if (target instanceof z.ZodArray || target instanceof z.ZodObject || target instanceof z.ZodRecord) {
243
313
  if (raw === "" || raw === "null")
@@ -290,7 +360,8 @@ function coerceForSchema(schema, raw, key) {
290
360
  function setPath(config, path, value) {
291
361
  if (path.length === 0)
292
362
  return config;
293
- const [head, ...rest] = path;
363
+ const head = path[0]; // non-empty: guarded by the `path.length === 0` check above
364
+ const rest = path.slice(1);
294
365
  const next = { ...config };
295
366
  if (rest.length === 0) {
296
367
  if (value === undefined) {
@@ -311,7 +382,8 @@ function setPath(config, path, value) {
311
382
  function unsetPath(config, path) {
312
383
  if (path.length === 0)
313
384
  return config;
314
- const [head, ...rest] = path;
385
+ const head = path[0]; // non-empty: guarded by the `path.length === 0` check above
386
+ const rest = path.slice(1);
315
387
  const next = { ...config };
316
388
  if (rest.length === 0) {
317
389
  delete next[head];
@@ -331,7 +403,24 @@ function unsetPath(config, path) {
331
403
  return next;
332
404
  }
333
405
  // ── Hint generation (#460) ──────────────────────────────────────────────────
334
- export function unknownKeyHint(_attempted) {
406
+ /**
407
+ * Per-key "use X instead" guidance for config keys retired before the 0.9
408
+ * cutover, keyed on the first dotted-path segment. Mitigation item 3: the
409
+ * generic "valid top-level keys" hint doesn't tell a pre-0.9 user what
410
+ * replaced the key they typed — this does.
411
+ */
412
+ const RETIRED_KEY_HINTS = {
413
+ stashDir: "stashDir was removed in 0.9; get the stash path from `akm config path --all` or `akm info`.",
414
+ sources: "sources was replaced by bundles in 0.9; run `akm-migrate apply` on a pre-0.9 config to convert it.",
415
+ installed: "installed was replaced by bundles in 0.9; run `akm-migrate apply` on a pre-0.9 config to convert it.",
416
+ wikiName: "the wiki subsystem was removed in 0.9; wikis are ordinary knowledge assets now — see `akm import`.",
417
+ wiki: "the wiki subsystem was removed in 0.9; wikis are ordinary knowledge assets now — see `akm import`.",
418
+ llm: "llm was replaced by named engines configuration in 0.9; configure `engines` instead.",
419
+ };
420
+ export function unknownKeyHint(attempted) {
335
421
  const keys = listTopLevelConfigKeys();
336
- return `Valid top-level keys: ${keys.join(", ")}. Use dotted paths for nested values (e.g. embedding.endpoint, profiles.llm.<name>.model).`;
422
+ const generic = `Valid top-level keys: ${keys.join(", ")}. Use dotted paths for nested values (e.g. embedding.endpoint, engines.<name>.model).`;
423
+ const firstSegment = attempted.split(".")[0] ?? "";
424
+ const retiredHint = RETIRED_KEY_HINTS[firstSegment];
425
+ return retiredHint ? `${retiredHint} ${generic}` : generic;
337
426
  }