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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (598) hide show
  1. package/CHANGELOG.md +1283 -22
  2. package/README.md +62 -37
  3. package/SECURITY.md +46 -31
  4. package/dist/akm +162 -38
  5. package/dist/akm-migrate +44 -0
  6. package/dist/assets/backends/schtasks-template.xml +2 -1
  7. package/dist/assets/hints/cli-hints-full.md +268 -118
  8. package/dist/assets/hints/cli-hints-short.md +87 -24
  9. package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
  10. package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
  11. package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
  12. package/dist/assets/improve-strategies/frequent.json +15 -0
  13. package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
  14. package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
  15. package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
  16. package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
  17. package/dist/assets/improve-strategies/reflect-distill.json +30 -0
  18. package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
  19. package/dist/assets/prompts/consolidate-system.md +5 -5
  20. package/dist/assets/prompts/extract-session.md +2 -6
  21. package/dist/assets/prompts/memory-infer-user.md +2 -3
  22. package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
  23. package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
  24. package/dist/assets/prompts/reflect-output-repair.md +3 -0
  25. package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
  26. package/dist/assets/stash-skeleton/README.md +38 -10
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
  39. package/dist/assets/tasks/core/extract.yml +3 -2
  40. package/dist/assets/tasks/core/improve.yml +2 -1
  41. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  42. package/dist/assets/tasks/core/sync.yml +1 -0
  43. package/dist/assets/tasks/core/version-check.yml +2 -1
  44. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  45. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  46. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  47. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  48. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  49. package/dist/assets/templates/html/health.html +5 -4
  50. package/dist/assets/workflows/workflow-template.md +31 -15
  51. package/dist/cli/invocation.js +279 -0
  52. package/dist/cli/parse-args.js +5 -90
  53. package/dist/cli/retired-commands.js +78 -0
  54. package/dist/cli/shared.js +158 -48
  55. package/dist/cli-node.mjs +2 -1
  56. package/dist/cli.js +747 -293
  57. package/dist/commands/agent/agent-dispatch.js +19 -18
  58. package/dist/commands/agent/agent-support.js +0 -24
  59. package/dist/commands/agent/contribute-cli.js +43 -97
  60. package/dist/commands/completions.js +80 -23
  61. package/dist/commands/config-cli.js +44 -281
  62. package/dist/commands/env/env-binding.js +99 -0
  63. package/dist/commands/env/env-cli.js +84 -224
  64. package/dist/commands/env/env.js +12 -163
  65. package/dist/commands/env/marker-path.js +6 -0
  66. package/dist/commands/env/secret-cli.js +45 -61
  67. package/dist/commands/env/secret.js +32 -62
  68. package/dist/commands/feedback-cli.js +179 -85
  69. package/dist/commands/health/accept-rate.js +58 -0
  70. package/dist/commands/health/advisories.js +7 -8
  71. package/dist/commands/health/checks.js +279 -94
  72. package/dist/commands/health/html-report.js +197 -578
  73. package/dist/commands/health/improve-metrics.js +277 -246
  74. package/dist/commands/health/llm-usage.js +19 -19
  75. package/dist/commands/health/md-report.js +16 -7
  76. package/dist/commands/health/metrics.js +67 -32
  77. package/dist/commands/health/renderers.js +47 -0
  78. package/dist/commands/health/report-view-model.js +508 -0
  79. package/dist/commands/health/stash-exposure.js +1 -1
  80. package/dist/commands/health/surfaces.js +16 -56
  81. package/dist/commands/health/task-runs.js +3 -67
  82. package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
  83. package/dist/commands/health/types-improve.js +29 -0
  84. package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
  85. package/dist/commands/health/types-result.js +7 -0
  86. package/dist/commands/health/types-runs.js +4 -0
  87. package/dist/commands/health/types-session-log.js +4 -0
  88. package/dist/commands/health/types-windows.js +4 -0
  89. package/dist/commands/health/types.js +26 -21
  90. package/dist/commands/health/windows.js +2 -3
  91. package/dist/commands/health.js +296 -167
  92. package/dist/commands/improve/anti-collapse.js +5 -5
  93. package/dist/commands/improve/autonomy-gate.js +68 -0
  94. package/dist/commands/improve/collapse-detector.js +65 -52
  95. package/dist/commands/improve/consolidate/chunking.js +9 -7
  96. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  97. package/dist/commands/improve/consolidate/merge.js +4 -0
  98. package/dist/commands/improve/consolidate.js +454 -1354
  99. package/dist/commands/improve/content-hash.js +39 -0
  100. package/dist/commands/improve/distill/content-repair.js +4 -10
  101. package/dist/commands/improve/distill/promote-memory.js +89 -64
  102. package/dist/commands/improve/distill/quality-gate.js +118 -42
  103. package/dist/commands/improve/distill-guards.js +1 -1
  104. package/dist/commands/improve/distill-promotion-policy.js +33 -888
  105. package/dist/commands/improve/distill.js +607 -363
  106. package/dist/commands/improve/eligibility.js +165 -79
  107. package/dist/commands/improve/extract-cli.js +35 -126
  108. package/dist/commands/improve/extract-prompt.js +6 -35
  109. package/dist/commands/improve/extract.js +640 -391
  110. package/dist/commands/improve/feedback-valence.js +2 -12
  111. package/dist/commands/improve/improve-cli.js +134 -135
  112. package/dist/commands/improve/improve-result-file.js +30 -50
  113. package/dist/commands/improve/improve-run-types.js +4 -0
  114. package/dist/commands/improve/improve-strategies.js +135 -0
  115. package/dist/commands/improve/improve.js +904 -701
  116. package/dist/commands/improve/locks.js +64 -111
  117. package/dist/commands/improve/loop-stages.js +1110 -923
  118. package/dist/commands/improve/memory/derived-ref.js +124 -0
  119. package/dist/commands/improve/memory/memory-belief.js +79 -7
  120. package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
  121. package/dist/commands/improve/memory/memory-improve.js +25 -37
  122. package/dist/commands/improve/outcome-loop.js +25 -88
  123. package/dist/commands/improve/preparation.js +1034 -813
  124. package/dist/commands/improve/proactive-maintenance.js +34 -9
  125. package/dist/commands/improve/proposal-envelope.js +31 -0
  126. package/dist/commands/improve/reflect.js +983 -794
  127. package/dist/commands/improve/run-context.js +119 -0
  128. package/dist/commands/improve/salience.js +24 -127
  129. package/dist/commands/improve/session-asset.js +7 -3
  130. package/dist/commands/improve/shared.js +14 -34
  131. package/dist/commands/improve/source-identity.js +28 -0
  132. package/dist/commands/improve/triage.js +20 -17
  133. package/dist/commands/lint/base-linter.js +340 -313
  134. package/dist/commands/lint/env-key-rules.js +31 -47
  135. package/dist/commands/lint/index.js +185 -30
  136. package/dist/commands/{events.js → log.js} +28 -38
  137. package/dist/commands/migrate-cli.js +54 -0
  138. package/dist/commands/migration-tool.js +55 -0
  139. package/dist/commands/observability-cli.js +70 -208
  140. package/dist/commands/proposal/diff-format.js +50 -0
  141. package/dist/commands/proposal/drain-policies.js +0 -6
  142. package/dist/commands/proposal/drain.js +91 -40
  143. package/dist/commands/proposal/proposal-cli.js +134 -132
  144. package/dist/commands/proposal/proposal-types.js +56 -0
  145. package/dist/commands/proposal/proposal.js +83 -65
  146. package/dist/commands/proposal/propose-cli.js +88 -0
  147. package/dist/commands/proposal/propose.js +105 -88
  148. package/dist/commands/proposal/repository.js +1303 -278
  149. package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
  150. package/dist/commands/proposal/validators/proposal-validators.js +61 -12
  151. package/dist/commands/proposal/validators/proposals.js +6 -8
  152. package/dist/commands/read/curate.js +78 -73
  153. package/dist/commands/read/knowledge.js +510 -13
  154. package/dist/commands/read/registry-search.js +2 -2
  155. package/dist/commands/read/remember-cli.js +84 -15
  156. package/dist/commands/read/search-cli.js +203 -96
  157. package/dist/commands/read/search.js +126 -94
  158. package/dist/commands/read/show.js +226 -250
  159. package/dist/commands/registry-cli.js +34 -60
  160. package/dist/commands/remember.js +18 -57
  161. package/dist/commands/sources/add-cli.js +104 -49
  162. package/dist/commands/sources/bundle-cli.js +166 -0
  163. package/dist/commands/sources/bundle-config-ops.js +63 -0
  164. package/dist/commands/sources/info.js +27 -15
  165. package/dist/commands/sources/init.js +30 -40
  166. package/dist/commands/sources/installed-stashes.js +469 -172
  167. package/dist/commands/sources/migration-help.js +7 -4
  168. package/dist/commands/sources/schema-repair.js +10 -9
  169. package/dist/commands/sources/self-update.js +182 -121
  170. package/dist/commands/sources/source-add.js +169 -178
  171. package/dist/commands/sources/source-clone.js +144 -41
  172. package/dist/commands/sources/source-manage.js +94 -59
  173. package/dist/commands/sources/sources-cli.js +64 -205
  174. package/dist/commands/sources/stash-cli.js +91 -54
  175. package/dist/commands/sources/stash-skeleton.js +1 -1
  176. package/dist/commands/tasks/tasks-cli.js +106 -104
  177. package/dist/commands/tasks/tasks.js +445 -262
  178. package/dist/commands/workflow-cli.js +232 -121
  179. package/dist/core/action-contributors.js +1 -1
  180. package/dist/core/activation-policy.js +49 -0
  181. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  182. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  183. package/dist/core/adapter/adapters/akm-lint.js +392 -0
  184. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  185. package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
  186. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  187. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  188. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  189. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  190. package/dist/core/adapter/adapters/index.js +80 -0
  191. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  192. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  193. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  194. package/dist/core/adapter/adapters/shared.js +286 -0
  195. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  196. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  197. package/dist/core/adapter/bundle-adapter.js +4 -0
  198. package/dist/core/adapter/detect-adapter.js +17 -0
  199. package/dist/core/adapter/recognize-match.js +44 -0
  200. package/dist/core/adapter/registry.js +56 -0
  201. package/dist/core/adapter/types.js +4 -0
  202. package/dist/core/asset/akm-markdown.js +30 -0
  203. package/dist/core/asset/asset-placement.js +243 -0
  204. package/dist/core/asset/asset-ref.js +110 -79
  205. package/dist/core/asset/asset-serialize.js +20 -0
  206. package/dist/core/asset/frontmatter.js +28 -12
  207. package/dist/core/asset/markdown.js +40 -51
  208. package/dist/core/asset/resolve-ref.js +274 -0
  209. package/dist/core/asset/stash-meta.js +2 -2
  210. package/dist/core/bundle-id.js +51 -0
  211. package/dist/core/common.js +281 -86
  212. package/dist/core/config/config-io.js +42 -128
  213. package/dist/core/config/config-schema.js +233 -834
  214. package/dist/core/config/config-sources.js +162 -39
  215. package/dist/core/config/config-types.js +16 -11
  216. package/dist/core/config/config-version.js +29 -0
  217. package/dist/core/config/config-walker.js +126 -37
  218. package/dist/core/config/config.js +154 -331
  219. package/dist/core/config/deep-merge.js +41 -0
  220. package/dist/core/config/engine-semantics.js +28 -0
  221. package/dist/core/config/experimental.js +21 -0
  222. package/dist/core/config/schema/embedding.js +38 -0
  223. package/dist/core/config/schema/engines.js +116 -0
  224. package/dist/core/config/schema/experimental.js +47 -0
  225. package/dist/core/config/schema/feedback.js +31 -0
  226. package/dist/core/config/schema/improve-processes.js +389 -0
  227. package/dist/core/config/schema/improve.js +94 -0
  228. package/dist/core/config/schema/index-config.js +176 -0
  229. package/dist/core/config/schema/output.js +18 -0
  230. package/dist/core/config/schema/primitives.js +94 -0
  231. package/dist/core/config/schema/search.js +30 -0
  232. package/dist/core/config/schema/setup.js +18 -0
  233. package/dist/core/config/schema/sources-bundles.js +169 -0
  234. package/dist/core/config/schema/workflow.js +29 -0
  235. package/dist/core/env-secret-ref.js +155 -20
  236. package/dist/core/errors.js +17 -15
  237. package/dist/core/events-types.js +4 -0
  238. package/dist/core/events.js +46 -128
  239. package/dist/core/extra-params.js +62 -0
  240. package/dist/core/file-change.js +17 -0
  241. package/dist/core/file-lock.js +202 -57
  242. package/dist/core/fs-txn.js +392 -0
  243. package/dist/core/git-message.js +59 -0
  244. package/dist/core/improve-result.js +167 -0
  245. package/dist/core/json-schema.js +142 -0
  246. package/dist/core/lesson-lint.js +1 -17
  247. package/dist/core/logs-db.js +1 -1
  248. package/dist/core/maintenance-barrier.js +135 -0
  249. package/dist/core/migration-operation.js +44 -0
  250. package/dist/core/mutation-target.js +78 -0
  251. package/dist/core/paths.js +22 -25
  252. package/dist/core/platform.js +10 -0
  253. package/dist/core/recognition-util.js +128 -0
  254. package/dist/core/redaction.js +392 -0
  255. package/dist/core/standards/resolve-standards-context.js +36 -65
  256. package/dist/core/standards/resolve-stash-standards.js +2 -2
  257. package/dist/core/standards/resolve-type-conventions.js +5 -5
  258. package/dist/core/state/migrations.js +242 -11
  259. package/dist/core/state-db.js +98 -10
  260. package/dist/core/structured.js +1 -1
  261. package/dist/core/subprocess.js +303 -0
  262. package/dist/core/text-truncation.js +9 -5
  263. package/dist/core/time.js +20 -0
  264. package/dist/core/type-presentation.js +130 -0
  265. package/dist/core/warn.js +0 -3
  266. package/dist/core/write-source.js +834 -118
  267. package/dist/indexer/bundle-identity-guard.js +92 -0
  268. package/dist/indexer/db/graph-db.js +1 -25
  269. package/dist/indexer/db/llm-cache.js +1 -1
  270. package/dist/indexer/ensure-index.js +30 -9
  271. package/dist/indexer/graph/graph-boost.js +9 -30
  272. package/dist/indexer/graph/graph-extraction.js +41 -27
  273. package/dist/indexer/graph/graph-types.js +4 -0
  274. package/dist/indexer/index-writer-lock.js +93 -49
  275. package/dist/indexer/index-written-assets.js +100 -53
  276. package/dist/indexer/indexer.js +746 -329
  277. package/dist/indexer/init.js +18 -25
  278. package/dist/indexer/installations.js +142 -0
  279. package/dist/indexer/passes/dir-staleness.js +18 -10
  280. package/dist/indexer/passes/memory-inference.js +25 -15
  281. package/dist/indexer/passes/metadata.js +412 -243
  282. package/dist/indexer/scan/doc-to-entry.js +160 -0
  283. package/dist/indexer/scan/drain-dir.js +134 -0
  284. package/dist/indexer/search/db-search.js +292 -108
  285. package/dist/indexer/search/fts-query.js +64 -0
  286. package/dist/indexer/search/ranking-contributors.js +145 -25
  287. package/dist/indexer/search/ranking-types.js +4 -0
  288. package/dist/indexer/search/ranking.js +28 -71
  289. package/dist/indexer/search/search-attribution.js +67 -0
  290. package/dist/indexer/search/search-fields.js +18 -3
  291. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  292. package/dist/indexer/search/search-source.js +157 -111
  293. package/dist/indexer/search/semantic-status.js +4 -1
  294. package/dist/indexer/usage/usage-events.js +10 -30
  295. package/dist/indexer/walk/file-context.js +3 -45
  296. package/dist/indexer/walk/matchers.js +42 -34
  297. package/dist/indexer/walk/path-resolver.js +11 -5
  298. package/dist/indexer/walk/walker.js +42 -14
  299. package/dist/integrations/agent/builder-shared.js +7 -0
  300. package/dist/integrations/agent/builders.js +5 -56
  301. package/dist/integrations/agent/config.js +3 -143
  302. package/dist/integrations/agent/detect.js +17 -2
  303. package/dist/integrations/agent/engine-resolution.js +231 -0
  304. package/dist/integrations/agent/index.js +1 -2
  305. package/dist/integrations/agent/model-aliases.js +16 -2
  306. package/dist/integrations/agent/profiles.js +36 -62
  307. package/dist/integrations/agent/prompts.js +46 -18
  308. package/dist/integrations/agent/runner-dispatch.js +93 -4
  309. package/dist/integrations/agent/runner.js +76 -208
  310. package/dist/integrations/agent/spawn.js +88 -196
  311. package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
  312. package/dist/integrations/harnesses/aider/index.js +48 -0
  313. package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
  314. package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
  315. package/dist/integrations/harnesses/amazonq/index.js +45 -0
  316. package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
  317. package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
  318. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  319. package/dist/integrations/harnesses/claude/index.js +24 -35
  320. package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
  321. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  322. package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
  323. package/dist/integrations/harnesses/codex/index.js +52 -0
  324. package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
  325. package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
  326. package/dist/integrations/harnesses/copilot/index.js +48 -0
  327. package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
  328. package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
  329. package/dist/integrations/harnesses/gemini/index.js +48 -0
  330. package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
  331. package/dist/integrations/harnesses/ids.js +24 -0
  332. package/dist/integrations/harnesses/index.js +54 -34
  333. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  334. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  335. package/dist/integrations/harnesses/opencode/index.js +14 -32
  336. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  337. package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
  338. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
  339. package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
  340. package/dist/integrations/harnesses/openhands/index.js +48 -0
  341. package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
  342. package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
  343. package/dist/integrations/harnesses/pi/index.js +45 -0
  344. package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
  345. package/dist/integrations/harnesses/shared.js +17 -0
  346. package/dist/integrations/harnesses/types.js +43 -32
  347. package/dist/integrations/lockfile.js +211 -24
  348. package/dist/integrations/session-logs/index.js +36 -39
  349. package/dist/integrations/session-logs/provider-base.js +113 -0
  350. package/dist/llm/client.js +182 -110
  351. package/dist/llm/embedders/deterministic.js +2 -2
  352. package/dist/llm/embedders/remote.js +21 -9
  353. package/dist/llm/feature-gate.js +17 -57
  354. package/dist/llm/graph-extract.js +12 -13
  355. package/dist/llm/index-passes.js +8 -42
  356. package/dist/llm/memory-infer.js +144 -1
  357. package/dist/llm/metadata-enhance.js +45 -30
  358. package/dist/llm/structured-call.js +16 -8
  359. package/dist/llm/usage-persist.js +30 -5
  360. package/dist/llm/usage-telemetry.js +59 -6
  361. package/dist/output/cli-hints.js +1 -2
  362. package/dist/output/command-registry.js +27 -0
  363. package/dist/output/context.js +22 -7
  364. package/dist/output/format-exempt.js +80 -0
  365. package/dist/output/generic-render.js +251 -0
  366. package/dist/output/html-render.js +11 -16
  367. package/dist/output/render-registry.js +57 -0
  368. package/dist/output/renderers.js +14 -279
  369. package/dist/output/shapes/curate.js +10 -1
  370. package/dist/output/shapes/events.js +12 -7
  371. package/dist/output/shapes/helpers.js +58 -84
  372. package/dist/output/shapes/passthrough.js +11 -39
  373. package/dist/output/shapes/proposal/producer.js +15 -7
  374. package/dist/output/shapes/registry.js +12 -6
  375. package/dist/output/shapes.js +0 -9
  376. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  377. package/dist/output/text/bundle-show.js +7 -0
  378. package/dist/output/text/command-format.js +562 -0
  379. package/dist/output/text/env.js +1 -3
  380. package/dist/output/text/events.js +8 -7
  381. package/dist/output/text/helpers.js +15 -1164
  382. package/dist/output/text/proposal/producer.js +4 -2
  383. package/dist/output/text/proposal-format.js +202 -0
  384. package/dist/output/text/registry-commands.js +1 -2
  385. package/dist/output/text/registry.js +12 -6
  386. package/dist/output/text/show-directives.js +117 -0
  387. package/dist/output/text/show-format.js +103 -0
  388. package/dist/output/text/sync.js +5 -0
  389. package/dist/output/text/workflow-format.js +332 -0
  390. package/dist/output/text/workflow.js +3 -2
  391. package/dist/output/text.js +10 -19
  392. package/dist/registry/factory.js +4 -6
  393. package/dist/registry/origin-resolve.js +16 -27
  394. package/dist/registry/providers/skills-sh.js +3 -3
  395. package/dist/registry/providers/static-index.js +15 -25
  396. package/dist/registry/resolve.js +43 -94
  397. package/dist/registry/semver.js +43 -0
  398. package/dist/runtime.js +81 -12
  399. package/dist/scripts/akm-migrate.js +35529 -0
  400. package/dist/setup/detect.js +5 -7
  401. package/dist/setup/detected-engines.js +136 -0
  402. package/dist/setup/engine-config.js +100 -0
  403. package/dist/setup/registry-stash-loader.js +3 -3
  404. package/dist/setup/semantic-assets.js +12 -9
  405. package/dist/setup/setup.js +444 -208
  406. package/dist/setup/steps/connection-shared.js +120 -0
  407. package/dist/setup/steps/connection.js +108 -305
  408. package/dist/setup/steps/platforms.js +13 -12
  409. package/dist/setup/steps/semantic.js +15 -3
  410. package/dist/setup/steps/sources.js +21 -15
  411. package/dist/setup/steps/stashdir.js +6 -4
  412. package/dist/setup/steps/tasks.js +236 -119
  413. package/dist/setup/steps.js +3 -2
  414. package/dist/sources/freshness.js +39 -0
  415. package/dist/sources/provider-factory.js +11 -17
  416. package/dist/sources/providers/filesystem.js +2 -3
  417. package/dist/sources/providers/git-install.js +278 -34
  418. package/dist/sources/providers/git-provider.js +54 -56
  419. package/dist/sources/providers/git-stash.js +420 -91
  420. package/dist/sources/providers/git.js +2 -2
  421. package/dist/sources/providers/npm.js +16 -19
  422. package/dist/sources/providers/provider-utils.js +47 -22
  423. package/dist/sources/providers/sync-from-ref.js +3 -9
  424. package/dist/sources/providers/website.js +2 -2
  425. package/dist/sources/resolve.js +11 -10
  426. package/dist/sources/snapshot-fetchers/types.js +4 -0
  427. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
  428. package/dist/storage/database.js +60 -4
  429. package/dist/storage/engines/sqlite-migrations.js +156 -5
  430. package/dist/storage/locations.js +1 -2
  431. package/dist/storage/repositories/canaries-repository.js +1 -1
  432. package/dist/storage/repositories/events-repository.js +51 -11
  433. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  434. package/dist/storage/repositories/index-connection.js +79 -0
  435. package/dist/storage/repositories/index-db.js +4 -3
  436. package/dist/storage/repositories/index-entries-repository.js +863 -0
  437. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  438. package/dist/storage/repositories/index-entry-types.js +4 -0
  439. package/dist/storage/repositories/index-fts-repository.js +167 -0
  440. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  441. package/dist/storage/repositories/index-meta-repository.js +49 -0
  442. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  443. package/dist/storage/repositories/index-sql.js +12 -0
  444. package/dist/storage/repositories/index-utility-repository.js +356 -0
  445. package/dist/storage/repositories/index-vec-repository.js +250 -0
  446. package/dist/storage/repositories/outcome-repository.js +119 -0
  447. package/dist/storage/repositories/proposals-repository.js +317 -75
  448. package/dist/storage/repositories/registry-cache.js +1 -1
  449. package/dist/storage/repositories/salience-repository.js +172 -0
  450. package/dist/storage/repositories/task-history-repository.js +110 -3
  451. package/dist/storage/repositories/workflow-runs-repository.js +240 -19
  452. package/dist/tasks/backends/cron.js +169 -46
  453. package/dist/tasks/backends/exec-utils.js +76 -3
  454. package/dist/tasks/backends/index.js +6 -9
  455. package/dist/tasks/backends/launchd.js +292 -55
  456. package/dist/tasks/backends/schtasks.js +557 -70
  457. package/dist/tasks/backends/types.js +4 -0
  458. package/dist/tasks/command-executable.js +93 -0
  459. package/dist/tasks/embedded.js +56 -38
  460. package/dist/tasks/parser.js +156 -64
  461. package/dist/tasks/resolve-akm-bin.js +144 -51
  462. package/dist/tasks/runner.js +377 -209
  463. package/dist/tasks/schedule.js +108 -19
  464. package/dist/tasks/scheduler-invocation.js +296 -0
  465. package/dist/tasks/schema.js +1 -1
  466. package/dist/tasks/task-id.js +35 -0
  467. package/dist/tasks/validator.js +30 -16
  468. package/dist/text-import-hook.mjs +1 -1
  469. package/dist/workflows/authoring/authoring.js +104 -43
  470. package/dist/workflows/authoring/scope-key.js +1 -1
  471. package/dist/workflows/cli.js +0 -16
  472. package/dist/workflows/concurrency-policy.js +15 -0
  473. package/dist/workflows/exec/brief.js +450 -0
  474. package/dist/workflows/exec/frozen-judge.js +47 -0
  475. package/dist/workflows/exec/native-executor.js +1038 -0
  476. package/dist/workflows/exec/param-secrets.js +115 -0
  477. package/dist/workflows/exec/report.js +1460 -0
  478. package/dist/workflows/exec/run-workflow.js +602 -0
  479. package/dist/workflows/exec/scheduler.js +71 -0
  480. package/dist/workflows/exec/step-work.js +1190 -0
  481. package/dist/workflows/exec/unit-writer.js +23 -0
  482. package/dist/workflows/exec/workflow-engine-gate.js +67 -0
  483. package/dist/workflows/exec/worktree.js +171 -0
  484. package/dist/workflows/ir/compile.js +246 -0
  485. package/dist/workflows/ir/freeze.js +233 -0
  486. package/dist/workflows/ir/params.js +54 -0
  487. package/dist/workflows/ir/plan-hash.js +68 -0
  488. package/dist/workflows/ir/schema.js +540 -0
  489. package/dist/workflows/parser.js +878 -304
  490. package/dist/workflows/program/expressions.js +181 -0
  491. package/dist/workflows/program/schema.js +51 -0
  492. package/dist/workflows/renderer.js +100 -45
  493. package/dist/workflows/resource-limits.js +22 -0
  494. package/dist/workflows/runtime/agent-identity.js +59 -14
  495. package/dist/workflows/runtime/checkin.js +1 -1
  496. package/dist/workflows/runtime/plan-classifier.js +131 -0
  497. package/dist/workflows/runtime/runs.js +376 -119
  498. package/dist/workflows/runtime/unit-checkin.js +45 -0
  499. package/dist/workflows/runtime/unit-phases.js +20 -0
  500. package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
  501. package/dist/workflows/schema.js +1 -11
  502. package/dist/workflows/validate-summary.js +2 -3
  503. package/dist/workflows/validator.js +52 -30
  504. package/docs/README.md +42 -78
  505. package/docs/migration/README.md +8 -0
  506. package/docs/migration/release-notes/0.6.0.md +1 -1
  507. package/docs/migration/release-notes/0.7.0.md +9 -8
  508. package/docs/migration/release-notes/0.9.0.md +158 -14
  509. package/docs/migration/v0.7-to-v0.8.md +46 -47
  510. package/docs/migration/v0.8-to-v0.9.md +844 -0
  511. package/docs/reference/README.md +12 -0
  512. package/docs/reference/data-and-telemetry.md +333 -0
  513. package/package.json +21 -17
  514. package/schemas/akm-asset-envelope.json +93 -0
  515. package/schemas/akm-config.json +4636 -0
  516. package/schemas/akm-task.json +87 -0
  517. package/schemas/akm-workflow.json +373 -0
  518. package/dist/akm-migrate-storage +0 -38
  519. package/dist/assets/help/help-accept.md +0 -12
  520. package/dist/assets/help/help-improve.md +0 -84
  521. package/dist/assets/help/help-proposals.md +0 -17
  522. package/dist/assets/help/help-propose.md +0 -17
  523. package/dist/assets/help/help-reject.md +0 -11
  524. package/dist/assets/profiles/frequent.json +0 -13
  525. package/dist/assets/profiles/recombine-only.json +0 -21
  526. package/dist/assets/profiles/reflect-distill.json +0 -30
  527. package/dist/assets/profiles/synthesize.json +0 -15
  528. package/dist/assets/prompts/procedural-system.md +0 -44
  529. package/dist/assets/prompts/recombine-system.md +0 -40
  530. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  531. package/dist/assets/tasks/core/backup.yml +0 -4
  532. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  533. package/dist/assets/templates/html/default.html +0 -78
  534. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  535. package/dist/assets/wiki/index-template.md +0 -12
  536. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  537. package/dist/assets/wiki/log-template.md +0 -8
  538. package/dist/assets/wiki/schema-template.md +0 -61
  539. package/dist/cli/config-migrate.js +0 -150
  540. package/dist/cli/config-validate.js +0 -39
  541. package/dist/commands/graph/graph-cli.js +0 -124
  542. package/dist/commands/graph/graph.js +0 -487
  543. package/dist/commands/improve/calibration.js +0 -161
  544. package/dist/commands/improve/dedup.js +0 -482
  545. package/dist/commands/improve/extract-watch.js +0 -140
  546. package/dist/commands/improve/hot-probation.js +0 -45
  547. package/dist/commands/improve/improve-auto-accept.js +0 -276
  548. package/dist/commands/improve/improve-profiles.js +0 -168
  549. package/dist/commands/improve/procedural.js +0 -398
  550. package/dist/commands/improve/recombine.js +0 -818
  551. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  552. package/dist/commands/lint/agent-linter.js +0 -44
  553. package/dist/commands/lint/command-linter.js +0 -44
  554. package/dist/commands/lint/default-linter.js +0 -16
  555. package/dist/commands/lint/fact-linter.js +0 -39
  556. package/dist/commands/lint/knowledge-linter.js +0 -16
  557. package/dist/commands/lint/memory-linter.js +0 -61
  558. package/dist/commands/lint/registry.js +0 -41
  559. package/dist/commands/lint/skill-linter.js +0 -45
  560. package/dist/commands/lint/task-linter.js +0 -50
  561. package/dist/commands/lint/workflow-linter.js +0 -81
  562. package/dist/commands/proposal/legacy-import.js +0 -115
  563. package/dist/commands/sources/history.js +0 -196
  564. package/dist/commands/tasks/default-tasks.js +0 -186
  565. package/dist/commands/wiki-cli.js +0 -292
  566. package/dist/core/asset/asset-registry.js +0 -76
  567. package/dist/core/asset/asset-spec.js +0 -259
  568. package/dist/core/config/config-migration.js +0 -602
  569. package/dist/core/deep-merge.js +0 -38
  570. package/dist/core/eval/rank-metrics.js +0 -113
  571. package/dist/core/ripgrep/install.js +0 -163
  572. package/dist/core/ripgrep/resolve.js +0 -81
  573. package/dist/indexer/db/db.js +0 -1413
  574. package/dist/indexer/manifest.js +0 -170
  575. package/dist/indexer/passes/metadata-contributors.js +0 -31
  576. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  577. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
  578. package/dist/llm/call-ai.js +0 -62
  579. package/dist/llm/memory-infer-impl.js +0 -138
  580. package/dist/output/shapes/distill.js +0 -14
  581. package/dist/output/shapes/history.js +0 -11
  582. package/dist/output/text/distill.js +0 -6
  583. package/dist/output/text/enable-disable.js +0 -8
  584. package/dist/output/text/history.js +0 -6
  585. package/dist/output/text/wiki.js +0 -16
  586. package/dist/registry/build-index.js +0 -386
  587. package/dist/scripts/migrate-storage.js +0 -19108
  588. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
  589. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  590. package/dist/setup/legacy-config.js +0 -106
  591. package/dist/storage/repositories/consolidation-repository.js +0 -38
  592. package/dist/storage/repositories/recombine-repository.js +0 -213
  593. package/dist/wiki/wiki-templates.js +0 -15
  594. package/dist/wiki/wiki.js +0 -1012
  595. package/dist/workflows/db.js +0 -215
  596. package/docs/data-and-telemetry.md +0 -226
  597. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  598. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -3,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
  }