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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (587) hide show
  1. package/CHANGELOG.md +1190 -52
  2. package/README.md +62 -37
  3. package/SECURITY.md +46 -31
  4. package/dist/akm +162 -38
  5. package/dist/akm-migrate +44 -0
  6. package/dist/assets/backends/schtasks-template.xml +2 -1
  7. package/dist/assets/hints/cli-hints-full.md +268 -118
  8. package/dist/assets/hints/cli-hints-short.md +87 -24
  9. package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
  10. package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
  11. package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
  12. package/dist/assets/improve-strategies/frequent.json +15 -0
  13. package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
  14. package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
  15. package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
  16. package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
  17. package/dist/assets/improve-strategies/reflect-distill.json +30 -0
  18. package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
  19. package/dist/assets/prompts/consolidate-system.md +5 -5
  20. package/dist/assets/prompts/extract-session.md +2 -6
  21. package/dist/assets/prompts/memory-infer-user.md +2 -3
  22. package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
  23. package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
  24. package/dist/assets/prompts/reflect-output-repair.md +3 -0
  25. package/dist/assets/stash-skeleton/README.md +38 -10
  26. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
  38. package/dist/assets/tasks/core/extract.yml +3 -2
  39. package/dist/assets/tasks/core/improve.yml +2 -1
  40. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  41. package/dist/assets/tasks/core/sync.yml +1 -0
  42. package/dist/assets/tasks/core/version-check.yml +2 -1
  43. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  44. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  45. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  46. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  47. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  48. package/dist/assets/templates/html/health.html +5 -4
  49. package/dist/assets/workflows/workflow-template.md +31 -15
  50. package/dist/cli/invocation.js +279 -0
  51. package/dist/cli/parse-args.js +5 -90
  52. package/dist/cli/retired-commands.js +78 -0
  53. package/dist/cli/shared.js +158 -48
  54. package/dist/cli-node.mjs +2 -1
  55. package/dist/cli.js +747 -293
  56. package/dist/commands/agent/agent-dispatch.js +19 -18
  57. package/dist/commands/agent/agent-support.js +0 -24
  58. package/dist/commands/agent/contribute-cli.js +43 -97
  59. package/dist/commands/completions.js +80 -23
  60. package/dist/commands/config-cli.js +44 -281
  61. package/dist/commands/env/env-binding.js +13 -9
  62. package/dist/commands/env/env-cli.js +76 -159
  63. package/dist/commands/env/env.js +12 -163
  64. package/dist/commands/env/marker-path.js +6 -0
  65. package/dist/commands/env/secret-cli.js +45 -61
  66. package/dist/commands/env/secret.js +32 -62
  67. package/dist/commands/feedback-cli.js +179 -85
  68. package/dist/commands/health/accept-rate.js +58 -0
  69. package/dist/commands/health/advisories.js +7 -8
  70. package/dist/commands/health/checks.js +279 -94
  71. package/dist/commands/health/html-report.js +197 -578
  72. package/dist/commands/health/improve-metrics.js +277 -246
  73. package/dist/commands/health/llm-usage.js +19 -19
  74. package/dist/commands/health/md-report.js +16 -7
  75. package/dist/commands/health/metrics.js +67 -32
  76. package/dist/commands/health/renderers.js +47 -0
  77. package/dist/commands/health/report-view-model.js +508 -0
  78. package/dist/commands/health/stash-exposure.js +1 -1
  79. package/dist/commands/health/surfaces.js +16 -56
  80. package/dist/commands/health/task-runs.js +3 -67
  81. package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
  82. package/dist/commands/health/types-improve.js +29 -0
  83. package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
  84. package/dist/commands/health/types-result.js +7 -0
  85. package/dist/commands/health/types-runs.js +4 -0
  86. package/dist/commands/health/types-session-log.js +4 -0
  87. package/dist/commands/health/types-windows.js +4 -0
  88. package/dist/commands/health/types.js +26 -21
  89. package/dist/commands/health/windows.js +2 -3
  90. package/dist/commands/health.js +296 -167
  91. package/dist/commands/improve/anti-collapse.js +5 -5
  92. package/dist/commands/improve/autonomy-gate.js +68 -0
  93. package/dist/commands/improve/collapse-detector.js +65 -52
  94. package/dist/commands/improve/consolidate/chunking.js +9 -7
  95. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  96. package/dist/commands/improve/consolidate/merge.js +4 -0
  97. package/dist/commands/improve/consolidate.js +454 -1354
  98. package/dist/commands/improve/content-hash.js +39 -0
  99. package/dist/commands/improve/distill/content-repair.js +4 -10
  100. package/dist/commands/improve/distill/promote-memory.js +89 -64
  101. package/dist/commands/improve/distill/quality-gate.js +118 -42
  102. package/dist/commands/improve/distill-guards.js +1 -1
  103. package/dist/commands/improve/distill-promotion-policy.js +33 -888
  104. package/dist/commands/improve/distill.js +607 -363
  105. package/dist/commands/improve/eligibility.js +165 -79
  106. package/dist/commands/improve/extract-cli.js +35 -126
  107. package/dist/commands/improve/extract-prompt.js +6 -35
  108. package/dist/commands/improve/extract.js +640 -391
  109. package/dist/commands/improve/feedback-valence.js +2 -12
  110. package/dist/commands/improve/improve-cli.js +134 -135
  111. package/dist/commands/improve/improve-result-file.js +30 -50
  112. package/dist/commands/improve/improve-run-types.js +4 -0
  113. package/dist/commands/improve/improve-strategies.js +135 -0
  114. package/dist/commands/improve/improve.js +904 -701
  115. package/dist/commands/improve/locks.js +64 -111
  116. package/dist/commands/improve/loop-stages.js +1110 -923
  117. package/dist/commands/improve/memory/derived-ref.js +124 -0
  118. package/dist/commands/improve/memory/memory-belief.js +79 -7
  119. package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
  120. package/dist/commands/improve/memory/memory-improve.js +25 -37
  121. package/dist/commands/improve/outcome-loop.js +25 -88
  122. package/dist/commands/improve/preparation.js +1034 -813
  123. package/dist/commands/improve/proactive-maintenance.js +34 -9
  124. package/dist/commands/improve/proposal-envelope.js +31 -0
  125. package/dist/commands/improve/reflect.js +983 -794
  126. package/dist/commands/improve/run-context.js +119 -0
  127. package/dist/commands/improve/salience.js +24 -127
  128. package/dist/commands/improve/session-asset.js +7 -3
  129. package/dist/commands/improve/shared.js +14 -34
  130. package/dist/commands/improve/source-identity.js +28 -0
  131. package/dist/commands/improve/triage.js +20 -17
  132. package/dist/commands/lint/base-linter.js +340 -313
  133. package/dist/commands/lint/env-key-rules.js +31 -47
  134. package/dist/commands/lint/index.js +185 -30
  135. package/dist/commands/{events.js → log.js} +28 -38
  136. package/dist/commands/migrate-cli.js +54 -0
  137. package/dist/commands/migration-tool.js +55 -0
  138. package/dist/commands/observability-cli.js +70 -208
  139. package/dist/commands/proposal/diff-format.js +50 -0
  140. package/dist/commands/proposal/drain-policies.js +0 -6
  141. package/dist/commands/proposal/drain.js +91 -40
  142. package/dist/commands/proposal/proposal-cli.js +134 -132
  143. package/dist/commands/proposal/proposal-types.js +56 -0
  144. package/dist/commands/proposal/proposal.js +83 -65
  145. package/dist/commands/proposal/propose-cli.js +88 -0
  146. package/dist/commands/proposal/propose.js +105 -88
  147. package/dist/commands/proposal/repository.js +1303 -278
  148. package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
  149. package/dist/commands/proposal/validators/proposal-validators.js +61 -12
  150. package/dist/commands/proposal/validators/proposals.js +6 -8
  151. package/dist/commands/read/curate.js +78 -73
  152. package/dist/commands/read/knowledge.js +510 -13
  153. package/dist/commands/read/registry-search.js +2 -2
  154. package/dist/commands/read/remember-cli.js +84 -15
  155. package/dist/commands/read/search-cli.js +203 -96
  156. package/dist/commands/read/search.js +126 -94
  157. package/dist/commands/read/show.js +226 -250
  158. package/dist/commands/registry-cli.js +34 -60
  159. package/dist/commands/remember.js +18 -57
  160. package/dist/commands/sources/add-cli.js +104 -49
  161. package/dist/commands/sources/bundle-cli.js +166 -0
  162. package/dist/commands/sources/bundle-config-ops.js +63 -0
  163. package/dist/commands/sources/info.js +27 -15
  164. package/dist/commands/sources/init.js +30 -40
  165. package/dist/commands/sources/installed-stashes.js +469 -172
  166. package/dist/commands/sources/schema-repair.js +10 -9
  167. package/dist/commands/sources/self-update.js +182 -121
  168. package/dist/commands/sources/source-add.js +169 -178
  169. package/dist/commands/sources/source-clone.js +144 -41
  170. package/dist/commands/sources/source-manage.js +94 -59
  171. package/dist/commands/sources/sources-cli.js +64 -205
  172. package/dist/commands/sources/stash-cli.js +91 -54
  173. package/dist/commands/sources/stash-skeleton.js +1 -1
  174. package/dist/commands/tasks/tasks-cli.js +106 -104
  175. package/dist/commands/tasks/tasks.js +445 -262
  176. package/dist/commands/workflow-cli.js +75 -228
  177. package/dist/core/action-contributors.js +1 -1
  178. package/dist/core/activation-policy.js +49 -0
  179. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  180. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  181. package/dist/core/adapter/adapters/akm-lint.js +392 -0
  182. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  183. package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
  184. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  185. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  186. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  187. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  188. package/dist/core/adapter/adapters/index.js +80 -0
  189. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  190. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  191. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  192. package/dist/core/adapter/adapters/shared.js +286 -0
  193. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  194. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  195. package/dist/core/adapter/bundle-adapter.js +4 -0
  196. package/dist/core/adapter/detect-adapter.js +17 -0
  197. package/dist/core/adapter/recognize-match.js +44 -0
  198. package/dist/core/adapter/registry.js +56 -0
  199. package/dist/core/adapter/types.js +4 -0
  200. package/dist/core/asset/akm-markdown.js +30 -0
  201. package/dist/core/asset/asset-placement.js +243 -0
  202. package/dist/core/asset/asset-ref.js +110 -79
  203. package/dist/core/asset/asset-serialize.js +20 -0
  204. package/dist/core/asset/frontmatter.js +28 -12
  205. package/dist/core/asset/markdown.js +40 -51
  206. package/dist/core/asset/resolve-ref.js +274 -0
  207. package/dist/core/asset/stash-meta.js +2 -2
  208. package/dist/core/bundle-id.js +51 -0
  209. package/dist/core/common.js +281 -86
  210. package/dist/core/config/config-io.js +42 -128
  211. package/dist/core/config/config-schema.js +233 -855
  212. package/dist/core/config/config-sources.js +162 -39
  213. package/dist/core/config/config-types.js +16 -11
  214. package/dist/core/config/config-version.js +29 -0
  215. package/dist/core/config/config-walker.js +126 -37
  216. package/dist/core/config/config.js +154 -331
  217. package/dist/core/config/deep-merge.js +41 -0
  218. package/dist/core/config/engine-semantics.js +28 -0
  219. package/dist/core/config/experimental.js +21 -0
  220. package/dist/core/config/schema/embedding.js +38 -0
  221. package/dist/core/config/schema/engines.js +116 -0
  222. package/dist/core/config/schema/experimental.js +47 -0
  223. package/dist/core/config/schema/feedback.js +31 -0
  224. package/dist/core/config/schema/improve-processes.js +389 -0
  225. package/dist/core/config/schema/improve.js +94 -0
  226. package/dist/core/config/schema/index-config.js +176 -0
  227. package/dist/core/config/schema/output.js +18 -0
  228. package/dist/core/config/schema/primitives.js +94 -0
  229. package/dist/core/config/schema/search.js +30 -0
  230. package/dist/core/config/schema/setup.js +18 -0
  231. package/dist/core/config/schema/sources-bundles.js +169 -0
  232. package/dist/core/config/schema/workflow.js +29 -0
  233. package/dist/core/env-secret-ref.js +155 -20
  234. package/dist/core/errors.js +17 -15
  235. package/dist/core/events-types.js +4 -0
  236. package/dist/core/events.js +46 -128
  237. package/dist/core/extra-params.js +62 -0
  238. package/dist/core/file-change.js +17 -0
  239. package/dist/core/file-lock.js +202 -57
  240. package/dist/core/fs-txn.js +392 -0
  241. package/dist/core/git-message.js +59 -0
  242. package/dist/core/improve-result.js +167 -0
  243. package/dist/core/lesson-lint.js +1 -17
  244. package/dist/core/logs-db.js +1 -1
  245. package/dist/core/maintenance-barrier.js +135 -0
  246. package/dist/core/migration-operation.js +44 -0
  247. package/dist/core/mutation-target.js +78 -0
  248. package/dist/core/paths.js +22 -25
  249. package/dist/core/platform.js +10 -0
  250. package/dist/core/recognition-util.js +128 -0
  251. package/dist/core/redaction.js +392 -0
  252. package/dist/core/standards/resolve-standards-context.js +36 -65
  253. package/dist/core/standards/resolve-stash-standards.js +2 -2
  254. package/dist/core/standards/resolve-type-conventions.js +5 -5
  255. package/dist/core/state/migrations.js +242 -11
  256. package/dist/core/state-db.js +98 -10
  257. package/dist/core/structured.js +1 -1
  258. package/dist/core/subprocess.js +303 -0
  259. package/dist/core/text-truncation.js +9 -5
  260. package/dist/core/time.js +20 -0
  261. package/dist/core/type-presentation.js +130 -0
  262. package/dist/core/warn.js +0 -3
  263. package/dist/core/write-source.js +834 -118
  264. package/dist/indexer/bundle-identity-guard.js +92 -0
  265. package/dist/indexer/db/graph-db.js +1 -25
  266. package/dist/indexer/db/llm-cache.js +1 -1
  267. package/dist/indexer/ensure-index.js +30 -9
  268. package/dist/indexer/graph/graph-boost.js +9 -30
  269. package/dist/indexer/graph/graph-extraction.js +41 -27
  270. package/dist/indexer/graph/graph-types.js +4 -0
  271. package/dist/indexer/index-writer-lock.js +93 -49
  272. package/dist/indexer/index-written-assets.js +100 -53
  273. package/dist/indexer/indexer.js +746 -329
  274. package/dist/indexer/init.js +18 -25
  275. package/dist/indexer/installations.js +142 -0
  276. package/dist/indexer/passes/dir-staleness.js +18 -10
  277. package/dist/indexer/passes/memory-inference.js +25 -15
  278. package/dist/indexer/passes/metadata.js +412 -243
  279. package/dist/indexer/scan/doc-to-entry.js +160 -0
  280. package/dist/indexer/scan/drain-dir.js +134 -0
  281. package/dist/indexer/search/db-search.js +292 -108
  282. package/dist/indexer/search/fts-query.js +64 -0
  283. package/dist/indexer/search/ranking-contributors.js +145 -25
  284. package/dist/indexer/search/ranking-types.js +4 -0
  285. package/dist/indexer/search/ranking.js +28 -71
  286. package/dist/indexer/search/search-attribution.js +67 -0
  287. package/dist/indexer/search/search-fields.js +18 -3
  288. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  289. package/dist/indexer/search/search-source.js +157 -111
  290. package/dist/indexer/search/semantic-status.js +4 -1
  291. package/dist/indexer/usage/usage-events.js +10 -30
  292. package/dist/indexer/walk/file-context.js +3 -45
  293. package/dist/indexer/walk/matchers.js +42 -73
  294. package/dist/indexer/walk/path-resolver.js +11 -5
  295. package/dist/indexer/walk/walker.js +42 -14
  296. package/dist/integrations/agent/builder-shared.js +7 -0
  297. package/dist/integrations/agent/builders.js +5 -58
  298. package/dist/integrations/agent/config.js +3 -143
  299. package/dist/integrations/agent/detect.js +17 -2
  300. package/dist/integrations/agent/engine-resolution.js +231 -0
  301. package/dist/integrations/agent/index.js +1 -2
  302. package/dist/integrations/agent/model-aliases.js +8 -3
  303. package/dist/integrations/agent/profiles.js +6 -99
  304. package/dist/integrations/agent/prompts.js +46 -18
  305. package/dist/integrations/agent/runner-dispatch.js +78 -13
  306. package/dist/integrations/agent/runner.js +76 -208
  307. package/dist/integrations/agent/spawn.js +48 -279
  308. package/dist/integrations/harnesses/aider/agent-builder.js +9 -8
  309. package/dist/integrations/harnesses/aider/index.js +2 -12
  310. package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -16
  311. package/dist/integrations/harnesses/amazonq/index.js +3 -17
  312. package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
  313. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  314. package/dist/integrations/harnesses/claude/index.js +1 -14
  315. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  316. package/dist/integrations/harnesses/codex/agent-builder.js +8 -7
  317. package/dist/integrations/harnesses/codex/index.js +2 -13
  318. package/dist/integrations/harnesses/copilot/agent-builder.js +9 -9
  319. package/dist/integrations/harnesses/copilot/index.js +1 -13
  320. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -9
  321. package/dist/integrations/harnesses/gemini/index.js +1 -13
  322. package/dist/integrations/harnesses/ids.js +24 -0
  323. package/dist/integrations/harnesses/index.js +31 -33
  324. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  325. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  326. package/dist/integrations/harnesses/opencode/index.js +1 -18
  327. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  328. package/dist/integrations/harnesses/opencode-sdk/harness.js +3 -17
  329. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +274 -191
  330. package/dist/integrations/harnesses/openhands/agent-builder.js +12 -10
  331. package/dist/integrations/harnesses/openhands/index.js +2 -12
  332. package/dist/integrations/harnesses/pi/agent-builder.js +11 -18
  333. package/dist/integrations/harnesses/pi/index.js +3 -16
  334. package/dist/integrations/harnesses/shared.js +17 -0
  335. package/dist/integrations/harnesses/types.js +38 -34
  336. package/dist/integrations/lockfile.js +211 -24
  337. package/dist/integrations/session-logs/index.js +24 -40
  338. package/dist/integrations/session-logs/provider-base.js +113 -0
  339. package/dist/llm/client.js +182 -110
  340. package/dist/llm/embedders/deterministic.js +2 -2
  341. package/dist/llm/embedders/remote.js +21 -9
  342. package/dist/llm/feature-gate.js +17 -57
  343. package/dist/llm/graph-extract.js +12 -13
  344. package/dist/llm/index-passes.js +8 -42
  345. package/dist/llm/memory-infer.js +144 -1
  346. package/dist/llm/metadata-enhance.js +45 -30
  347. package/dist/llm/structured-call.js +16 -8
  348. package/dist/llm/usage-persist.js +30 -5
  349. package/dist/llm/usage-telemetry.js +59 -6
  350. package/dist/output/cli-hints.js +1 -2
  351. package/dist/output/command-registry.js +27 -0
  352. package/dist/output/context.js +22 -7
  353. package/dist/output/format-exempt.js +80 -0
  354. package/dist/output/generic-render.js +251 -0
  355. package/dist/output/html-render.js +11 -16
  356. package/dist/output/render-registry.js +57 -0
  357. package/dist/output/renderers.js +15 -281
  358. package/dist/output/shapes/curate.js +10 -1
  359. package/dist/output/shapes/events.js +12 -7
  360. package/dist/output/shapes/helpers.js +58 -84
  361. package/dist/output/shapes/passthrough.js +8 -40
  362. package/dist/output/shapes/proposal/producer.js +15 -7
  363. package/dist/output/shapes/registry.js +12 -6
  364. package/dist/output/shapes.js +0 -9
  365. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  366. package/dist/output/text/bundle-show.js +7 -0
  367. package/dist/output/text/command-format.js +562 -0
  368. package/dist/output/text/env.js +1 -3
  369. package/dist/output/text/events.js +8 -7
  370. package/dist/output/text/helpers.js +15 -1375
  371. package/dist/output/text/proposal/producer.js +4 -2
  372. package/dist/output/text/proposal-format.js +202 -0
  373. package/dist/output/text/registry-commands.js +1 -2
  374. package/dist/output/text/registry.js +12 -6
  375. package/dist/output/text/show-directives.js +117 -0
  376. package/dist/output/text/show-format.js +103 -0
  377. package/dist/output/text/sync.js +5 -0
  378. package/dist/output/text/workflow-format.js +332 -0
  379. package/dist/output/text/workflow.js +1 -2
  380. package/dist/output/text.js +10 -19
  381. package/dist/registry/factory.js +4 -6
  382. package/dist/registry/origin-resolve.js +16 -27
  383. package/dist/registry/providers/skills-sh.js +3 -3
  384. package/dist/registry/providers/static-index.js +15 -25
  385. package/dist/registry/resolve.js +43 -94
  386. package/dist/registry/semver.js +43 -0
  387. package/dist/runtime.js +81 -12
  388. package/dist/scripts/akm-migrate.js +35529 -0
  389. package/dist/setup/detect.js +5 -7
  390. package/dist/setup/detected-engines.js +136 -0
  391. package/dist/setup/engine-config.js +100 -0
  392. package/dist/setup/registry-stash-loader.js +3 -3
  393. package/dist/setup/semantic-assets.js +12 -9
  394. package/dist/setup/setup.js +444 -208
  395. package/dist/setup/steps/connection-shared.js +120 -0
  396. package/dist/setup/steps/connection.js +108 -305
  397. package/dist/setup/steps/platforms.js +13 -12
  398. package/dist/setup/steps/semantic.js +15 -3
  399. package/dist/setup/steps/sources.js +21 -15
  400. package/dist/setup/steps/stashdir.js +6 -4
  401. package/dist/setup/steps/tasks.js +236 -119
  402. package/dist/setup/steps.js +3 -2
  403. package/dist/sources/freshness.js +39 -0
  404. package/dist/sources/provider-factory.js +11 -17
  405. package/dist/sources/providers/filesystem.js +2 -3
  406. package/dist/sources/providers/git-install.js +278 -34
  407. package/dist/sources/providers/git-provider.js +54 -56
  408. package/dist/sources/providers/git-stash.js +420 -91
  409. package/dist/sources/providers/git.js +2 -2
  410. package/dist/sources/providers/npm.js +16 -19
  411. package/dist/sources/providers/provider-utils.js +47 -22
  412. package/dist/sources/providers/sync-from-ref.js +3 -9
  413. package/dist/sources/providers/website.js +2 -2
  414. package/dist/sources/resolve.js +11 -10
  415. package/dist/sources/snapshot-fetchers/types.js +4 -0
  416. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
  417. package/dist/storage/database.js +60 -4
  418. package/dist/storage/engines/sqlite-migrations.js +156 -5
  419. package/dist/storage/locations.js +1 -2
  420. package/dist/storage/repositories/canaries-repository.js +1 -1
  421. package/dist/storage/repositories/events-repository.js +51 -11
  422. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  423. package/dist/storage/repositories/index-connection.js +79 -0
  424. package/dist/storage/repositories/index-db.js +4 -3
  425. package/dist/storage/repositories/index-entries-repository.js +863 -0
  426. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  427. package/dist/storage/repositories/index-entry-types.js +4 -0
  428. package/dist/storage/repositories/index-fts-repository.js +167 -0
  429. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  430. package/dist/storage/repositories/index-meta-repository.js +49 -0
  431. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  432. package/dist/storage/repositories/index-sql.js +12 -0
  433. package/dist/storage/repositories/index-utility-repository.js +356 -0
  434. package/dist/storage/repositories/index-vec-repository.js +250 -0
  435. package/dist/storage/repositories/outcome-repository.js +119 -0
  436. package/dist/storage/repositories/proposals-repository.js +317 -75
  437. package/dist/storage/repositories/registry-cache.js +1 -1
  438. package/dist/storage/repositories/salience-repository.js +172 -0
  439. package/dist/storage/repositories/task-history-repository.js +110 -3
  440. package/dist/storage/repositories/workflow-runs-repository.js +68 -35
  441. package/dist/tasks/backends/cron.js +169 -46
  442. package/dist/tasks/backends/exec-utils.js +76 -3
  443. package/dist/tasks/backends/index.js +6 -9
  444. package/dist/tasks/backends/launchd.js +292 -55
  445. package/dist/tasks/backends/schtasks.js +557 -70
  446. package/dist/tasks/backends/types.js +4 -0
  447. package/dist/tasks/command-executable.js +93 -0
  448. package/dist/tasks/embedded.js +56 -38
  449. package/dist/tasks/parser.js +156 -64
  450. package/dist/tasks/resolve-akm-bin.js +144 -51
  451. package/dist/tasks/runner.js +377 -209
  452. package/dist/tasks/schedule.js +108 -19
  453. package/dist/tasks/scheduler-invocation.js +296 -0
  454. package/dist/tasks/schema.js +1 -1
  455. package/dist/tasks/task-id.js +35 -0
  456. package/dist/tasks/validator.js +30 -16
  457. package/dist/workflows/authoring/authoring.js +96 -148
  458. package/dist/workflows/authoring/scope-key.js +1 -1
  459. package/dist/workflows/cli.js +0 -20
  460. package/dist/workflows/concurrency-policy.js +15 -0
  461. package/dist/workflows/exec/brief.js +25 -59
  462. package/dist/workflows/exec/frozen-judge.js +47 -0
  463. package/dist/workflows/exec/native-executor.js +157 -94
  464. package/dist/workflows/exec/report.js +365 -200
  465. package/dist/workflows/exec/run-workflow.js +46 -40
  466. package/dist/workflows/exec/scheduler.js +12 -41
  467. package/dist/workflows/exec/step-work.js +239 -205
  468. package/dist/workflows/exec/workflow-engine-gate.js +67 -0
  469. package/dist/workflows/ir/compile.js +141 -283
  470. package/dist/workflows/ir/freeze.js +233 -0
  471. package/dist/workflows/ir/plan-hash.js +40 -5
  472. package/dist/workflows/ir/schema.js +537 -1
  473. package/dist/workflows/parser.js +878 -306
  474. package/dist/workflows/program/expressions.js +20 -208
  475. package/dist/workflows/program/schema.js +7 -10
  476. package/dist/workflows/renderer.js +99 -121
  477. package/dist/workflows/resource-limits.js +22 -0
  478. package/dist/workflows/runtime/checkin.js +1 -1
  479. package/dist/workflows/runtime/plan-classifier.js +131 -0
  480. package/dist/workflows/runtime/runs.js +200 -113
  481. package/dist/workflows/runtime/unit-checkin.js +1 -1
  482. package/dist/workflows/runtime/unit-phases.js +20 -0
  483. package/dist/workflows/runtime/workflow-asset-loader.js +235 -97
  484. package/dist/workflows/schema.js +1 -11
  485. package/dist/workflows/validate-summary.js +4 -26
  486. package/dist/workflows/validator.js +52 -30
  487. package/docs/README.md +42 -78
  488. package/docs/migration/README.md +8 -0
  489. package/docs/migration/release-notes/0.6.0.md +1 -1
  490. package/docs/migration/release-notes/0.7.0.md +9 -8
  491. package/docs/migration/release-notes/0.9.0.md +158 -14
  492. package/docs/migration/v0.7-to-v0.8.md +46 -47
  493. package/docs/migration/v0.8-to-v0.9.md +844 -0
  494. package/docs/reference/README.md +12 -0
  495. package/docs/reference/data-and-telemetry.md +333 -0
  496. package/package.json +21 -17
  497. package/schemas/akm-asset-envelope.json +93 -0
  498. package/schemas/akm-config.json +4636 -0
  499. package/schemas/akm-task.json +87 -0
  500. package/{dist/schemas → schemas}/akm-workflow.json +127 -82
  501. package/dist/akm-migrate-storage +0 -38
  502. package/dist/assets/help/help-accept.md +0 -12
  503. package/dist/assets/help/help-improve.md +0 -84
  504. package/dist/assets/help/help-proposals.md +0 -17
  505. package/dist/assets/help/help-propose.md +0 -17
  506. package/dist/assets/help/help-reject.md +0 -11
  507. package/dist/assets/profiles/frequent.json +0 -13
  508. package/dist/assets/profiles/recombine-only.json +0 -21
  509. package/dist/assets/profiles/reflect-distill.json +0 -30
  510. package/dist/assets/profiles/synthesize.json +0 -15
  511. package/dist/assets/prompts/procedural-system.md +0 -44
  512. package/dist/assets/prompts/recombine-system.md +0 -40
  513. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  514. package/dist/assets/tasks/core/backup.yml +0 -4
  515. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  516. package/dist/assets/templates/html/default.html +0 -78
  517. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  518. package/dist/assets/wiki/index-template.md +0 -12
  519. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  520. package/dist/assets/wiki/log-template.md +0 -8
  521. package/dist/assets/wiki/schema-template.md +0 -61
  522. package/dist/cli/config-migrate.js +0 -150
  523. package/dist/cli/config-validate.js +0 -39
  524. package/dist/commands/graph/graph-cli.js +0 -124
  525. package/dist/commands/graph/graph.js +0 -487
  526. package/dist/commands/improve/calibration.js +0 -161
  527. package/dist/commands/improve/dedup.js +0 -482
  528. package/dist/commands/improve/extract-watch.js +0 -140
  529. package/dist/commands/improve/hot-probation.js +0 -45
  530. package/dist/commands/improve/improve-auto-accept.js +0 -276
  531. package/dist/commands/improve/improve-profiles.js +0 -168
  532. package/dist/commands/improve/procedural.js +0 -398
  533. package/dist/commands/improve/recombine.js +0 -818
  534. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  535. package/dist/commands/lint/agent-linter.js +0 -44
  536. package/dist/commands/lint/command-linter.js +0 -44
  537. package/dist/commands/lint/default-linter.js +0 -16
  538. package/dist/commands/lint/fact-linter.js +0 -39
  539. package/dist/commands/lint/knowledge-linter.js +0 -16
  540. package/dist/commands/lint/memory-linter.js +0 -61
  541. package/dist/commands/lint/registry.js +0 -41
  542. package/dist/commands/lint/skill-linter.js +0 -45
  543. package/dist/commands/lint/task-linter.js +0 -50
  544. package/dist/commands/lint/workflow-linter.js +0 -81
  545. package/dist/commands/proposal/legacy-import.js +0 -115
  546. package/dist/commands/sources/history.js +0 -196
  547. package/dist/commands/tasks/default-tasks.js +0 -186
  548. package/dist/commands/wiki-cli.js +0 -292
  549. package/dist/core/asset/asset-registry.js +0 -76
  550. package/dist/core/asset/asset-spec.js +0 -316
  551. package/dist/core/config/config-migration.js +0 -602
  552. package/dist/core/deep-merge.js +0 -38
  553. package/dist/core/eval/rank-metrics.js +0 -113
  554. package/dist/core/ripgrep/install.js +0 -163
  555. package/dist/core/ripgrep/resolve.js +0 -81
  556. package/dist/indexer/db/db.js +0 -1414
  557. package/dist/indexer/manifest.js +0 -170
  558. package/dist/indexer/passes/metadata-contributors.js +0 -31
  559. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  560. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
  561. package/dist/llm/call-ai.js +0 -62
  562. package/dist/llm/memory-infer-impl.js +0 -138
  563. package/dist/output/shapes/distill.js +0 -14
  564. package/dist/output/shapes/history.js +0 -11
  565. package/dist/output/text/distill.js +0 -6
  566. package/dist/output/text/enable-disable.js +0 -8
  567. package/dist/output/text/history.js +0 -6
  568. package/dist/output/text/wiki.js +0 -16
  569. package/dist/registry/build-index.js +0 -386
  570. package/dist/schemas/akm-config.json +0 -14225
  571. package/dist/scripts/migrate-storage.js +0 -13169
  572. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -10169
  573. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  574. package/dist/setup/legacy-config.js +0 -106
  575. package/dist/storage/repositories/consolidation-repository.js +0 -38
  576. package/dist/storage/repositories/recombine-repository.js +0 -213
  577. package/dist/wiki/wiki-templates.js +0 -15
  578. package/dist/wiki/wiki.js +0 -1012
  579. package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
  580. package/dist/workflows/db.js +0 -350
  581. package/dist/workflows/exec/watch.js +0 -116
  582. package/dist/workflows/program/parser.js +0 -760
  583. package/dist/workflows/program/project.js +0 -105
  584. package/docs/data-and-telemetry.md +0 -227
  585. package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
  586. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  587. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -7,7 +7,7 @@
