akm-cli 0.9.0-rc.1 → 0.9.0-rc.14

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 (601) hide show
  1. package/CHANGELOG.md +1284 -52
  2. package/README.md +62 -37
  3. package/SECURITY.md +46 -31
  4. package/dist/akm +162 -38
  5. package/dist/akm-migrate +46 -0
  6. package/dist/assets/backends/schtasks-template.xml +2 -1
  7. package/dist/assets/hints/cli-hints-full.md +267 -118
  8. package/dist/assets/hints/cli-hints-short.md +89 -26
  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 +32 -15
  50. package/dist/cli/invocation.js +280 -0
  51. package/dist/cli/parse-args.js +5 -90
  52. package/dist/cli/retired-commands.js +81 -0
  53. package/dist/cli/shared.js +158 -48
  54. package/dist/cli/unknown-flags.js +226 -0
  55. package/dist/cli-node.mjs +2 -1
  56. package/dist/cli.js +732 -294
  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 +58 -100
  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 +13 -9
  63. package/dist/commands/env/env-cli.js +76 -159
  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 +185 -88
  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 +64 -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 +343 -328
  134. package/dist/commands/lint/env-key-rules.js +31 -47
  135. package/dist/commands/lint/index.js +198 -43
  136. package/dist/commands/{events.js → log.js} +33 -38
  137. package/dist/commands/migrate-cli.js +54 -0
  138. package/dist/commands/migration-tool.js +54 -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 +1306 -281
  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 +512 -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 +39 -63
  160. package/dist/commands/remember.js +18 -57
  161. package/dist/commands/sources/add-cli.js +110 -55
  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/schema-repair.js +10 -9
  168. package/dist/commands/sources/self-update.js +205 -121
  169. package/dist/commands/sources/source-add.js +183 -177
  170. package/dist/commands/sources/source-clone.js +144 -41
  171. package/dist/commands/sources/source-manage.js +94 -59
  172. package/dist/commands/sources/sources-cli.js +64 -205
  173. package/dist/commands/sources/stash-cli.js +91 -54
  174. package/dist/commands/sources/stash-skeleton.js +1 -1
  175. package/dist/commands/tasks/tasks-cli.js +106 -104
  176. package/dist/commands/tasks/tasks.js +451 -263
  177. package/dist/commands/workflow-cli.js +195 -325
  178. package/dist/core/action-contributors.js +1 -1
  179. package/dist/core/activation-policy.js +49 -0
  180. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  181. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  182. package/dist/core/adapter/adapters/akm-lint.js +396 -0
  183. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  184. package/dist/core/adapter/adapters/akm-task-adapter.js +152 -0
  185. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  186. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  187. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  188. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  189. package/dist/core/adapter/adapters/index.js +80 -0
  190. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  191. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  192. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  193. package/dist/core/adapter/adapters/shared.js +286 -0
  194. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  195. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  196. package/dist/core/adapter/bundle-adapter.js +4 -0
  197. package/dist/core/adapter/detect-adapter.js +17 -0
  198. package/dist/core/adapter/recognize-match.js +44 -0
  199. package/dist/core/adapter/registry.js +56 -0
  200. package/dist/core/adapter/types.js +4 -0
  201. package/dist/core/asset/akm-markdown.js +63 -0
  202. package/dist/core/asset/asset-placement.js +243 -0
  203. package/dist/core/asset/asset-ref.js +110 -79
  204. package/dist/core/asset/asset-serialize.js +20 -0
  205. package/dist/core/asset/frontmatter.js +50 -12
  206. package/dist/core/asset/markdown.js +40 -51
  207. package/dist/core/asset/resolve-ref.js +294 -0
  208. package/dist/core/asset/stash-meta.js +2 -2
  209. package/dist/core/bundle-id.js +51 -0
  210. package/dist/core/common.js +326 -88
  211. package/dist/core/config/config-io.js +42 -128
  212. package/dist/core/config/config-schema.js +241 -855
  213. package/dist/core/config/config-sources.js +162 -39
  214. package/dist/core/config/config-types.js +16 -11
  215. package/dist/core/config/config-version.js +29 -0
  216. package/dist/core/config/config-walker.js +126 -37
  217. package/dist/core/config/config.js +154 -331
  218. package/dist/core/config/deep-merge.js +41 -0
  219. package/dist/core/config/engine-semantics.js +28 -0
  220. package/dist/core/config/experimental.js +21 -0
  221. package/dist/core/config/schema/embedding.js +38 -0
  222. package/dist/core/config/schema/engines.js +116 -0
  223. package/dist/core/config/schema/experimental.js +39 -0
  224. package/dist/core/config/schema/feedback.js +31 -0
  225. package/dist/core/config/schema/improve-processes.js +389 -0
  226. package/dist/core/config/schema/improve.js +94 -0
  227. package/dist/core/config/schema/index-config.js +176 -0
  228. package/dist/core/config/schema/output.js +18 -0
  229. package/dist/core/config/schema/primitives.js +94 -0
  230. package/dist/core/config/schema/search.js +30 -0
  231. package/dist/core/config/schema/setup.js +18 -0
  232. package/dist/core/config/schema/sources-bundles.js +180 -0
  233. package/dist/core/config/schema/workflow.js +31 -0
  234. package/dist/core/env-secret-ref.js +155 -20
  235. package/dist/core/errors.js +22 -15
  236. package/dist/core/events-types.js +4 -0
  237. package/dist/core/events.js +46 -128
  238. package/dist/core/extra-params.js +62 -0
  239. package/dist/core/file-change.js +17 -0
  240. package/dist/core/file-lock.js +202 -57
  241. package/dist/core/fs-txn.js +392 -0
  242. package/dist/core/git-message.js +59 -0
  243. package/dist/core/improve-result.js +167 -0
  244. package/dist/core/lesson-lint.js +1 -17
  245. package/dist/core/logs-db.js +3 -2
  246. package/dist/core/maintenance-barrier.js +135 -0
  247. package/dist/core/migration-operation.js +44 -0
  248. package/dist/core/mutation-target.js +78 -0
  249. package/dist/core/parse.js +4 -1
  250. package/dist/core/paths.js +22 -25
  251. package/dist/core/platform.js +10 -0
  252. package/dist/core/recognition-util.js +128 -0
  253. package/dist/core/redaction.js +392 -0
  254. package/dist/core/standards/resolve-standards-context.js +36 -65
  255. package/dist/core/standards/resolve-stash-standards.js +2 -2
  256. package/dist/core/standards/resolve-type-conventions.js +5 -5
  257. package/dist/core/state/migrations.js +242 -14
  258. package/dist/core/state-db.js +96 -10
  259. package/dist/core/structured.js +1 -1
  260. package/dist/core/subprocess.js +305 -0
  261. package/dist/core/text-truncation.js +9 -5
  262. package/dist/core/time.js +20 -0
  263. package/dist/core/type-presentation.js +130 -0
  264. package/dist/core/warn.js +0 -3
  265. package/dist/core/write-source.js +834 -118
  266. package/dist/indexer/bundle-identity-guard.js +92 -0
  267. package/dist/indexer/db/graph-db.js +1 -25
  268. package/dist/indexer/db/llm-cache.js +1 -1
  269. package/dist/indexer/ensure-index.js +30 -9
  270. package/dist/indexer/graph/graph-boost.js +9 -30
  271. package/dist/indexer/graph/graph-extraction.js +41 -27
  272. package/dist/indexer/graph/graph-types.js +4 -0
  273. package/dist/indexer/index-writer-lock.js +93 -49
  274. package/dist/indexer/index-written-assets.js +100 -53
  275. package/dist/indexer/indexer.js +761 -329
  276. package/dist/indexer/init.js +18 -25
  277. package/dist/indexer/installations.js +142 -0
  278. package/dist/indexer/passes/dir-staleness.js +18 -10
  279. package/dist/indexer/passes/memory-inference.js +25 -15
  280. package/dist/indexer/passes/metadata.js +412 -243
  281. package/dist/indexer/scan/doc-to-entry.js +160 -0
  282. package/dist/indexer/scan/drain-dir.js +134 -0
  283. package/dist/indexer/search/db-search.js +292 -108
  284. package/dist/indexer/search/fts-query.js +64 -0
  285. package/dist/indexer/search/ranking-contributors.js +145 -25
  286. package/dist/indexer/search/ranking-types.js +4 -0
  287. package/dist/indexer/search/ranking.js +28 -71
  288. package/dist/indexer/search/search-attribution.js +67 -0
  289. package/dist/indexer/search/search-fields.js +18 -3
  290. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  291. package/dist/indexer/search/search-source.js +158 -112
  292. package/dist/indexer/search/semantic-status.js +4 -1
  293. package/dist/indexer/usage/usage-events.js +10 -30
  294. package/dist/indexer/walk/file-context.js +3 -45
  295. package/dist/indexer/walk/matchers.js +45 -74
  296. package/dist/indexer/walk/path-resolver.js +11 -5
  297. package/dist/indexer/walk/walker.js +42 -14
  298. package/dist/integrations/agent/builder-shared.js +7 -0
  299. package/dist/integrations/agent/builders.js +5 -58
  300. package/dist/integrations/agent/config.js +4 -144
  301. package/dist/integrations/agent/detect.js +64 -19
  302. package/dist/integrations/agent/engine-resolution.js +231 -0
  303. package/dist/integrations/agent/index.js +1 -2
  304. package/dist/integrations/agent/model-aliases.js +8 -3
  305. package/dist/integrations/agent/profiles.js +13 -96
  306. package/dist/integrations/agent/prompts.js +46 -18
  307. package/dist/integrations/agent/runner-dispatch.js +78 -13
  308. package/dist/integrations/agent/runner.js +76 -208
  309. package/dist/integrations/agent/spawn.js +48 -280
  310. package/dist/integrations/harnesses/aider/agent-builder.js +9 -8
  311. package/dist/integrations/harnesses/aider/index.js +2 -12
  312. package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -16
  313. package/dist/integrations/harnesses/amazonq/index.js +3 -17
  314. package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
  315. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  316. package/dist/integrations/harnesses/claude/index.js +1 -14
  317. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  318. package/dist/integrations/harnesses/codex/agent-builder.js +8 -7
  319. package/dist/integrations/harnesses/codex/index.js +2 -13
  320. package/dist/integrations/harnesses/copilot/agent-builder.js +9 -9
  321. package/dist/integrations/harnesses/copilot/index.js +1 -13
  322. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -9
  323. package/dist/integrations/harnesses/gemini/index.js +1 -13
  324. package/dist/integrations/harnesses/ids.js +24 -0
  325. package/dist/integrations/harnesses/index.js +31 -33
  326. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  327. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  328. package/dist/integrations/harnesses/opencode/index.js +1 -18
  329. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  330. package/dist/integrations/harnesses/opencode-sdk/harness.js +3 -17
  331. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +280 -193
  332. package/dist/integrations/harnesses/openhands/agent-builder.js +12 -10
  333. package/dist/integrations/harnesses/openhands/index.js +2 -12
  334. package/dist/integrations/harnesses/pi/agent-builder.js +11 -18
  335. package/dist/integrations/harnesses/pi/index.js +3 -16
  336. package/dist/integrations/harnesses/shared.js +17 -0
  337. package/dist/integrations/harnesses/types.js +38 -34
  338. package/dist/integrations/lockfile.js +166 -24
  339. package/dist/integrations/session-logs/index.js +24 -40
  340. package/dist/integrations/session-logs/provider-base.js +113 -0
  341. package/dist/llm/client.js +182 -110
  342. package/dist/llm/embedders/deterministic.js +2 -2
  343. package/dist/llm/embedders/remote.js +21 -9
  344. package/dist/llm/feature-gate.js +17 -57
  345. package/dist/llm/graph-extract.js +12 -13
  346. package/dist/llm/index-passes.js +8 -42
  347. package/dist/llm/memory-infer.js +144 -1
  348. package/dist/llm/metadata-enhance.js +45 -30
  349. package/dist/llm/structured-call.js +16 -8
  350. package/dist/llm/usage-persist.js +30 -5
  351. package/dist/llm/usage-telemetry.js +59 -6
  352. package/dist/output/cli-hints.js +1 -2
  353. package/dist/output/command-registry.js +27 -0
  354. package/dist/output/context.js +22 -7
  355. package/dist/output/format-exempt.js +80 -0
  356. package/dist/output/generic-render.js +251 -0
  357. package/dist/output/html-render.js +11 -16
  358. package/dist/output/render-registry.js +57 -0
  359. package/dist/output/renderers.js +15 -281
  360. package/dist/output/shapes/curate.js +10 -1
  361. package/dist/output/shapes/events.js +12 -7
  362. package/dist/output/shapes/helpers.js +58 -84
  363. package/dist/output/shapes/passthrough.js +8 -44
  364. package/dist/output/shapes/proposal/producer.js +15 -7
  365. package/dist/output/shapes/registry.js +12 -6
  366. package/dist/output/shapes.js +0 -9
  367. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  368. package/dist/output/text/bundle-show.js +7 -0
  369. package/dist/output/text/command-format.js +562 -0
  370. package/dist/output/text/env.js +1 -3
  371. package/dist/output/text/events.js +8 -7
  372. package/dist/output/text/helpers.js +15 -1375
  373. package/dist/output/text/proposal/producer.js +4 -2
  374. package/dist/output/text/proposal-format.js +202 -0
  375. package/dist/output/text/registry-commands.js +1 -2
  376. package/dist/output/text/registry.js +12 -6
  377. package/dist/output/text/show-directives.js +115 -0
  378. package/dist/output/text/show-format.js +103 -0
  379. package/dist/output/text/sync.js +5 -0
  380. package/dist/output/text/workflow-format.js +277 -0
  381. package/dist/output/text/workflow.js +1 -6
  382. package/dist/output/text.js +10 -19
  383. package/dist/registry/factory.js +4 -6
  384. package/dist/registry/origin-resolve.js +16 -27
  385. package/dist/registry/providers/skills-sh.js +3 -3
  386. package/dist/registry/providers/static-index.js +15 -25
  387. package/dist/registry/resolve.js +43 -94
  388. package/dist/registry/semver.js +43 -0
  389. package/dist/runtime.js +81 -12
  390. package/dist/scripts/akm-migrate-node.js +58773 -0
  391. package/dist/scripts/akm-migrate.js +58114 -0
  392. package/dist/setup/detect.js +45 -22
  393. package/dist/setup/detected-engines.js +136 -0
  394. package/dist/setup/engine-config.js +100 -0
  395. package/dist/setup/registry-stash-loader.js +3 -3
  396. package/dist/setup/semantic-assets.js +12 -9
  397. package/dist/setup/setup.js +445 -209
  398. package/dist/setup/steps/connection-shared.js +120 -0
  399. package/dist/setup/steps/connection.js +108 -305
  400. package/dist/setup/steps/platforms.js +13 -12
  401. package/dist/setup/steps/semantic.js +15 -3
  402. package/dist/setup/steps/sources.js +21 -15
  403. package/dist/setup/steps/stashdir.js +6 -4
  404. package/dist/setup/steps/tasks.js +236 -119
  405. package/dist/setup/steps.js +3 -2
  406. package/dist/sources/freshness.js +39 -0
  407. package/dist/sources/provider-factory.js +11 -17
  408. package/dist/sources/providers/filesystem.js +2 -3
  409. package/dist/sources/providers/git-install.js +278 -34
  410. package/dist/sources/providers/git-provider.js +54 -56
  411. package/dist/sources/providers/git-stash.js +424 -93
  412. package/dist/sources/providers/git.js +2 -2
  413. package/dist/sources/providers/npm.js +16 -19
  414. package/dist/sources/providers/provider-utils.js +47 -22
  415. package/dist/sources/providers/sync-from-ref.js +3 -9
  416. package/dist/sources/providers/website.js +7 -2
  417. package/dist/sources/resolve.js +11 -10
  418. package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
  419. package/dist/sources/snapshot-fetchers/content-extract.js +370 -0
  420. package/dist/sources/snapshot-fetchers/fetcher-util.js +40 -0
  421. package/dist/sources/snapshot-fetchers/host-guard.js +199 -0
  422. package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +10 -1
  423. package/dist/sources/snapshot-fetchers/robots.js +348 -0
  424. package/dist/sources/snapshot-fetchers/rss.js +279 -0
  425. package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
  426. package/dist/sources/snapshot-fetchers/types.js +4 -0
  427. package/dist/sources/snapshot-fetchers/website-ingest.js +935 -0
  428. package/dist/sources/snapshot-fetchers/x.js +193 -0
  429. package/dist/storage/database.js +60 -4
  430. package/dist/storage/engines/sqlite-migrations.js +69 -3
  431. package/dist/storage/locations.js +1 -2
  432. package/dist/storage/repositories/canaries-repository.js +1 -1
  433. package/dist/storage/repositories/events-repository.js +51 -11
  434. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  435. package/dist/storage/repositories/index-connection.js +79 -0
  436. package/dist/storage/repositories/index-db.js +4 -3
  437. package/dist/storage/repositories/index-entries-repository.js +863 -0
  438. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  439. package/dist/storage/repositories/index-entry-types.js +4 -0
  440. package/dist/storage/repositories/index-fts-repository.js +167 -0
  441. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  442. package/dist/storage/repositories/index-meta-repository.js +49 -0
  443. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  444. package/dist/storage/repositories/index-sql.js +12 -0
  445. package/dist/storage/repositories/index-utility-repository.js +356 -0
  446. package/dist/storage/repositories/index-vec-repository.js +250 -0
  447. package/dist/storage/repositories/outcome-repository.js +119 -0
  448. package/dist/storage/repositories/proposals-repository.js +317 -75
  449. package/dist/storage/repositories/registry-cache.js +1 -1
  450. package/dist/storage/repositories/salience-repository.js +172 -0
  451. package/dist/storage/repositories/task-history-repository.js +110 -3
  452. package/dist/storage/repositories/workflow-runs-repository.js +68 -35
  453. package/dist/tasks/backends/cron.js +169 -46
  454. package/dist/tasks/backends/exec-utils.js +76 -3
  455. package/dist/tasks/backends/index.js +6 -9
  456. package/dist/tasks/backends/launchd.js +292 -55
  457. package/dist/tasks/backends/schtasks.js +557 -70
  458. package/dist/tasks/backends/types.js +4 -0
  459. package/dist/tasks/command-executable.js +93 -0
  460. package/dist/tasks/embedded.js +56 -38
  461. package/dist/tasks/parser.js +156 -64
  462. package/dist/tasks/resolve-akm-bin.js +144 -51
  463. package/dist/tasks/runner.js +394 -223
  464. package/dist/tasks/schedule.js +108 -19
  465. package/dist/tasks/scheduler-invocation.js +296 -0
  466. package/dist/tasks/schema.js +25 -2
  467. package/dist/tasks/task-id.js +35 -0
  468. package/dist/tasks/validator.js +30 -16
  469. package/dist/workflows/authoring/authoring.js +96 -148
  470. package/dist/workflows/authoring/scope-key.js +1 -1
  471. package/dist/workflows/concurrency-policy.js +15 -0
  472. package/dist/workflows/exec/brief.js +26 -60
  473. package/dist/workflows/exec/frozen-judge.js +73 -0
  474. package/dist/workflows/exec/native-executor.js +175 -95
  475. package/dist/workflows/exec/report.js +373 -201
  476. package/dist/workflows/exec/run-workflow.js +147 -82
  477. package/dist/workflows/exec/scheduler.js +12 -41
  478. package/dist/workflows/exec/step-work.js +257 -222
  479. package/dist/workflows/exec/unit-dispatch.js +4 -0
  480. package/dist/workflows/exec/workflow-engine-gate.js +65 -0
  481. package/dist/workflows/ir/compile.js +142 -284
  482. package/dist/workflows/ir/freeze.js +241 -0
  483. package/dist/workflows/ir/params.js +134 -10
  484. package/dist/workflows/ir/plan-hash.js +41 -6
  485. package/dist/workflows/ir/schema.js +541 -1
  486. package/dist/workflows/parser.js +878 -306
  487. package/dist/workflows/program/expressions.js +20 -208
  488. package/dist/workflows/program/schema.js +7 -10
  489. package/dist/workflows/renderer.js +100 -122
  490. package/dist/workflows/resource-limits.js +22 -0
  491. package/dist/workflows/runtime/checkin.js +4 -4
  492. package/dist/workflows/runtime/plan-classifier.js +131 -0
  493. package/dist/workflows/runtime/runs.js +243 -135
  494. package/dist/workflows/runtime/unit-checkin.js +1 -1
  495. package/dist/workflows/runtime/unit-phases.js +20 -0
  496. package/dist/workflows/runtime/workflow-asset-loader.js +235 -97
  497. package/dist/workflows/schema.js +1 -11
  498. package/dist/workflows/validate-summary.js +30 -36
  499. package/dist/workflows/validator.js +52 -30
  500. package/docs/README.md +42 -78
  501. package/docs/migration/README.md +8 -0
  502. package/docs/migration/release-notes/0.6.0.md +1 -1
  503. package/docs/migration/release-notes/0.7.0.md +9 -8
  504. package/docs/migration/release-notes/0.9.0.md +185 -14
  505. package/docs/migration/v0.7-to-v0.8.md +46 -47
  506. package/docs/migration/v0.8-to-v0.9.md +813 -0
  507. package/docs/reference/README.md +12 -0
  508. package/docs/reference/data-and-telemetry.md +333 -0
  509. package/package.json +25 -17
  510. package/schemas/akm-asset-envelope.json +93 -0
  511. package/schemas/akm-config.json +4660 -0
  512. package/schemas/akm-task.json +87 -0
  513. package/{dist/schemas → schemas}/akm-workflow.json +127 -82
  514. package/dist/akm-migrate-storage +0 -38
  515. package/dist/assets/help/help-accept.md +0 -12
  516. package/dist/assets/help/help-improve.md +0 -84
  517. package/dist/assets/help/help-proposals.md +0 -17
  518. package/dist/assets/help/help-propose.md +0 -17
  519. package/dist/assets/help/help-reject.md +0 -11
  520. package/dist/assets/profiles/frequent.json +0 -13
  521. package/dist/assets/profiles/recombine-only.json +0 -21
  522. package/dist/assets/profiles/reflect-distill.json +0 -30
  523. package/dist/assets/profiles/synthesize.json +0 -15
  524. package/dist/assets/prompts/procedural-system.md +0 -44
  525. package/dist/assets/prompts/recombine-system.md +0 -40
  526. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  527. package/dist/assets/tasks/core/backup.yml +0 -4
  528. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  529. package/dist/assets/templates/html/default.html +0 -78
  530. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  531. package/dist/assets/wiki/index-template.md +0 -12
  532. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  533. package/dist/assets/wiki/log-template.md +0 -8
  534. package/dist/assets/wiki/schema-template.md +0 -61
  535. package/dist/cli/config-migrate.js +0 -150
  536. package/dist/cli/config-validate.js +0 -39
  537. package/dist/commands/graph/graph-cli.js +0 -124
  538. package/dist/commands/graph/graph.js +0 -487
  539. package/dist/commands/improve/calibration.js +0 -161
  540. package/dist/commands/improve/dedup.js +0 -482
  541. package/dist/commands/improve/extract-watch.js +0 -140
  542. package/dist/commands/improve/hot-probation.js +0 -45
  543. package/dist/commands/improve/improve-auto-accept.js +0 -276
  544. package/dist/commands/improve/improve-profiles.js +0 -168
  545. package/dist/commands/improve/procedural.js +0 -398
  546. package/dist/commands/improve/recombine.js +0 -818
  547. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  548. package/dist/commands/lint/agent-linter.js +0 -44
  549. package/dist/commands/lint/command-linter.js +0 -44
  550. package/dist/commands/lint/default-linter.js +0 -16
  551. package/dist/commands/lint/fact-linter.js +0 -39
  552. package/dist/commands/lint/knowledge-linter.js +0 -16
  553. package/dist/commands/lint/memory-linter.js +0 -61
  554. package/dist/commands/lint/registry.js +0 -41
  555. package/dist/commands/lint/skill-linter.js +0 -45
  556. package/dist/commands/lint/task-linter.js +0 -50
  557. package/dist/commands/lint/workflow-linter.js +0 -81
  558. package/dist/commands/proposal/legacy-import.js +0 -115
  559. package/dist/commands/sources/history.js +0 -196
  560. package/dist/commands/tasks/default-tasks.js +0 -186
  561. package/dist/commands/wiki-cli.js +0 -292
  562. package/dist/core/asset/asset-registry.js +0 -76
  563. package/dist/core/asset/asset-spec.js +0 -316
  564. package/dist/core/config/config-migration.js +0 -602
  565. package/dist/core/deep-merge.js +0 -38
  566. package/dist/core/eval/rank-metrics.js +0 -113
  567. package/dist/core/ripgrep/install.js +0 -163
  568. package/dist/core/ripgrep/resolve.js +0 -81
  569. package/dist/indexer/db/db.js +0 -1414
  570. package/dist/indexer/manifest.js +0 -170
  571. package/dist/indexer/passes/metadata-contributors.js +0 -31
  572. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  573. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
  574. package/dist/llm/call-ai.js +0 -62
  575. package/dist/llm/memory-infer-impl.js +0 -138
  576. package/dist/output/shapes/distill.js +0 -14
  577. package/dist/output/shapes/history.js +0 -11
  578. package/dist/output/text/distill.js +0 -6
  579. package/dist/output/text/enable-disable.js +0 -8
  580. package/dist/output/text/history.js +0 -6
  581. package/dist/output/text/wiki.js +0 -16
  582. package/dist/registry/build-index.js +0 -386
  583. package/dist/schemas/akm-config.json +0 -14225
  584. package/dist/scripts/migrate-storage.js +0 -13169
  585. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -10169
  586. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  587. package/dist/setup/legacy-config.js +0 -106
  588. package/dist/sources/website-ingest.js +0 -635
  589. package/dist/storage/repositories/consolidation-repository.js +0 -38
  590. package/dist/storage/repositories/recombine-repository.js +0 -213
  591. package/dist/wiki/wiki-templates.js +0 -15
  592. package/dist/wiki/wiki.js +0 -1012
  593. package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
  594. package/dist/workflows/cli.js +0 -53
  595. package/dist/workflows/db.js +0 -350
  596. package/dist/workflows/exec/watch.js +0 -116
  597. package/dist/workflows/program/parser.js +0 -760
  598. package/dist/workflows/program/project.js +0 -105
  599. package/docs/data-and-telemetry.md +0 -227
  600. package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
  601. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
