akm-cli 0.9.0-beta.9 → 0.9.0-rc.1

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 (381) hide show
  1. package/CHANGELOG.md +715 -0
  2. package/README.md +12 -4
  3. package/dist/akm +38 -0
  4. package/dist/akm-migrate-storage +38 -0
  5. package/dist/assets/help/help-improve.md +9 -6
  6. package/dist/assets/hints/cli-hints-full.md +6 -5
  7. package/dist/assets/profiles/default.json +9 -4
  8. package/dist/assets/profiles/frequent.json +1 -1
  9. package/dist/assets/profiles/memory-focus.json +1 -1
  10. package/dist/assets/profiles/proactive-maintenance.json +25 -0
  11. package/dist/assets/profiles/quick.json +1 -1
  12. package/dist/assets/profiles/recombine-only.json +21 -0
  13. package/dist/assets/profiles/reflect-distill.json +30 -0
  14. package/dist/assets/profiles/synthesize.json +15 -0
  15. package/dist/assets/profiles/thorough.json +1 -1
  16. package/dist/assets/prompts/consolidate-system.md +23 -0
  17. package/dist/assets/prompts/contradiction-judge.md +33 -0
  18. package/dist/assets/prompts/distill-knowledge-system.md +22 -0
  19. package/dist/assets/prompts/distill-lesson-system.md +36 -0
  20. package/dist/assets/prompts/extract-session.md +11 -3
  21. package/dist/assets/prompts/graph-extract-system.md +1 -0
  22. package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
  23. package/dist/assets/prompts/memory-infer-system.md +1 -0
  24. package/dist/assets/prompts/memory-infer-user.md +5 -0
  25. package/dist/assets/prompts/metadata-enhance-system.md +1 -0
  26. package/dist/assets/prompts/procedural-system.md +44 -0
  27. package/dist/assets/prompts/recombine-system.md +40 -0
  28. package/dist/assets/prompts/staleness-detect-system.md +6 -0
  29. package/dist/assets/prompts/validate-summary-judge.md +1 -0
  30. package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
  39. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
  40. package/dist/assets/templates/html/health.html +281 -111
  41. package/dist/assets/wiki/ingest-workflow-template.md +45 -16
  42. package/dist/assets/wiki/schema-template.md +4 -4
  43. package/dist/cli/clack.js +56 -0
  44. package/dist/cli/config-migrate.js +7 -1
  45. package/dist/cli/confirm.js +1 -1
  46. package/dist/cli/parse-args.js +46 -1
  47. package/dist/cli/shared.js +28 -0
  48. package/dist/cli.js +25 -21
  49. package/dist/commands/agent/agent-dispatch.js +3 -2
  50. package/dist/commands/agent/agent-support.js +0 -7
  51. package/dist/commands/agent/contribute-cli.js +26 -7
  52. package/dist/commands/config-cli.js +26 -13
  53. package/dist/commands/env/child-env.js +47 -0
  54. package/dist/commands/env/env-binding.js +95 -0
  55. package/dist/commands/env/env-cli.js +228 -292
  56. package/dist/commands/env/env.js +14 -67
  57. package/dist/commands/env/secret-cli.js +140 -138
  58. package/dist/commands/feedback-cli.js +156 -155
  59. package/dist/commands/graph/graph-cli.js +5 -13
  60. package/dist/commands/graph/graph.js +3 -3
  61. package/dist/commands/health/advisories.js +151 -0
  62. package/dist/commands/health/checks.js +103 -16
  63. package/dist/commands/health/html-report.js +447 -81
  64. package/dist/commands/health/improve-metrics.js +771 -0
  65. package/dist/commands/health/llm-usage.js +65 -0
  66. package/dist/commands/health/md-report.js +103 -0
  67. package/dist/commands/health/metrics.js +278 -0
  68. package/dist/commands/health/stash-exposure.js +46 -0
  69. package/dist/commands/health/surfaces.js +216 -0
  70. package/dist/commands/health/task-runs.js +135 -0
  71. package/dist/commands/health/types.js +26 -0
  72. package/dist/commands/health/windows.js +195 -0
  73. package/dist/commands/health.js +91 -1091
  74. package/dist/commands/improve/anti-collapse.js +170 -0
  75. package/dist/commands/improve/calibration.js +161 -0
  76. package/dist/commands/improve/collapse-detector.js +421 -0
  77. package/dist/commands/improve/consolidate/chunking.js +141 -0
  78. package/dist/commands/improve/consolidate/eligibility.js +64 -0
  79. package/dist/commands/improve/consolidate/merge.js +145 -0
  80. package/dist/commands/improve/consolidate/sanitize.js +231 -0
  81. package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
  82. package/dist/commands/improve/consolidate.js +1295 -1277
  83. package/dist/commands/improve/dedup.js +482 -0
  84. package/dist/commands/improve/distill/content-repair.js +202 -0
  85. package/dist/commands/improve/distill/promote-memory.js +229 -0
  86. package/dist/commands/improve/distill/quality-gate.js +236 -0
  87. package/dist/commands/improve/distill-guards.js +127 -0
  88. package/dist/commands/improve/distill-promotion-policy.js +826 -167
  89. package/dist/commands/improve/distill.js +228 -605
  90. package/dist/commands/improve/eligibility.js +434 -0
  91. package/dist/commands/improve/encoding-salience.js +205 -0
  92. package/dist/commands/improve/extract-cli.js +179 -59
  93. package/dist/commands/improve/extract-prompt.js +54 -3
  94. package/dist/commands/improve/extract-watch.js +140 -0
  95. package/dist/commands/improve/extract.js +409 -43
  96. package/dist/commands/improve/feedback-valence.js +54 -0
  97. package/dist/commands/improve/hot-probation.js +45 -0
  98. package/dist/commands/improve/improve-auto-accept.js +157 -10
  99. package/dist/commands/improve/improve-cli.js +115 -73
  100. package/dist/commands/improve/improve-profiles.js +28 -8
  101. package/dist/commands/improve/improve-result-file.js +15 -25
  102. package/dist/commands/improve/improve-session.js +58 -0
  103. package/dist/commands/improve/improve.js +485 -2764
  104. package/dist/commands/improve/locks.js +154 -0
  105. package/dist/commands/improve/loop-stages.js +1100 -0
  106. package/dist/commands/improve/memory/memory-belief.js +14 -15
  107. package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
  108. package/dist/commands/improve/memory/memory-improve.js +27 -27
  109. package/dist/commands/improve/outcome-loop.js +270 -0
  110. package/dist/commands/improve/preparation.js +2002 -0
  111. package/dist/commands/improve/proactive-maintenance.js +37 -35
  112. package/dist/commands/improve/procedural.js +398 -0
  113. package/dist/commands/improve/recombine.js +818 -0
  114. package/dist/commands/improve/reflect-noise.js +0 -0
  115. package/dist/commands/improve/reflect.js +206 -45
  116. package/dist/commands/improve/salience.js +455 -0
  117. package/dist/commands/improve/schema-similarity-gate.js +168 -0
  118. package/dist/commands/improve/shared.js +51 -0
  119. package/dist/commands/improve/triage.js +93 -0
  120. package/dist/commands/lint/agent-linter.js +19 -24
  121. package/dist/commands/lint/base-linter.js +173 -60
  122. package/dist/commands/lint/command-linter.js +19 -24
  123. package/dist/commands/lint/env-key-rules.js +38 -1
  124. package/dist/commands/lint/fact-linter.js +39 -0
  125. package/dist/commands/lint/index.js +31 -13
  126. package/dist/commands/lint/memory-linter.js +1 -1
  127. package/dist/commands/lint/registry.js +7 -2
  128. package/dist/commands/lint/task-linter.js +3 -3
  129. package/dist/commands/lint/workflow-linter.js +26 -1
  130. package/dist/commands/observability-cli.js +4 -4
  131. package/dist/commands/proposal/drain-policies.js +13 -4
  132. package/dist/commands/proposal/drain.js +45 -51
  133. package/dist/commands/proposal/legacy-import.js +115 -0
  134. package/dist/commands/proposal/proposal-cli.js +24 -34
  135. package/dist/commands/proposal/proposal.js +2 -1
  136. package/dist/commands/proposal/propose.js +8 -3
  137. package/dist/commands/proposal/repository.js +829 -0
  138. package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
  139. package/dist/commands/proposal/validators/proposals.js +93 -895
  140. package/dist/commands/read/curate.js +410 -111
  141. package/dist/commands/read/knowledge.js +10 -3
  142. package/dist/commands/read/remember-cli.js +133 -138
  143. package/dist/commands/read/search-cli.js +15 -8
  144. package/dist/commands/read/search.js +22 -11
  145. package/dist/commands/read/show.js +106 -14
  146. package/dist/commands/registry-cli.js +76 -87
  147. package/dist/commands/remember.js +11 -12
  148. package/dist/commands/sources/add-cli.js +91 -95
  149. package/dist/commands/sources/history.js +1 -1
  150. package/dist/commands/sources/init.js +66 -18
  151. package/dist/commands/sources/installed-stashes.js +11 -3
  152. package/dist/commands/sources/migration-help.js +7 -4
  153. package/dist/commands/sources/schema-repair.js +44 -46
  154. package/dist/commands/sources/self-update.js +2 -2
  155. package/dist/commands/sources/source-add.js +7 -3
  156. package/dist/commands/sources/sources-cli.js +3 -3
  157. package/dist/commands/sources/stash-cli.js +19 -39
  158. package/dist/commands/sources/stash-skeleton.js +57 -8
  159. package/dist/commands/tasks/default-tasks.js +15 -2
  160. package/dist/commands/tasks/tasks-cli.js +20 -29
  161. package/dist/commands/tasks/tasks.js +39 -11
  162. package/dist/commands/wiki-cli.js +23 -38
  163. package/dist/commands/workflow-cli.js +291 -13
  164. package/dist/core/asset/asset-registry.js +3 -1
  165. package/dist/core/asset/asset-spec.js +79 -5
  166. package/dist/core/asset/frontmatter.js +188 -167
  167. package/dist/core/asset/markdown.js +8 -0
  168. package/dist/core/authoring-rules.js +92 -0
  169. package/dist/core/common.js +4 -23
  170. package/dist/core/concurrent.js +10 -1
  171. package/dist/core/config/config-io.js +10 -1
  172. package/dist/core/config/config-migration.js +18 -40
  173. package/dist/core/config/config-schema.js +403 -62
  174. package/dist/core/config/config-types.js +3 -3
  175. package/dist/core/config/config.js +67 -22
  176. package/dist/core/deep-merge.js +38 -0
  177. package/dist/core/errors.js +1 -0
  178. package/dist/core/eval/rank-metrics.js +113 -0
  179. package/dist/core/events.js +4 -7
  180. package/dist/core/improve-types.js +47 -8
  181. package/dist/core/json-schema.js +142 -0
  182. package/dist/core/logs-db.js +14 -75
  183. package/dist/core/parse.js +36 -16
  184. package/dist/core/paths.js +18 -18
  185. package/dist/core/standards/resolve-standards-context.js +87 -0
  186. package/dist/core/standards/resolve-stash-standards.js +99 -0
  187. package/dist/core/standards/resolve-type-conventions.js +66 -0
  188. package/dist/core/state/migrations.js +770 -0
  189. package/dist/core/state-db.js +132 -1126
  190. package/dist/core/structured.js +69 -0
  191. package/dist/core/time.js +53 -0
  192. package/dist/core/warn.js +21 -0
  193. package/dist/core/write-source.js +37 -0
  194. package/dist/indexer/db/db.js +261 -770
  195. package/dist/indexer/db/entry-mapper.js +41 -0
  196. package/dist/indexer/db/graph-db.js +129 -86
  197. package/dist/indexer/db/llm-cache.js +2 -2
  198. package/dist/indexer/db/schema.js +516 -0
  199. package/dist/indexer/ensure-index.js +36 -92
  200. package/dist/indexer/feedback/utility-policy.js +75 -0
  201. package/dist/indexer/graph/graph-boost.js +51 -41
  202. package/dist/indexer/graph/graph-extraction.js +207 -4
  203. package/dist/indexer/index-writer-lock.js +18 -11
  204. package/dist/indexer/index-written-assets.js +105 -0
  205. package/dist/indexer/indexer.js +182 -204
  206. package/dist/indexer/passes/dir-staleness.js +114 -0
  207. package/dist/indexer/passes/memory-inference.js +13 -5
  208. package/dist/indexer/passes/metadata.js +20 -0
  209. package/dist/indexer/read-preflight.js +23 -0
  210. package/dist/indexer/search/db-search.js +89 -13
  211. package/dist/indexer/search/fts-query.js +51 -0
  212. package/dist/indexer/search/ranking-contributors.js +95 -9
  213. package/dist/indexer/search/ranking.js +79 -3
  214. package/dist/indexer/search/search-fields.js +6 -0
  215. package/dist/indexer/search/search-source.js +32 -21
  216. package/dist/indexer/search/semantic-status.js +4 -0
  217. package/dist/indexer/walk/matchers.js +48 -0
  218. package/dist/indexer/walk/walker.js +21 -13
  219. package/dist/integrations/agent/builders.js +41 -13
  220. package/dist/integrations/agent/config.js +20 -59
  221. package/dist/integrations/agent/detect.js +9 -0
  222. package/dist/integrations/agent/index.js +3 -19
  223. package/dist/integrations/agent/model-aliases.js +16 -2
  224. package/dist/integrations/agent/profiles.js +79 -6
  225. package/dist/integrations/agent/prompts.js +75 -9
  226. package/dist/integrations/agent/runner-dispatch.js +83 -0
  227. package/dist/integrations/agent/runner.js +13 -9
  228. package/dist/integrations/agent/spawn.js +206 -81
  229. package/dist/integrations/harnesses/aider/agent-builder.js +113 -0
  230. package/dist/integrations/harnesses/aider/index.js +58 -0
  231. package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
  232. package/dist/integrations/harnesses/amazonq/agent-builder.js +153 -0
  233. package/dist/integrations/harnesses/amazonq/index.js +59 -0
  234. package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
  235. package/dist/integrations/harnesses/claude/agent-builder.js +46 -7
  236. package/dist/integrations/harnesses/claude/index.js +27 -23
  237. package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
  238. package/dist/integrations/harnesses/claude/session-log.js +10 -0
  239. package/dist/integrations/harnesses/codex/agent-builder.js +137 -0
  240. package/dist/integrations/harnesses/codex/index.js +63 -0
  241. package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
  242. package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
  243. package/dist/integrations/harnesses/copilot/index.js +60 -0
  244. package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
  245. package/dist/integrations/harnesses/gemini/agent-builder.js +121 -0
  246. package/dist/integrations/harnesses/gemini/index.js +60 -0
  247. package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
  248. package/dist/integrations/harnesses/index.js +28 -7
  249. package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
  250. package/dist/integrations/harnesses/opencode/index.js +17 -16
  251. package/dist/integrations/harnesses/opencode/session-log.js +173 -3
  252. package/dist/integrations/harnesses/opencode-sdk/harness.js +65 -0
  253. package/dist/integrations/harnesses/opencode-sdk/index.js +10 -34
  254. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +642 -71
  255. package/dist/integrations/harnesses/openhands/agent-builder.js +126 -0
  256. package/dist/integrations/harnesses/openhands/index.js +58 -0
  257. package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
  258. package/dist/integrations/harnesses/pi/agent-builder.js +104 -0
  259. package/dist/integrations/harnesses/pi/index.js +58 -0
  260. package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
  261. package/dist/integrations/harnesses/types.js +8 -0
  262. package/dist/integrations/session-logs/index.js +40 -11
  263. package/dist/llm/call-ai.js +2 -2
  264. package/dist/llm/client.js +34 -11
  265. package/dist/llm/embedder.js +67 -4
  266. package/dist/llm/embedders/cache.js +3 -1
  267. package/dist/llm/embedders/deterministic.js +66 -0
  268. package/dist/llm/embedders/local.js +73 -3
  269. package/dist/llm/feature-gate.js +16 -15
  270. package/dist/llm/graph-extract.js +67 -44
  271. package/dist/llm/memory-infer-impl.js +138 -0
  272. package/dist/llm/memory-infer.js +1 -127
  273. package/dist/llm/metadata-enhance.js +44 -31
  274. package/dist/llm/structured-call.js +49 -0
  275. package/dist/migrate-storage-node.mjs +8 -0
  276. package/dist/output/context.js +5 -5
  277. package/dist/output/renderers.js +87 -15
  278. package/dist/output/shapes/curate.js +14 -2
  279. package/dist/output/shapes/helpers.js +0 -3
  280. package/dist/output/shapes/passthrough.js +6 -1
  281. package/dist/output/text/helpers.js +241 -2
  282. package/dist/output/text/workflow.js +4 -1
  283. package/dist/registry/providers/skills-sh.js +21 -147
  284. package/dist/registry/providers/static-index.js +15 -157
  285. package/dist/registry/resolve.js +27 -9
  286. package/dist/runtime.js +25 -1
  287. package/dist/schemas/akm-config.json +14225 -0
  288. package/dist/schemas/akm-workflow.json +328 -0
  289. package/dist/scripts/migrate-storage.js +2743 -8390
  290. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +1652 -607
  291. package/dist/setup/detect.js +9 -0
  292. package/dist/setup/legacy-config.js +106 -0
  293. package/dist/setup/prompt.js +57 -0
  294. package/dist/setup/providers.js +14 -0
  295. package/dist/setup/registry-stash-loader.js +12 -0
  296. package/dist/setup/semantic-assets.js +124 -0
  297. package/dist/setup/setup.js +52 -1614
  298. package/dist/setup/steps/connection.js +734 -0
  299. package/dist/setup/steps/output.js +31 -0
  300. package/dist/setup/steps/platforms.js +124 -0
  301. package/dist/setup/steps/semantic.js +27 -0
  302. package/dist/setup/steps/sources.js +222 -0
  303. package/dist/setup/steps/stashdir.js +42 -0
  304. package/dist/setup/steps/tasks.js +152 -0
  305. package/dist/sources/include.js +6 -2
  306. package/dist/sources/providers/filesystem.js +0 -1
  307. package/dist/sources/providers/git-install.js +210 -0
  308. package/dist/sources/providers/git-provider.js +234 -0
  309. package/dist/sources/providers/git-stash.js +248 -0
  310. package/dist/sources/providers/git.js +10 -661
  311. package/dist/sources/providers/npm.js +2 -6
  312. package/dist/sources/providers/provider-utils.js +13 -7
  313. package/dist/sources/providers/sync-from-ref.js +9 -1
  314. package/dist/sources/providers/website.js +9 -5
  315. package/dist/sources/website-ingest.js +187 -29
  316. package/dist/sources/wiki-fetchers/registry.js +53 -0
  317. package/dist/sources/wiki-fetchers/youtube.js +239 -0
  318. package/dist/storage/database.js +45 -10
  319. package/dist/storage/managed-db.js +82 -0
  320. package/dist/storage/repositories/canaries-repository.js +107 -0
  321. package/dist/storage/repositories/consolidation-repository.js +38 -0
  322. package/dist/storage/repositories/embeddings-repository.js +72 -0
  323. package/dist/storage/repositories/events-repository.js +187 -0
  324. package/dist/storage/repositories/extract-sessions-repository.js +96 -0
  325. package/dist/storage/repositories/improve-runs-repository.js +146 -0
  326. package/dist/storage/repositories/index-db.js +14 -8
  327. package/dist/storage/repositories/proposals-repository.js +220 -0
  328. package/dist/storage/repositories/recombine-repository.js +213 -0
  329. package/dist/storage/repositories/registry-cache.js +93 -0
  330. package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
  331. package/dist/storage/repositories/task-history-repository.js +93 -0
  332. package/dist/storage/repositories/workflow-runs-repository.js +189 -1
  333. package/dist/storage/sqlite-pragmas.js +146 -0
  334. package/dist/tasks/backends/cron.js +1 -1
  335. package/dist/tasks/backends/index.js +9 -0
  336. package/dist/tasks/backends/launchd.js +1 -1
  337. package/dist/tasks/backends/schtasks.js +1 -1
  338. package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
  339. package/dist/tasks/runner.js +15 -13
  340. package/dist/text-import-hook.mjs +1 -1
  341. package/dist/wiki/wiki.js +52 -11
  342. package/dist/workflows/authoring/authoring.js +123 -10
  343. package/dist/workflows/authoring/workflow-program-template.yaml +31 -0
  344. package/dist/workflows/cli.js +5 -0
  345. package/dist/workflows/db.js +138 -4
  346. package/dist/workflows/exec/brief.js +484 -0
  347. package/dist/workflows/exec/native-executor.js +975 -0
  348. package/dist/workflows/exec/param-secrets.js +115 -0
  349. package/dist/workflows/exec/report.js +1295 -0
  350. package/dist/workflows/exec/run-workflow.js +596 -0
  351. package/dist/workflows/exec/scheduler.js +100 -0
  352. package/dist/workflows/exec/step-work.js +1156 -0
  353. package/dist/workflows/exec/unit-writer.js +23 -0
  354. package/dist/workflows/exec/watch.js +116 -0
  355. package/dist/workflows/exec/worktree.js +171 -0
  356. package/dist/workflows/ir/compile.js +388 -0
  357. package/dist/workflows/ir/params.js +54 -0
  358. package/dist/workflows/ir/plan-hash.js +33 -0
  359. package/dist/workflows/ir/schema.js +4 -0
  360. package/dist/workflows/parser.js +3 -1
  361. package/dist/workflows/program/expressions.js +369 -0
  362. package/dist/workflows/program/parser.js +760 -0
  363. package/dist/workflows/program/project.js +105 -0
  364. package/dist/workflows/program/schema.js +54 -0
  365. package/dist/workflows/renderer.js +82 -5
  366. package/dist/workflows/runtime/agent-identity.js +59 -14
  367. package/dist/workflows/runtime/runs.js +248 -153
  368. package/dist/workflows/runtime/unit-checkin.js +45 -0
  369. package/dist/workflows/runtime/workflow-asset-loader.js +188 -0
  370. package/dist/workflows/validate-summary.js +26 -10
  371. package/dist/workflows/validator.js +1 -1
  372. package/docs/README.md +69 -18
  373. package/docs/data-and-telemetry.md +7 -5
  374. package/docs/migration/release-notes/0.7.0.md +1 -1
  375. package/docs/migration/release-notes/0.9.0-beta.60.md +19 -0
  376. package/docs/migration/release-notes/0.9.0.md +39 -0
  377. package/package.json +10 -10
  378. package/dist/assets/tasks/core/update-stashes.yml +0 -4
  379. package/dist/commands/db-cli.js +0 -23
  380. package/dist/indexer/db/db-backup.js +0 -376
  381. package/dist/indexer/passes/staleness-detect.js +0 -488