7
7
  * Calls the configured `/embeddings` endpoint and L2-normalizes the returned
8
8
  * vectors so the scoring pipeline's L2-to-cosine conversion is correct.
9
9
  */
10
- import { fetchWithTimeout, isHttpUrl } from "../../core/common.js";
10
+ import { fetchWithTimeout, isHttpUrl, readBodyWithByteCap } from "../../core/common.js";
11
11
  import { resolveSecret } from "../../core/config/config.js";
12
12
  const DEFAULT_REMOTE_BATCH_SIZE = 100;
13
13
  /** Cheap token estimator: 4 chars ≈ 1 token. Used in verbose logging and error messages. */
@@ -39,17 +39,24 @@ export class RemoteEmbedder {
39
39
  if (ollamaOpts) {
40
40
  body.options = ollamaOpts;
41
41
  }
42
+ // `signal` MUST go through fetchWithTimeout's dedicated 4th parameter, not
43
+ // the RequestInit: fetchWithTimeout replaces `opts.signal` with its own
44
+ // controller (`{ ...opts, signal: controller.signal }`), so a signal passed
45
+ // inside `opts` is silently dropped and caller cancellation never fires.
42
46
  const response = await fetchWithTimeout(normalizeEmbeddingEndpoint(this.endpoint), {
43
47
  method: "POST",
44
48
  headers,
45
49
  body: JSON.stringify(body),
46
- signal,
47
- });
50
+ }, 30_000, signal);
48
51
  if (!response.ok) {
49
- const errBody = await response.text().catch(() => "");
52
+ const errBody = await readBodyWithByteCap(response, undefined, { bodyTimeoutMs: 30_000, signal }).catch((err) => {
53
+ if (signal?.aborted)
54
+ throw err;
55
+ return "";
56
+ });
50
57
  throw new Error(`Embedding request failed (${response.status}): ${errBody}`);
51
58
  }