package/CHANGELOG.md CHANGED
@@ -8,36 +8,1008 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
8
8
 
9
9
  ### Added
10
10
 
11
+ - **RSS, Bluesky, and X sources.** `akm bundle add` now recognizes three new
12
+ kinds of URL and snapshots them as knowledge assets instead of crawling
13
+ them as ordinary web pages:
14
+
15
+ ```sh
16
+ akm bundle add https://blog.example/feed # RSS 2.0 / Atom / RDF
17
+ akm bundle add https://bsky.app/profile/<handle> # public, no auth
18
+ akm bundle add https://x.com/<user> # see token note below
19
+ ```
20
+
21
+ Any of these falling through — a `/feed` URL that actually serves HTML, an
22
+ unresolvable Bluesky handle — degrades to the normal website crawl rather
23
+ than failing the command.
24
+
25
+ X needs credentials: set `X_BEARER_TOKEN` for the X API v2, or
26
+ `X_RSS_TEMPLATE` to an RSS bridge URL containing `{username}`. To keep the
27
+ token out of your shell history, store it as an akm secret and inject it
28
+ per-invocation:
29
+
30
+ ```sh
31
+ akm secret set x-bearer-token
32
+ akm secret run secrets/x-bearer-token X_BEARER_TOKEN -- akm bundle add https://x.com/<user>
33
+ ```
34
+
35
+ With neither set, the X fetcher emits one warning and falls through.
36
+
37
+ ### Changed
38
+
39
+ - **X source tokens now resolve from the secret store during bundle update.**
40
+ The `secrets/x-bearer-token` akm secret is honored on the provider
41
+ `sync()` / bundle-update path, not just when adding or importing a URL —
42
+ closing a gap where a refresh saw only the `X_BEARER_TOKEN` environment
43
+ variable. Implemented as a `SecretResolver` capability injected from above
44
+ the source-provider import cycle; internals are documented in
45
+ `docs/architecture/reviews/env-secret-access.md`.
46
+
47
+ - **`website` crawls now have a hard time limit.** `crawlTimeoutMs` (default
48
+ 600000 — 10 minutes) bounds the entire crawl, and unlike the previous
49
+ between-page check it aborts work already in flight: a `Retry-After` sleep
50
+ could previously park `akm bundle add` for as long as a rate-limiting server
51
+ asked, well past the advertised cap. Raise it for a large site, or set
52
+ `"crawlTimeoutMs": 0` to disable the cap. Relatedly, `fetchWithRetry` now
53
+ honors its caller's `AbortSignal` during retry backoff, so any operation that
54
+ passes a signal can actually interrupt a long wait.
55
+
56
+ - **Website snapshots now extract the page's main content.** Conversion moved
57
+ from a hand-rolled regex converter to a DOM parse plus Turndown, scoped to
58
+ the page's content region (`<main>`, `<article>`, `[role=main]`, then common
59
+ content ids/classes, falling back to `<body>` minus nav/header/footer/aside).
60
+ Navigation, ads, and boilerplate no longer land in snapshots, and tables,
61
+ nested lists, and fenced code blocks with language hints now survive
62
+ conversion. **Existing website snapshots will change on their next refresh**
63
+ — expect them to get shorter and cleaner. Link discovery still scans the
64
+ whole page, so crawl coverage is unchanged.
65
+
66
+
67
+ - **`website` sources now respect `robots.txt` by default.** Before crawling
68
+ an origin, akm fetches and parses that origin's `/robots.txt` and skips
69
+ paths disallowed for the `akm`/`akm-cli` product tokens (or `*`), honoring
70
+ `Crawl-delay` (clamped to 10s) between page fetches. This is a deliberate
71
+ behavior change: **existing website sources may return fewer pages, or
72
+ fail with an error if the start URL itself is disallowed, after
73
+ upgrading.** Re-running `akm bundle update` on a website source is what
74
+ surfaces it. Opt out with `"respectRobots": false` on the website
75
+ descriptor to restore the exact pre-upgrade behavior (no `/robots.txt`
76
+ request at all):
77
+
78
+ ```json
79
+ { "bundles": { "docs": { "website": { "url": "https://docs.example.com", "respectRobots": false } } } }
80
+ ```
81
+
82
+ ## [0.9.0-rc.13] - 2026-07-31
83
+
84
+ ### Security
85
+
86
+ - **`akm update` no longer deletes a previous install directory without
87
+ confirmation.** When a managed source's resolved content location moves,
88
+ `update` removed the old directory outright, while `akm remove` had always
89
+ required `--yes` in non-interactive mode. Only that destructive branch is
90
+ gated — a normal refresh, where the location does not move, still needs no
91
+ prompt and no flag, so existing CI invocations are unaffected. Pass
92
+ `-y`/`--yes` to allow the deletion non-interactively. A cleanup that fails
93
+ now warns instead of failing silently.
94
+
95
+ - **The dangerous-env-key install gate now scans `env/` recursively.** It
96
+ previously read only the top level, so a stash carrying `LD_PRELOAD` in
97
+ `env/nested/inner.env` installed cleanly with no warning. Files without a
98
+ `.env` suffix are still not scanned — no akm code path loads them as
99
+ environment variables.
100
+
101
+ ### Added
102
+
103
+ - **The `okf` adapter reads OKF v0.2's trust/provenance and lifecycle
104
+ frontmatter families.** `generated: {by, at}` (with `generated.at` taking
105
+ precedence over the legacy `timestamp` field, which remains a valid
106
+ fallback), `verified` (a list, or v0.2's permitted single-mapping
107
+ shorthand), `sources` (an object list — `resource` required; `id`/`title`/
108
+ `author`/`usage_count`/`last_modified` optional), `status`
109
+ (`draft`/`stable`/`deprecated`), and `stale_after` are now parsed leniently
110
+ from any OKF concept's frontmatter and surfaced on new, namespaced
111
+ `IndexDocument` fields (`provenance`, `lifecycleStatus`, `staleAfter`,
112
+ `okfVersion`) that never overload the pre-existing AKM-native `sources`
113
+ (wiki citation strings), `generation` (consolidation depth), or `quality`
114
+ fields. As with every other optional OKF field, a missing or malformed
115
+ value never rejects the document. The `okf` adapter remains consumer-only.
116
+
117
+ - **Accepting a proposal now stamps OKF v0.2 provenance onto the written
118
+ asset's frontmatter**, for AKM-native writes only (never through the `okf`
119
+ adapter, which stays consumer-only and unaffected by this). `promoteProposal`
120
+ projects the proposal system's own `source`/`sourceRun`/`gateDecision`/
121
+ `review` bookkeeping — already tracked in `state.db` but previously never
122
+ written to disk. `generated: {by, at}` and `verified: [{by, at}]` are written
123
+ **bare at the top level**, exactly as OKF v0.2 spells them, so a third-party
124
+ OKF v0.2 reader pointed at an AKM stash sees conformant trust metadata;
125
+ `sources` alone is namespaced as `provenance: {sources}`, because a bare
126
+ `sources:` collides with the pre-existing wiki citation-string convention.
127
+ `generated.by` records whether the content came from an automated pipeline
128
+ (`akm/<version>`) or a human-initiated source (`human:<id>`); `verified`
129
+ records whether the promotion itself was an automated gate decision or a
130
+ direct human accept, and accumulates rather than overwriting across
131
+ re-promotions; `evidenceSources`, when present, projects as
132
+ `provenance.sources`. AKM's own adapter rereads what it wrote, so `akm show`
133
+ surfaces it. Every AKM-native markdown type is stamped, `workflow` included.
134
+
135
+ Two consequences worth knowing: promotion re-serializes the whole frontmatter
136
+ block, so YAML **comments** in a hand-written proposal's frontmatter are not
137
+ preserved (values and body bytes are); and for a human-attributed promotion
138
+ with no configured actor id, `by` falls back to `human:<OS username>`, which
139
+ puts that username into content you may later commit and share.
140
+
141
+ - **Internal: a `capturedAtHead` integrity guard**
142
+ (`scripts/lint-golden-captured-at-head.ts`, wired into `bun run lint`) now
143
+ checks every golden fixture's recorded `capturedAtHead` commit SHA — it must
144
+ exist in the local object database and be reachable from at least one known
145
+ branch. Post-hoc review of this PR found all four new OKF format-family
146
+ goldens pointed at a commit that existed locally but was unreachable from
147
+ any ref (a pre-amend duplicate left behind by an interrupted git operation),
148
+ which would have 404'd on GitHub and vanished under a local `git gc`; a
149
+ human fixed that one by hand because nothing caught it. This guard is that
150
+ catch, going forward. In CI's shallow (`fetch-depth: 1`) checkout, a merely
151
+ *absent* commit object is inconclusive (indistinguishable from "just not
152
+ fetched") and only warns; a commit that *exists but is unreachable from any
153
+ branch* — the actual bug class above — still fails there too, since a
154
+ shallow clone can tell presence apart from absence just fine.
155
+
156
+ - **`akm log list --limit <n>`** returns the most recent N events. The flag was
157
+ documented but silently ignored, and there was no limiting mechanism at all
158
+ in the read path — the command returned the entire events table regardless of
159
+ history size. The default remains unlimited.
160
+
161
+ - **`--track-usage` (default on) on `akm search`, `akm curate`, and `akm show`.**
162
+ Pass `--no-track-usage` for a read-only lookup that does not feed usage
163
+ telemetry or the utility-score ranking signal. Previously a bare `akm search`
164
+ silently wrote a `utility_scores` row that influenced future ranking, with no
165
+ disclosure and no way to opt out.
166
+
167
+ - **`akm show` returns the canonical `ref` in every shape.** It was present only
168
+ under `--shape agent`, so a `--shape summary` consumer had to make a second
169
+ call at a different shape just to learn which asset it was looking at.
170
+
171
+ - **`akm info` gained `stashDir`, `defaultBundle`, and `indexStats.byType`.**
172
+ Answering "which stash is primary" previously required a separate
173
+ `akm sources list`.
174
+
175
+ - **`instruction` is a stash-resident asset type.** It was already in
176
+ `KNOWN_TYPES` and had a presentation entry, but had no placement spec — so
177
+ there was nowhere to put one and the indexer never recognized one. `akm bundle create`
178
+ now creates an `instructions/` directory, `.md` files under it index as
179
+ `instruction`, and `--type instruction` is accepted and tab-completable
180
+ everywhere `--type` is. A compile-time assertion now pins
181
+ `placementTypes() ⊆ KnownType`, so the half-registered state this fixes
182
+ cannot recur silently.
183
+
184
+ - **Schedule tasks from any configured bundle via `--bundle <bundle>`** (#711).
185
+ `akm task add`, `run`, `sync`, and `history` accept `--bundle` to
186
+ operate on a non-default bundle instead of only the primary stash. `add`
187
+ resolves through the normal writable-target rules; `run --bundle X` resolves
188
+ the task file and relative asset refs from bundle X. A non-default bundle is
189
+ recorded in the scheduler entry as `--bundle <bundle>`, so scheduled
190
+ `akm task run` resolves the right bundle. Scheduler ids stay bare and a
191
+ collision with another bundle is a hard error rather than a silent clobber.
192
+
193
+ - **Orphan-GC pass for unresolvable `asset_salience` / `asset_outcome` state
194
+ rows** (#733). A new improve maintenance pass (`runOrphanStateGcPass`, run
195
+ next to the existing orphan-proposal purge) stamps `missing_since` on any
196
+ state row whose ref no longer resolves against `entries.item_ref`, clears
197
+ the stamp the moment the ref resolves again, and — only when
198
+ `improve.stateGc.collect` is set to `true` (**default `false`**) — deletes
199
+ rows whose stamp is older than a fixed 7-day grace window
200
+ (`STATE_GC_GRACE_MS`). The pass always runs and always reports counts via
201
+ the new `asset_state_gc` event (`{pending, collected, byTable}`), emitted
202
+ only when there is something to report, so live data can prove the report
203
+ clean before `collect` is ever turned on. Additive migration
204
+ `021-asset-state-missing-since` adds the `missing_since` column to both
205
+ tables. Deliberately lean by design (Workstream C): no quarantine archive,
206
+ no circuit breaker, no health-advisory plumbing, no new tables — "ref not
207
+ present in `entries.item_ref`" is trusted as the authoritative-deletion
208
+ predicate because the indexer already preserves a source's last-known-good
209
+ rows when its scan is incomplete, so a temporarily unreachable source never
210
+ contributes false candidates. `usage_events` is out of scope (already
211
+ covered by cascade-on-delete plus its own 90-day retention purge).
212
+
213
+ ### Changed
214
+
215
+ - **Workflow execution is consolidated on stable `akm workflow run`.** The
216
+ public `workflow start`, `next`, and `complete` commands are removed with
217
+ explicit `UNKNOWN_COMMAND` migration hints; `run <ref|run-id>` now owns
218
+ creation, active-run continuation, native dispatch, completion, and durable
219
+ replay. It is no longer gated by `experimental.workflowEngine`; only the
220
+ experimental `brief`/`report` external-driver protocol retains that opt-in.
221
+ Workflow parameters move from the opaque `--params '<json>'` bag to exact
222
+ declared flags (`--version 1.2.3`, repeated array flags, JSON object/array
223
+ values) coerced through the frozen parameter schemas. New invocation controls
224
+ add bounded failed-step retries (`--max-retries`) and a whole-run timeout
225
+ (`--timeout N|Nms|Ns|Nm`); failures, gate rejection, timeout, and signals now
226
+ produce non-zero process statuses while leaving interrupted work resumable.
227
+
228
+ Criteria-bearing gates now require `workflow.judgeEngine`, which may name a
229
+ configured LLM or agent engine and is frozen into the run. Verification is
230
+ fail-closed: a missing/failing verifier or malformed verdict rejects instead
231
+ of silently advancing. Scheduled workflow tasks now execute through the same
232
+ native orchestrator rather than stopping after run creation. Migration:
233
+ replace `workflow start/next/complete` loops with `workflow run`, replace
234
+ `--params` with exact declared flags, and configure `workflow.judgeEngine`
235
+ before running a workflow with a non-empty `### gate` rubric.
236
+
237
+ - **The two workflow authoring formats — markdown documents and YAML
238
+ orchestration programs — are unified into one format**, per
239
+ `docs/architecture/specs/workflow-format-unification.md`. A workflow is
240
+ now always a single markdown asset: the standard AKM frontmatter envelope
241
+ carries the whole orchestration graph (`params`, `steps` with
242
+ `unit`/`map`/`route`, `inputs`, `output`, `gate`, `defaults`, `budget`),
243
+ and the body carries each step's instructions under a bare `## <step-id>`
244
+ heading, joined to the frontmatter by step id. `.yaml`/`.yml` workflow
245
+ files, the `# Workflow:` / `## Step:` / `Step ID:` markdown headings, and
246
+ `akm workflow create <name>.yaml` are all gone; `akm workflow create`
247
+ always writes the one unified template
248
+ (`src/assets/workflows/workflow-template.md`).
249
+
250
+ **Prose is never interpolated.** The YAML program's `${{ … }}` template
251
+ language, and the markdown format's decorative — and never
252
+ substituted — `{{ … }}` moustaches, are both removed. Data reaches a
253
+ dispatched unit as *attached context* instead: the run's params, its
254
+ item and index for a map unit, and the artifacts its step's new
255
+ `inputs:` key declares. Instructions refer to that context in plain
256
+ language ("clone the repository named by the `repo` parameter") rather
257
+ than splicing a value into the instruction string. Bare reference
258
+ strings (two roots, `params.<name>` and `steps.<id>.output…`) now appear
259
+ only in three frontmatter positions: `map.over`, `route.input`, and
260
+ `inputs:`.
261
+
262
+ **Gate rubrics move to the body.** A step's completion criteria are no
263
+ longer a frontmatter `gate.criteria` list or a `### Completion Criteria`
264
+ bullet section — they live under a step's `### gate` sub-heading, the
265
+ format's one reserved marker, as full prose a judge receives byte-exact.
266
+ Frontmatter `gate:` now carries only optional `max_loops` configuration.
267
+ Omitted or empty rubric text skips validation; a non-empty rubric requires
268
+ the frozen `workflow.judgeEngine`, and unavailable or malformed judges reject
269
+ the gate.
270
+
271
+ This is a **pre-1.0 format change**. The ten example workflows under
272
+ `scripts/akm-eval/example-stash/workflows/` are rewritten to the unified
273
+ format in this change; existing user-authored workflow assets must be updated
274
+ manually before execution.
275
+
276
+ - **akm is described as a knowledge toolkit, not a package manager** (R-048).
277
+ The npm one-liner, the README lede, and the `concepts.md` opener all led with
278
+ "a package manager for AI agent capabilities", which misstates the product to
279
+ its distribution channel and sets package-manager expectations for verbs
280
+ (`update` / `upgrade` / `sync`) that don't mean what a package manager's do.
281
+
282
+ - **BREAKING: a command group invoked with no subcommand is now always a usage
283
+ error, exit 2** (owner ruling 12). The eleven `akm <group>` groups did three
284
+ different things when invoked bare: `graph`, `config`, `env`, `secret`,
285
+ `task`, `workflow`, and `proposal` ran an implicit default action and exited
286
+ 0 (bare `akm graph` silently rendered `graph summary`); `registry`, `log`, and
287
+ `lessons` printed citty's human usage banner to stdout; only `migrate` raised
288
+ a structured error. All eleven now emit the same
289
+ `MISSING_REQUIRED_ARGUMENT` envelope on stderr, naming the available
290
+ subcommands, and exit 2 — matching STABILITY.md's exit-code table (2 =
291
+ usage) and the exit code already used for unknown commands. Matching exit
292
+ codes alone was not enough: a script could not parse the failure uniformly
293
+ while three groups answered on stdout in prose.
294
+
295
+ Migration: name the subcommand. `akm graph` → `akm graph summary`,
296
+ `akm config` → `akm config list`, `akm env` → `akm env list`, `akm secret` →
297
+ `akm secret list`, `akm task` → `akm task doctor`, `akm workflow` →
298
+ `akm workflow list --active`, `akm proposal` → `akm proposal list` (which
299
+ takes the same `--status`/`--queue`/`--ref`/`--type` flags the bare form did).
300
+
301
+ - **BREAKING: `akm sync` persists `eventType: "sync"`, not the legacy
302
+ `"save"`.** The event name now matches the command name. Historical
303
+ `state.db` rows are left as-is — `akm log` and `akm log tail` treat `"save"`
304
+ and `"sync"` as synonyms on **read**, so `akm log --type save` keeps
305
+ returning both old and new rows. Only newly written events use `"sync"`.
306
+
307
+ Migration: none for `akm log --type save`. A script matching raw event rows
308
+ by `eventType === "save"` — reading state.db directly, bypassing `akm log` —
309
+ should also match `"sync"` to see new syncs.
310
+
311
+ - **BREAKING: dropped the dead `installedKitCount` field from the `add`,
312
+ `remove`, and `update` JSON envelopes.** It was a raw lockfile-entry count
313
+ that nothing — internal code or test — ever read.
314
+
315
+ Migration: a script parsing `.config.installedKitCount` should stop; the
316
+ field is gone, not renamed. `config.sourceCount` remains and is unaffected.
317
+
318
+ - **BREAKING: dropped the dead `graphPath` field from every `akm graph *` JSON
319
+ envelope** (`summary`, `entities`, `relations`, `export`, `related`, `entity`,
320
+ `orphans`). It always resolved to the shared state.db path, never a
321
+ per-graph artifact, and carried nothing `stashPath` did not already provide.
322
+
323
+ Migration: a script reading `.graphPath` from any `akm graph` subcommand
324
+ should stop; `stashPath` remains.
325
+
326
+ - **BREAKING: `semanticSearchMode` now defaults to `"off"`.** A bare or
327
+ headless install (`akm init`, `akm setup --yes`, `akm setup --config`) was
328
+ silently downloading the ~130 MB local embedding model on its first `akm
329
+ index`, because the fallback used when the key is absent was `"auto"`. The
330
+ interactive `akm setup` wizard still pre-selects semantic search **on** — a
331
+ human is present to decide — and now shows the asset/download warning
332
+ *before* the prompt rather than after, so the pre-checked box is an informed
333
+ choice. When a remote `embedding.endpoint` is configured, enabling semantic
334
+ search downloads nothing.
335
+
336
+ Migration: existing saved configs are unaffected — the flip only changes the
337
+ fallback used when the key is absent. To keep semantic search on for a
338
+ headless or CI install, set `semanticSearchMode: "auto"` explicitly, or point
339
+ `embedding.endpoint` at a remote embedder.
340
+
341
+ - **BREAKING: `akm workflow run|brief|report` refuse to run until
342
+ `experimental.workflowEngine` is set** (0.9.0 decision Q-05). The native
343
+ workflow executor — including fan-out scheduling and worktree isolation —
344
+ is experimental, and shipping it enabled by default would have made an
345
+ unreviewed execution engine reachable from a plain `akm workflow run`. The
346
+ gated surfaces now exit `78` with a `ConfigError` naming the exact key, and
347
+ `akm task doctor` reports the gate's state. Authoring and linting the unified
348
+ markdown format, along with every other `akm workflow` subcommand, remain
349
+ ungated.
350
+
351
+ Migration: `akm config set experimental.workflowEngine true`.
352
+
353
+ - **BREAKING: the `env:<name>` / `secret:<name>` colon ref spelling is
354
+ rejected** (0.9.0 decision Q-08). Refs are slash conceptIds only — `env/foo`,
355
+ `secrets/deploy-key`. The colon form previously resolved as an undocumented
356
+ alias in some places and fell through as a literal filename in others. It now
357
+ fails with a usage error naming the slash replacement, rather than silently
358
+ doing the wrong thing.
359
+
360
+ Migration: rewrite `env:<name>` as `env/<name>` and `secret:<name>` as
361
+ `secrets/<name>`. The error message prints the exact replacement.
362
+
363
+ - **`akm improve` is review-first by default; autonomy is opt-in** (0.9.0
364
+ decision D8). The command stays ON — schedules, reflect/distill proposals, and
365
+ graph extraction are unchanged — but the lanes that mutate assets *without*
366
+ review now require `akm config set experimental.improveAutonomy true`:
367
+ memory-inference writes, the memory-cleanup pass, and triage
368
+ `applyMode: "promote"` (which downgrades to `queue` rather than disabling
369
+ triage). Consolidation remains review-oriented and is not gated.
370
+
371
+ A gated lane is never a silent no-op: it warns on stderr naming the lane and
372
+ the key, appends an `improve_skipped` event with `reason: "autonomy_gated"`,
373
+ and is counted in `akm health`'s improve skip-reason summary.
374
+
375
+ Migration: set `experimental.improveAutonomy: true` to restore the previous
376
+ behavior. `sync.push` is **not** affected — it keeps its `true` default and its
377
+ own `sync.push: false` / `--no-push` controls. Two other direct writes stay
378
+ ungated by design: `extract`'s additive session indexing and distill's
379
+ encoding-salience frontmatter stamp. Because the gate is applied before the LLM
380
+ preflight, a review-first workspace may now need fewer engines configured than
381
+ before.
382
+
383
+ Also: `akm improve` no longer rejects the global `--format`. It emits an
384
+ envelope through `output()` (always under `--dry-run`, otherwise under
385
+ `--json-to-stdout`), so `--format` applies to that envelope; progress output
386
+ stays on stderr. Previously it exited 2 with `INVALID_FLAG_VALUE`, which made
387
+ it the one command that rejected a valid global flag.
388
+
389
+ - **`akm health --report` replaces the html-only full report** (D7
390
+ follow-through). The full health report — per-run rows, trend deltas vs the
391
+ prior window, and the pending proposal queue — is now a **data** flag, not a
392
+ side effect of asking for html: `akm health --report --format html` renders
393
+ the rich report, and the identical dataset comes back under `--format json`
394
+ (previously that data was reachable only as html). The registered md/html
395
+ renderers fire on the shape of the result, and `akm health` no longer reads
396
+ `--format` at all.
397
+
398
+ Migration: `akm health --format html` → `akm health --report --format html`
399
+ (the bare form now renders the plain check generically); the html-only
400
+ `--compare` flag is removed — use `--window-compare`, which with `--report`
401
+ defaults to the `--since` window so trend deltas stay like-for-like.
402
+
403
+ - **Global output flags parse correctly next to positionals.** citty parses
404
+ each command level against only its own declared args, so a root-declared
405
+ global flag was unknown at the leaf and its space-separated value fell
406
+ through as a positional — `akm sync --format json` synced a bundle named
407
+ "json", and `akm env unset env:x KEY --format json` tried to unset a key
408
+ named "json". The global output flags (`--format`, `--detail`, `--shape`,
409
+ `--output`) are now declared on every leaf command so their values are
410
+ consumed by the parser; the two bespoke argv-inspection workarounds this
411
+ replaces are deleted. Three more non-exempt commands (`akm health`, `akm
412
+ index`, `akm lint`) now declare these flags too, purely for `--help`
413
+ visibility — all three already parsed `--format`/`--detail`/`--shape`/
414
+ `--output` correctly, since none of them has a positional a stray value
415
+ could fall into.
416
+
417
+ - **BREAKING: unknown commands and missing required arguments now exit `2`
418
+ (usage), not `1`.** citty's own command-dispatch wrapper unconditionally
419
+ called `process.exit(1)` for any error it raised before a command's own
420
+ body ever ran — `akm totally-bogus` (unknown command), bare `akm log` /
421
+ `akm lessons` (a subcommand group invoked with no subcommand), and a
422
+ command missing a required positional (e.g. bare `akm import`) all exited
423
+ `1`, contradicting the documented exit-code table (`1` = general error /
424
+ not found, `2` = usage / bad input). The CLI now drives command dispatch
425
+ directly instead of going through that wrapper, so it can reclassify this
426
+ one error family as `2` while leaving `--help`, `--version`, and every
427
+ other exit code unchanged.
428
+
429
+ Migration: a script that treated exit `1` as "something went wrong" for a
430
+ mistyped command or missing argument should check for `2` instead (or
431
+ keep treating any non-zero exit as failure, which was already correct).
432
+
433
+ - **BREAKING: `akm completions --shell <unsupported>` now exits `2` with the
434
+ standard JSON error envelope, not `1` with a raw stack trace.**
435
+ `completions` stays format-exempt (its own output is shell-script source,
436
+ not a result envelope — see STABILITY.md), but its body is now wrapped in
437
+ the same error-classification path every other command uses.
438
+
439
+ Migration: a script parsing this failure should now expect
440
+ `{"ok":false,"error":"...","code":"INVALID_FLAG_VALUE","hint":...}` on
441
+ stderr and exit code `2` in place of a stack trace and exit code `1`.
442
+
443
+ - **BREAKING: `akm index --dry-run` without `--clean` now exits `2` instead
444
+ of running a real index.** The flag only ever gated the `--clean`
445
+ stale-entry removal pass — every other phase (walk, LLM enrichment,
446
+ embeddings, FTS, the adapter-detection config write) ran for real
447
+ regardless, so `akm index --dry-run` alone silently performed a full index
448
+ despite its name. The combination is now rejected with the standard usage
449
+ envelope instead of quietly doing something other than what "dry run"
450
+ promised.
451
+
452
+ Migration: a script or cron invoking bare `akm index --dry-run` was
453
+ already getting a real index, so nothing there needs to change in effect —
454
+ but it will now fail loudly instead. Pass `akm index --clean --dry-run` to
455
+ preview the stale-entry removal pass, or `akm index --clean` to apply it;
456
+ drop `--dry-run` entirely to keep running a plain real index.
457
+
458
+ - **BREAKING: a corrupt or unparseable `akm.lock` now makes lockfile WRITES
459
+ throw, instead of silently destroying every entry.** The previous lenient
460
+ reader returned `[]` on unparseable JSON; a write path that upserted a
461
+ single entry onto that `[]` then overwrote the file, permanently deleting
462
+ every other tracked bundle's lock entry. Install/update/remove write paths
463
+ now use a strict reader that throws on the same corruption instead of
464
+ reaching the destructive overwrite.
465
+
466
+ Migration: if a write now fails with a lockfile-parse error, `akm.lock` is
467
+ genuinely corrupt — inspect and repair it by hand, or restore it from a
468
+ backup (e.g. git history), before retrying the write. Reads elsewhere are
469
+ unaffected; the lenient read contract is unchanged.
470
+
471
+ - **BREAKING: `AKM_NPM_REGISTRY` now redirects npm package METADATA lookups,
472
+ not just the trusted-tarball allowlist.** Previously the override only
473
+ widened which tarball hosts were trusted for download while metadata
474
+ queries stayed hardcoded to `registry.npmjs.org`, so a configured private
475
+ mirror was never actually consulted for package info — the error hint that
476
+ points users at this variable was false. The override now also replaces
477
+ the metadata registry base, matching how a private npm registry is meant
478
+ to work (like npm's own `--registry` flag: wholesale replacement, not a
479
+ merge with the public registry).
480
+
481
+ Migration: an operator who set `AKM_NPM_REGISTRY` expecting only tarball
482
+ downloads to be redirected, with metadata still served from the public
483
+ registry, should confirm the mirror actually serves equivalent package
484
+ metadata — `akm add`/`akm update` for npm-sourced bundles now resolve
485
+ entirely against the configured mirror when it is set.
486
+
487
+ - **`akm remember --show-similar` and `akm migrate apply --dry-run` are the
488
+ documented, canonical spellings** (previously `--showSimilar` /
489
+ `--dryRun`), matching every other multi-word flag in the CLI. Not a
490
+ breaking change: citty registers both the camelCase and kebab-case
491
+ spelling of any declared flag name automatically, so `--showSimilar` /
492
+ `--dryRun` keep working — they're now explicit, documented aliases instead
493
+ of an undocumented accident.
494
+
495
+ - **`--detail` and `--shape` help text is scoped honestly.** The per-command
496
+ `--detail` description now names `info`, `list`, and `remember` as the
497
+ commands where it has no effect (verified byte-identical output at every
498
+ level — `akm show` is not one of these; it has three distinct
499
+ brief/normal/full payloads). `--shape`'s per-command help now repeats the
500
+ "`summary` is only valid on `akm show`" caveat the root help already
501
+ documented.
502
+
503
+ - **All six `--format` values work on every command** (0.9.0 decision D7).
504
+ `json|jsonl|yaml|text|md|html` are now universal. Previously there were three
505
+ inconsistent behaviours: `md` silently emitted the JSON envelope everywhere
506
+ except `akm health`, `html` was rejected with exit 2 everywhere except
507
+ `akm health`, and `akm health` reached neither because it intercepted the
508
+ format itself. Rendering is now registry-driven — a command may register a
509
+ renderer for a document format, and anything unregistered falls back to a real
510
+ rendering of its own envelope (headings, tables for arrays of uniform objects,
511
+ lists otherwise). `akm health` keeps its per-run/window-compare tables and its
512
+ full HTML report by registering them; the output is unchanged.
513
+
514
+ Migration: none required for `json|jsonl|yaml|text`. `--format md` on a
515
+ non-health command previously returned JSON and now returns Markdown; a script
516
+ that parsed that JSON should ask for `--format json` explicitly. `--format
517
+ html` previously exited 2 on non-health commands and now succeeds.
518
+
519
+ Also: `akm graph export --format` is **removed** — it declared `--format`
520
+ locally as well as globally (one token, two parsers). The artifact payload
521
+ now follows the `--out` extension (`--out g.jsonl` writes JSONL, anything
522
+ else JSON); the global flag only renders the command's own envelope. A dead
523
+ local `--format` declaration on `akm history` was removed too (it was never
524
+ read). Commands
525
+ whose output is not an envelope (`completions`, `setup`, `env run`,
526
+ `secret run`, `agent`, `workflow template`, `help migrate`) are declared
527
+ format-exempt in `src/output/format-exempt.ts` and now warn when given
528
+ `--format` instead of ignoring it silently. `output.format` in config accepts
529
+ all six values.
530
+
531
+ - **Subtree browse is a conceptId prefix, not `<type>:`** (0.9.0 decision D4).
532
+ `akm search` enumerates on `memories/`, `memories/projecta/`, `bundle//`, and
533
+ `bundle//skills/`; a trailing `/` is still required. The prefix now matches the
534
+ **conceptId** rather than the item name, so a ref copied out of search output
535
+ can be truncated to a prefix and pasted straight back in — previously that
536
+ round-trip degraded silently into a keyword search. Enumeration no longer
537
+ validates against the `akm` adapter's placement types, so items from every
538
+ adapter browse the same way, and `bundle//` lists a whole bundle (the
539
+ replacement for the removed `akm bundle items`).
540
+
541
+ Migration: `akm search "memory:"` → `akm search "memories/"`;
542
+ `akm search "memory:projectA/"` → `akm search "memories/projectA/"`;
543
+ `akm search "session:"` → `akm search "sessions/"`. The retired spelling is
544
+ now an ordinary keyword search; when it returns nothing, the tip names the
545
+ conceptId spelling that replaces it. `scripts/lint-shipped-assets.ts` no
546
+ longer exempts the old spelling, so it is an offense in agent-facing assets.
547
+
548
+ - **`akm task sync [--bundle <bundle>]` reconciles a single bundle.** Sync now
549
+ attributes each installed scheduler entry to its bundle (parsed from the
550
+ `--bundle` token; absent ⇒ primary) and reconciles only the entries for the
551
+ bundle being synced. A plain (primary) sync never installs from, updates, or
552
+ removes another bundle's entries, and sync never scans all bundles — task
553
+ activation stays explicit (`add --bundle` or `sync --bundle`), so registering a bundle
554
+ still never activates code. When the target is the default bundle (or omitted),
555
+ installed scheduler entries are byte-identical to before, so upgrading shows no
556
+ spurious drift.
557
+
558
+ - **The R2 salience ranking boost no longer applies to default `search`/`curate`
559
+ ranking** (#692). `asset_salience.rank_score` (an encoding + outcome +
560
+ retrieval projection, recomputed every `improve` run) previously composed
561
+ into every default search as a bounded multiplicative boost
562
+ (`salience-ranking`, ×[1.0–1.2]), loaded best-effort from `state.db` on the
563
+ hot path. On live data it measured as noise (max observed multiplier
564
+ ×1.071, mean ×1.016): the boost was retrieval-dominated with no source
565
+ filter — double-counting the same `usage_events` the utility-score
566
+ contributor already reinforces — warm-started non-zero with no outcome
567
+ evidence, and had zero pack coverage, so it could only ever favor
568
+ self-generated personal assets over an equally-relevant pack asset.
569
+ Removing the default `state.db` load also fixes a confirmed hot-path
570
+ defect: whenever `state.db` already existed, every default search
571
+ synchronously waited on the maintenance-activity barrier before ranking
572
+ could even start — up to a 5-second stall on a blocking wait loop, plus a
573
+ lock-file create, before the load's own 250ms SQLite `busy_timeout` ever
574
+ applied. No config gate was added: a key for a term being removed would be
575
+ dead surface for the upcoming 1.0 contract freeze to carry forever.
576
+ `rank_score` itself, and everything `improve` computes and does with it
577
+ internally, are unchanged — only its promotion into user-facing ranking is
578
+ removed. The contributor stays in the codebase (unwired) for a future
579
+ gated, outcome-backed experiment.
580
+
581
+ - **Internal: `asset_salience` / `asset_outcome` state.db access moved behind
582
+ `src/storage/repositories/{salience,outcome}-repository.ts`** (#672 part 2).
583
+ Mirrors the existing state.db repository precedents
584
+ (`proposals-repository.ts`, `improve-runs-repository.ts`,
585
+ `events-repository.ts`): the raw SQL, row-mapping, and the #644
586
+ encoding-provenance CASE guards are extracted verbatim, only relocated —
587
+ `commands/improve/salience.ts` and `outcome-loop.ts` re-export the moved
588
+ functions, so no importer or test churns. A new `state-table-sql` rule in
589
+ `scripts/lint-repository-sql.ts` now fails the build if raw
590
+ `asset_salience`/`asset_outcome` SQL reappears outside the repository
591
+ directory (or `core/state/migrations.ts`). Not a user-visible behavior
592
+ change: `rank_score`, `outcome_score`, and everything `improve`/`health`
593
+ compute from them are identical.
594
+
595
+ ### Fixed
596
+
597
+ - **The compiled standalone binary can run `akm migrate`.** Release binaries
598
+ compiled only `src/cli.ts`, and the migrator was resolved as a sibling file
599
+ and spawned — neither candidate exists inside a compiled executable, so the
600
+ documented `./akm-0.9 migrate status/apply` upgrade path always failed with
601
+ `FILE_NOT_FOUND`. Standalone builds now compile `scripts/akm-standalone.ts`,
602
+ a wrapper that embeds both the CLI and the migrator (src never imports
603
+ scripts/ — the dist build's tsc forbids it); `akm migrate` re-execs the
604
+ binary with an `AKM_MIGRATE_ENTRY` marker the wrapper dispatches on. The
605
+ repo and npm layouts keep the subprocess path.
606
+
607
+ - **Quarantined migration rows are retained in full, not reduced to a count.**
608
+ When the 0.8→0.9 cutover met a durable ref it could not map, it recorded
609
+ surface/ref/count in `legacy_state` and then deleted the rows — destroying
610
+ proposal payloads, event and task history, fingerprints, and canary anchors,
611
+ contrary to the migration guide's "quarantined, not dropped". Complete rows
612
+ are now preserved as JSON in `legacy_state_rows` before leaving the live
613
+ tables.
614
+
615
+ - **A failed content migration fails the apply instead of reporting success.**
616
+ Root discovery, sidecar folding, or the legacy-proposal import throwing was
617
+ swallowed and logged; the apply then advanced and cleared its journal, and —
618
+ because 0.9 removed the live `.stash.json` and filesystem-proposal readers —
619
+ the affected metadata and pending proposals became permanently inaccessible
620
+ behind an apparently successful upgrade. The step now fails the apply with
621
+ the journal intact; the committed cutover is untouched and the next apply
622
+ retries.
623
+
624
+ - **Sidecar provenance survives the fold.** Folding a `.stash.json` into
625
+ frontmatter dropped `xrefs` and `sources` entirely and mapped legacy
626
+ `sourceRefs` to a `source_refs` key that could never fire (the validator
627
+ stopped copying the field) and that 0.9 never reads — then deleted the only
628
+ copy. `xrefs`/`sources` now fold through, and legacy `sourceRefs` merge into
629
+ `xrefs`.
630
+
631
+ - **A reserved-filename rename re-keys durable state.** The D-R6 rename of a
632
+ mis-named `index.md`/`log.md` concept ran after the cutover had keyed usage,
633
+ salience, and proposal rows to the old conceptId, stranding that learned
634
+ state. The rename now feeds the same re-key engine the cutover uses, with
635
+ the pairs persisted before re-keying so a crash between the two stays
636
+ retryable.
637
+
638
+ - **v1 tasks in a read-only bundle are surfaced with a remedy instead of being
639
+ silently skipped.** The 0.9 runtime removed the v1 task parser, so silently
640
+ skipping a `writable: false` bundle left tasks that would start failing after
641
+ an upgrade that reported current. The preflight now warns per bundle and
642
+ lists the stranded files in the plan (`readOnlyLegacyTasks`). It does not
643
+ block the apply: the migration deliberately never rewrites a read-only
644
+ bundle, and the fix for a lock-materialized git/npm bundle belongs upstream.
645
+
646
+ - **Lock resolution metadata survives migration.** Merging the migrator's
647
+ sparse lock entries replaced whole rows by id, discarding
648
+ `resolvedVersion`/`resolvedRevision`/`integrity`/`installedAt` recorded by a
649
+ real install. Merge now preserves existing fields the incoming entry does
650
+ not define.
651
+
652
+ - **Migrating a pre-0.9 config no longer silently changes source policy.**
653
+ Three settings were dropped by the config-shape migration: an explicit
654
+ `writable: false` (an omitted filesystem `writable` reads as `true` in the
655
+ new shape, so a source the user deliberately protected became writable), an
656
+ explicit `enabled: false` (resuming refreshes and indexing for content the
657
+ operator had turned off), and a website source's `maxDepth` (silently
658
+ resetting crawl depth). All three now round-trip to the runtime source entry;
659
+ `bundles.<id>.enabled` is a supported key.
660
+
661
+ - **`akm mv` refuses a bundle marked `writable: false`.** It renamed the file
662
+ and rewrote citers anyway, because its preflight checked adapter
663
+ compatibility rather than writability — every other write command already
664
+ refused.
665
+
666
+ - **Memory belief edges written by `--supersedes` are no longer ignored.**
667
+ `writeSupersededEdge` persists a fully-qualified conceptId, but the belief
668
+ analyzer accepted only the internal `memory:<name>` spelling, so every edge
669
+ from `akm remember --supersedes` / `akm import --supersedes` was dropped and
670
+ a superseded memory read back as active.
671
+
672
+ - **`akm env run <ref> -- <cmd> --help` runs the command.** The builtin
673
+ help-flag scan read the child tail after `--` and printed akm's own usage
674
+ instead.
675
+
676
+ - **`akm mv` works under an `AKM_STASH_DIR` override again.** A valid override
677
+ not owned by a configured bundle failed with `No configured bundle owns move
678
+ source`.
679
+
680
+ - **An unexpected internal error exits 70 with the JSON failure envelope.** The
681
+ residual dispatch boundary exited 1 with an unstructured message, so
682
+ automation could not tell an internal defect from an ordinary failure.
683
+
684
+ - **Concurrent `akm config set` processes no longer give up prematurely.** The
685
+ contended-lock wait budget was 500ms total, so several concurrent writers on
686
+ a loaded machine could exhaust it and fail with "Timed out waiting for config
687
+ lock" against a healthy but busy lock. Abandoned locks are still reclaimed by
688
+ the stale probe, which this budget does not gate.
689
+
690
+ - **Config keys named in indexer output and comments now exist.** Four sites
691
+ pointed at a top-level `llm.*` namespace that the config schema has no such
692
+ key for — including the user-facing "Increase llm.timeoutMs" warning on an
693
+ exceeded enrichment budget. The enrichment budget lives at
694
+ `index.enrichment.timeoutMs` (or `index.defaults.timeoutMs`). Indexing
695
+ concurrency is auto-derived (2 remote / 1 local) and currently has no config
696
+ override on that path: `engines.<name>.concurrency` is a valid schema field
697
+ but the engine resolver does not forward it (documented in
698
+ `docs/architecture/internals/indexing.md`).
699
+
700
+ - **The bundle-identity-drift warning stops naming a command that doesn't
701
+ exist.** It told users to "rekey it atomically via the bundle-rename
702
+ command"; 0.9.0 ships no such command. It now gives the two remedies that
703
+ work: restore the previous bundle id in `config.json`, or keep the new id and
704
+ `akm index --full` to re-mint, accepting the loss of learned state keyed to
705
+ the old id.
706
+
707
+ - **The scaffolded `organization.md` convention no longer contradicts `akm
708
+ mv`.** It told authoring agents "there is no command that preserves an
709
+ asset's identity or learned state" across a rename and showed a raw `mv`.
710
+ `akm mv` does exactly that — it rewrites inbound refs and re-keys the index
711
+ row, usage history, and state.db salience/outcome rows. The convention now
712
+ points at it, flagged Experimental.
713
+
714
+ - **`setup.taskSchedules` is no longer documented.** The key was removed from
715
+ the schema in 0.9.0 (nothing ever read or wrote it), but
716
+ `docs/reference/configuration.md` still described its two sub-keys.
717
+
718
+ - **A freshly scaffolded stash passes its own `akm lint`.** All 12 shipped
719
+ `facts/conventions/**` convention templates carry frontmatter but none
720
+ carried an `updated` field, so the first `akm lint` after `akm init` flagged
721
+ 12 `missing-updated` issues on files the user never wrote. The templates now
722
+ ship the field, and a regression test lints a freshly scaffolded stash and
723
+ requires nothing flagged.
724
+
725
+ - **`akm show akm//meta` is the documented spelling for the primary stash.**
726
+ `docs/reference/cli.md` and `docs/guides/concepts.md` showed
727
+ `akm show local//meta`, which errors with `ASSET_NOT_FOUND` — `local//` is no
728
+ longer a scoping prefix, so it reads as a bundle named `local`.
729
+
730
+ - **`akm sync` emits `shape: "sync"`.** The envelope kept the `"save"` shape
731
+ from the command's pre-rename name even after the persisted `eventType` was
732
+ renamed. Unlike the event log, the shape is per-invocation and never
733
+ persisted, so it needs no read-side synonym.
734
+
735
+ - **`akm add <pkg> --provider npm` adds an npm source instead of a broken
736
+ filesystem bundle.** `--provider` was only read inside the remote-URL branch,
737
+ so any non-URL target fell through to the filesystem path with the flag
738
+ ignored, producing a bundle pointed at `<cwd>/<pkg>`. A URL target with
739
+ `--provider npm` is now rejected at add time rather than storing the URL as a
740
+ package spec and failing much later at first sync.
741
+
742
+ - **`akm add --provider` no longer prints `Installed undefined`.** Two
743
+ incompatible result shapes reached one text formatter; each is now rendered
744
+ honestly, including whether a follow-up `akm update` or `akm index` is needed.
745
+
746
+ - **`akm update --all` accounts for every configured source.** It previously
747
+ considered only registry-managed installs and reported `nothing to update`
748
+ for a stash full of plain sources — nothing was updated because nothing was
749
+ looked at. Plain git and npm sources are now synced (npm is promoted to a
750
+ lock-backed install on first sync) and website/filesystem sources are
751
+ reported through a new `skipped` field with the reason. A successful update of
752
+ a plain source no longer renders as `nothing to update` either.
753
+
754
+ - **`akm search` with no query browses**, as `--help` has always documented,
755
+ instead of exiting 2.
756
+
757
+ - **`akm curate --type <t>` curates within the type instead of bypassing
758
+ curation.** The filter skipped ranking, intent nudges, the score floor, and
759
+ family collapse entirely — and could return a hit of the *wrong* type while
760
+ dropping a higher-scoring correct one.
761
+
762
+ - **`akm curate` respects `--limit` for registry hits**, which were capped at a
763
+ hard-coded 2 regardless.
764
+
765
+ - **`akm search --no-project-context` works.** citty strips a leading `--no-`
766
+ before consulting declared args, so a flag *declared* as `no-project-context`
767
+ could never be set — the ranking boost was identical with and without it. The
768
+ flag users type is unchanged.
769
+
770
+ - **`akm env run`, `akm secret run`, `akm migrate`, `akm agent`, `akm proposal new`,
771
+ `akm task run`, and `akm improve` no longer skip cleanup on exit.** They
772
+ called `process.exit()` directly — in two cases even on success — bypassing
773
+ teardown of spawned subprocesses. Exit codes, including forwarded non-zero
774
+ child codes, are unchanged.
775
+
776
+ - **The `blocked` semantic-search warning names the cause.** It emitted one
777
+ fixed string for every failure and discarded the status ledger's reason, so
778
+ "no embedding provider configured" and "the configured endpoint is failing"
779
+ read identically.
780
+
781
+ - **Shell completion for `--source` no longer suggests `stash|registry|both`
782
+ on commands where that enum doesn't apply.** `--source` means a closed
783
+ `stash|registry|both` enum on `akm search`/`akm curate`, but a free-form
784
+ stash name/path on every `akm graph` subcommand and a free-form URL/ref/
785
+ path on `akm remember`. The generated completion script keyed its value
786
+ list by flag name only, so the search/curate enum leaked onto `akm graph
787
+ --source <TAB>` and `akm remember --source <TAB>`. Value completion is now
788
+ scoped per command path; commands without a fixed value set get no
789
+ suggestion instead of the wrong one.
790
+
791
+ - **`akm setup --config <file>` / `--from <file>` no longer silently drops
792
+ six valid config keys** (`index`, `search`, `feedback`,
793
+ `archiveRetentionDays`, `workflow`, `experimental`). The allowlist was a
794
+ hand-copied set that had drifted out of sync with the config schema; a
795
+ user handing setup a config containing any of these keys got a different,
796
+ silently truncated config written back, with only a warning and exit `0`.
797
+ The allowlist is now derived from the schema's own key list so it cannot
798
+ drift again. Keys that remain genuinely retired (`profiles`, `llm`,
799
+ `agent`, `features`, `stashes`, `bindings`, `writable`) still warn-and-drop
800
+ as before.
801
+
802
+ Note: a config that previously relied on one of these six keys being
803
+ ignored (because the drop was silent) will now have it applied — re-check
804
+ `--config`/`--from` inputs if you were unknowingly depending on that gap.
805
+
806
+ - **`akm index` no longer persists adapter auto-detection to `config.json`
807
+ with zero disclosure.** Detecting and writing a bundle component's adapter
808
+ (`bundles.<id>.components.<component>.adapter`) previously happened
809
+ silently on every index run. It is now reported in the result envelope as
810
+ an additive `configUpdated.detectedAdapters` map and on stderr, and only
811
+ when a write actually happened.
812
+
813
+ - **`akm add owner/repo` now resolves as GitHub shorthand instead of failing
814
+ with "Local path not found".** Any ref containing a `/` was treated as an
815
+ explicit local path, so the local-ref resolver threw before the
816
+ GitHub-shorthand fallback ever ran, making the advertised `owner/repo` form
817
+ unreachable. A bare two-segment `owner/repo` (or `owner/repo#ref`) now
818
+ falls through to the registry resolver when no such directory exists on
819
+ disk; `./`, `../`, absolute, and three-or-more-segment paths still resolve
820
+ as explicit local paths exactly as before.
821
+
822
+ - **Internal output-shape command keys renamed `events-list`/`events-tail` →
823
+ `log-list`/`log-tail`**, matching the `akm log` command they back (the
824
+ command group used to be `akm events`, removed in 0.9.0). Internal-only:
825
+ the shape name is a registry lookup key that never reaches the wire (no
826
+ output field, no schema change), so this is not a user-visible behavior
827
+ change and carries no `schemaVersion` bump. The documented `[events-tail]`
828
+ stderr trailer text is deliberately left as-is pending a separate ruling.
829
+
830
+ ### Removed
831
+
832
+ - **BREAKING: `akm upgrade --skip-checksum` is removed.** STABILITY.md has
833
+ always said checksum verification is not optional and that the recovery hatch
834
+ is an environment variable — but the flag shipped anyway, tab-completable,
835
+ while the documented variable existed nowhere in the source. The code now
836
+ matches the spec: set `AKM_UPGRADE_SKIP_CHECKSUM=1` if you must bypass a
837
+ genuinely broken `checksums.txt`. It is deliberately undiscoverable.
838
+
839
+ - **BREAKING: `akm config enable|disable` is removed.** It was a hard-coded
840
+ toggle for one target, the skills.sh registry, and the bare `akm enable` /
841
+ `akm disable` aliases were already removed in 0.9.0. Use
842
+ `akm registry add|remove`.
843
+
844
+ - **BREAKING: `akm mv` is removed.** No alias, no stub — `akm mv …` fails with
845
+ the standard unknown-command error. It claimed to preserve identity across a
846
+ rename, but its inbound-ref rewrite matched bare conceptIds rather than the
847
+ anchored `bundle//conceptId` prose form, so it could rewrite ordinary prose
848
+ while leaving real refs dangling. Renames are delete + create per
849
+ `STABILITY.md`: move the file, `akm index`, `akm lint`. The one capability
850
+ nothing else covered — carrying an asset's earned signal across the rename —
851
+ moves to `bun scripts/rekey-asset-ref.ts <old-ref> <new-ref>` (maintainer
852
+ tooling, `--dry-run` supported, idempotent), which re-keys the index
853
+ `entries` row in place plus the `asset_salience` / `asset_outcome` /
854
+ `usage_events` rows. The `mv` event type and output shape are gone; the
855
+ script emits a `rekey` event instead. A leftover `kind:"mv"` transaction
856
+ journal from an rc build is now swept by the recovery scanner rather than
857
+ failing it — an unregistered journal kind no longer bricks index refresh or
858
+ proposal accept/reject.
859
+
860
+ - **The CHURN alert class is removed from the collapse detector.** Its input was
861
+ a hard-coded `0` from the 0.9.0 confidence-gate deletion onward, so the alert
862
+ could never fire. The other three alert classes are unaffected. The
863
+ `improve_cycle_metrics.accepted_actions` column stays and is written as `0`
864
+ because deployed 0.8 `state.db` files already contain it.
865
+
866
+ - **`IndexResponse.graphQuality` is removed** from the `akm index` envelope — it
867
+ was declared but never assigned in any code path, so it was always absent.
868
+
869
+ - **`akm secret path` and `akm secret remove` are removed.** The two resolved a
870
+ secret ref through *different* stash-selection logic — `path` through the
871
+ read-side, all-sources resolver and `remove` through the write-target
872
+ resolver — so for a ref present in more than one stash they could name
873
+ different files: you could inspect one secret and delete another. Rather than
874
+ reconcile the resolvers, both subcommands are gone; `akm secret` now exposes
875
+ only `list`, `run`, and `set`. Both spellings exit 2 with `Unknown command`.
876
+
877
+ Migration: a ref's file lives at `<stash>/secrets/<name>` (run `akm sources
878
+ list` for stash roots) — locate or delete it directly, or use `akm secret run
879
+ <ref> <VAR> -- <command>` to consume the value without it touching disk. `akm
880
+ env path` and `akm env remove` are unaffected.
881
+
882
+ - Removed the dead `"backup"` output-shape registration left over from the
883
+ removed `akm backup` command (superseded by `akm-migrate backup`). Already
884
+ unreachable; no user-visible effect.
885
+
886
+ - **`akm task list`, `akm task show`, and `akm task remove` are removed** as
887
+ redundant with the generic asset commands. List and inspect tasks with `akm
888
+ search` / `akm show <bundle//tasks/id>` (both already cross-bundle); to remove a
889
+ scheduled task, delete its file in the owning bundle and run `akm task sync`
890
+ (sync uninstalls the orphaned scheduler entry). Run `akm task doctor` for
891
+ scheduler diagnostics — bare `akm task` is a usage error, see the canonical
892
+ bare-group change above.
893
+
894
+ - **The `akm show <ref> toc|section|lines|frontmatter|full` view-mode grammar is
895
+ removed** (0.9.0 decision D2). `#fragment` is now the only section selector,
896
+ and a positional after the ref is a usage error that names it. Migration:
897
+
898
+ | Old | New |
899
+ | --- | --- |
900
+ | `akm show knowledge/guide section "Auth"` | `akm show knowledge/guide#auth` |
901
+ | `akm show knowledge/guide full` | `akm show knowledge/guide` |
902
+ | `akm show knowledge/guide toc` | `akm show knowledge/guide#<unmatched>` — the error lists the available fragment slugs |
903
+ | `akm show knowledge/guide lines 10 30` | no replacement — every response carries `path`, so slice the file yourself |
904
+ | `akm show knowledge/guide frontmatter` | no replacement — if a raw-YAML projection proves necessary it returns as a `--shape` value |
905
+
906
+ The undocumented `--akmView` / `--akmHeading` / `--akmStart` / `--akmEnd`
907
+ flags the grammar injected into argv are gone with it.
908
+
909
+ ## [0.9.0] (planned)
910
+
911
+ 0.9.0 is the format-neutral **bundle / adapter** refactor: it replaces the flat
912
+ asset-type registry with per-format adapters, adopts one canonical ref grammar,
913
+ and consolidates the durable databases and config. This section supersedes the
914
+ earlier `0.9.0-rc.1` / `0.9.0-beta.*` development entries below.
915
+
916
+ ### Breaking changes & migration
917
+
918
+ - **Installed non-akm bundles reclassify on your next `akm index`.** The
919
+ indexer now dispatches each installed bundle's *detected* adapter (Claude
920
+ tool dirs, LLM wikis, website snapshots, agent-skills packs, …) instead of
921
+ recognizing everything with the akm-stash adapter. Entries in such bundles
922
+ change type and ref spelling to the owning adapter's own scheme the first
923
+ time you reindex. No action needed — the index is a regenerable cache and
924
+ rebuilds itself — but searches/saved refs into those bundles may resolve to
925
+ the new spellings afterwards.
926
+ - **Ref grammar cutover — `type:name` → `[bundle//]conceptId`.** Every ref is
927
+ now a subdir-qualified concept id inside its bundle (`skills/code-review`,
928
+ `memories/vpn-note`, `env/prod`), optionally prefixed with a `bundle//`
929
+ installation slug and suffixed with `#fragment`. Durable state stores the
930
+ fully-qualified `bundle//conceptId`; the short bundle-omitted form is accepted
931
+ input only (resolved against `defaultBundle`, then installation-priority
932
+ order). The pre-0.9.0 `[origin//]type:name` grammar is removed — there is no
933
+ compatibility parser; the frozen migrator in `scripts/akm-migrate/migrate/`
934
+ is the only place it survives.
935
+ - **Explicit, crash-resumable cutover (`akm migrate apply`).** The
936
+ migrator re-keys all durable state to the new spelling, folds the former
937
+ `workflow.db` into `state.db` (four databases down to three: `state.db` /
938
+ `index.db` / a separate `logs.db`), and migrates config from the flat
939
+ `stashDir` / `sources` / `installed` / `wikiName` keys to `bundles` /
940
+ `defaultBundle`. A semantically verified, installation-scoped **backup manifest v4**
941
+ (covering the pre-rescue `index.db`) is taken before mutation. One phase-free
942
+ incomplete sentinel retains that backup and target; expected orphans are
943
+ quarantined, integrity failures fail closed, and the whole cutover reruns
944
+ idempotently after a crash. Normal commands refuse an
945
+ un-migrated or divergent durable schema rather than migrating as a side effect.
946
+ The retired `stashDir` / `sources` / `installed` keys are **hard-rejected** by
947
+ the 0.9.0 config schema whenever present (the error names `akm migrate apply`);
948
+ registry-installed bundles keep only their desired locator (`git`/`npm` +
949
+ `registryId`) in config, with resolved cache state living exclusively in the
950
+ lockfile.
951
+ - **`index.md` / `log.md` are reserved structural files.** Per the Open
952
+ Knowledge Format, `index.md` (directory listing) and `log.md` (update history)
953
+ are never indexed as concepts and are never valid write / `mv` targets at any
954
+ bundle depth. Existing stash files with those names are excluded from the
955
+ index (and renamed by the content migration when they hold a real concept).
956
+ - **`vault` asset type removed.** Use `env` (a whole `.env` group; key names
957
+ surfaced, values never) and `secret` (a single sensitive value), addressed as
958
+ `env/<name>` and `secrets/<name>`. `akm-migrate storage` performs the
959
+ non-destructive `vaults/` → `env/` copy for older stashes.
960
+ - **0.8-era CLI aliases removed.** The flat proposal verbs (`akm proposals`,
961
+ `akm accept`, `akm reject`, `akm diff`, `akm revert`, `akm show proposal`),
962
+ `akm save`, top-level `akm enable` / `akm disable`, `akm events`,
963
+ `--detail summary|agent`, `--for-agent`, `--note`, and `--source` (on
964
+ accept/reject/history) are gone — use the canonical spellings documented in
965
+ `STABILITY.md`.
966
+
967
+ See `docs/migration/v0.8-to-v0.9.md` and
968
+ `docs/migration/release-notes/0.9.0.md` for the full upgrade procedure.
969
+
970
+ ### Added
971
+
972
+ - **Local downstream value attribution for memory inference and graph
973
+ extraction.** Private search-hit sidecars now write versioned, source-qualified
974
+ per-entry `usage_events.metadata` for emitted MI direct/surface value and the
975
+ active graph contributor's positive applied/capped contribution. Current plain
976
+ traffic is marked as control, brief/replaced MI surfaces and graph ablations do
977
+ not claim attribution, and nested curate reads avoid duplicate show rows. The
978
+ read-only `akm-eval-attribution-rollup` separates user-only exposure,
979
+ selection/show consumption, current controls, and historical unattributed rows
980
+ without emitting bodies, query text, or provenance content. Graph contribution
981
+ is an input attribution signal, not a causal claim that rank changed. No table,
982
+ migration, dashboard, or health schema was added.
983
+ - **Explicit, crash-resumable 0.9 migration coordination.** `akm migrate
984
+ status` classifies config, `state.db`, and `workflow.db` independently;
985
+ `akm migrate apply [--config <prepared>]` creates a semantically verified,
986
+ installation-scoped config/database backup before applying pending migrations.
987
+ Apply and restore use one phase-free incomplete sentinel, bounded control-file
988
+ reads, SQLite integrity and ordered-ledger checks, active-writer barriers,
989
+ WAL/SHM-safe publication, and idempotent replay. Legacy checksum columns are
990
+ inert. Routine reads and current database opens no longer depend on a
991
+ historical cutover bundle. See `docs/migration/release-notes/0.9.0.md`.
11
992
  - **Workflow orchestration engine (experimental).** akm can now execute
12
- multi-step workflows as deterministic **YAML programs**, driven either by a
13
- native engine or by any agent session. This is a new, self-contained
14
- surface; classic linear **markdown workflows and the stable workflow CLI
15
- contract (`start`/`next`/`complete`/`status`/`list`) are unchanged**. What
16
- ships:
17
- - **Authoring.** Orchestrated workflows are YAML programs
18
- (`workflows/*.yaml`, `version: 1`) validated against a published JSON
19
- Schema (`schemas/akm-workflow.json`) by `akm workflow validate`; scaffold
20
- one with `akm workflow template --yaml` or `akm workflow create
21
- <name>.yaml`. A closed `${{ }}` expression language (exactly
22
- `params.<name>`, `steps.<id>.output.<path>`, `item`, `item_index`, parsed
23
- once into an AST) wires steps together. `validate` also surfaces non-fatal
24
- **warnings** (a step with no typed `output:` schema; a `${{ params.<name> }}`
25
- reference to a param the declared `params:` block omits) that never change
26
- the frozen plan or its hash. Creating a workflow whose canonical name
27
- collides with an existing asset of a **different** extension (`foo.yaml`
28
- while `foo.md` exists, or vice-versa) is refused, since the two would
29
- silently shadow each other.
30
- - **Compilation + frozen plans.** `akm workflow start` compiles the program
993
+ multi-step workflows through a native engine or any agent session. Workflow
994
+ assets use the unified markdown format described above; the stable manual
995
+ CLI contract (`start`/`next`/`complete`/`status`/`list`) and the experimental
996
+ engine consume the same asset. What ships:
997
+ - **Authoring.** A workflow is a markdown asset whose frontmatter graph is
998
+ validated against `schemas/akm-workflow.json` and whose `## <step-id>` body
999
+ sections carry instructions and gate rubrics. `akm workflow create`
1000
+ scaffolds that format; `akm lint --type workflows` parses and compiles it.
1001
+ Bare references (`params.<name>` and `steps.<id>.output.<path>`) wire
1002
+ `map.over`, `route.input`, and `inputs`; prose is never interpolated.
1003
+ - **Compilation + frozen plans.** `akm workflow start` compiles the workflow
31
1004
  into a backend-agnostic Workflow Plan Graph IR (`src/workflows/ir/`) and
32
1005
  freezes it on the run row (`plan_json` + `plan_hash`); a run executes the
33
1006
  plan compiled at start, and edits to the source file require a new run.
34
- - **Per-step orchestration.** A step can declare a runner, model, timeout,
1007
+ - **Per-step orchestration.** A step can declare an engine, model, timeout,
35
1008
  fan-out (`map`/`over` with a `concurrency` cap and a `collect` | `vote`
36
1009
  reducer), a typed `output` JSON Schema (validated via a `runStructured`
37
1010
  retry-with-feedback loop), `env` bindings (resolved through the existing
38
1011
  `akm env run` machinery — secret tokens, dangerous-key policy, keys-only
39
- audit events), classify-and-dispatch `route` steps, and `depends_on`
40
- ordering.
1012
+ audit events), and classify-and-dispatch `route` steps.
41
1013
  - **Determinism + replay.** Journaled unit identity is content-derived
