akm-cli 0.9.1 → 0.9.2-alpha.2

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 (350) hide show
  1. package/CHANGELOG.md +103 -28
  2. package/README.md +3 -1
  3. package/SECURITY.md +1 -1
  4. package/STABILITY.md +1 -1
  5. package/dist/akm +2 -2
  6. package/dist/akm-migrate +2 -2
  7. package/dist/assets/hints/cli-hints-full.md +14 -9
  8. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
  9. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  10. package/dist/assets/models.json +35 -0
  11. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +3 -4
  12. package/dist/assets/stash-skeleton/facts/conventions/organization.md +1 -3
  13. package/dist/assets/tasks/core/extract.yml +6 -5
  14. package/dist/assets/tasks/core/improve.yml +6 -5
  15. package/dist/assets/tasks/core/index-refresh.yml +6 -5
  16. package/dist/assets/tasks/core/sync.yml +6 -5
  17. package/dist/assets/tasks/core/version-check.yml +6 -5
  18. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
  19. package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
  20. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
  21. package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
  22. package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
  23. package/dist/cli/confirm.js +2 -2
  24. package/dist/cli/parse-args.js +3 -24
  25. package/dist/cli/retired-commands.js +1 -1
  26. package/dist/cli/shared.js +2 -2
  27. package/dist/cli.js +11 -9
  28. package/dist/commands/agent/agent-dispatch.js +55 -89
  29. package/dist/commands/agent/contribute-cli.js +12 -45
  30. package/dist/commands/command/builtin-action.js +32 -0
  31. package/dist/commands/command/command-cli.js +99 -0
  32. package/dist/commands/command/command-execution.js +308 -0
  33. package/dist/commands/command/execution-source-loader.js +176 -0
  34. package/dist/commands/command/portable-template.js +60 -0
  35. package/dist/commands/config-cli.js +10 -4
  36. package/dist/commands/env/env.js +4 -2
  37. package/dist/commands/feedback-cli.js +1 -1
  38. package/dist/commands/health/checks.js +241 -29
  39. package/dist/commands/health/html-report.js +0 -14
  40. package/dist/commands/health/report-view-model.js +0 -1
  41. package/dist/commands/health/surfaces.js +6 -7
  42. package/dist/commands/health/types.js +0 -2
  43. package/dist/commands/health.js +63 -18
  44. package/dist/commands/improve/collapse-detector.js +5 -6
  45. package/dist/commands/improve/consolidate.js +251 -214
  46. package/dist/commands/improve/distill/promote-memory.js +71 -34
  47. package/dist/commands/improve/distill/quality-gate.js +17 -5
  48. package/dist/commands/improve/distill.js +232 -155
  49. package/dist/commands/improve/eligibility.js +112 -79
  50. package/dist/commands/improve/execution.js +57 -0
  51. package/dist/commands/improve/extract-cli.js +5 -5
  52. package/dist/commands/improve/extract-prompt.js +64 -22
  53. package/dist/commands/improve/extract.js +608 -360
  54. package/dist/commands/improve/improve-strategies.js +43 -14
  55. package/dist/commands/improve/improve.js +249 -29
  56. package/dist/commands/improve/loop-stages.js +11 -17
  57. package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
  58. package/dist/commands/improve/outcome-loop.js +22 -38
  59. package/dist/commands/improve/planner.js +134 -0
  60. package/dist/commands/improve/preparation.js +730 -409
  61. package/dist/commands/improve/reflect.js +386 -223
  62. package/dist/commands/improve/run-context.js +3 -4
  63. package/dist/commands/improve/salience.js +6 -58
  64. package/dist/commands/improve/session-asset.js +12 -12
  65. package/dist/commands/lint/index.js +101 -29
  66. package/dist/commands/migrate-cli.js +11 -69
  67. package/dist/commands/migration-tool.js +6 -9
  68. package/dist/commands/models-cli.js +27 -0
  69. package/dist/commands/proposal/drain.js +258 -186
  70. package/dist/commands/proposal/proposal-cli.js +32 -10
  71. package/dist/commands/proposal/proposal.js +2 -5
  72. package/dist/commands/proposal/propose.js +192 -172
  73. package/dist/commands/proposal/repository.js +54 -91
  74. package/dist/commands/proposal/validators/proposal-validators.js +9 -7
  75. package/dist/commands/read/curate.js +53 -22
  76. package/dist/commands/read/registry-search.js +25 -9
  77. package/dist/commands/read/remember-cli.js +14 -2
  78. package/dist/commands/read/search.js +10 -4
  79. package/dist/commands/read/show.js +139 -153
  80. package/dist/commands/registry-cli.js +16 -7
  81. package/dist/commands/remember.js +33 -18
  82. package/dist/commands/sources/add-cli.js +19 -178
  83. package/dist/commands/sources/bundle-cli.js +15 -3
  84. package/dist/commands/sources/dangerous-env-audit.js +135 -0
  85. package/dist/commands/sources/info.js +2 -1
  86. package/dist/commands/sources/installed-stashes.js +901 -177
  87. package/dist/commands/sources/schema-repair.js +174 -95
  88. package/dist/commands/sources/self-update.js +30 -74
  89. package/dist/commands/sources/source-add.js +3 -5
  90. package/dist/commands/sources/sources-cli.js +2 -15
  91. package/dist/commands/sources/update-transaction.js +220 -0
  92. package/dist/commands/tasks/tasks-cli.js +3 -3
  93. package/dist/commands/tasks/tasks.js +736 -317
  94. package/dist/commands/workflow-cli.js +2 -2
  95. package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
  96. package/dist/core/adapter/adapters/akm-adapter.js +85 -35
  97. package/dist/core/adapter/adapters/akm-lint.js +54 -39
  98. package/dist/core/adapter/adapters/akm-metadata.js +45 -45
  99. package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
  100. package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
  101. package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
  102. package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
  103. package/dist/core/adapter/adapters/index.js +0 -9
  104. package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
  105. package/dist/core/adapter/adapters/okf-adapter.js +4 -0
  106. package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
  107. package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
  108. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
  109. package/dist/core/adapter/execution-source.js +308 -0
  110. package/dist/core/adapter/recognize-match.js +36 -13
  111. package/dist/core/adapter/registry.js +0 -9
  112. package/dist/core/asset/stash-meta.js +94 -4
  113. package/dist/core/common.js +6 -11
  114. package/dist/core/config/config-io.js +3 -3
  115. package/dist/core/config/config-schema.js +18 -40
  116. package/dist/core/config/config-sources.js +11 -21
  117. package/dist/core/config/config-walker.js +31 -13
  118. package/dist/core/config/config.js +23 -26
  119. package/dist/core/config/schema/engines.js +8 -7
  120. package/dist/core/config/schema/improve-processes.js +29 -5
  121. package/dist/core/config/schema/index-config.js +0 -27
  122. package/dist/core/config/schema/primitives.js +1 -23
  123. package/dist/core/config/schema/sources-bundles.js +13 -16
  124. package/dist/core/errors.js +2 -0
  125. package/dist/core/events.js +68 -32
  126. package/dist/core/extra-params.js +1 -0
  127. package/dist/core/improve-result.js +315 -0
  128. package/dist/core/lesson-lint.js +0 -6
  129. package/dist/core/maintenance-barrier.js +4 -4
  130. package/dist/core/network-policy.js +152 -0
  131. package/dist/core/paths.js +1 -1
  132. package/dist/core/recognition-util.js +4 -4
  133. package/dist/core/registry-url.js +456 -0
  134. package/dist/core/state/migrations.js +161 -47
  135. package/dist/core/state-db.js +453 -80
  136. package/dist/core/system-error.js +32 -0
  137. package/dist/core/time.js +2 -12
  138. package/dist/core/write-source.js +0 -18
  139. package/dist/execution/directory-identity.js +52 -0
  140. package/dist/execution/executable-identity.js +107 -0
  141. package/dist/execution/guarded-source.js +398 -0
  142. package/dist/execution/json.js +95 -0
  143. package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
  144. package/dist/execution/record.js +55 -0
  145. package/dist/execution/resolved-request.js +730 -0
  146. package/dist/execution/source.js +320 -0
  147. package/dist/indexer/bundle-identity-guard.js +5 -4
  148. package/dist/indexer/db/graph-db.js +33 -0
  149. package/dist/indexer/graph/graph-boost.js +3 -4
  150. package/dist/indexer/graph/graph-extraction.js +562 -373
  151. package/dist/indexer/index-written-assets.js +78 -39
  152. package/dist/indexer/indexer.js +471 -432
  153. package/dist/indexer/installations.js +6 -0
  154. package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
  155. package/dist/indexer/materialize-embeddings.js +155 -0
  156. package/dist/indexer/passes/memory-inference.js +227 -174
  157. package/dist/indexer/passes/metadata.js +263 -118
  158. package/dist/indexer/scan/doc-to-entry.js +7 -10
  159. package/dist/indexer/scan/drain-dir.js +51 -23
  160. package/dist/indexer/search/db-search.js +156 -50
  161. package/dist/indexer/search/fts-query.js +40 -40
  162. package/dist/indexer/search/ranking.js +36 -1
  163. package/dist/indexer/search/search-attribution.js +3 -1
  164. package/dist/indexer/search/search-fields.js +23 -14
  165. package/dist/indexer/search/search-hit-enrichers.js +1 -1
  166. package/dist/indexer/search/search-source.js +7 -16
  167. package/dist/indexer/search/semantic-status.js +10 -1
  168. package/dist/indexer/usage/show-usage.js +105 -0
  169. package/dist/indexer/usage/usage-events.js +7 -2
  170. package/dist/indexer/walk/matchers.js +40 -10
  171. package/dist/indexer/walk/path-resolver.js +5 -2
  172. package/dist/indexer/walk/walker.js +20 -2
  173. package/dist/integrations/agent/builder-shared.js +3 -6
  174. package/dist/integrations/agent/conversation-fallback.js +16 -0
  175. package/dist/integrations/agent/engine-resolution.js +87 -87
  176. package/dist/integrations/agent/execution-cascade.js +566 -0
  177. package/dist/integrations/agent/execution-definitions.js +211 -0
  178. package/dist/integrations/agent/execution-lowering.js +811 -0
  179. package/dist/integrations/agent/execution-preparation.js +67 -0
  180. package/dist/integrations/agent/index.js +0 -2
  181. package/dist/integrations/agent/inline-execution.js +74 -0
  182. package/dist/integrations/agent/model-map.js +515 -0
  183. package/dist/integrations/agent/persona-fallback.js +30 -0
  184. package/dist/integrations/agent/request-lowering.js +186 -0
  185. package/dist/integrations/agent/runner-dispatch.js +230 -37
  186. package/dist/integrations/agent/runner.js +12 -83
  187. package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
  188. package/dist/integrations/harnesses/aider/index.js +0 -1
  189. package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
  190. package/dist/integrations/harnesses/amazonq/index.js +0 -1
  191. package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
  192. package/dist/integrations/harnesses/claude/index.js +1 -5
  193. package/dist/integrations/harnesses/claude/session-log.js +3 -33
  194. package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
  195. package/dist/integrations/harnesses/codex/index.js +0 -1
  196. package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
  197. package/dist/integrations/harnesses/copilot/index.js +0 -1
  198. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
  199. package/dist/integrations/harnesses/gemini/index.js +0 -1
  200. package/dist/integrations/harnesses/index.js +4 -44
  201. package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
  202. package/dist/integrations/harnesses/opencode/index.js +0 -2
  203. package/dist/integrations/harnesses/opencode/session-log.js +14 -204
  204. package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
  205. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
  206. package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
  207. package/dist/integrations/harnesses/openhands/index.js +0 -1
  208. package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
  209. package/dist/integrations/harnesses/pi/index.js +0 -1
  210. package/dist/integrations/harnesses/shared.js +0 -1
  211. package/dist/integrations/harnesses/types.js +1 -3
  212. package/dist/integrations/lockfile.js +82 -79
  213. package/dist/integrations/session-logs/index.js +6 -17
  214. package/dist/integrations/session-logs/provider-base.js +1 -29
  215. package/dist/llm/client.js +10 -5
  216. package/dist/llm/embedder.js +6 -7
  217. package/dist/llm/embedders/local.js +37 -88
  218. package/dist/llm/embedders/types.js +1 -1
  219. package/dist/llm/graph-extract.js +75 -50
  220. package/dist/llm/index-passes.js +43 -5
  221. package/dist/llm/memory-infer.js +8 -6
  222. package/dist/llm/metadata-enhance.js +5 -3
  223. package/dist/llm/structured-call.js +122 -25
  224. package/dist/output/format-exempt.js +1 -1
  225. package/dist/output/render-registry.js +0 -16
  226. package/dist/output/renderers.js +12 -7
  227. package/dist/output/shapes/curate.js +1 -0
  228. package/dist/output/shapes/helpers.js +10 -2
  229. package/dist/output/shapes/passthrough.js +2 -0
  230. package/dist/output/text/command-format.js +31 -33
  231. package/dist/output/text/health-format.js +1 -29
  232. package/dist/output/text/migrate.js +6 -56
  233. package/dist/output/text/proposal-format.js +16 -1
  234. package/dist/output/text/workflow-format.js +16 -0
  235. package/dist/registry/network.js +279 -0
  236. package/dist/registry/pinned-request-helper.js +247 -0
  237. package/dist/registry/pinned-transport.js +717 -0
  238. package/dist/registry/providers/skills-sh.js +18 -6
  239. package/dist/registry/providers/static-index.js +20 -7
  240. package/dist/registry/resolve.js +53 -28
  241. package/dist/scripts/akm-migrate-node.js +19334 -52269
  242. package/dist/scripts/akm-migrate.js +19270 -51612
  243. package/dist/setup/registry-stash-loader.js +64 -20
  244. package/dist/setup/semantic-assets.js +9 -34
  245. package/dist/setup/setup.js +12 -30
  246. package/dist/setup/source-identity.js +17 -0
  247. package/dist/setup/steps/sources.js +36 -15
  248. package/dist/setup/steps/tasks.js +39 -11
  249. package/dist/sources/providers/git-provider.js +3 -3
  250. package/dist/sources/providers/npm.js +2 -2
  251. package/dist/sources/providers/provider-utils.js +4 -3
  252. package/dist/sources/providers/website.js +11 -7
  253. package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
  254. package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
  255. package/dist/sources/website-url.js +73 -0
  256. package/dist/storage/engines/sqlite-migrations.js +81 -26
  257. package/dist/storage/managed-db.js +27 -24
  258. package/dist/storage/repositories/events-repository.js +3 -0
  259. package/dist/storage/repositories/index-connection.js +42 -10
  260. package/dist/storage/repositories/index-entries-repository.js +203 -229
  261. package/dist/storage/repositories/index-entry-mapper.js +8 -12
  262. package/dist/storage/repositories/index-entry-schema.js +255 -0
  263. package/dist/storage/repositories/index-fts-repository.js +64 -71
  264. package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
  265. package/dist/storage/repositories/index-meta-repository.js +0 -11
  266. package/dist/storage/repositories/index-schema.js +74 -350
  267. package/dist/storage/repositories/index-utility-repository.js +12 -17
  268. package/dist/storage/repositories/index-vec-repository.js +56 -7
  269. package/dist/storage/repositories/proposals-repository.js +4 -127
  270. package/dist/storage/repositories/registry-cache.js +2 -1
  271. package/dist/storage/repositories/task-history-repository.js +20 -40
  272. package/dist/storage/repositories/workflow-runs-repository.js +228 -129
  273. package/dist/storage/sqlite-read-snapshot.js +148 -0
  274. package/dist/tasks/backends/cron.js +170 -42
  275. package/dist/tasks/backends/index.js +1 -1
  276. package/dist/tasks/backends/launchd.js +787 -202
  277. package/dist/tasks/backends/schtasks.js +282 -83
  278. package/dist/tasks/embedded.js +7 -7
  279. package/dist/tasks/frozen-script.js +50 -0
  280. package/dist/tasks/resolve-akm-bin.js +5 -1
  281. package/dist/tasks/runner.js +239 -251
  282. package/dist/tasks/runtime-v3.js +281 -0
  283. package/dist/tasks/scheduler-binding.js +272 -0
  284. package/dist/tasks/scheduler-invocation.js +57 -43
  285. package/dist/tasks/scheduler-sync.js +654 -0
  286. package/dist/tasks/source-v3.js +752 -0
  287. package/dist/tasks/standalone-script-entry.js +5 -0
  288. package/dist/tasks/task-id.js +29 -0
  289. package/dist/workflows/authoring/authoring.js +15 -32
  290. package/dist/workflows/exec/dispatch-redaction.js +14 -8
  291. package/dist/workflows/exec/exec-unit.js +7 -28
  292. package/dist/workflows/exec/frozen-judge.js +57 -89
  293. package/dist/workflows/exec/lowering-notices.js +23 -0
  294. package/dist/workflows/exec/native-executor.js +301 -458
  295. package/dist/workflows/exec/param-secrets.js +4 -3
  296. package/dist/workflows/exec/run-workflow.js +26 -32
  297. package/dist/workflows/exec/step-work.js +105 -109
  298. package/dist/workflows/exec/unit-dispatch.js +103 -27
  299. package/dist/workflows/exec/unit-writer.js +3 -3
  300. package/dist/workflows/exec/worktree.js +2 -2
  301. package/dist/workflows/ir/compile.js +86 -72
  302. package/dist/workflows/ir/environment-v4.js +328 -0
  303. package/dist/workflows/ir/freeze-v4.js +122 -0
  304. package/dist/workflows/ir/plan-hash.js +13 -7
  305. package/dist/workflows/ir/schema-v4.js +525 -0
  306. package/dist/workflows/ir/schema.js +25 -284
  307. package/dist/workflows/ir/source-freeze-v4.js +506 -0
  308. package/dist/workflows/parser.js +27 -24
  309. package/dist/workflows/program/schema.js +1 -2
  310. package/dist/workflows/renderer.js +42 -29
  311. package/dist/workflows/resource-limits.js +4 -5
  312. package/dist/workflows/runtime/agent-identity.js +11 -13
  313. package/dist/workflows/runtime/plan-classifier.js +8 -8
  314. package/dist/workflows/runtime/runs.js +27 -43
  315. package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
  316. package/dist/workflows/source-files.js +373 -0
  317. package/dist/workflows/source-ir/compile.js +196 -0
  318. package/dist/workflows/source-ir/github-yaml.js +577 -0
  319. package/dist/workflows/source-ir/ordering.js +38 -0
  320. package/dist/workflows/source-ir/program.js +50 -0
  321. package/dist/workflows/source-ir/result.js +26 -0
  322. package/dist/workflows/source-ir/schema.js +772 -0
  323. package/dist/workflows/source-ir/semantics.js +242 -0
  324. package/dist/workflows/source-ir/uses.js +14 -0
  325. package/docs/README.md +2 -0
  326. package/docs/migration/README.md +3 -1
  327. package/docs/migration/release-notes/0.9.2.md +55 -0
  328. package/docs/migration/release-notes/README.md +5 -0
  329. package/docs/migration/v0.8-to-v0.9.md +76 -1077
  330. package/docs/migration/v0.9.0-troubleshooting.md +104 -516
  331. package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
  332. package/docs/reference/README.md +1 -0
  333. package/docs/reference/cli.md +230 -98
  334. package/docs/reference/configuration.md +159 -36
  335. package/docs/reference/data-and-telemetry.md +19 -1
  336. package/docs/reference/supported-formats.md +23 -3
  337. package/docs/reference/tasks.md +182 -0
  338. package/docs/reference/workflow-schema.md +91 -40
  339. package/docs/reference/workflows.md +33 -6
  340. package/package.json +10 -6
  341. package/schemas/akm-config.json +372 -224
  342. package/schemas/akm-task.json +324 -80
  343. package/schemas/akm-workflow.json +6 -9
  344. package/dist/core/migration-operation.js +0 -75
  345. package/dist/integrations/agent/model-aliases.js +0 -74
  346. package/dist/tasks/parser.js +0 -380
  347. package/dist/tasks/schema.js +0 -123
  348. package/dist/tasks/validator.js +0 -80
  349. package/dist/workflows/ir/freeze.js +0 -320
  350. package/dist/workflows/runtime/document-cache.js +0 -13