52
- const json = (await response.json());
59
+ const json = JSON.parse(await readBodyWithByteCap(response, undefined, { bodyTimeoutMs: 30_000, signal }));
53
60
  if (!json.data?.[0]?.embedding) {
54
61
  throw new Error(`Unexpected embedding response format: missing data[0].embedding.${embeddingEndpointPathHint(this.endpoint)}`);
55
62
  }
@@ -74,17 +81,22 @@ export class RemoteEmbedder {
74
81
  if (ollamaOpts) {
75
82
  body.options = ollamaOpts;
76
83
  }
84
+ // See embed(): `signal` goes through the 4th parameter, not the
85
+ // RequestInit, or fetchWithTimeout drops it.
77
86
  const response = await fetchWithTimeout(normalizeEmbeddingEndpoint(this.endpoint), {
78
87
  method: "POST",
79
88
  headers,
80
89
  body: JSON.stringify(body),
81
- signal,
82
- });
90
+ }, 30_000, signal);
83
91
  if (!response.ok) {
84
- const respBody = await response.text().catch(() => "");
92
+ const respBody = await readBodyWithByteCap(response, undefined, { bodyTimeoutMs: 30_000, signal }).catch((err) => {
93
+ if (signal?.aborted)
94
+ throw err;
95
+ return "";
96
+ });
85
97
  throw new Error(`Embedding batch request failed (${response.status}): ${respBody}`);
86
98
  }