42
1014
  (`<step>:<sha256(item)[:12]>`, `:solo` for a single unit), so cached
43
1015
  results survive item-list reordering; a completed unit whose recorded
@@ -46,9 +1018,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
46
1018
  `workflow_run_units` table behind a serialized writer queue.
47
1019
  - **Execution (`akm workflow run`).** A semaphore-bounded scheduler fans a
48
1020
  step's units out (concurrency defaults to 1 per the local-model
49
- LLM-defaults rule, capped by the engine-wide `workflow.maxConcurrency`
50
- config knob unset = `min(16, max(1, cores 2))`, explicit values
51
- clamped to `[1, 64]`), enforces per-unit
1021
+ LLM-defaults rule and is the minimum of the map request, frozen workflow
1022
+ limit, selected frozen LLM engine limit, and current host safety limit),
1023
+ enforces per-unit
52
1024
  timeouts (default 10 m) and run **budget ceilings** (`budget.max_tokens` /
53
1025
  `budget.max_units`, seeded from the journal so they span resumes), and
54
1026
  advances the run **strictly through `completeWorkflowStep`** so completion
@@ -59,9 +1031,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
59
1031
  criteria-bearing gate judges that **artifact** (canonical JSON, clipped)
60
1032
  rather than machine prose, and each engine-driven evaluation is journaled