@@ -18,13 +18,48 @@
18
18
  */
19
19
  import fs from "node:fs";
20
20
  import { parseFrontmatter } from "../../../core/asset/frontmatter.js";
21
+ import { ConfigError } from "../../../core/errors.js";
21
22
  import { appendEvent } from "../../../core/events.js";
22
23
  import { parseEmbeddedJsonResponse } from "../../../core/parse.js";
24
+ import { callStructured } from "../../../llm/structured-call.js";
23
25
  import { isProposalSkipped } from "../../proposal/repository.js";
24
26
  import { assessMemoryKnowledgePromotionCandidate } from "../distill-promotion-policy.js";
25
27
  import { emitProposal } from "../proposal-envelope.js";
26
28
  import { durableImproveRef } from "../source-identity.js";
27
29
  import { persistOutputEncodingSalience, runLessonQualityJudge, writeQualityRejection } from "./quality-gate.js";
30
+ /** Read-only classification of the deterministic promotion path and destination conflict. */
31
+ export async function planMemoryKnowledgePromotion(ctx) {
32
+ const durableInputRef = ctx.durableInputRef ?? ctx.inputRef;
33
+ const promotion = ctx.targetKind === "lesson"
34
+ ? null
35
+ : assessMemoryKnowledgePromotionCandidate({
36
+ inputRef: durableInputRef,
37
+ assetContent: ctx.assetContent,
38
+ feedbackEvents: ctx.filteredEvents.map((event) => ({
39
+ ...(event.metadata !== undefined ? { metadata: event.metadata } : {}),
40
+ })),
41
+ });
42
+ if (!(promotion?.promote && promotion.content && (ctx.targetKind === "knowledge" || ctx.targetKind === "auto"))) {
43
+ return null;
44
+ }
45
+ const existingKnowledgePath = await ctx.lookup(durableImproveRef(promotion.knowledgeRef));
46
+ let existingKnowledgeContent = null;
47
+ if (existingKnowledgePath && fs.existsSync(existingKnowledgePath)) {
48
+ try {
49
+ existingKnowledgeContent = fs.readFileSync(existingKnowledgePath, "utf8");
50
+ }
51
+ catch {
52
+ existingKnowledgeContent = null;
53
+ }
54
+ }
55
+ return { promotion: promotion, existingKnowledgeContent };
56
+ }
57
+ /** Whether a classified promotion will actually call merge generation and/or the judge. */
58
+ export function memoryKnowledgePromotionRequiresDispatch(ctx, plan) {
59
+ const hasRunner = Boolean(ctx.llmRunner);
60
+ return ((Boolean(plan.existingKnowledgeContent) && hasRunner) ||
61
+ (ctx.strategy?.processes?.distill?.qualityGate?.enabled ?? true));
62
+ }
28
63
  /**
29
64
  * Resolve the knowledge content to propose when a memory promotes to knowledge,
30
65
  * reconciling it with any existing knowledge file at the destination (D-1 / #369).
@@ -35,21 +70,14 @@ import { persistOutputEncodingSalience, runLessonQualityJudge, writeQualityRejec
35
70
  * an LLM the existing content is appended as reviewer-reference context so the
36
71
  * merge can be done by hand. Logic is byte-identical to the prior inline block.
37
72
  */
