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
@@ -2,24 +2,37 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { getHarness, SESSION_LOG_HARNESSES } from "../harnesses/index.js";
5
- import { ClaudeCodeProvider } from "../harnesses/claude/session-log.js";
6
- import { OpenCodeProvider } from "../harnesses/opencode/session-log.js";
7
5
  export { extractInlineRefMentions } from "./inline-refs.js";
8
- const HARNESSES = [new ClaudeCodeProvider(), new OpenCodeProvider()];
9
- // #562: the unified HARNESS_REGISTRY is the single source of truth for which
10
- // harnesses expose session logs. Validate (behaviour-preserving) that every
11
- // session-log provider instantiated above resolves to a registry harness whose
12
- // `sessionLogs` capability is set and via the id-normalization bridge, so a
13
- // provider named "claude-code" still maps to the canonical "claude" harness.
14
- // This turns a silently-drifting third registry into a startup invariant.
6
+ // #562/P2 (plan §"Kill registry drift"): the provider array is DERIVED from
7
+ // the unified HARNESS_REGISTRY every harness with `capabilities.sessionLogs`
8
+ // must supply a `sessionLogProvider` factory on its descriptor, and this is
9
+ // the only place providers are instantiated. Adding a session-log harness is
10
+ // therefore one registry entry, never an edit here.
11
+ //
12
+ // Ordered by canonical id so the pre-derivation provider order
13
+ // ([claude-code, opencode] — visible in e.g. `extract --auto` result order)
14
+ // is preserved deterministically, independent of HARNESS_REGISTRY declaration
15
+ // order (which is pinned for JSON-schema enum stability).
16
+ const HARNESSES = [...SESSION_LOG_HARNESSES]
17
+ .sort((a, b) => a.id.localeCompare(b.id))
18
+ .map((h) => {
19
+ const provider = h.sessionLogProvider?.();
20
+ if (!provider) {
21
+ throw new Error(`[akm] harness "${h.id}" declares capabilities.sessionLogs but no sessionLogProvider factory (src/integrations/harnesses). Add one to its descriptor.`);
22
+ }
23
+ return provider;
24
+ });
25
+ // Reverse invariant (kept from #562): every derived provider's runtime name
26
+ // must resolve back — via the id-normalization bridge, so a provider named
27
+ // "claude-code" still maps to the canonical "claude" harness — to a registry
28
+ // harness whose `sessionLogs` capability is set. Catches a descriptor whose
29
+ // factory returns a provider named for a different/unregistered harness.
15
30
  for (const provider of HARNESSES) {
16
31
  const harness = getHarness(provider.name);
17
32
  if (!harness?.capabilities.sessionLogs) {
18
33
  throw new Error(`[akm] session-log provider "${provider.name}" is not registered as a sessionLogs harness in HARNESS_REGISTRY (src/integrations/harnesses). Add it there.`);
19
34
  }
20
35
  }
21
- // Touch the derived list so the dependency is explicit and tree-shake-safe.
22
- void SESSION_LOG_HARNESSES;
23
36
  const ERROR_PATTERNS = /error|failed|exception|cannot|undefined|null pointer|ENOENT|timeout/i;