61
1033
  as a gate unit row. `gate.max_loops` bounds an evaluator-optimizer retry
62
- loop (feedback threaded into re-dispatched unit prompts); `gate.required`
63
- (or the run-wide `--require-gates`) makes a gate with no available judge
64
- **block** for a human instead of failing open.
1034
+ loop (feedback threaded into re-dispatched unit prompts). Gates are
1035
+ optional validation: omitted/empty rubrics and unavailable or malformed
1036
+ judges skip validation.
65
1037
  - **Failure policy.** Per-unit `on_error: fail | continue` (fail-fast
66
1038
  default) plus bounded `retry: { max, on: [<failure_reason>…] }` keyed on
67
1039
  the persisted failure taxonomy.
@@ -105,21 +1077,279 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
105
1077
  result extractor; agent-identity detection and the session-log provider
106
1078
  list are derived from the registry, and harness-native session ids are
107
1079
  journaled opportunistically for future session reuse.
108
- - **Storage.** Additive `workflow.db` migrations 004–009 (unit journal,
1080
+ - **Storage.** Additive `workflow.db` migrations 004–010 (unit journal,
109
1081
  harness session ids, frozen plans + run leases, check-in heartbeats,
110
1082
  attempt counter, unit claims); migrations 001–003 are untouched and linear
111
1083
  workflows behave exactly as before.
112
1084
 
113
1085
  See "Orchestrated steps" and "Driving a run from any agent" in
114
1086
  `docs/features/workflows.md`, the redesign addendum in
115
- `docs/technical/akm-workflows-orchestration-plan.md`, and `STABILITY.md`
1087
+ `docs/archive/akm-workflows-orchestration-plan.md`, and `STABILITY.md`
116
1088
  (Experimental).
117
1089
  - **`fable` built-in model alias** — resolves to `claude-fable-5`
118
1090
  (`opencode/claude-fable-5` on opencode); recommended resolution target for
119
1091
  the `deep` workflow model tier.
1092
+ - **`akm lint` now checks the frontmatter xref channels for broken refs.**
1093
+ The existing `missing-ref` check additionally scans the `xrefs:`,
1094
+ `supersededBy:`, and `contradictedBy:` frontmatter keys of non-wiki markdown
1095
+ assets (memories, knowledge, lessons, facts, agents, commands, skills,
1096
+ workflows) — the channels the stash back-linking conventions route
1097
+ provenance and correction links through, and previously the only ref channel
1098
+ with zero checking. Dangling refs are flagged with a detail naming the key
1099
+ (`missing ref: <ref> (frontmatter <key>; resolved to <relPath>)`). The
1100
+ `refs: []` body-scan carve-out does not suppress the new pass; `lint_skip:
1101
+ [missing-ref]` suppresses both; non-ref values (URLs, `raw/<slug>`,
1102
+ `<placeholder>` templates, shell vars) are ignored; refs resolving in a
1103
+ configured extra stash root stay clean. **Note for `--fail-on-flagged` CI
1104
+ users:** stashes with already-dangling xrefs (e.g. from past renames) will
1105
+ gain new `missing-ref` findings on upgrade — fix the refs or add
1106
+ `lint_skip: [missing-ref]` per file. `sources:`, `source_refs:`, and
1107
+ `evidenceSources:` are deliberately not checked (wiki `sources:` is covered
1108
+ by `akm wiki lint`; the latter two legitimately point at merged-away
1109
+ assets).
1110
+ - **`--xref <ref>` on `akm remember` and `akm import` — write-time
1111
+ cross-references with validation.** The stash back-linking conventions route
1112
+ provenance and associative links through `xrefs:` frontmatter, but neither
1113
+ CLI write flow could express them (remember always generated its own
1114
+ frontmatter block; import wrote content verbatim). The new repeatable flag
1115
+ records refs in the written asset's `xrefs:` frontmatter list, which the
1116
+ indexer folds into search hints — the new asset becomes findable from
1117
+ searches for its source. `remember` merges the refs into its generated
1118
+ frontmatter (composes with `--tag`/scope flags; does not trigger the
1119
+ tags-required check); `import` dedupe-appends into the document's existing
1120
+ frontmatter, or adds a block when the document has none — never a nested
1121
+ second block. A document whose existing frontmatter is not a parseable YAML
1122
+ mapping aborts the import (exit 2, nothing written) rather than being
1123
+ rewritten lossily; importing it without `--xref` still preserves it
1124
+ verbatim. Every ref is validated before anything is written, against the
1125
+ write target plus all configured sources (read-only cross-stash sources
1126
+ count): an unresolvable ref fails with the standard usage envelope (exit 2)
1127
+ and leaves the stash untouched. The conventions' ~5-xref cap stays soft —
1128
+ exceeding it warns on stderr but still writes. Additionally, a type-root
1129
+ write (no `--path`, flat name) into a stash carrying convention facts now
1130
+ returns an additive `hint` output key pointing at the stash's placement
1131
+ conventions (`facts/conventions/organization` when that fact exists), so CLI
1132
+ writers see the conventions that LLM flows already receive by injection.
1133
+ - **`--supersedes <ref>` on `akm remember` and `akm import` — atomic
1134
+ correction + demotion of the superseded asset.** The stash conventions'
1135
+ corrections pattern needs TWO writes (the new correction asset with an xref
1136
+ to what it corrects, plus a metadata edit demoting the old asset), which
1137
+ previously meant hand-editing the old file's frontmatter and remembering to
1138
+ reindex it. The new repeatable flag does both: the correction is written
1139
+ with the old ref folded into its `xrefs:` (correction provenance), and the
1140
+ old asset gains `beliefState: superseded` +
1141
+ `supersededBy: [<new ref>]` via the shared `writeSupersededEdge` primitive
1142
+ (sibling of `writeContradictEdge`) — a metadata-only frontmatter edit that
1143
+ preserves every other key and the body byte-for-byte, sorted-set-appended
1144
+ and idempotent across re-runs. The mutated old file is reindexed by the
1145
+ write path, so `--belief current` hides it and ranking demotes it
1146
+ immediately. An unresolvable ref is input validation: exit 2 with the
1147
+ standard `{ok:false,error,code}` envelope and NOTHING written or demoted
1148
+ (no partial correction); a ref resolving to the asset being written itself
1149
+ (self-supersede via `--force` overwrite) is rejected the same way instead
1150
+ of letting a correction demote itself. An old asset that resolves only
1151
+ outside the write target and the working stash (in a read-only source, or
1152
+ in a writable source that is not this write's target) is not mutated: the
1153
+ correction still writes, stderr warns, and the JSON output reports the
1154
+ additive `superseded: [{ref, applied: false, reason}]` key (`applied: true`
1155
+ on success) — the reason names the `--target` remedy when one exists. An
1156
+ old asset whose existing frontmatter is not parseable YAML is likewise
1157
+ skipped (`applied: false`) rather than rewritten through the lossy lenient
1158
+ parser. On a git write target the demotion is ordered before the
1159
+ batch-at-boundary commit, so the correction and the demoted old asset land
1160
+ in one commit.
1161
+ - **Ref-prefix search queries — `akm search "<subdir>/<prefix>/"` now enumerates
1162
+ that subtree.** A query shaped like a ref prefix (trailing slash required:
1163
+ `memories/projectA/`; a bare `memories/` lists the whole type) translates to a
1164
+ typed index enumeration narrowed to entry names under the prefix, instead of
1165
+ degenerating into the AND-token FTS query its sanitized form used to produce
1166
+ (`"memory projectA"` — noise, since `entry_type` is not an FTS column). The
1167
+ listing is recursive and `/`-boundary exact (`projectA/` cannot leak a
1168
+ sibling `projectAlpha/…` scope), matches names case-insensitively (the CLI
1169
+ lowercases queries; on-disk scope directories may carry mixed case), and
1170
+ composes with `--limit`, `--belief`, `--filter`, and named `--source`
1171
+ narrowing exactly like the existing empty-query enumeration — hits carry the
1172
+ fixed browse score `1` in deterministic listing order, not a relevance
1173
+ ranking. The parsed type is explicit intent: a bare `sessions/` enumerates
1174
+ sessions just like `--type session` (the default session exclusion is an
1175
+ untyped-path policy), while an explicit `--type` flag always wins over the
1176
+ type parsed from the query (the branch fires only on untyped searches). A
1177
+ full ref without the trailing slash (`memories/projectA/auth-tip`) stays an
1178
+ ordinary keyword search — resolving a single ref is `akm show`'s job.
1179
+ **Stable-surface note:** `akm search` is Stable; this changes results for a
1180
+ query shape that previously returned noise or nothing. A user literally
1181
+ keyword-searching for the string `memories/x/` loses the old fuzzy token
1182
+ behavior — accepted as negligible.
1183
+ - **The `category:` frontmatter key is now captured into the index** as
1184
+ `entry.category` (entry_json only — no schema migration). The key already
1185
+ drives convention-fact prompt injection (`resolveStashStandards`) and the
1186
+ fact linter, but the indexer never captured it, so no category-keyed search
1187
+ or ranking policy was implementable. Captured for all markdown asset types
1188
+ alongside `beliefState` (trimmed; blank/non-string values ignored; no
1189
+ default invented), captured directly onto the index entry. Search results
1190
+ and ranking are unchanged — this is capture
1191
+ only (a unit test pins that `category` never enters the FTS search
1192
+ fields). **Requires a reindex to take effect** for existing entries. The
1193
+ companion rank-time demotion of `category: convention` facts on untyped
1194
+ queries was NOT shipped: the prescribed measurement (full skeleton
1195
+ convention facts plus a real `knowledge/auth` asset, untyped `auth` query,
1196
+ semantic off) shows no crowding — FTS is exact-first, so prefix expansion
1197
+ onto the facts' tokens only happens when nothing matches the query exactly,
1198
+ and a real domain asset always outranks the facts. That invariant is pinned
1199
+ by `tests/search-convention-fact-demotion.test.ts`, which becomes the
1200
+ regression guard if a demotion contributor is ever revisited.
1201
+ - **Config-gated indexing of the self-situating body opening —
1202
+ `index.indexBodyOpening` (default `false`).** Body prose is not indexed
1203
+ (the FTS `content` column carries only TOC headings and parameters), which
1204
+ is why the stash conventions route orientation into
1205
+ `description:`/`when_to_use:`. With the new flag enabled, the metadata pass
1206
+ captures the first prose paragraph of each markdown asset body — skipping
1207
+ headings (ATX and setext), fenced code blocks, thematic breaks, and a
1208
+ leading nested frontmatter block (only when its content is actually
1209
+ frontmatter-shaped: prose wrapped in decorative `---` lines is captured,
1210
+ not discarded); capped at 280 chars with word-boundary truncation and a
1211
+ trailing ellipsis — into `entry.bodyOpening`, which folds into the
1212
+ lowest-weight `content` FTS column (bm25 weight 1.0, so a name match always
1213
+ outranks a body-opening-only match) and into the search/embedding text.
1214
+ Secret and env files are never read for it, and session-kind memories
1215
+ (`akm_memory_kind` in outer or nested inner frontmatter) are excluded —
1216
+ their bodies are raw transcripts. Both indexing walks and write-path
1217
+ indexing honor the flag (the metadata pass reads the user config directly).
1218
+ With the flag absent or `false`, entries and search fields stay
1219
+ byte-identical to before. **Costs of toggling (either direction):** indexed
1220
+ text changes, so collapse-detector canary recall baselines shift — re-mint
1221
+ via `akm improve canary --refresh` — and embeddings are NOT regenerated for
1222
+ entries that already have one, while incremental runs re-extract only
1223
+ changed files. Run `akm index --full` after toggling: it re-extracts every
1224
+ entry and wipes embeddings so they rebuild from the new text; until then
1225
+ `akm index` warns that the flag differs from the state the index was built
1226
+ with. The conventions' `description:`/`when_to_use:` orientation routing
1227
+ remains primary — this flag makes body openings additionally pay retrieval
1228
+ rent, it does not replace structured metadata. See `docs/configuration.md`.
1229
+ - **`akm mv <ref> <new-name>` — rename with inbound-xref rewrite and
1230
+ utility-history preservation (Experimental).** The stash conventions'
1231
+ forced-rename procedure ("grep and fix inbound xrefs in the same pass") was
1232
+ agent-executable except for the part only the CLI can do: a rename used to
1233
+ mint a new index row, orphaning the `utility_scores` /
1234
+ `utility_scores_scoped` / embeddings / salience rows keyed by entry id —
1235
+ the "rename resets learned ranking" cost the conventions warn about. The
1236
+ new verb does the whole pass: it moves the file (a memory's `.derived.md`
1237
+ twin moves together, keeping the `entry_key + ".derived"` belief-inheritance
1238
+ coupling), rewrites inbound refs across the writable stash's markdown files
1239
+ — body prose, frontmatter ref-list keys (`xrefs:`/`refs:`/`supersededBy:`/
1240
+ …), and fenced code blocks — with complete-ref boundary matching (a longer
1241
+ ref sharing the old ref as a prefix is untouched), and re-keys the index
1242
+ row **in place** so the row id and every id-keyed ranking table survive;
1243
+ the moved row and rewritten citers are FTS-refreshed so search reflects the
1244
+ new name immediately. Scope v1: flat-markdown asset types (`memory`,
1245
+ `knowledge`, `command`, `agent`, `workflow`, `lesson`, `session`, `fact`)
1246
+ in the primary writable stash only, and the source ref must be the
1247
+ canonical spelling — a ref that resolves only through one of lint's
1248
+ fallback resolutions (knowledge-subdir alias, direct-path) is rejected
1249
+ naming the canonical ref, since a fallback-keyed move would strand the
1250
+ index row and dangle canonical citers. Wiki refs, cross-type targets,
1251
+ existing targets, unresolvable refs, type-root escapes, `.derived` twin
1252
+ refs as the source (rename the base — the twin follows), and target names
1253
+ ending in `.derived` (reserved twin suffix) are rejected with the
1254
+ standard envelope (exit 2, nothing moved). Read-only sources are scanned
1255
+ but never written — their citing files are reported in `readOnlyCiters` as
1256
+ manual follow-ups. Output:
1257
+ `{ok, from, to, rewrote: [{file, count}], readOnlyCiters, utilityPreserved}`;
1258
+ a successful move appends an exactly-once `mv` event. A durable mutation
1259
+ journal stages citer rewrites and the asset publication, preserves
1260
+ source-qualified utility/salience history, and resumes index/state
1261
+ finalization after interruption. Divergent citers and late-created targets
1262
+ fail closed instead of being overwritten. Added to the v1 §9.4 command
1263
+ surface as an Experimental-tier additive entry (see `STABILITY.md`).
1264
+
1265
+ ### Changed
1266
+
1267
+ - **Improve-stage extraction and proactive maintenance now ship opt-in.** The
1268
+ built-in `default` and `frequent` strategies resolve extract off, while
1269
+ `default` and `reflect-distill` resolve `proactiveMaintenance` off. The
1270
+ dedicated `proactive-maintenance` strategy remains enabled. Built-ins such as
1271
+ `thorough` that omit these fields inherit the new `default` off values; user
1272
+ overrides are merged last, so explicit `enabled: true` values still win.
1273
+ Standalone extraction remains independent of the improve-stage toggle but
1274
+ still requires `--type <harness>` or `--auto`. The bundled, unselected
1275
+ `core/extract` task now uses `akm extract --auto`; existing scheduled tasks
1276
+ with invalid bare `akm extract` commands must be updated explicitly.
1277
+ - **Indexing dispatches each bundle's detected adapter.** The indexer's per-
1278
+ directory scan now resolves the component's adapter (`adapterForId`) and runs
1279
+ THAT adapter's `recognize`, instead of always using the `akm` adapter. A
1280
+ component whose adapter id is unknown is skipped with a warning. Adapter-owned
1281
+ filtering moves the AKM-stash sensitive/infra exclusions (env/secret
1282
+ `.sensitive`-marker skips, the legacy `vaults/` skip, wiki infra files) out of
1283
+ the core scan and into the `akm` adapter's own recognition, so each adapter
1284
+ owns its bundle's filtering. **Reindex note:** any non-`akm` bundle that was
1285
+ previously probed as one adapter id but still recognized by `akm` will
1286
+ re-index under its own adapter on the next `akm index` — the index is a
1287
+ regenerable cache, so no migration is required.
1288
+ - **Improve target identity is now end-to-end and source-qualified.** Explicit
1289
+ targets govern reads, generated proposals, triage promotion, consolidation,
1290
+ retrieval signals, cooldowns, and replay state. Duplicate bare refs in other
1291
+ sources no longer affect the selected corpus. Generated lessons and
1292
+ provenance follow stash placement conventions and canonical `xrefs`.
1293
+ - **Writable Git boundaries commit only operation-owned paths.** Improve,
1294
+ proposal, supersedes, and direct write flows preserve unrelated staged or
1295
+ dirty work, including files beside generated assets in `content/` layouts.
1296
+
1297
+ - **Directory (scope/domain) tokens now always merge into `tags` at index
1298
+ time**, even when an asset sets explicit `tags:` frontmatter. Previously
1299
+ explicit tags suppressed all path-derived tags, so a nested asset like
1300
+ `memories/projectA/auth-tip` with `tags: [auth]` silently lost the exact
1301
+ tag-match ranking boost for its scope token unless the author restated it.
1302
+ The merged tokens come from the canonical ref subpath
1303
+ (`extractDirTagsFromName`), which also fixes the flat-walk indexing path
1304
+ losing directory segments in the empty-tags fallback. Filename tokens are
1305
+ still auto-derived only when `tags` is empty (they already live in the FTS
1306
+ name column and aliases), and the empty-tags fallback itself is unchanged.
1307
+ **Operator notes:** the change takes effect on the next reindex and alters
1308
+ indexed tag text for nested assets with explicit tags, so collapse-detector
1309
+ canary recall baselines may shift — re-mint them with `akm improve canary
1310
+ --refresh`. Embeddings are not regenerated when indexed text changes; the
1311
+ drift here is small (the merged tokens already appear in the name field),
1312
+ but a purge/re-embed picks up the new text exactly.
1313
+ - **Demoting belief states now cap an entry's final search score**
1314
+ (superseded ≤ 0.25, contradicted ≤ 0.2, archived ≤ 0.15, deprecated ≤
1315
+ 0.28). The existing additive belief penalties are applied inside the
1316
+ multiplicative boost sum on a min-max-normalized FTS base (rank-1 vs rank-2
1317
+ base can differ by up to 0.7), so a superseded incumbent that was the best
1318
+ keyword match stayed clamp-pinned at 1.0 above its own correction — the
1319
+ demotion was invisible exactly when the corrections pattern needs it. The
1320
+ ceiling is applied once at the end of the single scoring pipeline (sort
1321
+ order and displayed scores stay consistent); demoted entries remain listed
1322
+ under the default `--belief all`, keep their relative ordering, and the
1323
+ `--belief` filter axis is unchanged. Semantic-only hits are judged against
1324
+ the `search.minScore` floor by their pre-ceiling score, so a ceiling below
1325
+ the floor (archived 0.15 < default 0.2) ranks the hit last instead of
1326
+ silently dropping it. Ordering changes only for stashes containing
1327
+ belief-flagged assets.
1328
+ - **`mutateFrontmatter` (belief-edge writers: supersede/contradict edges,
1329
+ belief refresh) now preserves the body bytes verbatim** when the file
1330
+ already has a frontmatter block, instead of re-normalizing the
1331
+ fence-to-body separator through `assembleAsset`. A metadata edit is no
1332
+ longer a (whitespace-level) content edit; files gaining their first
1333
+ frontmatter block still use the canonical shape.
120
1334
 
121
1335
  ### Fixed
122
1336
 
1337
+ - **Improve RC stabilization.** Restored one ownership-safe whole-run lock from
1338
+ triage through final sync; `--skip-if-locked` is a true no-op; the run deadline
1339
+ now starts before indexing and reaches index waits, generation, reindexing, and
1340
+ quality judges; reflect judges the sanitized final candidate with bounded
1341
+ changed-region context; write-target selectors no longer replace durable source
1342
+ identity; and vLLM thinking controls cannot be overridden through `extraParams`.
1343
+ - **Proposal promotion, reversion, and rejection are durable and recoverable.**
1344
+ Acceptance and reversion persist target ownership and content fingerprints,
1345
+ publish atomically across filesystem layouts, index immediately, commit exact
1346
+ Git paths, and emit idempotent lifecycle events. Crash recovery and legacy
1347
+ accepted proposals fail closed on ambiguous targets instead of clobbering
1348
+ another source.
1349
+ - **Engine/setup/health behavior now matches the effective improve plan.**
1350
+ Built-in strategies compose over one baseline, setup preserves independent
1351
+ general and LLM defaults, native OpenCode SDK execution does not require an
1352
+ unused fallback, and health checks each enabled process and credential.
123
1353
  - **Check-in directives now survive plain-text output and `workflow
124
1354
  status`** (check-in review C2/M1): `formatWorkflowNextPlain` and
125
1355
  `formatWorkflowStatusPlain` render the `CONTINUE` directive, and every
@@ -129,7 +1359,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
129
1359
  keys (`name`, `updated` were missing); removed the documented-but-nonexistent
130
1360
  `akm workflow step` alias from `docs/features/workflows.md`.
131
1361
 
132
- ## [0.9.0] 2026-06-30
1362
+ ## [0.9.0-rc.1] - 2026-06-30
133
1363
 
134
1364
  ### Fixed
135
1365
 
@@ -268,7 +1498,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
268
1498
  convention, or `.meta/index.md` files. Seeding stays absent-only and never
269
1499
  overwrites a user-edited file. (#646)
270
1500
 
271
- ## [0.9.0-beta.36] 2026-06-22
1501
+ ## [0.9.0-beta.36] - 2026-06-22
272
1502
 
273
1503
  ### Added
274
1504
 
@@ -303,7 +1533,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
303
1533
  - Corrected a prompt/validator drift where the distill system prompt asked for an
304
1534
  80–200 char description while the gate enforced 20–400. (#645)
305
1535
 
306
- ## [0.9.0-beta.35] 2026-06-21
1536
+ ## [0.9.0-beta.35] - 2026-06-21
307
1537
 
308
1538
  ### Fixed
309
1539
 
@@ -331,7 +1561,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
331
1561
  LLM call per processed session (the session summary); set it to `false` to halve
332
1562
  per-session extract cost. Unchanged/skipped sessions still cost zero.
333
1563
 
334
- ## [0.9.0-beta.34] 2026-06-21
1564
+ ## [0.9.0-beta.34] - 2026-06-21
335
1565
 
336
1566
  ### Fixed
337
1567
 
@@ -346,7 +1576,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
346
1576
  and falls back to the JSON layout. Verified end-to-end through the plugin's
347
1577
  `session.idle` hook.
348
1578
 
349
- ## [0.9.0-beta.33] 2026-06-21
1579
+ ## [0.9.0-beta.33] - 2026-06-21
350
1580
 
351
1581
  ### Fixed
352
1582
 
@@ -362,7 +1592,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
362
1592
  already-extracted session with zero LLM calls) and only `--force` re-extracts. This
363
1593
  makes a session-end hook firing `extract --session-id <id>` precise AND idempotent.
364
1594
 
365
- ## [0.9.0-beta.32] 2026-06-21
1595
+ ## [0.9.0-beta.32] - 2026-06-21
366
1596
 
367
1597
  ### Added
368
1598
 
@@ -388,7 +1618,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
388
1618
  with freshly-read timestamp maps INSIDE the lock (`filterProactiveDue`), dropping
389
1619
  refs a concurrent run already reflected.
390
1620
 
391
- ## [0.9.0-beta.31] 2026-06-20
1621
+ ## [0.9.0-beta.31] - 2026-06-20
392
1622
 
393
1623
  ### Changed
394
1624
 
@@ -401,7 +1631,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
401
1631
  On the live stash this turns the recombine cluster set from generic 66–171-member
402
1632
  buckets into tight topical clusters (`auth`, `architecture`, `patterns`, …).
403
1633
 
404
- ## [0.9.0-beta.30] 2026-06-20
1634
+ ## [0.9.0-beta.30] - 2026-06-20
405
1635
 
406
1636
  ### Changed / Fixed
407
1637
 
@@ -420,7 +1650,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
420
1650
  membership-overlap (≥ 0.7) and reuses its stable ref, so the streak accumulates
421
1651
  through membership drift. First/non-overlapping induction is unchanged.
422
1652
 
423
- ## [0.9.0-beta.29] 2026-06-20
1653
+ ## [0.9.0-beta.29] - 2026-06-20
424
1654
 
425
1655
  ### Reverted
426
1656
 
@@ -428,7 +1658,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
428
1658
  `akm fact` CLI shipped in beta.28 was reverted pending rework. Phase 1 (#629, the
429
1659
  `fact` asset type itself) remains in place.
430
1660
 
431
- ## [0.9.0-beta.27] 2026-06-20
1661
+ ## [0.9.0-beta.27] - 2026-06-20
432
1662
 
433
1663
  All new behavior is **opt-in / default-preserving** — default runs are byte-identical.
434
1664
 
@@ -474,7 +1704,7 @@ All new behavior is **opt-in / default-preserving** — default runs are byte-id
474
1704
  hang/timeout** (the busy-spin can rarely fire even at `--parallel=1`) and never
475
1705
  on a real test failure, so genuine red tests still fail fast and are never masked.
476
1706
 
477
- ## [0.9.0-beta.26] 2026-06-20
1707
+ ## [0.9.0-beta.26] - 2026-06-20
478
1708
 
479
1709
  ### Added
480
1710
 
@@ -491,7 +1721,7 @@ All new behavior is **opt-in / default-preserving** — default runs are byte-id
491
1721
  Azure Container Apps). New docs section "Hosting AKM databases on a network share
492
1722
  (NFS/SMB)" in `docs/configuration.md`.
493
1723
 
494
- ## [0.9.0-beta.25] 2026-06-19
1724
+ ## [0.9.0-beta.25] - 2026-06-19
495
1725
 
496
1726
  Completes the recombine / extract-efficiency / graph thread. All new improve
497
1727
  passes are **opt-in (default off)**, so default behavior is unchanged.
@@ -529,20 +1759,20 @@ passes are **opt-in (default off)**, so default behavior is unchanged.
529
1759
  sandbox dirs left by force-killed workers — eliminating the tmpfs accumulation
530
1760
  that caused intermittent `EEXIST: epoll_ctl` test flakes.
531
1761
 
532
- ## [0.9.0-beta.20] 2026-06-18
1762
+ ## [0.9.0-beta.20] - 2026-06-18
533
1763
 
534
1764
  ### Fixed
535
1765
 
536
1766
  - **`akm update --all` no longer fails for writable `github:` entries stored as `source:"git"`**. `updateRegistryEntry` was using `synced.source` (re-derived from the ref scheme as `"github"`) instead of the existing `entry.source`, causing the config validator to reject `writable:true` on every update cycle.
537
1767
 
538
- ## [0.9.0-beta.19] 2026-06-17
1768
+ ## [0.9.0-beta.19] - 2026-06-17
539
1769
 
540
1770
  ### Fixed
541
1771
 
542
1772
  - **`akm feedback` now completes in ~0.3s** (was 3+ minutes). Root cause: the command was calling `ensureIndex` with `mode: "blocking"` inside `withIndexWriterLease`, triggering a full reindex on every feedback call. Fix: removed the `ensureIndex` call entirely (feedback only needs the index to exist, not be current — a stale index is fine for ref lookup); removed the application-level writer lock (SQLite WAL + `busy_timeout=30s` handles concurrent access with `akm improve`); added a fast DB-exists guard with a clear error for first-time users.
543
1773
  - **`akm health --format html` now completes in ~11s** (was ~18s). Root cause: `akmHealth()` was called twice — once for the main result and once to get `deltas`. Fix: merged into a single call passing both `groupBy: "run"` and `windowCompare` together.
544
1774
 
545
- ## [0.9.0-beta.18] 2026-06-17
1775
+ ## [0.9.0-beta.18] - 2026-06-17
546
1776
 
547
1777
  ### Changed
548
1778
 
@@ -994,14 +2224,16 @@ proposal and log storage, `--format html` output, and per-stage LLM telemetry.
994
2224
 
995
2225
  ### Added
996
2226
 
997
- - **Cross-runtime: akm now runs on Node.js (≥ 20) in addition to Bun** (#560,
2227
+ - **Cross-runtime: akm now runs on Node.js >= 22 in addition to Bun** (#560,
998
2228
  #465). A two-file runtime boundary (`src/storage/database.ts` owns SQLite via
999
2229
  `bun:sqlite` on Bun / `better-sqlite3` on Node; `src/runtime.ts` owns every
1000
2230
  `Bun.*` API) contains all runtime-specific code, enforced by a lint guard so it
1001
2231
  cannot leak back out. A CI `node-smoke` matrix runs the built CLI under Node
1002
- 20 and 22. **Minimum Node is 20** — the prompts dependency (`@clack/core`) uses
1003
- `node:util.styleText`, added in Node 20.12; Node 18 is EOL and unsupported.
1004
- Bun remains the primary/default runtime.
2232
+ 20 and 22. The prompts dependency (`@clack/core`) uses `node:util.styleText`,
2233
+ added in Node 20.12; Node 18 is EOL and unsupported. The npm package uses Node
2234
+ as its bootstrap and prefers a working Bun >= 1.0 for execution when both are
2235
+ available. Old, unusable, or absent Bun installations fall back to Node.js;
2236
+ standalone binaries remain runtime-free.
1005
2237
  - **`session` asset type — agent sessions are now searchable** (#561). The
1006
2238
  `extract` pass, after distilling memory proposals from a session, additionally
1007
2239
  writes the session itself as a first-class `session` asset
@@ -1610,7 +2842,7 @@ behind an interactive prompt (or `-y` / `--yes` in non-interactive use).
1610
2842
 
1611
2843
  ### Changed
1612
2844
 
1613
- - **Rebrand**: the full name "Agent Kit Manager" is now **Agent Knowledge Management** — `akm` stands for Agent Knowledge Management going forward. The binary name, npm package (`akm-cli`), and all APIs remain unchanged.
2845
+ - **Rebrand**: the full name "Agent Kit Manager" is now **Agent Knowledge Manager** — `akm` stands for Agent Knowledge Manager going forward. The binary name, npm package (`akm-cli`), and all APIs remain unchanged.
1614
2846
 
1615
2847
  - **Config layer rewrite** — single-source-of-truth Zod schema in
1616
2848
  `src/core/config-schema.ts` replaces the per-field parse switch AND
@@ -1798,7 +3030,7 @@ See `docs/migration/v0.7-to-v0.8.md` for the user-facing migration guide.
1798
3030
 
1799
3031
  ### Migration
1800
3032
 
1801
- - See [`docs/migration/release-notes/0.7.0.md`](docs/migration/release-notes/0.7.0.md) for the operator summary and [`docs/migration/v1.md`](docs/migration/v1.md) for the canonical per-surface delta from any 0.6.x baseline.
3033
+ - See [`docs/migration/release-notes/0.7.0.md`](docs/migration/release-notes/0.7.0.md) for the operator summary and the [archived pre-1.0 plan](docs/archive/pre-1.0-migration.md) for the historical per-surface delta from any 0.6.x baseline.
1802
3034
 
1803
3035
  ## [0.6.0] - 2026-04-23
1804
3036
 
@@ -1817,7 +3049,7 @@ See `docs/migration/v0.7-to-v0.8.md` for the user-facing migration guide.
1817
3049
 
1818
3050
  ### Changed (breaking)
1819
3051
 
1820
- - **v1 architecture refactor.** The internal architecture was rebuilt around a single minimal `SourceProvider` interface (`{ name, kind, init, path, sync? }`), a unified FTS5 index that owns search and show, and a single `writeAssetToSource` helper that owns all writes. The CLI command surface and all user-visible config keys are unchanged. See `docs/migration/v1.md` for the full guide.
3052
+ - **v1 architecture refactor.** The internal architecture was rebuilt around a single minimal `SourceProvider` interface (`{ name, kind, init, path, sync? }`), a unified FTS5 index that owns search and show, and a single `writeAssetToSource` helper that owns all writes. The CLI command surface and all user-visible config keys are unchanged. See `docs/archive/pre-1.0-migration.md` for the historical guide.
1821
3053
  - **Config key `stashes[]` renamed to `sources[]`.** Configs with the legacy key load with one deprecation warning and are auto-migrated in memory; the new key is persisted on the next `akm config` write. New configs should use `sources[]`. Configs that contain both keys are rejected with `ConfigError`.
1822
3054
  - **Error hints surface without `--verbose`.** Error classes own their `hint()` text; the regex-on-message hint chain in `cli.ts` is removed. Hints print to stderr inline alongside the error message.
1823
3055
  - **Registry providers loop through a uniform interface.** Context Hub is no longer a special-cased provider type. Add it as a regular git source (`akm add github:andrewyng/context-hub`) or include it as a kit in your registry index. Legacy `type: "context-hub"` entries normalize to `type: "git"` at load time.