87
- const json = (await response.json());
99
+ const json = JSON.parse(await readBodyWithByteCap(response, undefined, { bodyTimeoutMs: 30_000, signal }));
88
100
  if (!json.data || json.data.length !== batch.length) {
89
101
  throw new Error(`Unexpected embedding batch response: expected ${batch.length} embeddings, got ${json.data?.length ?? 0}.${embeddingEndpointPathHint(this.endpoint)}`);
90
102
  }
@@ -3,54 +3,33 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
5
  * For each feature key, return the effective enabled state by reading the
6
- * new 0.8.0 config shape. Defaults match the legacy `LlmFeatureFlags` docstrings.
6
+ * 0.9.0 config shape.
7
7
  */
8
- // Defaults below mirror the legacy LlmFeatureFlags docstrings so existing
9
- // behaviour is preserved when a config is silent on a flag.
10
8
  const FEATURE_LOCATION = {
11
- // Legacy default: false → memory_consolidation only runs when explicitly enabled
12
- // (either via the user's improve profile or the built-in `default` profile).
13
- memory_consolidation: (cfg) => cfg.profiles?.improve?.default?.processes?.consolidate?.enabled ?? false,
14
- // 0.8.0 unified gate: replaces the legacy `feedback_distillation` key.
15
- // The orchestration gate (planner) and the LLM-call gate now share the same
16
- // source of truth: `processes.distill.enabled`. Default: true (matches the
17
- // built-in `default` profile).
18
- distill: (cfg) => cfg.profiles?.improve?.default?.processes?.distill?.enabled ?? true,
19
- // Legacy default: true
20
- memory_inference: (cfg) => cfg.profiles?.improve?.default?.processes?.memoryInference?.enabled ?? true,
21
- // Legacy default: true
22
- graph_extraction: (cfg) => cfg.profiles?.improve?.default?.processes?.graphExtraction?.enabled ?? true,
23
- // Legacy default: false
9
+ memory_inference: (cfg) => cfg.index?.memory?.enabled ?? true,
10
+ graph_extraction: (cfg) => cfg.index?.graph?.enabled ?? true,
24
11
  metadata_enhance: (cfg) => cfg.index?.metadataEnhance?.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,
32
- // Legacy default: false
33
- proposal_quality_gate: (cfg) => cfg.profiles?.improve?.default?.processes?.reflect?.qualityGate?.enabled ?? false,
34
- // Legacy default: false
35
- memory_contradiction_detection: (cfg) => cfg.profiles?.improve?.default?.processes?.consolidate?.contradictionDetection?.enabled ?? false,
36
12
  // Always on at the LLM-wrapper level. Enablement is decided ONCE at the
37
13
  // extract entry point (`akmExtract`): the `extract.enabled` process toggle
38
- // gates extract as a STAGE of `akm improve` (the active improve profile, per
14
+ // gates extract as a STAGE of `akm improve` (the active improve strategy, per
39
15
  // #593/#594), while an explicit `akm extract` command always runs. Gating the
40
16
  // inner LLM calls on `default.processes.extract.enabled` here was a footgun —
41
- // dropping extract from the daily improve profile silently disabled the
17
+ // dropping extract from the daily improve strategy silently disabled the
42
18
  // standalone `akm extract` command. (cfg unused — kept for resolver signature.)
43
19
  session_extraction: (_cfg) => true,
44
20
  };