24
37
  /**
25
38
  * Returns all available session log harnesses for the current machine.
@@ -28,6 +41,22 @@ const ERROR_PATTERNS = /error|failed|exception|cannot|undefined|null pointer|ENO
28
41
  export function getAvailableHarnesses() {
29
42
  return HARNESSES.filter((harness) => harness.isAvailable());
30
43
  }
44
+ /**
45
+ * Map each available harness to its `{ harnessName, roots }` watch target,
46
+ * skipping harnesses that expose no roots (absent `watchRoots()` or an empty
47
+ * result). This is the one stable entry point the watcher uses so it never
48
+ * reaches into providers directly.
49
+ */
50
+ export function getWatchTargets() {
51
+ const targets = [];
52
+ for (const harness of getAvailableHarnesses()) {
53
+ const roots = harness.watchRoots?.() ?? [];
54
+ if (roots.length === 0)
55
+ continue;
56
+ targets.push({ harnessName: harness.name, roots });
57
+ }
58
+ return targets;
59
+ }
31
60
  export function normalizeSessionTopic(text) {
32
61
  const normalized = text.replace(/\s+/g, " ").trim().toLowerCase();
33
62
  if (normalized.length < 10)
@@ -3,7 +3,7 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { getDefaultLlmConfig } from "../core/config/config.js";
5
5
  import { warn } from "../core/warn.js";
6
- import { resolveAgentProfile, runAgent } from "../integrations/agent/index.js";
6
+ import { resolveProfileFromConfig, runAgent } from "../integrations/agent/index.js";
7
7
  import { chatCompletion } from "./client.js";
8
8
  /**
9
9
  * Unified AI call: prefers the default agent profile, falls back to the
@@ -14,7 +14,7 @@ export async function callAi(config, prompt, opts = {}) {
14
14
  const defaultAgentName = config.defaults?.agent;
15
15
  if (defaultAgentName) {
16
16
  try {
17
- const profile = resolveAgentProfile(defaultAgentName, config.profiles?.agent?.[defaultAgentName]);
17
+ const profile = resolveProfileFromConfig(defaultAgentName, config);
18
18
  if (!profile) {
19
19
  return {
20
20
  ok: false,
@@ -103,18 +103,29 @@ function retryBackoffMs() {
103
103
  return RETRY_BACKOFF_MIN_MS + Math.random() * (RETRY_BACKOFF_MAX_MS - RETRY_BACKOFF_MIN_MS);
104
104
  }
105
105
  /**
106
- * Detect whether an error message indicates a context-size-exceeded condition.
107
- * Mirrors the heuristic in `graph-extract.ts` retrying a context overflow
108
- * cannot shrink the input, so it must not be retried.
106
+ * Detect whether an error message indicates a context size exceeded condition.
107
+ * Covers common patterns from OpenAI-compatible APIs (LM Studio, Ollama, etc).
108
+ *
109
+ * Requires BOTH a context keyword AND token-count/overflow evidence so that
110
+ * model prose merely mentioning "context size" / "context length" (e.g. gemma
111
+ * narrating about a document) does not get misclassified as a provider
112
+ * context-limit error (#496).
113
+ *
114
+ * Canonical home: `graph-extract.ts` re-exports this so the index-pass
115
+ * graph extractor and the retry classifier (`isRetryable`) share one
116
+ * definition — retrying a context overflow cannot shrink the input, so it
117
+ * must never be retried.
109
118
  */
110
- function looksLikeContextOverflow(message) {
119
+ export function isContextSizeError(message) {
111
120
  const lower = message.toLowerCase();
112
- return (lower.includes("context") &&
113
- (lower.includes("context size") ||
114
- lower.includes("context length") ||
115
- lower.includes("context_window") ||
116
- lower.includes("prompt too long") ||
117
- lower.includes("exceeds")));
121
+ const contextKw = /context (size|length|window)|prompt too long|exceeds.*context/.test(lower);
122
+ if (!contextKw) {
123
+ return false;
124
+ }
125
+ const evidence = /\b\d+\s*(token|tokens|tk)\b/.test(lower) ||
126
+ /max(imum)?\s+(context|token|input)/.test(lower) ||
127
+ /exceeded|over.*limit|too.*long/.test(lower);
128
+ return evidence;
118
129
  }
119
130
  /**
120
131
  * Decide whether a first-attempt {@link LlmCallError} is eligible for a single
@@ -138,7 +149,7 @@ function looksLikeContextOverflow(message) {
138
149
  * failure in the improve/reflect and capability-probe flows.
139
150
  */
140
151
  function isRetryable(err) {
141
- if (looksLikeContextOverflow(err.message))
152
+ if (isContextSizeError(err.message))
142
153
  return false;
143
154
  if (err.code === "provider_error") {
144
155
  return typeof err.statusCode === "number" && err.statusCode >= 500;
@@ -154,7 +165,19 @@ function isRetryable(err) {
154
165
  }
155
166
  return false;
156
167
  }
168
+ // ── Test seam ────────────────────────────────────────────────────────────────
169
+ // Swap-and-restore override. Inert in production; only tests call the setter.
170
+ let chatCompletionOverride;
171
+ /** TEST-ONLY. Swap the implementation of `chatCompletion`; pass undefined to restore. */
172
+ export function _setChatCompletionForTests(fake) {
173
+ chatCompletionOverride = fake;
174
+ }
157
175
  export async function chatCompletion(config, messages, options) {
176
+ if (chatCompletionOverride)
177
+ return chatCompletionOverride(config, messages, options);
178
+ return chatCompletionReal(config, messages, options);
179
+ }
180
+ async function chatCompletionReal(config, messages, options) {
158
181
  const effectiveTimeoutMs = options?.timeoutMs ?? config.timeoutMs ?? 120_000;
159
182
  const started = Date.now();
160
183
  try {
@@ -2,11 +2,27 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { embedCacheKey, getCachedEmbedding, setCachedEmbedding } from "./embedders/cache.js";
5
- import { isTransformersAvailable, LocalEmbedder } from "./embedders/local.js";
5
+ import { DETERMINISTIC_EMBED_MODEL_ID, deterministicEmbed, isDeterministicEmbedEnabled, } from "./embedders/deterministic.js";
6
+ import { DEFAULT_LOCAL_MODEL, isTransformersAvailable as isTransformersAvailableReal, LocalEmbedder, } from "./embedders/local.js";
6
7
  import { hasRemoteEndpoint, RemoteEmbedder } from "./embedders/remote.js";
7
8
  // ── Re-exports (public API) ─────────────────────────────────────────────────
8
9
  export { clearEmbeddingCache } from "./embedders/cache.js";
9
- export { DEFAULT_LOCAL_MODEL, isTransformersAvailable } from "./embedders/local.js";
10
+ export { _setTransformersLoaderForTests, DEFAULT_LOCAL_MODEL } from "./embedders/local.js";
11
+ let embedderOverrides;
12
+ /** TEST-ONLY. Swap embedder implementations; pass undefined to restore. */
13
+ export function _setEmbedderForTests(fakes) {
14
+ embedderOverrides = fakes;
15
+ }
16
+ /**
17
+ * Check whether the @huggingface/transformers package is importable.
18
+ * Delegating wrapper around `./embedders/local`'s probe so tests can swap it
19
+ * via {@link _setEmbedderForTests}.
20
+ */
21
+ export function isTransformersAvailable() {
22
+ if (embedderOverrides?.isTransformersAvailable)
23
+ return embedderOverrides.isTransformersAvailable();
24
+ return isTransformersAvailableReal();
25
+ }
10
26
  // ── Singleton local embedder ────────────────────────────────────────────────
11
27
  // `_localEmbedder` is an intentional module-level singleton but constructed
12
28
  // lazily on first use. The underlying @huggingface/transformers pipeline is
@@ -39,6 +55,12 @@ export function resetLocalEmbedder() {
39
55
  * and embedding config. Repeated identical queries return the cached vector.
40
56
  */
41
57
  export async function embed(text, embeddingConfig, signal) {
58
+ if (embedderOverrides?.embed)
59
+ return embedderOverrides.embed(text, embeddingConfig, signal);
60
+ // Deterministic mode (env-gated, test/bench only): model-free, stable.
61
+ if (isDeterministicEmbedEnabled()) {
62
+ return deterministicEmbed(text);
63
+ }
42
64
  const key = embedCacheKey(text, embeddingConfig);
43
65
  const cached = getCachedEmbedding(key);
44
66
  if (cached)
@@ -52,16 +74,28 @@ export async function embed(text, embeddingConfig, signal) {
52
74
  /**
53
75
  * Generate embeddings for multiple texts in batch.
54
76
  * Uses the OpenAI-compatible batch API for remote endpoints (batches of 100).
55
- * Falls back to sequential embedding for the local transformer pipeline.
77
+ * Uses the LocalEmbedder.embedBatch path for the local transformer pipeline,
78
+ * which processes texts in chunks of 32 for genuine batched inference.
56
79
  */
57
80
  export async function embedBatch(texts, embeddingConfig, signal) {
81
+ if (embedderOverrides?.embedBatch)
82
+ return embedderOverrides.embedBatch(texts, embeddingConfig, signal);
58
83
  if (texts.length === 0)
59
84
  return [];
85
+ // Deterministic mode (env-gated, test/bench only): model-free, stable.
86
+ if (isDeterministicEmbedEnabled()) {
87
+ return texts.map((t) => deterministicEmbed(t));
88
+ }
60
89
  if (embeddingConfig && hasRemoteEndpoint(embeddingConfig)) {
61
90
  return new RemoteEmbedder(embeddingConfig).embedBatch(texts, signal);
62
91
  }
63
- // Local transformer: process sequentially (pipeline handles one at a time)
92
+ // Local transformer: use the batched path (chunks of 32 via LocalEmbedder).
93
+ // When a localModel override is set we cannot share the singleton (which uses
94
+ // the default model), so fall back to per-text embedWithModel in that case.
64
95
  const localModel = embeddingConfig?.localModel;
96
+ if (!localModel) {
97
+ return getLocalEmbedder().embedBatch(texts, signal);
98
+ }
65
99
  const results = [];
66
100
  for (const text of texts) {
67
101
  if (signal?.aborted) {
@@ -77,11 +111,40 @@ export async function embedBatch(texts, embeddingConfig, signal) {
77
111
  // facade and its `@huggingface/transformers` import chain. Re-export
78
112
  // preserves the existing public API.
79
113
  export { cosineSimilarity } from "./embedders/types.js";
114
+ // ── Model ID resolution ─────────────────────────────────────────────────────
115
+ /**
116
+ * Derive a stable string identifier for the embedding model in use.
117
+ * This is the `model_id` stored in `body_embeddings` (and used for the
118
+ * drop-all-on-mismatch purge when the model changes).
119
+ *
120
+ * Rules:
121
+ * - Remote endpoint: use `config.model` (the API-level model name).
122
+ * - Local transformers: use `config.localModel ?? DEFAULT_LOCAL_MODEL`.
123
+ * - No config: use `DEFAULT_LOCAL_MODEL` (the shared singleton model).
124
+ */
125
+ export function resolveEmbeddingModelId(embeddingConfig) {
126
+ if (embedderOverrides?.resolveEmbeddingModelId)
127
+ return embedderOverrides.resolveEmbeddingModelId(embeddingConfig);
128
+ if (isDeterministicEmbedEnabled())
129
+ return DETERMINISTIC_EMBED_MODEL_ID;
130
+ if (!embeddingConfig)
131
+ return DEFAULT_LOCAL_MODEL;
132
+ if (hasRemoteEndpoint(embeddingConfig))
133
+ return embeddingConfig.model ?? "remote";
134
+ return embeddingConfig.localModel ?? DEFAULT_LOCAL_MODEL;
135
+ }
80
136
  // ── Availability check ──────────────────────────────────────────────────────
81
137
  /**
82
138
  * Check whether embedding is available with a detailed reason on failure.
83
139
  */
84
140
  export async function checkEmbeddingAvailability(embeddingConfig) {
141
+ if (embedderOverrides?.checkEmbeddingAvailability) {
142
+ return embedderOverrides.checkEmbeddingAvailability(embeddingConfig);
143
+ }
144
+ // Deterministic mode (env-gated): always available — no model, no network.
145
+ if (isDeterministicEmbedEnabled()) {
146
+ return { available: true };
147
+ }
85
148
  if (embeddingConfig && hasRemoteEndpoint(embeddingConfig)) {
86
149
  try {
87
150
  await new RemoteEmbedder(embeddingConfig).embed("test");
@@ -25,7 +25,9 @@ export function getCachedEmbedding(key) {
25
25
  return cached;
26
26
  }
27
27
  export function setCachedEmbedding(key, value) {
28
- // Evict oldest entry if at capacity
28
+ // Delete first so an overwrite refreshes LRU recency AND is not counted as a
29
+ // new insert: only a genuinely new key at capacity should evict the oldest.
30
+ embedCache.delete(key);
29
31
  if (embedCache.size >= EMBED_CACHE_MAX) {
30
32
  const oldest = embedCache.keys().next().value;
31
33
  if (oldest !== undefined) {
@@ -0,0 +1,66 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /** Env var that switches the whole embedding facade into deterministic mode. */
5
+ export const DETERMINISTIC_EMBED_ENV = "AKM_EMBED_DETERMINISTIC";
6
+ /**
7
+ * Vector width. Matches the default local model (`bge-small`, 384 dims) so the
8
+ * index DB's embedding column and sqlite-vec table dimensions line up without
9
+ * any extra config.
10
+ */
11
+ export const DETERMINISTIC_EMBED_DIM = 384;
12
+ /**
13
+ * Stable model id reported for deterministic mode. Used as the embedding
14
+ * `model_id` and folded into the provider fingerprint so a deterministic index
15
+ * is never confused with a real-model index (and vice versa).
16
+ */
17
+ export const DETERMINISTIC_EMBED_MODEL_ID = "akm-deterministic-hash-v1";
18
+ /** True when deterministic embedding is enabled via env. */
19
+ export function isDeterministicEmbedEnabled() {
20
+ return process.env[DETERMINISTIC_EMBED_ENV] === "1";
21
+ }
22
+ /** FNV-1a 32-bit hash. Platform- and version-stable. */
23
+ function fnv1a(str) {
24
+ let h = 0x811c9dc5;
25
+ for (let i = 0; i < str.length; i++) {
26
+ h ^= str.charCodeAt(i);
27
+ // 32-bit FNV prime multiply via shifts to stay in uint32.
28
+ h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;
29
+ }
30
+ return h >>> 0;
31
+ }
32
+ /** Lowercase, split on non-alphanumeric, drop empties. */
33
+ function tokenize(text) {
34
+ return text
35
+ .toLowerCase()
36
+ .split(/[^a-z0-9]+/)
37
+ .filter((t) => t.length > 0);
38
+ }
39
+ /**
40
+ * Deterministically embed `text` into a unit-length vector of width `dim`
41
+ * using feature hashing. Empty / token-less input returns a fixed unit
42
+ * vector so cosine similarity never sees a zero vector (NaN guard).
43
+ */
44
+ export function deterministicEmbed(text, dim = DETERMINISTIC_EMBED_DIM) {
45
+ const vec = new Array(dim).fill(0);
46
+ const tokens = tokenize(text);
47
+ for (const tok of tokens) {
48
+ const h = fnv1a(tok);
49
+ const idx = h % dim;
50
+ // Use a higher bit for the sign so it is independent of the bucket index.
51
+ const sign = (h >>> 16) & 1 ? 1 : -1;
52
+ vec[idx] += sign;
53
+ }
54
+ let norm = 0;
55
+ for (const v of vec)
56
+ norm += v * v;
57
+ norm = Math.sqrt(norm);
58
+ if (norm === 0) {
59
+ // No usable tokens — return a fixed, stable unit vector.
60
+ vec[0] = 1;
61
+ return vec;
62
+ }
63
+ for (let i = 0; i < dim; i++)
64
+ vec[i] /= norm;
65
+ return vec;
66
+ }
@@ -19,8 +19,30 @@ import { getDirname, resolveModule } from "../../runtime.js";
19
19
  * `all-MiniLM-L6-v2` at the same 384-dimension footprint.
20
20
  */
21
21
  export const DEFAULT_LOCAL_MODEL = "Xenova/bge-small-en-v1.5";
22
+ /** Type-guard: true when the value looks like a batch Tensor (has .dims). */
23
+ function isBatchTensor(v) {
24
+ return (v !== null &&
25
+ typeof v === "object" &&
26
+ "data" in v &&
27
+ "dims" in v &&
28
+ Array.isArray(v.dims) &&
29
+ v.dims.length >= 2);
30
+ }
31
+ const realTransformersLoader = () => import("@huggingface/transformers");
32
+ let transformersLoader = realTransformersLoader;
33
+ /** TEST-ONLY. Swap the transformers module loader; pass undefined to restore. */
34
+ export function _setTransformersLoaderForTests(fake) {
35
+ transformersLoader = fake ?? realTransformersLoader;
36
+ }
22
37
  const LOCAL_EMBEDDER_DTYPE = "fp32";
23
38
  const LOCAL_EMBEDDER_FALLBACK_DTYPE = "auto";
39
+ /**
40
+ * Maximum texts per batch for the local transformers pipeline. The pipeline
41
+ * can run genuine batched inference over a string array; 32 is a safe default
42
+ * that fits well inside most model context budgets while providing 10–50×
43
+ * throughput improvement over one-at-a-time calls on the cold minority.
44
+ */
45
+ const LOCAL_BATCH_SIZE = 32;
24
46
  /**
25
47
  * Return the local model name that will be used for embedding.
26
48
  * When `overrideModel` is provided it takes precedence; otherwise
@@ -77,15 +99,63 @@ export class LocalEmbedder {
77
99
  }
78
100
  return this.embedWithModel(text, this.defaultModel);
79
101
  }
102
+ /**
103
+ * Embed a batch of texts. Processes in chunks of `LOCAL_BATCH_SIZE` (32) so
104
+ * the transformers pipeline can run genuine batched inference rather than one
105
+ * call per text. Falls back to one-at-a-time if the pipeline does not support
106
+ * array input (older versions of @huggingface/transformers). Each chunk is
107
+ * checked against the AbortSignal between calls.
108
+ */
80
109
  async embedBatch(texts, signal) {
81
110
  if (texts.length === 0)
82
111
  return [];
112
+ if (signal?.aborted) {
113
+ throw signal.reason instanceof Error ? signal.reason : new Error("embedding interrupted");
114
+ }
115
+ const pipeline = await this.getPipeline(this.defaultModel);
83
116
  const results = [];
84
- for (const text of texts) {
117
+ for (let i = 0; i < texts.length; i += LOCAL_BATCH_SIZE) {
85
118
  if (signal?.aborted) {
86
119
  throw signal.reason instanceof Error ? signal.reason : new Error("embedding interrupted");
87
120
  }
88
- results.push(await this.embedWithModel(text, this.defaultModel));
121
+ const chunk = texts.slice(i, i + LOCAL_BATCH_SIZE);
122
+ try {
123
+ // @huggingface/transformers feature-extraction pipeline accepts a
124
+ // string[] and returns a batch Tensor (NOT an Array<{data}>).
125
+ // The Tensor has .data (flat Float32Array, length = batch * dim) and
126
+ // .dims = [batch, dim]. Slice .data into per-row vectors using .dims.
127
+ const batchResult = await pipeline(chunk, {
128
+ pooling: "mean",
129
+ normalize: true,
130
+ });
131
+ if (isBatchTensor(batchResult)) {
132
+ const dim = batchResult.dims[1];
133
+ for (let row = 0; row < chunk.length; row++) {
134
+ results.push(Array.from(batchResult.data.subarray(row * dim, (row + 1) * dim)));
135
+ }
136
+ }
137
+ else if (Array.isArray(batchResult)) {
138
+ // Older versions of @huggingface/transformers returned Array<{data}>.
139
+ for (const r of batchResult) {
140
+ results.push(Array.from(r.data));
141
+ }
142
+ }
143
+ else {
144
+ // Single-text result returned for a chunk — should not happen for
145
+ // string[] input, but handle defensively.
146
+ throw new Error("unexpected pipeline return shape for batch input");
147
+ }
148
+ }
149
+ catch {
150
+ // Fallback: process one-at-a-time (older pipeline versions or mismatched
151
+ // return type). Fail-open per text: a single failure aborts the chunk.
152
+ for (const text of chunk) {
153
+ if (signal?.aborted) {
154
+ throw signal.reason instanceof Error ? signal.reason : new Error("embedding interrupted");
155
+ }
156
+ results.push(await this.embedWithModel(text, this.defaultModel));
157
+ }
158
+ }
89
159
  }
90
160
  return results;
91
161
  }
@@ -116,7 +186,7 @@ export class LocalEmbedder {
116
186
  }
117
187
  let pipeline;
118
188
  try {
119
- const mod = await import("@huggingface/transformers");
189
+ const mod = await transformersLoader();
120
190
  pipeline = mod.pipeline;
121
191
  }
122
192
  catch (importError) {
@@ -22,18 +22,25 @@ const FEATURE_LOCATION = {
22
22
  graph_extraction: (cfg) => cfg.profiles?.improve?.default?.processes?.graphExtraction?.enabled ?? true,
23
23
  // Legacy default: false
24
24
  metadata_enhance: (cfg) => cfg.index?.metadataEnhance?.enabled ?? false,
25
- // Legacy default: false
26
- curate_rerank: (cfg) => cfg.search?.curateRerank?.enabled ?? false,
27
- // Legacy default: false
28
- lesson_quality_gate: (cfg) => cfg.profiles?.improve?.default?.processes?.distill?.qualityGate?.enabled ?? false,
25
+ // Default ON since R3 (docs/design/improve-self-learning-analysis.md G5):
26
+ // distill is a primary acquisition path, so the gate guards minted content by
27
+ // default. The judge fails CLOSED (07 P0-2): no LLM / timeout / parse failure
28
+ // reject the proposal rather than passing it through — an unjudgeable proposal
29
+ // must not slip into the stash. Opt out via
30
+ // profiles.improve.default.processes.distill.qualityGate.enabled: false.
31
+ lesson_quality_gate: (cfg) => cfg.profiles?.improve?.default?.processes?.distill?.qualityGate?.enabled ?? true,
29
32
  // Legacy default: false
30
33
  proposal_quality_gate: (cfg) => cfg.profiles?.improve?.default?.processes?.reflect?.qualityGate?.enabled ?? false,
31
34
  // Legacy default: false
32
35
  memory_contradiction_detection: (cfg) => cfg.profiles?.improve?.default?.processes?.consolidate?.contradictionDetection?.enabled ?? false,
33
- // Default: true. Session extraction replaces the akm-plugin checkpoint hook
34
- // and is the primary path for capturing durable signal from real sessions.
35
- // Opt out via `profiles.improve.default.processes.extract.enabled: false`.
36
- session_extraction: (cfg) => cfg.profiles?.improve?.default?.processes?.extract?.enabled ?? true,
36
+ // Always on at the LLM-wrapper level. Enablement is decided ONCE at the
37
+ // extract entry point (`akmExtract`): the `extract.enabled` process toggle
38
+ // gates extract as a STAGE of `akm improve` (the active improve profile, per
39
+ // #593/#594), while an explicit `akm extract` command always runs. Gating the
40
+ // inner LLM calls on `default.processes.extract.enabled` here was a footgun —
41
+ // dropping extract from the daily improve profile silently disabled the
42
+ // standalone `akm extract` command. (cfg unused — kept for resolver signature.)
43
+ session_extraction: (_cfg) => true,
37
44
  };
38
45
  /**
39
46
  * Pure predicate: is the named feature gate enabled in `config`?
@@ -89,14 +96,11 @@ export async function tryLlmFeature(feature, config, fn, fallback, opts) {
89
96
  export function isProcessEnabled(section, processName, config) {
90
97
  if (!config)
91
98
  return false;
92
- // index.metadataEnhance / index.stalenessDetection are first-class new-shape entries.
99
+ // index.metadataEnhance is a first-class new-shape entry.
93
100
  if (section === "index") {
94
101
  if (processName === "metadata_enhance" || processName === "metadataEnhance") {
95
102
  return config.index?.metadataEnhance?.enabled ?? true;
96
103
  }
97
- if (processName === "staleness_detection" || processName === "stalenessDetection") {
98
- return config.index?.stalenessDetection?.enabled ?? false;
99
- }
100
104
  if (processName === "memory_inference" || processName === "memoryInference") {
101
105
  return isLlmFeatureEnabled(config, "memory_inference");
102
106
  }
@@ -104,9 +108,6 @@ export function isProcessEnabled(section, processName, config) {
104
108
  return isLlmFeatureEnabled(config, "graph_extraction");
105
109
  }
106
110
  }
107
- if (section === "search" && (processName === "curate_rerank" || processName === "curateRerank")) {
108
- return config.search?.curateRerank?.enabled ?? false;
109
- }
110
111
  if (section === "improve") {
111
112
  const processes = config.profiles?.improve?.default?.processes;
112
113
  const entry = processes?.[processName];