38
- async function resolveKnowledgePromotionContent(ctx, baseContent, knowledgeRef) {
73
+ async function resolveKnowledgePromotionContent(ctx, plan) {
39
74
  const durableInputRef = ctx.durableInputRef ?? ctx.inputRef;
75
+ const baseContent = plan.promotion.content;
76
+ const knowledgeRef = plan.promotion.knowledgeRef;
40
77
  let resolvedPromotionContent = baseContent;
41
- const existingKnowledgePath = await ctx.lookup(durableImproveRef(knowledgeRef));
42
- const existingKnowledgeContent = existingKnowledgePath && fs.existsSync(existingKnowledgePath)
43
- ? (() => {
44
- try {
45
- return fs.readFileSync(existingKnowledgePath, "utf8");
46
- }
47
- catch {
48
- return null;
49
- }
50
- })()
51
- : null;
52
- if (existingKnowledgeContent && ctx.llmConfig) {
78
+ const existingKnowledgeContent = plan.existingKnowledgeContent;
79
+ const runner = ctx.llmRunner;
80
+ if (existingKnowledgeContent && runner) {
53
81
  // Existing content found: call LLM for contradiction-resolution merge.
54
82
  const mergePrompt = [
55
83
  "You are merging two versions of a knowledge document.",
@@ -68,10 +96,23 @@ async function resolveKnowledgePromotionContent(ctx, baseContent, knowledgeRef)
68
96
  "```",
69
97
  ].join("\n");
70
98
  try {
71
- const mergeResponse = await ctx.chat(ctx.llmConfig, [
72
- { role: "system", content: "Return only valid JSON. No prose." },
73
- { role: "user", content: mergePrompt },
74
- ], ctx.signal ? { signal: ctx.signal } : undefined);
99
+ const mergeResponse = await callStructured({
100
+ feature: "distill",
101
+ runner,
102
+ ...(ctx.lease ? { lease: ctx.lease } : {}),
103
+ messages: [
104
+ { role: "system", content: "Return only valid JSON. No prose." },
105
+ { role: "user", content: mergePrompt },
106
+ ],
107
+ request: {
108
+ ...(ctx.signal ? { signal: ctx.signal } : {}),
109
+ ...(ctx.chat ? { chat: ctx.chat } : {}),
110
+ },
111
+ parse: (raw) => raw ?? "",
112
+ onError: () => "",
113
+ fallback: "",
114
+ ...(ctx.onNotices ? { onNotices: ctx.onNotices } : {}),
115
+ });
75
116
  const mergeResult = parseEmbeddedJsonResponse(mergeResponse);
76
117
  if (mergeResult?.action === "NOOP") {
77
118
  // Existing content is authoritative — no update needed.
@@ -104,7 +145,9 @@ async function resolveKnowledgePromotionContent(ctx, baseContent, knowledgeRef)
104
145
  }
105
146
  }
106
147
  }
107
- catch {
148
+ catch (error) {
149
+ if (error instanceof ConfigError)
150
+ throw error;
108
151
  // LLM merge failed — fall through with the original promotion content.
109
152
  // The reviewer will see both versions in the proposal diff.
110
153
  }
@@ -132,26 +175,18 @@ async function resolveKnowledgePromotionContent(ctx, baseContent, knowledgeRef)
132
175
  * not a promotion candidate and the caller should continue to the ordinary
133
176
  * lesson/knowledge distillation path.
134
177
  */
135
- export async function promoteMemoryToKnowledge(ctx) {
136
- const { targetKind, inputRef, assetContent, config, chat, stash, fetchSimilarLessonsFn, existingRefVocabulary, outcomeWeightEnabled, eligMeta, exclusionSetSize, filteredFeedbackCount, feedbackFullyFiltered, } = ctx;
178
+ export async function promoteMemoryToKnowledge(ctx, planned) {
179
+ const { inputRef, assetContent, config, chat, stash, fetchSimilarLessonsFn, existingRefVocabulary, outcomeWeightEnabled, eligMeta, exclusionSetSize, filteredFeedbackCount, feedbackFullyFiltered, } = ctx;
137
180
  const durableInputRef = ctx.durableInputRef ?? inputRef;
138
- const promotion = targetKind === "lesson"
139
- ? null
140
- : assessMemoryKnowledgePromotionCandidate({
141
- inputRef: durableInputRef,
142
- assetContent,
143
- feedbackEvents: ctx.filteredEvents.map((event) => ({
144
- ...(event.metadata !== undefined ? { metadata: event.metadata } : {}),
145
- })),
146
- });
147
- if (!(promotion?.promote && promotion.content && (targetKind === "knowledge" || targetKind === "auto"))) {
181
+ const promotionPlan = planned === undefined ? await planMemoryKnowledgePromotion(ctx) : planned;
182
+ if (!promotionPlan)
148
183
  return null;
149
- }
184
+ const promotion = promotionPlan.promotion;
150
185
  // D-1 / #369: When the destination knowledge file already exists, route
151
186
  // through the LLM for contradiction resolution instead of silently
152
187
  // overwriting. Follows mem0 ADD/UPDATE/DELETE/NOOP pattern (arXiv:2504.19413 §3.2)
153
188
  // and A-MEM dynamic linking (arXiv:2502.12110).
154
- const merged = await resolveKnowledgePromotionContent(ctx, promotion.content, promotion.knowledgeRef);
189
+ const merged = await resolveKnowledgePromotionContent(ctx, promotionPlan);
155
190
  if ("earlyResult" in merged)
156
191
  return merged.earlyResult;
157
192
  const resolvedPromotionContent = merged.resolvedContent;
@@ -164,8 +199,10 @@ export async function promoteMemoryToKnowledge(ctx) {
164
199
  const similarLessons = await fetchSimilarLessonsFn(resolvedPromotionContent.slice(0, 500), 3);
165
200
  const judgeResult = await runLessonQualityJudge(config, resolvedPromotionContent, assetContent ?? "", chat, {
166
201
  ...(similarLessons.length > 0 ? { similarLessons } : {}),
167
- ...(ctx.llmConfig ? { llmConfig: ctx.llmConfig } : {}),
202
+ ...(ctx.llmRunner ? { llmRunner: ctx.llmRunner } : {}),
203
+ ...(ctx.lease ? { lease: ctx.lease } : {}),
168
204
  ...(ctx.signal ? { signal: ctx.signal } : {}),
205
+ ...(ctx.onNotices ? { onNotices: ctx.onNotices } : {}),
169
206
  });
170
207
  if (!judgeResult.pass) {
171
208
  if (judgeResult.reviewNeeded) {
@@ -186,7 +223,7 @@ export async function promoteMemoryToKnowledge(ctx) {
186
223
  ref: promotion.knowledgeRef,
187
224
  source: "distill",
188
225
  // §23.6 fingerprint model-id term (WI-6.4).
189
- ...(ctx.llmConfig?.model ? { modelId: ctx.llmConfig.model } : {}),
226
+ ...(ctx.llmRunner?.connection.model ? { modelId: ctx.llmRunner.connection.model } : {}),
190
227
  ...(ctx.sourceRun !== undefined ? { sourceRun: ctx.sourceRun } : {}),
191
228
  payload: {
192
229
  content: resolvedPromotionContent,
@@ -12,14 +12,15 @@ import fs from "node:fs";
12
12
  import path from "node:path";
13
13
  import { parseRefInput } from "../../../core/asset/resolve-ref.js";
14
14
  import { timestampForFilename } from "../../../core/common.js";
15
+ import { ConfigError } from "../../../core/errors.js";
15
16
  import { appendEvent } from "../../../core/events.js";
16
17
  import { parseEmbeddedJsonResponse } from "../../../core/parse.js";
17
18
  import { withStateDb } from "../../../core/state-db.js";
18
19
  import { recordWrittenPath } from "../../../core/write-provenance.js";
19
- import { getDefaultLlmConfig } from "../../../integrations/agent/engine-resolution.js";
20
20
  import { callStructured } from "../../../llm/structured-call.js";
21
21
  import { akmSearch } from "../../read/search.js";
22
22
  import { scoreEncodingSalience } from "../encoding-salience.js";
23
+ import { resolveImproveLlmExecution } from "../execution.js";
23
24
  import { computeSalience, upsertAssetSalience } from "../salience.js";
24
25
  // ── D-4 / #390: Top-3 similar lessons retrieval ──────────────────────────────
25
26
  /**
@@ -158,8 +159,13 @@ export function buildReflectJudgePrompt(candidateContent, sourceContent, feedbac
158
159
  ].join("\n");
159
160
  }
160
161
  async function runQualityJudge(feature, config, prompt, chat, options = {}) {
161
- const llmConfig = options.llmConfig ?? getDefaultLlmConfig(config);
162
- if (!llmConfig) {
162
+ const resolvedDefault = !options.runnerSelectionFrozen && !options.llmRunner
163
+ ? resolveImproveLlmExecution({ config, processName: `${feature}-judge` })
164
+ : null;
165
+ if (resolvedDefault)
166
+ options.onNotices?.(resolvedDefault.notices);
167
+ const runner = options.llmRunner ?? resolvedDefault?.runner;
168
+ if (!runner) {
163
169
  return { pass: false, score: -1, reason: "no LLM configured — cannot judge, failing closed" };
164
170
  }
165
171
  try {
@@ -168,7 +174,8 @@ async function runQualityJudge(feature, config, prompt, chat, options = {}) {
168
174
  // propagates into the fail-closed catch below. `feature` labels the call.
169
175
  const raw = await callStructured({
170
176
  feature,
171
- config: llmConfig,
177
+ runner,
178
+ ...(options.lease ? { lease: options.lease } : {}),
172
179
  messages: [
173
180
  { role: "system", content: "Return only valid JSON. No prose." },
174
181
  { role: "user", content: prompt },
@@ -183,6 +190,7 @@ async function runQualityJudge(feature, config, prompt, chat, options = {}) {
183
190
  // Unreachable on the ungated path (errors propagate); fail closed anyway.
184
191
  onError: () => "",
185
192
  fallback: "",
193
+ ...(options.onNotices ? { onNotices: options.onNotices } : {}),
186
194
  });
187
195
  const parsed = parseEmbeddedJsonResponse(raw);
188
196
  if (!parsed ||
@@ -205,7 +213,11 @@ async function runQualityJudge(feature, config, prompt, chat, options = {}) {
205
213
  return { pass: false, score, reason, reviewNeeded: true };
206
214
  return { pass: false, score, reason };
207
215
  }
208
- catch {
216
+ catch (error) {
217
+ // Invalid symbolic credentials are configuration failures, not a negative
218
+ // content verdict. Provider/runtime failures retain the fail-closed result.
219
+ if (error instanceof ConfigError)
220
+ throw error;
209
221
  return { pass: false, score: -1, reason: "judge timeout/error — cannot judge, failing closed" };
210
222
  }
211
223
  }