45
21
  /**
46
22
  * Pure predicate: is the named feature gate enabled in `config`?
47
23
  *
48
- * Reads from the unified 0.8.0 config shape. Defaults follow the legacy
49
- * `LlmFeatureFlags` docstring defaults.
24
+ * Reads from the unified 0.9.0 config shape.
50
25
  */
51
- export function isLlmFeatureEnabled(config, feature) {
26
+ export function isLlmFeatureEnabled(config, feature, improveEnabled) {
52
27
  if (!config)
53
28
  return false;
29
+ // Improve resolves enablement from its selected strategy and passes the
30
+ // decision in. This module does not own a second improve config lookup.
31
+ if (improveEnabled !== undefined)
32
+ return improveEnabled;
54
33
  const resolver = FEATURE_LOCATION[feature];
55
34
  if (!resolver)
56
35
  return false;
@@ -67,13 +46,13 @@ const DEFAULT_TIMEOUT_MS = 600_000;
67
46
  */
68
47
  export async function tryLlmFeature(feature, config, fn, fallback, opts) {
69
48
  const resolveFallback = async () => typeof fallback === "function" ? await fallback() : fallback;
70
- if (!isLlmFeatureEnabled(config, feature)) {
49
+ if (!isLlmFeatureEnabled(config, feature, opts?.enabled)) {
71
50
  opts?.onFallback?.({ feature, reason: "disabled" });
72
51
  return resolveFallback();
73
52
  }
74
- const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
53
+ const timeoutMs = opts && Object.hasOwn(opts, "timeoutMs") ? (opts.timeoutMs ?? null) : DEFAULT_TIMEOUT_MS;
75
54
  try {
76
- if (timeoutMs <= 0) {
55
+ if (timeoutMs === null || timeoutMs <= 0) {
77
56
  return await fn();
78
57
  }
79
58
  return await runWithTimeout(fn, timeoutMs, feature);
@@ -86,17 +65,15 @@ export async function tryLlmFeature(feature, config, fn, fallback, opts) {
86
65
  }
87
66
  }
88
67
  /**
89
- * Section-agnostic process gate. After the 0.8.0 migration, the canonical
90
- * accessor is the `FEATURE_LOCATION` map above; this helper exists so older
91
- * call sites that knew the (section, processName) pair don't all need to
92
- * relearn the new mapping.
68
+ * Section-agnostic process gate that maps process identifiers to their current
69
+ * config locations.
93
70
  *
94
71
  * For unknown (section, processName) pairs the result is `false`.
95
72
  */
96
73
  export function isProcessEnabled(section, processName, config) {
97
74
  if (!config)
98
75
  return false;
99
- // index.metadataEnhance is a first-class new-shape entry.
76
+ // Index passes are first-class 0.9 entries.
100
77
  if (section === "index") {
101
78
  if (processName === "metadata_enhance" || processName === "metadataEnhance") {
102
79
  return config.index?.metadataEnhance?.enabled ?? true;
@@ -108,23 +85,6 @@ export function isProcessEnabled(section, processName, config) {
108
85
  return isLlmFeatureEnabled(config, "graph_extraction");
109
86
  }
110
87
  }
111
- if (section === "improve") {
112
- const processes = config.profiles?.improve?.default?.processes;
113
- const entry = processes?.[processName];
114
- if (entry && typeof entry.enabled === "boolean")
115
- return entry.enabled;
116
- // Fallback to default-enabled state for known processes.
117
- switch (processName) {
118
- case "reflect":
119
- case "distill":
120
- case "consolidate":
121
- case "memoryInference":
122
- case "graphExtraction":
123
- return true;
124
- default:
125
- return false;
126
- }
127
- }
128
88
  return false;
129
89
  }
130
90
  /** Specific error class so call sites and the wrapper can tell timeouts apart from generic throws. */
@@ -7,7 +7,7 @@
7
7
  * Given a single asset body (typically a `memory:` or `knowledge:` file),
8
8
  * asks the configured LLM to surface the entities mentioned in it and the
9
9
  * relations between them. The pass itself
10
- * (`src/indexer/graph-extraction.ts`) is responsible for deciding which
10
+ * (`src/indexer/graph/graph-extraction.ts`) is responsible for deciding which
11
11
  * files to extract, persisting the resulting nodes/edges to the index DB,
12
12
  * and feeding the graph data into the FTS5+boosts
13
13
  * search pipeline as a single boost component.
@@ -15,16 +15,15 @@
15
15
  * This module is intentionally tiny and stateless so tests can stub it via
16
16
  * `mock.module("../src/llm/graph-extract", ...)` without hitting a network.
17
17
  *
18
- * Locked v1 contract (#208): the LLM connection always comes from the
19
- * shared `akm.llm` block — never from a per-pass override. Callers obtain
20
- * the connection via `resolveIndexPassLLM("graph", config)` and pass it
21
- * straight through.
18
+ * The LLM connection comes from the selected named engine. Callers obtain it
19
+ * via `resolveIndexPassLLM("graph", config)` and pass it straight through.
22
20
  */
23
21
  import systemPromptTemplate from "../assets/prompts/graph-extract-system.md" with { type: "text" };
24
22
  import userPromptTemplate from "../assets/prompts/graph-extract-user-prompt.md" with { type: "text" };
25
23
  import { toErrorMessage } from "../core/common.js";
24
+ import { parseEmbeddedJsonResponse } from "../core/parse.js";
26
25
  import { warn, warnVerbose } from "../core/warn.js";
27
- import { chatCompletion, isContextSizeError, parseEmbeddedJsonResponse } from "./client.js";
26
+ import { chatCompletion, isContextSizeError } from "./client.js";
28
27
  import { tryLlmFeature } from "./feature-gate.js";
29
28
  import { callStructured } from "./structured-call.js";
30
29
  /**
@@ -47,11 +46,6 @@ const SYSTEM_PROMPT = systemPromptTemplate;
47
46
  const USER_PROMPT_PREFIX = userPromptTemplate
48
47
  .replace("{{MAX_ENTITIES}}", String(MAX_ENTITIES_PER_ASSET))
49
48
  .replace("{{MAX_RELATIONS}}", String(MAX_RELATIONS_PER_ASSET));
50
- // `isContextSizeError` is defined in `./client` and re-exported here so the
51
- // graph extractor and the retry classifier (`isRetryable`) share one
52
- // definition (#496). Re-exported (not just imported) to preserve existing
53
- // importers of this module — including its unit test.
54
- export { isContextSizeError } from "./client.js";
55
49
  const GENERIC_ENTITIES = new Set([
56
50
  "agent",
57
51
  "application",
@@ -749,5 +743,10 @@ export async function extractGraphFromBody(llmConfig, body, signal, akmConfig, o
749
743
  onFallback,
750
744
  });
751
745
  }
752
- // deduplicateGraph moved to src/indexer/graph-dedup.ts (pure utility, no LLM calls).
753
- export { deduplicateGraph } from "../indexer/graph/graph-dedup.js";
746
+ // deduplicateGraph lives in src/indexer/graph/graph-dedup.ts (pure utility, no
747
+ // LLM calls) — import it from there directly. The re-export that used to live
748
+ // here created a value edge back to graph-dedup.ts, which (via its type-only
749
+ // import of GraphExtraction/GraphRelation below) formed a 2-file import cycle
750
+ // (chunk 9 WI-9.8 KILL 4 sever). No src or test consumer used this re-export
751
+ // (graph-extraction.ts and the test suite already import graph-dedup.ts
752
+ // directly), so it is deleted outright rather than repointed.
@@ -1,50 +1,16 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { getDefaultLlmConfig, getIndexPassConfig } from "../core/config/config.js";
4
+ import { materializeLlmConnection, resolveLlmEngineUse } from "../integrations/agent/engine-resolution.js";
5
5
  /**
6
- * Map a pass name (as used by callers — "memory", "graph", etc.) to the
7
- * matching key under `profiles.improve.default.processes`. Pass names with
8
- * no improve-profile counterpart return undefined and resolve via the
9
- * default LLM only.
6
+ * Resolve standalone index passes from the index section only. Improve
7
+ * strategies own improve-triggered calls and are intentionally not consulted.
10
8
  */
11
- function improveProcessKeyForPass(passName) {
12
- switch (passName) {
13
- case "memory":
14
- return "memoryInference";
15
- case "graph":
16
- return "graphExtraction";
17
- default:
18
- return undefined;
19
- }
20
- }
21
9
  export function resolveIndexPassLLM(passName, config) {
22
- // Gate 1 — explicit opt-out via the index-config block stays authoritative.
23
- const passConfig = getIndexPassConfig(config.index, passName);
24
- if (passConfig?.llm === false)
10
+ const pass = config.index?.[passName];
11
+ if (pass?.enabled === false)
25
12
  return undefined;
26
- // Gate 2 — per-process profile from the improve profile, when present.
27
- // This is the path that lets
28
- // profiles.improve.default.processes.graphExtraction.profile = "ministral-3b"
29
- // actually take effect on the graph pass instead of being silently
30
- // ignored.
31
- const processKey = improveProcessKeyForPass(passName);
32
- if (processKey) {
33
- const processConfig = config.profiles?.improve?.default?.processes?.[processKey];
34
- // Honor enabled === false here too — an explicit disable wins.
35
- if (processConfig?.enabled === false)
36
- return undefined;
37
- const profileName = processConfig?.profile;
38
- if (profileName) {
39
- const profile = config.profiles?.llm?.[profileName];
40
- if (profile)
41
- return profile;
42
- // A named-but-missing profile is a configuration error in spirit, but
43
- // we fall through to default rather than throwing — callers gracefully
44
- // treat `undefined` as "pass disabled" and emitting a hard throw here
45
- // would take the whole improve run down on a typo.
46
- }
47
- }
48
- // Gate 3 — fall back to the default LLM profile.
49
- return getDefaultLlmConfig(config);
13
+ const defaults = config.index?.defaults;
14
+ const resolved = resolveLlmEngineUse(config, [defaults ?? {}, pass ?? {}], { optional: true });
15
+ return resolved ? materializeLlmConnection(resolved) : undefined;
50
16
  }
@@ -1,4 +1,147 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- export { compressMemoryToDerivedMemory, } from "./memory-infer-impl.js";
4
+ /**
5
+ * LLM helper for the `akm index` memory-inference pass (#201).
6
+ *
7
+ * Compresses a single memory body into one higher-signal derived memory. The
8
+ * pass itself (in `src/indexer/passes/memory-inference.ts`) is responsible for
9
+ * deciding which memories are pending, persisting the derived memory with the
10
+ * correct frontmatter (`inferred: true`, `source: <parent-ref>`), and marking
11
+ * the parent as processed for idempotency.
12
+ *
13
+ * This module is intentionally tiny and stateless so tests can stub it via
14
+ * `mock.module("../src/llm/memory-infer", ...)` without hitting a network.
15
+ *
16
+ * The LLM connection comes from the selected named engine. Callers obtain it
17
+ * via `resolveIndexPassLLM("memory", config)` and pass it straight through.
18
+ */
19
+ import memoryInferSystemPrompt from "../assets/prompts/memory-infer-system.md" with { type: "text" };
20
+ import memoryInferUserPrompt from "../assets/prompts/memory-infer-user.md" with { type: "text" };
21
+ import { toErrorMessage } from "../core/common.js";
22
+ import { parseEmbeddedJsonResponse } from "../core/parse.js";
23
+ import { warn } from "../core/warn.js";
24
+ import { callStructured } from "./structured-call.js";
25
+ /** Hard cap on body chars sent to the model — pragmatic and matches `runLlmEnrich`. */
26
+ const MAX_BODY_CHARS = 4000;
27
+ const SYSTEM_PROMPT = memoryInferSystemPrompt;
28
+ const USER_PROMPT_PREFIX = memoryInferUserPrompt;
29
+ const PROMPT_PLACEHOLDERS = new Set([
30
+ "short title string",
31
+ "one sentence summary string",
32
+ "tag1",
33
+ "tag2",
34
+ "search phrase 1",
35
+ "search phrase 2",
36
+ "2-3 sentence compressed body preserving key facts verbatim",
37
+ ]);
38
+ /**
39
+ * Strict JSON Schema for the derived-memory payload. Sent to providers that
40
+ * opt in via `ChatCompletionConfig.supportsJsonSchema = true`; the client
41
+ * silently drops the schema for providers that don't.
42
+ *
43
+ * Extends the responseSchema lift (PR 1, asset-writers-investigation §5) to
44
+ * the memory-inference path. Mirrors the validation gate below
45
+ * (title/description/content + non-empty tags/searchHints) so a
46
+ * schema-compliant response is guaranteed to pass the downstream check
47
+ * — no more "incomplete derived memory payload from LLM; skipping memory"
48
+ * for shape-only failures.
49
+ */
50
+ const DERIVED_MEMORY_JSON_SCHEMA = {
51
+ type: "object",
52
+ properties: {
53
+ title: { type: "string", minLength: 1 },
54
+ description: { type: "string", minLength: 1 },
55
+ content: { type: "string", minLength: 1 },
56
+ tags: { type: "array", items: { type: "string" }, minItems: 1, maxItems: 8 },
57
+ searchHints: { type: "array", items: { type: "string" }, minItems: 1, maxItems: 6 },
58
+ },
59
+ required: ["title", "description", "content", "tags", "searchHints"],
60
+ additionalProperties: false,
61
+ };
62
+ /**
63
+ * Compress a single memory body into one derived memory via the configured LLM.
64
+ *
65
+ * Returns `undefined` on any failure (timeout, invalid JSON, empty response).
66
+ * Errors are logged via `warn()` but never thrown — a failed split for one memory
67
+ * must not abort the rest of the index pass.
68
+ *
69
+ * Routes through `callStructured({ feature: "memory_inference", ... })` so the
70
+ * feature gate, error classification, and onFallback hook are honoured uniformly
71
+ * (Fix C5).
72
+ */
73
+ export async function compressMemoryToDerivedMemory(llmConfig, body, signal, akmConfig, onFallback, telemetry, onRetryAttempt) {
74
+ const trimmedBody = body.trim();
75
+ if (!trimmedBody)
76
+ return undefined;
77
+ const userPrompt = `${USER_PROMPT_PREFIX}${trimmedBody.slice(0, MAX_BODY_CHARS)}`;
78
+ // Memory inference is always gated: no config closes the gate instead of
79
+ // taking callStructured's ungated path for direct callers.
80
+ if (!akmConfig) {
81
+ onFallback?.({ feature: "memory_inference", reason: "disabled" });
82
+ return undefined;
83
+ }
84
+ return callStructured({
85
+ feature: "memory_inference",
86
+ akmConfig,
87
+ config: llmConfig,
88
+ messages: [
89
+ { role: "system", content: SYSTEM_PROMPT },
90
+ { role: "user", content: userPrompt },
91
+ ],
92
+ request: {
93
+ temperature: 0.1,
94
+ timeoutMs: llmConfig.timeoutMs,
95
+ signal,
96
+ responseSchema: DERIVED_MEMORY_JSON_SCHEMA,
97
+ onRetryAttempt,
98
+ },
99
+ parse: (raw) => {
100
+ if (!raw)
101
+ return undefined;
102
+ const parsed = parseEmbeddedJsonResponse(raw);
103
+ if (!parsed) {
104
+ warn("memory inference: invalid JSON response from LLM; skipping memory.");
105
+ return undefined;
106
+ }
107
+ const title = typeof parsed.title === "string" ? parsed.title.trim() : "";
108
+ const description = typeof parsed.description === "string" ? parsed.description.trim() : "";
109
+ const content = typeof parsed.content === "string" ? parsed.content.trim() : "";
110
+ const tags = Array.isArray(parsed.tags)
111
+ ? parsed.tags
112
+ .filter((t) => typeof t === "string")
113
+ .map((t) => t.trim())
114
+ .filter(Boolean)
115
+ .slice(0, 8)
116
+ : [];
117
+ const searchHints = Array.isArray(parsed.searchHints)
118
+ ? parsed.searchHints
119
+ .filter((h) => typeof h === "string")
120
+ .map((h) => h.trim())
121
+ .filter(Boolean)
122
+ .slice(0, 6)
123
+ : [];
124
+ if (!title || !description || !content || tags.length === 0 || searchHints.length === 0) {
125
+ warn("memory inference: incomplete derived memory payload from LLM; skipping memory.");
126
+ return undefined;
127
+ }
128
+ if ([title, description, content, ...tags, ...searchHints].some((value) => PROMPT_PLACEHOLDERS.has(value.toLowerCase()))) {
129
+ warn("memory inference: prompt placeholder response from LLM; skipping memory.");
130
+ return undefined;
131
+ }
132
+ return { title, description, tags, searchHints, content };
133
+ },
134
+ onError: (cls, err) => {
135
+ if (cls === "html") {
136
+ if (telemetry)
137
+ telemetry.htmlErrorCount = (telemetry.htmlErrorCount ?? 0) + 1;
138
+ warn(`memory inference: provider returned HTML instead of JSON; skipping memory: ${toErrorMessage(err)}`);
139
+ return undefined;
140
+ }
141
+ warn(`memory inference failed: ${toErrorMessage(err)}`);
142
+ return undefined;
143
+ },
144
+ fallback: undefined,
145
+ onFallback,
146
+ });
147
+ }
@@ -4,12 +4,11 @@
4
4
  /**
5
5
  * LLM-driven metadata enhancement for stash entries.
6
6
  *
7
- * Split out of `llm.ts` so the higher-level workflow (prompting the LLM to
8
- * improve descriptions/tags/searchHints) lives separately from the low-level
9
- * transport client in `client.ts`.
7
+ * Keeps the higher-level workflow for improving descriptions, tags, and search
8
+ * hints separate from the low-level transport client.
10
9
  */
11
10
  import metadataEnhanceSystemPrompt from "../assets/prompts/metadata-enhance-system.md" with { type: "text" };
12
- import { parseJsonResponse } from "./client.js";
11
+ import { parseJsonResponse } from "../core/parse.js";
13
12
  import { callStructured } from "./structured-call.js";
14
13
  const SYSTEM_PROMPT = metadataEnhanceSystemPrompt;
15
14
  /**
@@ -17,10 +16,11 @@ const SYSTEM_PROMPT = metadataEnhanceSystemPrompt;
17
16
  * generate searchHints, and suggest tags.
18
17
  *
19
18
  * When `akmConfig` is provided, routes through
20
- * `tryLlmFeature("metadata_enhance", ...)` so the feature gate is honoured and
21
- * errors are swallowed to `{}`. When `akmConfig` is `undefined` the gate is
22
- * bypassed entirely — the LLM call runs unconditionally and errors propagate to
23
- * the caller (pre-gate behaviour, used by direct callers such as tests).
19
+ * `tryLlmFeature("metadata_enhance", ...)` so the feature gate is honoured: a
20
+ * closed gate yields `{ status: "skipped" }` and a thrown/timed-out call yields
21
+ * `{ status: "failed" }` — neither is reported as an enrichment. When
22
+ * `akmConfig` is `undefined` the gate is bypassed entirely: the LLM call runs
23
+ * unconditionally and errors propagate to direct callers such as tests.
24
24
  */
25
25
  export async function enhanceMetadata(config, entry, fileContent, signal, akmConfig) {
26
26
  const contextParts = [`Name: ${entry.name}`, `Type: ${entry.type}`];
@@ -41,12 +41,14 @@ Generate improved metadata for this ${entry.type}. Return JSON with these fields
41
41
  - "tags": an array of 3-8 relevant keyword tags
42
42
 
43
43
  Return ONLY the JSON object, no explanation.`;
44
- // `parse` owns the raw response: the `!raw`/unparseable case ⇒ `{}`, plus the
45
- // description/searchHints/tags shaping. `enhanceMetadata` never warns and
46
- // never bumps telemetry, so `onError` (gated path only) just swallows to `{}`
47
- // — identical to the surrounding control flow's pre-migration behaviour. The
48
- // ungated path (akmConfig === undefined) propagates errors via callStructured.
49
- return callStructured({
44
+ // `parse` owns the raw response: the `!raw`/unparseable case ⇒ empty metadata
45
+ // (still a genuine success), plus the description/searchHints/tags shaping.
46
+ // `enhanceMetadata` never warns and never bumps telemetry — `onError` (gated
47
+ // path only) reports `failed` WITHOUT warning, carrying the message so the
48
+ // caller can surface it. The ungated path (akmConfig === undefined) propagates
49
+ // errors via callStructured.
50
+ let timedOut = false;
51
+ const outcome = await callStructured({
50
52
  feature: "metadata_enhance",
51
53
  akmConfig,
52
54
  config,
@@ -57,23 +59,36 @@ Return ONLY the JSON object, no explanation.`;
57
59
  request: { signal, timeoutMs: config.timeoutMs },
58
60
  parse: (raw) => {
59
61
  const parsed = raw ? parseJsonResponse(raw) : undefined;
60
- if (!parsed)
61
- return {};
62
- const result = {};
63
- if (typeof parsed.description === "string" && parsed.description) {
64
- result.description = parsed.description;
62
+ const metadata = {};
63
+ if (parsed) {
64
+ if (typeof parsed.description === "string" && parsed.description) {
65
+ metadata.description = parsed.description;
66
+ }
67
+ if (Array.isArray(parsed.searchHints)) {
68
+ metadata.searchHints = parsed.searchHints
69
+ .filter((s) => typeof s === "string" && s.trim().length > 0)
70
+ .slice(0, 8);
71
+ }
72
+ if (Array.isArray(parsed.tags)) {
73
+ metadata.tags = parsed.tags
74
+ .filter((s) => typeof s === "string" && s.trim().length > 0)
75
+ .slice(0, 10);
76
+ }
65
77
  }
66
- if (Array.isArray(parsed.searchHints)) {
67
- result.searchHints = parsed.searchHints
68
- .filter((s) => typeof s === "string" && s.trim().length > 0)
69
- .slice(0, 8);
70
- }
71
- if (Array.isArray(parsed.tags)) {
72
- result.tags = parsed.tags.filter((s) => typeof s === "string" && s.trim().length > 0).slice(0, 10);
73
- }
74
- return result;
78
+ return { status: "enriched", metadata };
79
+ },
80
+ onError: (_cls, err) => ({ status: "failed", error: err instanceof Error ? err.message : String(err) }),
81
+ fallback: { status: "skipped" },
82
+ // The seam returns the `skipped` fallback for a closed gate AND for a
83
+ // wrapper-level timeout. Record the timeout so we can reclassify it below —
84
+ // a timed-out call is a failure, not a silent skip.
85
+ onFallback: (event) => {
86
+ if (event.reason === "timeout")
87
+ timedOut = true;
75
88
  },
76
- onError: () => ({}),
77
- fallback: {},
78
89
  });
90
+ if (outcome.status === "skipped" && timedOut) {
91
+ return { status: "failed", error: "metadata_enhance timed out" };
92
+ }
93
+ return outcome;
79
94
  }
@@ -1,7 +1,7 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { chatCompletion, isContextSizeError, LlmCallError } from "./client.js";
4
+ import { chatCompletion, isContextSizeError, LlmCallError, } from "./client.js";
5
5
  import { tryLlmFeature } from "./feature-gate.js";
6
6
  /**
7
7
  * Classify a thrown LLM error into one of the three buckets. This is the single
@@ -17,14 +17,21 @@ export function classifyLlmError(err) {
17
17
  return "other";
18
18
  }
19
19
  export async function callStructured(opts) {
20
- const { feature, akmConfig, config, messages, request, parse, onError, fallback, onFallback } = opts;
20
+ const { feature, akmConfig, enabled, config, messages, request, parse, onError, fallback, onFallback } = opts;
21
21
  const chat = request?.chat ?? chatCompletion;
22
+ // Forward each option key ONLY when present on `request` — see the
23
+ // key-presence semantics note on CallStructuredRequest: for `timeoutMs`,
24
+ // present-but-undefined means "explicitly disabled" while absent means
25
+ // "use the default", both in the feature-gate wrapper and the transport.
26
+ const has = (key) => request !== undefined && Object.hasOwn(request, key);
22
27
  const chatOptions = {
23
- temperature: request?.temperature,
24
- timeoutMs: request?.timeoutMs,
25
- signal: request?.signal,
26
- responseSchema: request?.responseSchema,
27
- onRetryAttempt: request?.onRetryAttempt,
28
+ ...(has("temperature") ? { temperature: request?.temperature } : {}),
29
+ ...(has("timeoutMs") ? { timeoutMs: request?.timeoutMs } : {}),
30
+ ...(has("signal") ? { signal: request?.signal } : {}),
31
+ ...(has("responseSchema") ? { responseSchema: request?.responseSchema } : {}),
32
+ ...(has("maxTokens") ? { maxTokens: request?.maxTokens } : {}),
33
+ ...(has("enableThinking") ? { enableThinking: request?.enableThinking } : {}),
34
+ ...(has("onRetryAttempt") ? { onRetryAttempt: request?.onRetryAttempt } : {}),
28
35
  };
29
36
  // UNGATED: run the chat+parse directly. Errors propagate — no `onError`
30
37
  // funnel — matching the pre-gate behaviour of direct callers.
@@ -43,7 +50,8 @@ export async function callStructured(opts) {
43
50
  return onError(classifyLlmError(err), err);
44
51
  }
45
52
  }, fallback, {
46
- timeoutMs: request?.timeoutMs,
53
+ ...(has("timeoutMs") ? { timeoutMs: request?.timeoutMs } : {}),
54
+ ...(enabled !== undefined ? { enabled } : {}),
47
55
  onFallback,
48
56
  });
49
57
  }