package/CHANGELOG.md CHANGED
@@ -6,6 +6,721 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### Added
10
+
11
+ - **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
31
+ into a backend-agnostic Workflow Plan Graph IR (`src/workflows/ir/`) and
32
+ freezes it on the run row (`plan_json` + `plan_hash`); a run executes the
33
+ 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,
35
+ fan-out (`map`/`over` with a `concurrency` cap and a `collect` | `vote`
36
+ reducer), a typed `output` JSON Schema (validated via a `runStructured`
37
+ retry-with-feedback loop), `env` bindings (resolved through the existing
38
+ `akm env run` machinery — secret tokens, dangerous-key policy, keys-only
39
+ audit events), classify-and-dispatch `route` steps, and `depends_on`
40
+ ordering.
41
+ - **Determinism + replay.** Journaled unit identity is content-derived
42
+ (`<step>:<sha256(item)[:12]>`, `:solo` for a single unit), so cached
43
+ results survive item-list reordering; a completed unit whose recorded
44
+ inputs differ on replan is a hard **replay-divergence** failure naming the
45
+ unit, never a silent re-dispatch. Every unit is recorded in the new
46
+ `workflow_run_units` table behind a serialized writer queue.
47
+ - **Execution (`akm workflow run`).** A semaphore-bounded scheduler fans a
48
+ 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
52
+ timeouts (default 10 m) and run **budget ceilings** (`budget.max_tokens` /
53
+ `budget.max_units`, seeded from the journal so they span resumes), and
54
+ advances the run **strictly through `completeWorkflowStep`** so completion
55
+ gates are never bypassed. Every dispatched unit gets a standard akm
56
+ preamble (run/unit ids, knowledge + env/secret + reporting contract).
57
+ - **Typed artifacts + honest gates.** A step's promoted artifact is
58
+ validated against its declared `output` schema before completion; a
59
+ criteria-bearing gate judges that **artifact** (canonical JSON, clipped)
60
+ rather than machine prose, and each engine-driven evaluation is journaled
61
+ 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.
65
+ - **Failure policy.** Per-unit `on_error: fail | continue` (fail-fast
66
+ default) plus bounded `retry: { max, on: [<failure_reason>…] }` keyed on
67
+ the persisted failure taxonomy.
68
+ - **Isolation + leases.** `isolation: worktree` runs each file-mutating unit
69
+ in a fresh detached git worktree (journaled path; clean trees
70
+ auto-removed, dirty ones retained). A run **lease** (`engine_lease_*`)
71
+ ensures a run is driven by exactly one engine or one external driver at a
72
+ time; manual `complete` is refused while a live engine lease is held.
73
+ - **Harness-neutral driver protocol.** An orchestrated run can be driven by
74
+ ANY agent session (Claude Code, opencode, Codex, a human at a shell), not
75
+ only the native engine. **`akm workflow brief <run>`** is read-only (takes
76
+ no lease, mutates nothing) and emits the active step's expected work-list —
77
+ per-unit content-derived id, resolved instructions + input hash
78
+ (byte-identical to the engine's dispatch), output schema, env binding
79
+ NAMES only, and the exact `report` command lines. **`akm workflow report
80
+ <run> --unit <id> --status completed|failed|running`** is the one mutating
81
+ verb, ingesting a unit's result through the SAME shared step semantics the
82
+ engine uses (idempotent same-hash re-report, replay-divergence on a
83
+ differing hash, budget enforcement, schema validation, and the
84
+ artifact-judged gate/`max_loops` completion path). `--status running`
85
+ claims/heartbeats a unit for stale-driver detection without advancing the
86
+ spine; `--rerun` records a fresh attempt for a failed unit (carrying its
87
+ prior token total forward). Every report command carries `--expect-step`
88
+ (refused if the spine has moved since the brief), and `report --settle`
89
+ (no `--unit`) advances a step that dispatches no reportable units — a
90
+ params-only route, an empty fan-out, or an all-unresolvable work-list — so
91
+ a driver is never wedged. The engine and the brief/report surfaces are
92
+ proven to produce **identical unit graphs**
93
+ (`tests/workflows/conformance/driver-parity.test.ts`).
94
+ - **Observability.** `akm workflow watch <run>` tails the run's `workflow_*`
95
+ / `workflow_unit_*` events as NDJSON (`--stream` foreground-polls to a
96
+ terminal status, no daemon); `akm workflow status --units` lists per-unit
97
+ diagnostics (failure reason + result/error text) without feeding them into
98
+ the deterministic artifact graph; unit lifecycle emits
99
+ `workflow_unit_started` / `workflow_unit_finished` events carrying
100
+ ids/status/enums only. `akm show workflow:<name>` summarizes each step's
101
+ orchestration.
102
+ - **Harness adapters.** Seven local coding-agent CLIs are first-class
103
+ dispatch targets — Codex, Copilot CLI, Pi, Gemini, Aider, Amazon Q, and
104
+ OpenHands — each registered in `HARNESS_REGISTRY` with a command builder +
105
+ result extractor; agent-identity detection and the session-log provider
106
+ list are derived from the registry, and harness-native session ids are
107
+ journaled opportunistically for future session reuse.
108
+ - **Storage.** Additive `workflow.db` migrations 004–009 (unit journal,
109
+ harness session ids, frozen plans + run leases, check-in heartbeats,
110
+ attempt counter, unit claims); migrations 001–003 are untouched and linear
111
+ workflows behave exactly as before.
112
+
113
+ See "Orchestrated steps" and "Driving a run from any agent" in
114
+ `docs/features/workflows.md`, the redesign addendum in
115
+ `docs/technical/akm-workflows-orchestration-plan.md`, and `STABILITY.md`
116
+ (Experimental).
117
+ - **`fable` built-in model alias** — resolves to `claude-fable-5`
118
+ (`opencode/claude-fable-5` on opencode); recommended resolution target for
119
+ the `deep` workflow model tier.
120
+
121
+ ### Fixed
122
+
123
+ - **Check-in directives now survive plain-text output and `workflow
124
+ status`** (check-in review C2/M1): `formatWorkflowNextPlain` and
125
+ `formatWorkflowStatusPlain` render the `CONTINUE` directive, and every
126
+ run-detail response (status/start/complete) evaluates the check-in instead
127
+ of only `workflow next`.
128
+ - Workflow frontmatter validator error message now lists the actually-allowed
129
+ keys (`name`, `updated` were missing); removed the documented-but-nonexistent
130
+ `akm workflow step` alias from `docs/features/workflows.md`.
131
+
132
+ ## [0.9.0] — 2026-06-30
133
+
134
+ ### Fixed
135
+
136
+ - **improve/recombine: cap-aware decay — the `maxClustersPerRun` cap no longer
137
+ traps recurring hypotheses below `confirmThreshold` (#658).** Recombine is a
138
+ two-pass design: a cluster must be re-induced on `confirmThreshold` (=2) runs
139
+ before its `type:hypothesis` proposal promotes to an auto-accepted
140
+ `type:lesson`. But only the top-`maxClustersPerRun` (=5) clusters are
141
+ processed per run, and `decayUnseenRecombineHypotheses` hard-reset the
142
+ confirmation streak of every hypothesis not processed that run. A cluster that
143
+ genuinely re-forms every run but is displaced out of the top-5 (slots are tied
144
+ on member-count and broken by an arbitrary alphabetical tiebreak) had its
145
+ streak zeroed — it could never win two consecutive slots, so its proposal sat
146
+ pending forever (6 such proposals were stuck in one production stash).
147
+ `decayUnseenRecombineHypotheses` is now **cap-aware**: `recombine.ts` passes
148
+ the FULL pre-cap cluster set, and a hypothesis is spared from reset when its
149
+ cluster still Jaccard-matches a present cluster (same signature, overlap ≥ 0.7
150
+ — the same rule used for re-induction). Only hypotheses with no matching
151
+ current cluster (the corpus stopped supporting them) decay. This does **not**
152
+ lower the recurrence bar: the confirmation count is still advanced only by
153
+ genuine re-induction in the processed slice (`recordRecombineInduction`);
154
+ sparing merely avoids an artificial reset, so a genuinely non-recurring
155
+ hypothesis still decays to 0 and never confirms (no new bland-hypothesis churn,
156
+ cf. #632/#633). No schema change. The cap now lives in a new `capClusters`
157
+ helper split out of `buildRelatednessClusters` so the full ranked set stays
158
+ available for the decay sweep.
159
+ - **`improve` reflect no longer emits proposals doomed to fail the
160
+ `invalid-description` gate when the source asset has no frontmatter
161
+ `description` (#636).** Reflect echoed the source frontmatter, so for assets
162
+ that carry other keys but no `description` (notably scraped docs:
163
+ `source`/`title`/`scraped`) the proposal inherited the missing/empty
164
+ description and the promote-time validator (`isValidDescription`, 20–400
165
+ chars) rejected it — observed as ~14/16 rejects in one triage pass, blocking
166
+ the whole scraped-doc/knowledge cluster from reflect improvement. The fix is
167
+ **generation-time only**: (1) `buildReflectPrompt` now injects an explicit
168
+ "synthesize a `description`" instruction whenever the source lacks a non-empty
169
+ `description` and the asset type requires one (per `authoring-rules.ts`
170
+ `DESCRIPTION_TYPES`), telling the model it MUST author a valid 20–400-char
171
+ plain-prose description from the asset's `title:`/first `# Heading`/opening
172
+ body; and (2) a deterministic reflect-side belt-and-suspenders in
173
+ `sanitizeReflectPayload` — if a source that already had frontmatter still ends
174
+ up with a missing/empty description after generation, reflect derives one
175
+ deterministically from `title:`/first heading (validated against
176
+ `isValidDescription`, never free-form invention) **before** the proposal is
177
+ created. The validator, `authoring-rules.ts` bounds, `repairProposalContent`,
178
+ and the drain are unchanged — nothing in the validator/promote path fabricates
179
+ content to pass itself.
180
+ - **The high-salience improve admission lane (#608) now requires a
181
+ content-derived encoding score, not the per-type weight stub (#655,
182
+ #608/#644 follow-up).** The lane previously admitted any zero-feedback ref
183
+ whose `asset_salience.encoding_salience >= salienceThreshold` (default 0.75).
184
+ But for assets distill has not content-scored, `encoding_salience` is just the
185
+ per-type WEIGHT STUB (skill/agent 0.9, command/workflow 0.8, lesson 0.75), so
186
+ "high-salience" degenerated into "is a skill/agent/command/lesson" — which
187
+ selected the type-stub `lore-writer` agent on every run (prod: 1 content-scored
188
+ / 37 type-stub / 1826 NULL-legacy rows). The gate now also requires
189
+ `isContentEncodingRow(row, parseAssetRef(ref).type)` (the #644 provenance
190
+ helper), so only genuinely content-scored assets qualify. This preserves
191
+ #608's intent — distilled assets, the lane's real targets, keep their real
192
+ content score and still qualify — while cutting the type-stub waste; type-stub
193
+ rows must earn retrieval/feedback signal via the other lanes. NULL-legacy rows
194
+ follow `isContentEncodingRow`'s differs-from-stub heuristic. An aggregated log
195
+ line now reports how many refs the lane admitted so lane composition is
196
+ observable. The threshold, type-weight table, 10% cap, and `isContentEncodingRow`
197
+ are unchanged.
198
+
199
+ - **Auto-sync no longer refuses to commit akm's own changes when unrelated
200
+ non-akm files are present in the stash working tree.** When a stash root is
201
+ shared with a project repo, stray files written into the stash root (e.g. a
202
+ `tasks.bak-…` backup dir or report artifacts like `data.js`,
203
+ `akm-health-report.html`, `reports/`) previously tripped the #476 safety
204
+ guard, which threw `refusing to push: … has uncommitted non-akm changes` on
205
+ **every** `akm improve` end-of-run auto-sync, `akm sync`, and `akm push`. In
206
+ one production incident this silently blocked all commits for ~1.5 days while
207
+ akm kept accepting proposals it never persisted. `saveGitStash` now **scopes
208
+ what it stages** instead of refusing: (1) an explicit modified-file list when
209
+ the caller passes `opts.paths`, else (2) the akm-managed pathspecs
210
+ (`TYPE_DIRS` values + `.akm`) that exist on disk — which by construction never
211
+ stages non-akm WIP, preserving the #476 protection without an all-or-nothing
212
+ refusal — and only as a last resort (3) `git add -A` when no managed pathspec
213
+ can be resolved. If nothing akm-managed is staged the run returns
214
+ `nothing to commit` (no empty commit, no throw). Unrelated non-akm files are
215
+ left untouched and uncommitted.
216
+
217
+ ### Changed
218
+
219
+ - **BEHAVIOR CHANGE — `akm init --dir <path>` no longer silently repoints your
220
+ default stash.** Previously, `akm init --dir X` unconditionally wrote
221
+ `stashDir: X` to `config.json` whenever `X` differed from the configured
222
+ default — so initializing a throwaway or secondary stash (e.g.
223
+ `akm init --dir /tmp/scratch`) would hijack the user's real default stash
224
+ pointer (the footgun documented in `memory:akm-init-persists-stashdir-warning`).
225
+ Now `init` persists `stashDir` to config **only** when one of the following
226
+ holds: (a) **no `--dir`** was provided (the default `~/akm` setup flow —
227
+ unchanged), (b) `--dir` was provided and **no `stashDir` exists in config yet**
228
+ (first-time bootstrap), or (c) `--dir` was provided **with the new
229
+ `--set-default` flag** (explicit opt-in). Otherwise `init` still scaffolds and
230
+ backfills the target dir exactly as before, but **leaves your default stash
231
+ pointer untouched** and prints:
232
+ `Your default stash is unchanged (<existing>). Re-run with --set-default to make <dir> the default.`
233
+ The `InitResponse` JSON gains `defaultStashUpdated: boolean` and an optional
234
+ `previousStashDir`. To make a `--dir` target your default, pass
235
+ `akm init --dir <path> --set-default`. (`akm setup` is unaffected — it remains
236
+ the explicit configuration flow and always sets the default.)
237
+
238
+ ### Added
239
+
240
+ - **Per-type SOFT authoring conventions are now user-editable stash facts.** A
241
+ third authoring-guidance layer joins the hard rules (#645) and general stash
242
+ standards (#642): a stash owner can author
243
+ `facts/conventions/assets/<type>.md` (e.g. `…/skill.md`, `…/command.md`) to
244
+ capture soft, type-specific guidance — voice, structure, length *preference*,
245
+ naming style. When an agent authors a `skill:x`, the body of
246
+ `fact:conventions/assets/skill` is injected (type-scoped — authoring
247
+ `command:y` pulls the `command` convention, never the `skill` one), labeled
248
+ as soft guidance and kept separate from the validator-enforced hard rules.
249
+ The basename must be a `getAssetTypes()`-validated asset type; facts are read
250
+ straight from disk (no index rebuild) and degrade to empty safely. When no
251
+ per-type fact exists, the built-in `TYPE_HINTS` fallback is unchanged (no
252
+ regression). These facts carry soft conventions only and can never weaken the
253
+ authoring contract the gate enforces (`authoringRulesForType` remains the sole
254
+ source of validator-rejecting rules). The general convention/meta resolver now
255
+ excludes `facts/conventions/assets/*` so per-type guidance never leaks
256
+ un-type-scoped into other authoring flows. (#646)
257
+ - **`akm init` now seeds default per-type SOFT convention templates.** Starter
258
+ `facts/conventions/assets/<type>.md` templates ship in the stash skeleton for
259
+ the authored types (`lesson, skill, command, agent, knowledge, memory,
260
+ workflow, script, fact`; `wiki`/`env`/`secret` excluded) so a stash owner has
261
+ an editable starting point. Each expands the matching built-in `TYPE_HINTS`
262
+ one-liner into soft starter guidance, carries `category: convention`
263
+ frontmatter, and states in-body that it is advice, not enforced — it carries
264
+ **no** validator-rejecting rules, so editing or deleting one cannot weaken the
265
+ gate (#645). The stash-skeleton copy is now recursive (preserving nested
266
+ subpaths), and `akm init` seeds **unconditionally** rather than only on first
267
+ create: re-running it on an existing stash backfills any missing skeleton,
268
+ convention, or `.meta/index.md` files. Seeding stays absent-only and never
269
+ overwrites a user-edited file. (#646)
270
+
271
+ ## [0.9.0-beta.36] — 2026-06-22
272
+
273
+ ### Added
274
+
275
+ - **Stash standards + wiki schemas are surfaced to authoring agents at write
276
+ time.** When an agent edits a page under `wikis/<name>/`, that wiki's
277
+ `schema.md` body is injected into the prompt; when it creates/edits a non-wiki
278
+ asset, the bodies of `category: convention`/`meta` `fact` assets are injected.
279
+ Two mutually-exclusive features selected by target type, sharing one
280
+ `standardsContext` prompt seam. Wired into reflect, propose, and every
281
+ improve authoring pass (distill, consolidate, recombine, procedural, extract,
282
+ schema-repair). (#642)
283
+ - **Unified, validator-sourced authoring-rules seam.** A new
284
+ `authoringRulesForType(type)` injects the hard authoring rules (no
285
+ pseudo-frontmatter in body, exactly two `---` fences, description/`when_to_use`
286
+ length + shape) into every authoring prompt. The numeric bounds live in one
287
+ module that the validators import, so the prompt can no longer drift from what
288
+ the gate enforces. (#645)
289
+
290
+ ### Fixed
291
+
292
+ - **High-salience reflect lane now reflects each asset at most once.** The
293
+ `#608` admission gate lacked the cooldown its sibling high-retrieval gate has,
294
+ so zero-feedback assets were re-selected on every run (auto-accept emits
295
+ `promoted`, not `feedback`), burning LLM calls and churning assets. (#643)
296
+ - **Stuck validation-failing proposals no longer dead-end.** The triage drain no
297
+ longer overwrites an `auto-rejected` gate stamp with a misleading
298
+ `auto-accepted` (the failure stays truthful and visible). A bounded,
299
+ content-preserving auto-repair (strip pseudo-frontmatter / stray `---`, repair
300
+ truncated descriptions) runs at the promote boundary and re-validates — fixable
301
+ proposals promote; genuinely unrepairable ones stay `pending` for manual
302
+ review, with nothing fabricated and validation never bypassed. (#645)
303
+ - Corrected a prompt/validator drift where the distill system prompt asked for an
304
+ 80–200 char description while the gate enforced 20–400. (#645)
305
+
306
+ ## [0.9.0-beta.35] — 2026-06-21
307
+
308
+ ### Fixed
309
+
310
+ - **Default extract discovery window is now "since the last run" (floored at 48h),
311
+ not a fixed 24h.** An intermittently-online host that was off for longer than
312
+ the old 24h window could permanently miss sessions that ended during the gap.
313
+ Discovery now looks back to the last recorded extract run for the harness, never
314
+ less than 48h. Widening is free of redundant LLM cost — the content-hash ledger
315
+ skips unchanged sessions with zero LLM calls. An explicit `--since`/`defaultSince`
316
+ still wins.
317
+ - **Per-session lock prevents concurrent double-extraction.** A session-end hook
318
+ firing `extract --session-id` while the periodic `akm improve` extract pass runs
319
+ discovery could both LLM-process the SAME session (duplicate spend + near-dup
320
+ proposals). A per-(harness, session) advisory lock (co-located with state.db,
321
+ PID + age staleness recovery) now makes the second run skip without any LLM call.
322
+ - **`minNewSessions` is read from the ACTIVE improve profile, not always `default`.**
323
+ A non-default profile (e.g. `frequent`) setting `minNewSessions` was silently
324
+ ignored because the gate (and its candidate-count discovery window) read
325
+ `profiles.improve.default`. They now read the resolved active profile, matching
326
+ how `extract.enabled` already resolves.
327
+
328
+ ### Docs
329
+
330
+ - Documented that `processes.extract.indexSessions` (default on) makes a second
331
+ LLM call per processed session (the session summary); set it to `false` to halve
332
+ per-session extract cost. Unchanged/skipped sessions still cost zero.
333
+
334
+ ## [0.9.0-beta.34] — 2026-06-21
335
+
336
+ ### Fixed
337
+
338
+ - **`akm extract --type opencode` reads opencode's SQLite session store.** opencode
339
+ migrated session storage from per-file JSON (`storage/session/<projectId>/<id>.json`
340
+ + `storage/message/<id>/*.json`) to a single Drizzle-managed database at
341
+ `<base>/opencode.db` (tables `session`/`message`/`part`; message text lives in
342
+ `part` rows with `data` JSON `type:"text"`). The legacy JSON layout went stale
343
+ ~2026-02, so extract discovered 0 sessions on current opencode and the
344
+ `session.idle` extract hook had nothing to read. `OpenCodeProvider` now prefers
345
+ `opencode.db` when present (read-only, via the cross-driver `openDatabase` seam)
346
+ and falls back to the JSON layout. Verified end-to-end through the plugin's
347
+ `session.idle` hook.
348
+
349
+ ## [0.9.0-beta.33] — 2026-06-21
350
+
351
+ ### Fixed
352
+
353
+ - **`akm extract` decoupled from the improve-stage toggle.** `processes.extract.enabled`
354
+ now gates extract only as a STAGE of `akm improve` (the active improve profile, per
355
+ #593/#594); an explicit `akm extract` command always runs. Previously dropping extract
356
+ from the daily improve profile silently disabled the standalone command (and its LLM
357
+ calls, via the shared `session_extraction` feature gate).
358
+ - **`extract --session-id` now respects the content-hash ledger; `--force` overrides.**
359
+ Explicit single-session extraction previously bypassed the #602 already-extracted skip
360
+ unconditionally — re-paying the LLM on every call and risking double-extraction against
361
+ the cron. Now a targeted `extract --session-id <id>` is idempotent (skips an unchanged,
362
+ already-extracted session with zero LLM calls) and only `--force` re-extracts. This
363
+ makes a session-end hook firing `extract --session-id <id>` precise AND idempotent.
364
+
365
+ ## [0.9.0-beta.32] — 2026-06-21
366
+
367
+ ### Added
368
+
369
+ - **Recombine acceptance path — confirmed lessons now auto-accept.** Recombine
370
+ hypotheses that reach the confirmation threshold (promoted to `type: lesson`,
371
+ #625/#633) now flow to ACCEPTED by reusing the existing drain mechanism instead
372
+ of piling up pending forever: the `personal-stash` drain policy gains a
373
+ `{ generator: "recombine", requireType: "lesson", maxDiffLines: 200 }` rule, via
374
+ a new optional `requireType` frontmatter filter on `DrainAcceptRule`. Only
375
+ confirmed `type: lesson` proposals auto-accept; unconfirmed `type: hypothesis`
376
+ proposals stay pending; the existing proposal quality gate still applies.
377
+ - **`processes.reflect.lowValueFilter` (opt-in, default OFF)** — deterministic
378
+ semantic value-floor that defers trivial reflect rewrites (#639A).
379
+ - **`processes.extract.triage.proceduralAwareFloor` (opt-in, default OFF)** —
380
+ triage floor requiring markers/edits so real lessons always pass (#641).
381
+
382
+ ### Fixed
383
+
384
+ - **Select-time proactive cooldown leak.** `selectProactiveMaintenanceRefs` plans
385
+ the due set BEFORE acquiring `reflect-distill.lock`, so overlapping/back-to-back
386
+ improve runs reused stale due-state and re-reflected the same asset repeatedly
387
+ (observed up to ~16× in a day). The orchestrator now re-applies the dueDays gate
388
+ with freshly-read timestamp maps INSIDE the lock (`filterProactiveDue`), dropping
389
+ refs a concurrent run already reflected.
390
+
391
+ ## [0.9.0-beta.31] — 2026-06-20
392
+
393
+ ### Changed
394
+
395
+ - **#632 — recombine now filters junk tags structurally.** Frontmatter tags that
396
+ are pure numbers, dates (`20260529`), short hex hashes (`002c624c`), version
397
+ strings (`0.8.0`, `v2`), single chars, or common English stopwords (`is`, `the`,
398
+ `for`, `when`, …) carry no topical signal and never form a recombine cluster.
399
+ Unlike `excludeTags` (a fixed project list), this catches the OPEN-ENDED junk —
400
+ every new date or commit hash — with no config upkeep. Exposed as `isJunkTag`.
401
+ On the live stash this turns the recombine cluster set from generic 66–171-member
402
+ buckets into tight topical clusters (`auth`, `architecture`, `patterns`, …).
403
+
404
+ ## [0.9.0-beta.30] — 2026-06-20
405
+
406
+ ### Changed / Fixed
407
+
408
+ - **#632 — recombine cluster tuning (opt-in, default-preserving).** Recombine
409
+ clustered memories by frontmatter tag and preferred the LARGEST buckets, so it
410
+ always picked the coarsest whole-stash tags (`session`/`claude`/`akm`, 63–171
411
+ members) and produced bland generalizations. Two new `processes.recombine` knobs:
412
+ `maxClusterSize` (skip clusters larger than N, so over-broad buckets no longer
413
+ reach/starve the largest-first slice) and `excludeTags` (tags that may never form
414
+ a tag cluster). Both UNSET = byte-identical to prior behavior.
415
+ - **#633 — recombine confirmation loop fixed.** The hypothesis confirmation streak
416
+ was keyed on a hash of the EXACT member set, so a growing stash drifted the key
417
+ every run → a fresh row at count 1 → `confirmThreshold` never reached → no
418
+ hypothesis ever promoted to a lesson (a dead two-pass loop). A freshly-induced
419
+ cluster now matches an existing pending row by signature + Jaccard
420
+ membership-overlap (≥ 0.7) and reuses its stable ref, so the streak accumulates
421
+ through membership drift. First/non-overlapping induction is unchanged.
422
+
423
+ ## [0.9.0-beta.29] — 2026-06-20
424
+
425
+ ### Reverted
426
+
427
+ - **#630 — `fact` asset type phase 2 reverted (#631).** The pinned-core assembly +
428
+ `akm fact` CLI shipped in beta.28 was reverted pending rework. Phase 1 (#629, the
429
+ `fact` asset type itself) remains in place.
430
+
431
+ ## [0.9.0-beta.27] — 2026-06-20
432
+
433
+ All new behavior is **opt-in / default-preserving** — default runs are byte-identical.
434
+
435
+ ### Added
436
+
437
+ - **#624 P2 — priority-ranked graph extraction.** `processes.graphExtraction.topN`:
438
+ when set, the graph-extraction pass ranks eligible files by asset utility
439
+ (`utility_scores`, read-only join) and processes only the top-N per run, so
440
+ high-value assets get graphed first instead of a ~55h full-corpus sweep. Unset
441
+ (default) = no ranking, byte-identical.
442
+ - **#624 P3 — lazy on-demand graph extraction.** New `graph_extraction_queue` table
443
+ + `enqueueGraphExtraction`/`drainExtractionQueue`/`extractGraphForSingleFile`.
444
+ `akm curate` enqueues an ungraphed hit (non-blocking); `akm show` can extract a
445
+ missing graph inline — gated on `index.graph.lazyGraphExtraction: true`
446
+ (**default off**: `show` makes no LLM call by default), model-guarded, and bounded
447
+ by a 30s timeout so it never hangs. The pass drains the queue before the ranked
448
+ sweep. This **closes #624** (all three layers shipped).
449
+ - **#616 — bounded multi-cycle phasing.** `profiles.improve.<name>.maxCycles`
450
+ (default 1): when > 1, the improve passes run in an N-cycle loop so gate-accepted
451
+ output of cycle N feeds cycle N+1 within the same run (re-running ensureIndex +
452
+ ref selection each cycle), stopping at a fixed point and respecting the run budget.
453
+ `maxCycles: 1` = byte-identical to today.
454
+
455
+ ### Fixed
456
+
457
+ - **Release CI unblocked.** `runCliCapture` (test harness) restored `process.exitCode`
458
+ to a captured `undefined`, which under `bun test` does not clear a previously-set
459
+ non-zero exit code — so the unit suite exited 1 with 0 failures at `TEST_PARALLEL=1`
460
+ (exactly how `release.yml` runs), silently blocking every npm publish since beta.11.
461
+ Fixed to restore to `0`. (This is why beta.26 was the first successful workflow publish.)
462
+
463
+ ### Changed
464
+
465
+ - **CI/release tests sharded across runner jobs (~15 min → ~2 min).** Bun 1.3.x
466
+ in-process test parallelism (`--parallel=N`, N>1) hits an intermittent
467
+ `epoll_ctl EEXIST` race / busy-spin hang on the `--isolate` workers, which had
468
+ forced fully-sequential (`TEST_PARALLEL=1`) runs. Tests now shard across separate
469
+ runner jobs (each a separate process tree, so no cross-shard fd/epoll collisions)
470
+ with `--parallel=1` within each shard; the matrix runs shards concurrently. The
471
+ release gate runs the identical set of tests. Local `bun run check` defaults to
472
+ sequential too (the only safe mode on this Bun version). Coverage unchanged.
473
+ Each shard runs through `scripts/run-test-shard.sh`, which retries **only on a
474
+ hang/timeout** (the busy-spin can rarely fire even at `--parallel=1`) and never
475
+ on a real test failure, so genuine red tests still fail fast and are never masked.
476
+
477
+ ## [0.9.0-beta.26] — 2026-06-20
478
+
479
+ ### Added
480
+
481
+ - **#628 — configurable SQLite journal mode (`AKM_SQLITE_JOURNAL_MODE`) for network
482
+ filesystems.** AKM previously opened every database with `PRAGMA journal_mode = WAL`
483
+ unconditionally, which cannot run on a network filesystem (NFS/SMB/Azure Files) —
484
+ WAL's `-shm` shared-memory wal-index can't be `mmap`'d over a network mount. You can
485
+ now set `AKM_SQLITE_JOURNAL_MODE` to `WAL` (default), `DELETE`, or `TRUNCATE`, applied
486
+ at **all five** db openers (`state.db`, `index.db` ×2 paths, `workflow.db`, `logs.db`).
487
+ At the `WAL` default AKM auto-detects a network mount for the data dir and transparently
488
+ falls back to `DELETE` (rollback journal + `synchronous = FULL`) with a one-line warning;
489
+ invalid values warn once and fall back to `WAL`. **Default behavior is byte-identical.**
490
+ This lets the AKM database subtree live on a shared volume (e.g. Azure Files under
491
+ Azure Container Apps). New docs section "Hosting AKM databases on a network share
492
+ (NFS/SMB)" in `docs/configuration.md`.
493
+
494
+ ## [0.9.0-beta.25] — 2026-06-19
495
+
496
+ Completes the recombine / extract-efficiency / graph thread. All new improve
497
+ passes are **opt-in (default off)**, so default behavior is unchanged.
498
+
499
+ ### Added
500
+
501
+ - **#606 — event-driven extract (`akm extract --watch`).** Opt-in watch mode: an
502
+ injectable, debounced watcher triggers extraction shortly after a session file
503
+ appears, with a clean `stop()` handle. The `8,28,48` cron remains the fallback;
504
+ no daemon is auto-launched.
505
+ - **#625 — recombine second pass (hypothesis → lesson).** The opt-in `recombine`
506
+ process (#609) now consumes `confirmThreshold` (default 2): a generalization
507
+ re-induced that many consecutive runs is promoted from a `type: hypothesis`
508
+ proposal to a `type: lesson` proposal through the normal queue + quality gate
509
+ (never a direct stash write). Hypotheses that stop recurring decay. Backed by a
510
+ new `recombine_hypotheses` table in `state.db`.
511
+
512
+ ### Changed
513
+
514
+ - **#624 (P1) — graph storage decoupled from `entries.id`.** `graph_files` is
515
+ re-keyed on `(stash_root, file_path, body_hash)`, so extracted graph data now
516
+ **survives a reindex** of unchanged files instead of being cascade-wiped. The
517
+ upgrade is migrated in a **targeted, graph-only path** that preserves existing
518
+ graph data and leaves the entry index, embeddings, FTS, and LLM-enrichment cache
519
+ untouched — **no full index rebuild and no re-embed** on upgrade. (P2 priority-
520
+ ranked extraction and P3 lazy/on-demand extraction remain deferred.)
521
+
522
+ ### Fixed
523
+
524
+ - Graph re-key migration no longer triggers a destructive full-index rebuild: it
525
+ is a graph-scoped table migration (no `DB_VERSION` bump), and it **copies** the
526
+ existing graph rows into the new schema rather than dropping them.
527
+ - Test-suite `/tmp` hygiene: sandbox teardown now fires on `SIGINT`/`SIGTERM`/
528
+ `SIGHUP` (not just clean exit), and a `sweep:tmp` step reclaims stale `akm-*`
529
+ sandbox dirs left by force-killed workers — eliminating the tmpfs accumulation
530
+ that caused intermittent `EEXIST: epoll_ctl` test flakes.
531
+
532
+ ## [0.9.0-beta.20] — 2026-06-18
533
+
534
+ ### Fixed
535
+
536
+ - **`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
+
538
+ ## [0.9.0-beta.19] — 2026-06-17
539
+
540
+ ### Fixed
541
+
542
+ - **`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
+ - **`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
+
545
+ ## [0.9.0-beta.18] — 2026-06-17
546
+
547
+ ### Changed
548
+
549
+ - **Health report: Recent Runs table now shows all filtered runs in descending order** (newest first) instead of capping at the last 10.
550
+ - **Health report: Removed "Command Set Used" section.**
551
+ - **Health report: All timestamps now display in the viewer's local timezone** (chart axis labels, runs table, freshness line, executive summary, footer). Server-rendered ISO strings are wrapped in `<time data-iso>` elements and converted to local time by client-side JS on page load.
552
+
553
+ ### Changed (migration required)
554
+
555
+ - **WS-2 outcome loop (#613) — default-off weight change (state.db migration 010).**
556
+ Every `akm improve` run now writes an `asset_outcome` row per processed asset
557
+ (state.db migration `010`) and computes a differential usefulness signal
558
+ (`outcome_score`) per ref. The outcome signal is persisted and visible in the
559
+ health report, but the **weight change is gated behind a config flag** (see
560
+ below). Ranking is unchanged from WS-1 by default.
561
+
562
+ **Opt-in weight change.** The WS-2 projection weights (`w_e=0.25, w_o=0.15,
563
+ w_r=0.60`) affect ranking only when you explicitly set
564
+ `improve.salience.outcomeWeightEnabled: true` in your `akm.yaml`. The default
565
+ (`false`) keeps WS-1 parity weights (`w_e=0.30, w_r=0.70`, `w_o=0`), so
566
+ existing users see no ranking change on upgrade.
567
+
568
+ **Part-V measurement gate.** Before enabling the weight change, run the Part-V
569
+ T0 baseline (`scripts/akm-eval` + `akm health`; confirm proactive accept
570
+ ≥ 0.9× reactive; reversion ≤ 0.15; retrieval-delta ≥ 0; coverage not
571
+ regressed). That gate requires a running production stash and cannot be
572
+ exercised in CI. Once confirmed, set
573
+ `improve.salience.outcomeWeightEnabled: true` to activate the three-way split.
574
+
575
+ **Outcome loop mechanics.** `outcome_score` is a differential prediction-error
576
+ signal: `(retrieval_delta − expected_delta) − PENALTY × retrieval_delta × (1 −
577
+ accepted_change_rate) + valence`, tracked via an EMA (α=0.3). New rows are
578
+ warm-started from the utility EMA score (clipped to 0.3) so the signal is
579
+ non-zero from launch. A stash-wide diversity floor (10% of the max score) prevents
580
+ rare-but-correct assets from being permanently outcompeted. An inverted-proxy
581
+ tripwire (`corr(outcome_score, accepted_change_rate) < −0.3`) emits an
582
+ `outcome_proxy_inverted` health event when the signal degrades.
583
+
584
+ `review_pressure` is computed and persisted per asset but is **not yet wired into
585
+ the admission policy** — that is deferred to a later work stream per plan §Part-VI
586
+ #613. The column is present and populated; routing it into the consolidation-
587
+ selection filter is the next step.
588
+
589
+ - **WS-1 salience vector (#618) — default-on ranking change.** The eligibility sort
590
+ for all `akm improve` runs (whole-stash, type, and ref scope) has changed from
591
+ `combinedEligibilityScore = utility·0.7 + negativeOnlyRatio·0.3` to
592
+ `rankScore = (0.3·encodingSalience + 0.7·retrievalSalience) × sizePenalty`
593
+ (feedback valence and utility EMA dropped from ordering until WS-2 re-introduces
594
+ outcome salience). Assets are now ranked by retrieval frequency × recency × type
595
+ importance rather than by feedback magnitude. Because the old
596
+ `combinedEligibilityScore` ordering was never persisted, a forgetting comparison is
597
+ not possible on the first run; instead a one-time `improve_salience_first_run` marker
598
+ event is emitted to record the transition. On every subsequent run a stash-wide
599
+ `improve_salience_rank_change` drift report (including `stashSize`) is emitted so
600
+ rank movement under the new scoring can be tracked over time.
601
+ The Part-V measurement protocol (T0 baseline via `scripts/akm-eval` + health report,
602
+ throughput/quality gate) is deferred to the WS-2 milestone, when outcome salience
603
+ re-joins the projection and re-tuning is triggered.
604
+
605
+ ## [0.9.0-beta.12] - 2026-06-15
606
+
607
+ Improve-tuning work streams (all **default-off / parity-preserving** — no behavior
608
+ change until explicitly enabled).
609
+
610
+ ### Added
611
+
612
+ - **#617 — deterministic near-duplicate memory dedup** (`processes.consolidate.dedup`,
613
+ default off). A cheap no-LLM pre-pass in front of consolidation collapses obvious
614
+ duplicates — `.derived`+origin pairs and content twins (normalized content-hash
615
+ equality, or embedding cosine ≥ `cosineThreshold`, default 0.97). Each dropped
616
+ variant is archived + backed up before deletion; hot memories are never
617
+ collapsed; distinct-but-related memories fall through to the LLM.
618
+ - **#581 — judged-state cache for consolidation** (`processes.consolidate.judgedCache`,
619
+ default off). New state.db table (`consolidation_judged`) records each memory's
620
+ content hash + outcome when the LLM judges it; subsequent runs skip
621
+ judged-unchanged memories, converting coverage from O(time-window) to
622
+ O(changed/new) so a run can sweep the full corpus. Fails open; failed chunks
623
+ and dry-runs never poison the cache. (state.db migration `007`.)
624
+ - **#612 — auto-accept gate calibration** (`improve.calibration`, auto-tune default
625
+ off). Joins predicted gate confidence to realized accept/reject outcomes into a
626
+ reliability table + calibration gap, surfaced in `akm health` (+ summary rows in
627
+ the HTML report). Opt-in bounded threshold auto-tune nudges the accept threshold
628
+ within a configured band toward a target accept rate, logged via a
629
+ `calibration_autotune` event. (Replay-prioritization from prediction error is
630
+ deferred — it depends on the #610 replay budget, a 0.10 item.)
631
+
632
+ ### Fixed
633
+
634
+ - **#614 — symmetric valence weighting** (`profiles.improve.*.symmetricValence`,
635
+ default off). The eligibility sort weighted feedback negative-only; when enabled
636
+ it uses a symmetric `|valence|` magnitude so strong positive and strong negative
637
+ feedback both drive attention (utility stays the dominant factor), routing
638
+ high-negative → fix and high-positive → reinforce lanes.
639
+
640
+ ## [0.9.0-beta.11] - 2026-06-15
641
+
642
+ ### Added
643
+
644
+ - **`extract.maxSessionsPerRun`** (default 25) — caps the NEW sessions the
645
+ extract pass LLM-processes in a single run so a backlog (e.g. after downtime)
646
+ can't push one run past its scheduled-task timeout. Overflow sessions stay
647
+ unseen and are picked up by later runs, so coverage is preserved. `0` disables.
648
+
649
+ ### Fixed
650
+
651
+ - **Auto-accept validation failures are no longer a blind leak.** When a
652
+ confidence-passing proposal fails promotion validation, the gate now captures
653
+ the reason (the `validateProposal` finding kind, e.g. `validation:description-quality`),
654
+ records it on the proposal (`akm proposal show` explains the rejection), logs
655
+ it, and exposes `failedByReason` on the gate result — so the ~5% leak is
656
+ diagnosable instead of silently warned-and-dropped.
657
+ - **Inflated skip-reason aggregates in `akm health`.** `no_new_signal` /
658
+ `profile_filtered_all_passes` are per-run snapshots of a stable set; the
659
+ window aggregator summed their per-run counts (≈2.7M / 3M). It now uses the
660
+ most recent run's count for these aggregated-snapshot reasons while still
661
+ summing genuine per-occurrence skips.
662
+
663
+ ## [0.9.0-beta.10] - 2026-06-15
664
+
665
+ ### Added
666
+
667
+ - **#603** — `akm health` pool-saturation advisory. Instead of alerting on the
668
+ raw `sessionsScanned` count (which false-alarmed on normal cadence changes),
669
+ a new `pool-saturation` advisory reports the ratio of new (unseen) sessions
670
+ to the total session pool: informational below 10% (expected steady state),
671
+ warning below 2% (possible discovery/dedup bug). Heuristic, never gates
672
+ overall status.
673
+ - **#576** — the `akm health` HTML report now renders the real per-stage LLM
674
+ token/time aggregate (a "🧠 LLM Work" KPI card + LLM token/call/wall-time
675
+ summary rows) from the captured `llm_usage` events, replacing the GPU-time
676
+ proxy.
677
+ - **Built-in `akm health --format html` report overhaul** — the report is now a
678
+ strict superset of (and supersedes) the external `akm-health-report` stash
679
+ skill. Restored the interactive filter bar (time-slice 1d–21d, task, status)
680
+ with client-side chart/table re-render and the Last-10 "Task" column;
681
+ reordered sections to a decision-first flow (verdict → action items → KPIs →
682
+ table → charts); added a synthesized one-sentence **Verdict** (status + 2–3
683
+ drivers) and a freshness line; merged the duplicate Advisories / What-to-Watch
684
+ into one prioritized, de-duplicated **Action Items** list (P1/P2/P3 +
685
+ remediation command); added a per-stage **LLM token** stacked-bar chart and
686
+ `dataZoom` sliders on dense charts; fixed the failed-run scatter x-alignment
687
+ (now shape-encoded); KPI-card colors are now health signals (not decoration);
688
+ added metric-glossary tooltips, chart `aria-label`s, contrast fixes, and
689
+ empty-state overlays. Deterministic output preserved.
690
+
691
+ ### Fixed
692
+
693
+ - **Health report accuracy** (follow-ups to the overhaul): the per-run **Task**
694
+ column/filter now show the real scheduled task (`akm-improve-frequent`, …) via
695
+ a ±5min `task_history` join instead of the run's scope (which is `all` for
696
+ every scheduled run); the time-**slice** filter options are now derived from
697
+ the report's `--since` window (e.g. All/3d/1d/12h/6h for a 7d report) and
698
+ default to "All" — replacing the hard-coded 1d–21d list that didn't match the
699
+ window; and the trend **deltas** now default their compare window to `--since`
700
+ (like-for-like, e.g. last 7d vs prior 7d) instead of a fixed 24h, which had
701
+ produced nonsensical period-over-period percentages on multi-day reports.
702
+ - **Inflated stash-snapshot metrics in `akm health`.** `memorySummary`
703
+ (derived/eligible) and `profileFilteredRefs` are whole-stash snapshots recorded
704
+ on every run, but the window aggregator was **summing** them across all runs —
705
+ e.g. "915,258 of 1,226,025 eligible" and a 2.4M filtered-ref count. They now
706
+ take the most recent run's snapshot (the current state). Per-run *work* metrics
707
+ (promoted, MI written, graph entities, …) remain genuine window sums.
708
+ - **Health report polish:** the akm version is stamped in the header (under the
709
+ AKM logo) and footer; the steady-state `no new signal since last proposal`
710
+ distill reason is excluded from the skip-reason chart (it drowned out the
711
+ actionable reasons); and the Consolidation Output chart now draws Promoted as a
712
+ line on a secondary right-hand axis (it dwarfs merged/deleted) with merged and
713
+ deleted as bars on the left axis.
714
+
715
+ - **#598** — process-level tuning fields (`consolidate.incrementalSince`,
716
+ `minPoolSize`, `neighborsPerChanged`, `extract.minContentChars`, per-process
717
+ `enabled` flags) now survive an `akm config` rewrite. They are first-class
718
+ typed `ImproveProcessConfigSchema` fields, so the load→save round trip no
719
+ longer silently drops them. Unknown process sub-keys hard-error at load
720
+ (`ConfigError`) rather than being silently discarded — the deliberate,
721
+ documented resolution. Regression-guarded by
722
+ `tests/config-process-roundtrip.test.ts`.
723
+
9
724
  ## [0.9.0-beta.9] - 2026-06-14
10
725
 
11
726
  Restore and instrument `akm improve` steady-state output. The reflect/distill