akm-cli 0.9.17-alpha.2 → 0.9.17-alpha.4

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 (343) hide show
  1. package/CHANGELOG.md +756 -0
  2. package/dist/akm +94 -196
  3. package/dist/cli/shared.js +6 -2
  4. package/dist/cli.js +22 -9
  5. package/dist/commands/agent/agent-dispatch.js +1 -1
  6. package/dist/commands/command/command-execution.js +24 -62
  7. package/dist/commands/feedback-cli.js +0 -1
  8. package/dist/commands/health/accept-rate.js +2 -2
  9. package/dist/commands/health/checks.js +30 -75
  10. package/dist/commands/health/config-skew.js +38 -0
  11. package/dist/commands/health/egress.js +54 -0
  12. package/dist/commands/health/html-report.js +0 -38
  13. package/dist/commands/health/improve-metrics.js +123 -562
  14. package/dist/commands/health/plugin-staleness.js +53 -3
  15. package/dist/commands/health/renderers.js +12 -4
  16. package/dist/commands/health/report-view-model.js +11 -106
  17. package/dist/commands/health/types-improve.js +4 -19
  18. package/dist/commands/health/windows.js +64 -73
  19. package/dist/commands/health.js +122 -143
  20. package/dist/commands/improve/consolidate/chunking.js +25 -100
  21. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  22. package/dist/commands/improve/consolidate.js +538 -1075
  23. package/dist/commands/improve/content-hash.js +16 -24
  24. package/dist/commands/improve/distill/content-repair.js +18 -100
  25. package/dist/commands/improve/distill-guards.js +20 -81
  26. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  27. package/dist/commands/improve/distill.js +608 -1075
  28. package/dist/commands/improve/eligibility.js +126 -400
  29. package/dist/commands/improve/execution.js +3 -5
  30. package/dist/commands/improve/extract.js +487 -1046
  31. package/dist/commands/improve/feedback-valence.js +0 -25
  32. package/dist/commands/improve/improve-cli.js +29 -166
  33. package/dist/commands/improve/improve-result-file.js +10 -66
  34. package/dist/commands/improve/improve-strategies.js +12 -7
  35. package/dist/commands/improve/improve-usage-report.js +18 -64
  36. package/dist/commands/improve/improve.js +443 -1063
  37. package/dist/commands/improve/ledger.js +114 -0
  38. package/dist/commands/improve/locks.js +2 -8
  39. package/dist/commands/improve/loop-stages.js +459 -1172
  40. package/dist/commands/improve/memory/derived-ref.js +12 -77
  41. package/dist/commands/improve/memory/memory-belief.js +14 -118
  42. package/dist/commands/improve/memory/memory-improve.js +4 -3
  43. package/dist/commands/improve/outcome-loop.js +28 -156
  44. package/dist/commands/improve/planner.js +5 -10
  45. package/dist/commands/improve/preparation.js +851 -2339
  46. package/dist/commands/improve/proactive-maintenance.js +34 -101
  47. package/dist/commands/improve/reflect-noise.js +104 -280
  48. package/dist/commands/improve/reflect.js +621 -1367
  49. package/dist/commands/improve/salience.js +46 -232
  50. package/dist/commands/improve/session-asset.js +19 -100
  51. package/dist/commands/improve/stage.js +323 -0
  52. package/dist/commands/proposal/drain.js +251 -644
  53. package/dist/commands/proposal/proposal-cli.js +3 -18
  54. package/dist/commands/proposal/proposal-types.js +20 -41
  55. package/dist/commands/proposal/proposal.js +1 -2
  56. package/dist/commands/proposal/propose.js +134 -160
  57. package/dist/commands/proposal/repository.js +502 -1487
  58. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  59. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  60. package/dist/commands/proposal/validators/proposals.js +13 -89
  61. package/dist/commands/read/curate.js +63 -413
  62. package/dist/commands/read/search-cli.js +16 -33
  63. package/dist/commands/read/search.js +17 -23
  64. package/dist/commands/read/show.js +2 -13
  65. package/dist/commands/sources/bundle-cli.js +25 -2
  66. package/dist/commands/sources/bundle-config-ops.js +7 -0
  67. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  68. package/dist/commands/sources/info.js +2 -11
  69. package/dist/commands/sources/installed-stashes.js +197 -746
  70. package/dist/commands/sources/schema-repair.js +98 -129
  71. package/dist/commands/sources/source-add.js +62 -12
  72. package/dist/commands/sources/stash-cli.js +1 -1
  73. package/dist/commands/tasks/explain.js +10 -13
  74. package/dist/commands/tasks/tasks-cli.js +9 -8
  75. package/dist/commands/tasks/tasks.js +326 -930
  76. package/dist/commands/tasks/validate.js +42 -21
  77. package/dist/commands/workflow/plan.js +22 -29
  78. package/dist/commands/workflow-cli.js +4 -4
  79. package/dist/core/adapter/adapters/akm-adapter.js +0 -1
  80. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  81. package/dist/core/adapter/adapters/akm-metadata.js +11 -12
  82. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  83. package/dist/core/adapter/execution-source.js +17 -29
  84. package/dist/core/asset/resolve-ref.js +1 -1
  85. package/dist/core/bundle-id.js +42 -5
  86. package/dist/core/bundle-rename.js +291 -0
  87. package/dist/core/config/config-io.js +1 -2
  88. package/dist/core/config/config-schema.js +1 -33
  89. package/dist/core/config/config-walker.js +1 -1
  90. package/dist/core/config/config.js +163 -68
  91. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  92. package/dist/core/config/schema/embedding.js +20 -5
  93. package/dist/core/config/schema/engines.js +5 -0
  94. package/dist/core/config/schema/execution.js +1 -1
  95. package/dist/core/config/schema/experimental.js +1 -1
  96. package/dist/core/config/schema/improve-processes.js +21 -95
  97. package/dist/core/config/schema/improve.js +4 -42
  98. package/dist/core/config/schema/scheduler.js +12 -12
  99. package/dist/core/config/schema/search.js +6 -22
  100. package/dist/core/env-secret-ref.js +0 -1
  101. package/dist/core/errors.js +8 -9
  102. package/dist/core/file-lock.js +76 -173
  103. package/dist/core/logs-db.js +2 -2
  104. package/dist/core/paths.js +0 -27
  105. package/dist/core/redaction.js +109 -2
  106. package/dist/core/run-lock.js +2 -5
  107. package/dist/core/spawn-env.js +1 -1
  108. package/dist/core/state/migrations.js +108 -61
  109. package/dist/core/state-db-scope.js +2 -4
  110. package/dist/core/state-db.js +126 -692
  111. package/dist/core/type-presentation.js +1 -9
  112. package/dist/core/write-source.js +293 -1012
  113. package/dist/execution/input-contract.js +1 -1
  114. package/dist/execution/resolved-request.js +135 -689
  115. package/dist/execution/source.js +63 -257
  116. package/dist/execution/target-ref.js +1 -1
  117. package/dist/indexer/bundle-identity-guard.js +2 -2
  118. package/dist/indexer/db/graph-db.js +106 -46
  119. package/dist/indexer/ensure-index.js +44 -85
  120. package/dist/indexer/graph/graph-extraction.js +340 -562
  121. package/dist/indexer/graph/graph-related.js +130 -0
  122. package/dist/indexer/index-rebuild-lock.js +3 -11
  123. package/dist/indexer/index-writer-lock.js +8 -17
  124. package/dist/indexer/index-written-assets.js +139 -151
  125. package/dist/indexer/indexer.js +524 -846
  126. package/dist/indexer/materialize-embeddings.js +60 -397
  127. package/dist/indexer/passes/memory-inference.js +81 -90
  128. package/dist/indexer/passes/metadata.js +132 -200
  129. package/dist/indexer/read-preflight.js +0 -7
  130. package/dist/indexer/scan/doc-to-entry.js +1 -3
  131. package/dist/indexer/scan/drain-dir.js +1 -1
  132. package/dist/indexer/search/db-search.js +181 -590
  133. package/dist/indexer/search/fts-query.js +30 -41
  134. package/dist/indexer/search/ranking.js +28 -154
  135. package/dist/indexer/search/search-attribution.js +12 -32
  136. package/dist/indexer/search/search-fields.js +11 -15
  137. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  138. package/dist/indexer/search/search-source.js +1 -4
  139. package/dist/indexer/usage/usage-events.js +2 -7
  140. package/dist/integrations/agent/engine-fallback.js +23 -40
  141. package/dist/integrations/agent/engine-resolution.js +93 -183
  142. package/dist/integrations/agent/execution.js +507 -0
  143. package/dist/integrations/agent/model-map.js +28 -156
  144. package/dist/integrations/agent/request-lowering.js +66 -141
  145. package/dist/integrations/agent/runner-dispatch.js +143 -321
  146. package/dist/integrations/agent/runner.js +54 -14
  147. package/dist/integrations/lockfile.js +53 -101
  148. package/dist/llm/embedders/deterministic.js +2 -3
  149. package/dist/llm/embedders/profile.js +71 -0
  150. package/dist/llm/embedders/remote.js +10 -15
  151. package/dist/llm/graph-extract.js +3 -12
  152. package/dist/llm/index-passes.js +3 -5
  153. package/dist/llm/memory-infer.js +1 -2
  154. package/dist/llm/metadata-enhance.js +1 -2
  155. package/dist/llm/structured-call.js +5 -24
  156. package/dist/output/generic-render.js +23 -11
  157. package/dist/output/html-render.js +13 -10
  158. package/dist/output/render-registry.js +3 -32
  159. package/dist/output/shapes/helpers.js +2 -34
  160. package/dist/output/shapes/passthrough.js +1 -9
  161. package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
  162. package/dist/output/text/command-format.js +60 -23
  163. package/dist/output/text/helpers.js +1 -1
  164. package/dist/output/text/migrate.js +5 -14
  165. package/dist/output/text/proposal-format.js +1 -2
  166. package/dist/output/text/workflow-format.js +0 -32
  167. package/dist/output/text.js +2 -0
  168. package/dist/registry/factory.js +4 -19
  169. package/dist/registry/network.js +66 -220
  170. package/dist/registry/providers/index.js +0 -2
  171. package/dist/registry/providers/skills-sh.js +3 -14
  172. package/dist/registry/providers/static-index.js +24 -26
  173. package/dist/registry/resolve.js +55 -131
  174. package/dist/scripts/akm-migrate-node.js +43937 -93313
  175. package/dist/scripts/akm-migrate.js +43697 -93071
  176. package/dist/setup/registry-stash-loader.js +4 -13
  177. package/dist/setup/semantic-assets.js +3 -44
  178. package/dist/setup/setup.js +1 -1
  179. package/dist/setup/steps/tasks.js +25 -15
  180. package/dist/sources/provider-factory.js +17 -18
  181. package/dist/sources/providers/filesystem.js +2 -3
  182. package/dist/sources/providers/git-install.js +7 -1
  183. package/dist/sources/providers/git-provider.js +0 -3
  184. package/dist/sources/providers/git-stash.js +0 -17
  185. package/dist/sources/providers/npm.js +2 -4
  186. package/dist/sources/providers/provider-utils.js +5 -10
  187. package/dist/sources/providers/website.js +0 -2
  188. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  189. package/dist/sources/website-url.js +2 -2
  190. package/dist/storage/database.js +9 -35
  191. package/dist/storage/repositories/improve-ledger-repository.js +168 -0
  192. package/dist/storage/repositories/index-connection.js +34 -70
  193. package/dist/storage/repositories/index-entries-repository.js +69 -111
  194. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  195. package/dist/storage/repositories/index-entry-schema.js +83 -269
  196. package/dist/storage/repositories/index-fts-repository.js +86 -256
  197. package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
  198. package/dist/storage/repositories/index-meta-repository.js +6 -4
  199. package/dist/storage/repositories/index-schema.js +192 -220
  200. package/dist/storage/repositories/index-utility-repository.js +8 -29
  201. package/dist/storage/repositories/index-vec-repository.js +133 -414
  202. package/dist/storage/repositories/outcome-repository.js +2 -1
  203. package/dist/storage/repositories/proposals-repository.js +35 -0
  204. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  205. package/dist/storage/repositories/task-history-repository.js +26 -4
  206. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  207. package/dist/storage/sqlite-migrations.js +136 -0
  208. package/dist/storage/sqlite-pragmas.js +11 -9
  209. package/dist/storage/sqlite-transaction.js +170 -0
  210. package/dist/storage/state-db-integrity.js +34 -27
  211. package/dist/tasks/activation-config.js +134 -62
  212. package/dist/tasks/backends/cron.js +129 -277
  213. package/dist/tasks/backends/exec-utils.js +2 -5
  214. package/dist/tasks/backends/launchd.js +125 -745
  215. package/dist/tasks/backends/schtasks.js +101 -620
  216. package/dist/tasks/prepare/prepare-support.js +5 -15
  217. package/dist/tasks/prepare/prepare.js +0 -2
  218. package/dist/tasks/resolve-akm-bin.js +20 -79
  219. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  220. package/dist/tasks/scheduler-binding.js +18 -238
  221. package/dist/tasks/scheduler-invocation.js +52 -52
  222. package/dist/tasks/scheduler-lock.js +53 -0
  223. package/dist/tasks/scheduler-sync.js +363 -679
  224. package/dist/tasks/source/parse-task-source.js +160 -10
  225. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  226. package/dist/tasks/source/task-to-v4.js +2 -2
  227. package/dist/workflows/authoring/authoring.js +3 -12
  228. package/dist/workflows/compile.js +211 -0
  229. package/dist/workflows/concurrency-policy.js +13 -74
  230. package/dist/workflows/exec/child-invocation.js +3 -17
  231. package/dist/workflows/exec/child-workflow.js +32 -141
  232. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  233. package/dist/workflows/exec/environment.js +98 -0
  234. package/dist/workflows/exec/exec-unit.js +33 -140
  235. package/dist/workflows/exec/frozen-judge.js +7 -59
  236. package/dist/workflows/exec/native-executor.js +82 -341
  237. package/dist/workflows/exec/param-secrets.js +29 -47
  238. package/dist/workflows/exec/run-workflow.js +154 -387
  239. package/dist/workflows/exec/scheduler.js +9 -36
  240. package/dist/workflows/exec/step-work.js +127 -430
  241. package/dist/workflows/exec/unit-dispatch.js +11 -63
  242. package/dist/workflows/exec/unit-writer.js +8 -52
  243. package/dist/workflows/exec/worktree.js +39 -273
  244. package/dist/workflows/freeze/child-output-references.js +4 -15
  245. package/dist/workflows/freeze/environment.js +99 -92
  246. package/dist/workflows/freeze/freeze.js +172 -0
  247. package/dist/workflows/freeze/step-values.js +19 -21
  248. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  249. package/dist/workflows/freeze/targets/command.js +10 -33
  250. package/dist/workflows/freeze/targets/script.js +5 -12
  251. package/dist/workflows/freeze/targets/shell.js +3 -6
  252. package/dist/workflows/freeze/targets/task.js +25 -80
  253. package/dist/workflows/freeze/task-bindings.js +20 -67
  254. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  255. package/dist/workflows/ir/params.js +6 -51
  256. package/dist/workflows/ir/plan-hash.js +2 -34
  257. package/dist/workflows/parser.js +140 -43
  258. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  259. package/dist/workflows/renderer.js +36 -69
  260. package/dist/workflows/resource-limits.js +12 -120
  261. package/dist/workflows/runtime/agent-identity.js +8 -40
  262. package/dist/workflows/runtime/run-outputs.js +3 -6
  263. package/dist/workflows/runtime/run-plan.js +316 -0
  264. package/dist/workflows/runtime/runs.js +48 -200
  265. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  266. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  267. package/dist/workflows/validate-summary.js +2 -7
  268. package/docs/integration/bundling-akm.md +49 -42
  269. package/docs/migration/README.md +1 -0
  270. package/docs/migration/release-notes/0.9.17.md +41 -0
  271. package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
  272. package/docs/reference/cli.md +182 -125
  273. package/docs/reference/configuration.md +49 -56
  274. package/docs/reference/data-and-telemetry.md +19 -20
  275. package/docs/reference/tasks.md +86 -38
  276. package/docs/reference/workflow-schema.md +14 -18
  277. package/docs/reference/workflows.md +6 -9
  278. package/package.json +1 -1
  279. package/schemas/akm-config.json +87 -406
  280. package/dist/commands/health/advisories.js +0 -150
  281. package/dist/commands/health/metrics.js +0 -329
  282. package/dist/commands/health/surfaces.js +0 -102
  283. package/dist/commands/improve/anti-collapse.js +0 -83
  284. package/dist/commands/improve/collapse-detector.js +0 -432
  285. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  286. package/dist/commands/improve/consolidate/merge.js +0 -146
  287. package/dist/commands/improve/distill/promote-memory.js +0 -329
  288. package/dist/commands/improve/distill/quality-gate.js +0 -500
  289. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  290. package/dist/commands/improve/proposal-envelope.js +0 -31
  291. package/dist/commands/improve/run-context.js +0 -123
  292. package/dist/commands/improve/shared.js +0 -21
  293. package/dist/commands/improve/source-identity.js +0 -28
  294. package/dist/commands/improve/triage.js +0 -96
  295. package/dist/commands/proposal/drain-policies.js +0 -151
  296. package/dist/commands/sources/update-transaction.js +0 -220
  297. package/dist/core/action-contributors.js +0 -28
  298. package/dist/core/config/config-version-shim.js +0 -101
  299. package/dist/core/config/retired-experimental-keys-shim.js +0 -62
  300. package/dist/core/fs-txn.js +0 -405
  301. package/dist/core/lexical-score.js +0 -25
  302. package/dist/core/maintenance-barrier.js +0 -167
  303. package/dist/execution/executable-identity.js +0 -105
  304. package/dist/execution/guarded-source.js +0 -427
  305. package/dist/indexer/graph/graph-boost.js +0 -427
  306. package/dist/indexer/graph/graph-dedup.js +0 -95
  307. package/dist/indexer/search/name-match.js +0 -35
  308. package/dist/indexer/search/ranking-contributors.js +0 -515
  309. package/dist/indexer/walk/project-context.js +0 -192
  310. package/dist/integrations/agent/execution-cascade.js +0 -566
  311. package/dist/integrations/agent/execution-definitions.js +0 -202
  312. package/dist/integrations/agent/execution-lowering.js +0 -841
  313. package/dist/integrations/agent/execution-preparation.js +0 -98
  314. package/dist/integrations/agent/inline-execution.js +0 -74
  315. package/dist/registry/create-provider-registry.js +0 -29
  316. package/dist/registry/pinned-request-helper.js +0 -247
  317. package/dist/registry/pinned-transport.js +0 -717
  318. package/dist/sources/providers/index.js +0 -14
  319. package/dist/storage/engines/sqlite-migrations.js +0 -271
  320. package/dist/storage/repositories/canaries-repository.js +0 -107
  321. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  322. package/dist/storage/repositories/registry-cache.js +0 -113
  323. package/dist/tasks/scheduler-sync-preview.js +0 -52
  324. package/dist/workflows/freeze/resolve-steps.js +0 -86
  325. package/dist/workflows/freeze/source-freeze.js +0 -64
  326. package/dist/workflows/ir/compile.js +0 -321
  327. package/dist/workflows/ir/environment-v4.js +0 -330
  328. package/dist/workflows/ir/freeze-v4.js +0 -153
  329. package/dist/workflows/ir/schema-v4.js +0 -745
  330. package/dist/workflows/ir/schema.js +0 -354
  331. package/dist/workflows/program/schema.js +0 -78
  332. package/dist/workflows/runtime/checkin.js +0 -57
  333. package/dist/workflows/runtime/plan-classifier.js +0 -196
  334. package/dist/workflows/runtime/unit-checkin.js +0 -45
  335. package/dist/workflows/runtime/unit-phases.js +0 -20
  336. package/dist/workflows/schema.js +0 -4
  337. package/dist/workflows/source-ir/compile.js +0 -200
  338. package/dist/workflows/source-ir/program.js +0 -50
  339. package/dist/workflows/source-ir/result.js +0 -26
  340. package/dist/workflows/source-ir/schema.js +0 -786
  341. package/dist/workflows/source-ir/triggers.js +0 -79
  342. package/dist/workflows/source-ir/uses.js +0 -40
  343. package/dist/workflows/validator.js +0 -60
@@ -1,329 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * Memory→knowledge promotion branch for `akm distill`.
6
- *
7
- * This is an entire second command that used to be inlined inside `akmDistill`:
8
- * when a `memory:*` ref is reinforced enough (per the deterministic stability
9
- * heuristic in `distill-promotion-policy`), distill graduates it into a
10
- * `knowledge:*` proposal instead of a lesson. The branch owns its own LLM
11
- * contradiction-merge (mem0 ADD/UPDATE/NOOP), quality gate, proposal creation,
12
- * and `distill_invoked` event emit.
13
- *
14
- * {@link promoteMemoryToKnowledge} returns the finished {@link AkmDistillResult}
15
- * when the branch fired, or `null` when the ref is not a promotion candidate —
16
- * in which case the caller falls through to the ordinary lesson/knowledge LLM
17
- * path. Logic is byte-identical to the pre-extraction inline code.
18
- */
19
- import fs from "node:fs";
20
- import { parseFrontmatter } from "../../../core/asset/frontmatter.js";
21
- import { ConfigError } from "../../../core/errors.js";
22
- import { appendEvent } from "../../../core/events.js";
23
- import { parseEmbeddedJsonResponse } from "../../../core/parse.js";
24
- import { callStructured } from "../../../llm/structured-call.js";
25
- import { isProposalSkipped } from "../../proposal/repository.js";
26
- import { assessMemoryKnowledgePromotionCandidate } from "../distill-promotion-policy.js";
27
- import { emitProposal } from "../proposal-envelope.js";
28
- import { durableImproveRef } from "../source-identity.js";
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
- /**
58
- * PRECHECK (tier3-0917): read-only classification of whether distill would
59
- * promote this memory to knowledge — used by the improve loop's distill
60
- * pre-generation proposal guard (`loop-stages.ts`) to pre-check the SAME ref
61
- * {@link planMemoryKnowledgePromotion} will target at dispatch time
62
- * (knowledgeRef when this resolves `true`, the derived lesson ref
63
- * otherwise), rather than guessing which of the two a guard hit applies to.
64
- * Delegates to {@link planMemoryKnowledgePromotion} itself so the
65
- * classification can never drift from the real dispatch decision — no LLM
66
- * call, no side effect. Every {@link PromoteMemoryContext} field this
67
- * classification does not read (chat, fetchSimilarLessonsFn,
68
- * existingRefVocabulary, …) is a safe placeholder here.
69
- */
70
- export async function wouldPromoteMemoryToKnowledge(args) {
71
- const plan = await planMemoryKnowledgePromotion({
72
- targetKind: "auto",
73
- inputRef: args.inputRef,
74
- durableInputRef: args.durableInputRef,
75
- assetContent: args.assetContent,
76
- filteredEvents: args.feedbackEvents,
77
- config: args.config,
78
- stash: args.stash,
79
- lookup: args.lookup,
80
- fetchSimilarLessonsFn: () => Promise.resolve([]),
81
- existingRefVocabulary: new Set(),
82
- outcomeWeightEnabled: false,
83
- eligMeta: {},
84
- exclusionSetSize: 0,
85
- filteredFeedbackCount: 0,
86
- feedbackFullyFiltered: false,
87
- });
88
- return plan !== null;
89
- }
90
- /** Whether a classified promotion will actually call merge generation and/or the judge. */
91
- export function memoryKnowledgePromotionRequiresDispatch(ctx, plan) {
92
- const hasRunner = Boolean(ctx.llmRunner);
93
- return ((Boolean(plan.existingKnowledgeContent) && hasRunner) ||
94
- (ctx.strategy?.processes?.distill?.qualityGate?.enabled ?? true));
95
- }
96
- /**
97
- * Resolve the knowledge content to propose when a memory promotes to knowledge,
98
- * reconciling it with any existing knowledge file at the destination (D-1 / #369).
99
- *
100
- * When the destination already exists and an LLM is configured, follows the
101
- * mem0 ADD/UPDATE/NOOP pattern (arXiv:2504.19413 §3.2): ADD/UPDATE swap in the
102
- * merged content, NOOP short-circuits with a terminal "skipped" result. Without
103
- * an LLM the existing content is appended as reviewer-reference context so the
104
- * merge can be done by hand. Logic is byte-identical to the prior inline block.
105
- */
106
- async function resolveKnowledgePromotionContent(ctx, plan) {
107
- const durableInputRef = ctx.durableInputRef ?? ctx.inputRef;
108
- const baseContent = plan.promotion.content;
109
- const knowledgeRef = plan.promotion.knowledgeRef;
110
- let resolvedPromotionContent = baseContent;
111
- const existingKnowledgeContent = plan.existingKnowledgeContent;
112
- const runner = ctx.llmRunner;
113
- if (existingKnowledgeContent && runner) {
114
- // Existing content found: call LLM for contradiction-resolution merge.
115
- const mergePrompt = [
116
- "You are merging two versions of a knowledge document.",
117
- "Existing content is already committed; new content comes from a memory distillation run.",
118
- "Choose one of: ADD (combine both), UPDATE (replace existing with new), NOOP (keep existing unchanged).",
119
- 'Return ONLY valid JSON: {"action": "ADD"|"UPDATE"|"NOOP", "content": "<merged markdown if ADD/UPDATE, empty string if NOOP>"}',
120
- "",
121
- "## Existing knowledge content",
122
- "```",
123
- existingKnowledgeContent.slice(0, 3000),
124
- "```",
125
- "",
126
- "## New content from distillation",
127
- "```",
128
- baseContent.slice(0, 3000),
129
- "```",
130
- ].join("\n");
131
- try {
132
- const mergeResponse = await callStructured({
133
- feature: "distill",
134
- runner,
135
- ...(ctx.lease ? { lease: ctx.lease } : {}),
136
- messages: [
137
- { role: "system", content: "Return only valid JSON. No prose." },
138
- { role: "user", content: mergePrompt },
139
- ],
140
- request: {
141
- ...(ctx.signal ? { signal: ctx.signal } : {}),
142
- ...(ctx.chat ? { chat: ctx.chat } : {}),
143
- },
144
- parse: (raw) => raw ?? "",
145
- onError: () => "",
146
- fallback: "",
147
- ...(ctx.onNotices ? { onNotices: ctx.onNotices } : {}),
148
- });
149
- const mergeResult = parseEmbeddedJsonResponse(mergeResponse);
150
- if (mergeResult?.action === "NOOP") {
151
- // Existing content is authoritative — no update needed.
152
- appendEvent({
153
- eventType: "distill_invoked",
154
- // Use item_ref when resolved, otherwise the input conceptId.
155
- ref: ctx.itemRef ?? durableInputRef,
156
- metadata: {
157
- outcome: "skipped",
158
- proposalRef: knowledgeRef,
159
- message: "D-1: LLM resolved destination conflict as NOOP — existing content kept",
160
- ...ctx.eligMeta,
161
- },
162
- }, ctx.eventsCtx);
163
- return {
164
- earlyResult: {
165
- schemaVersion: 1,
166
- ok: true,
167
- outcome: "skipped",
168
- inputRef: ctx.inputRef,
169
- proposalRef: knowledgeRef,
170
- skipReason: "conflict_noop",
171
- message: "Existing knowledge content unchanged (contradiction resolution: NOOP)",
172
- },
173
- };
174
- }
175
- if (mergeResult?.action && (mergeResult.action === "ADD" || mergeResult.action === "UPDATE")) {
176
- if (mergeResult.content?.trim()) {
177
- resolvedPromotionContent = mergeResult.content;
178
- }
179
- }
180
- }
181
- catch (error) {
182
- if (error instanceof ConfigError)
183
- throw error;
184
- // LLM merge failed — fall through with the original promotion content.
185
- // The reviewer will see both versions in the proposal diff.
186
- }
187
- }
188
- else if (existingKnowledgeContent) {
189
- // No LLM configured: include existing content as context in the proposal
190
- // so the reviewer can do the contradiction resolution manually.
191
- resolvedPromotionContent = [
192
- baseContent,
193
- "",
194
- "---",
195
- "<!-- D-1 / #369: Existing knowledge content is shown below for reviewer reference. -->",
196
- "<!-- Review: decide whether to ADD (merge), UPDATE (replace), or NOOP (keep existing). -->",
197
- "",
198
- "## Existing content (for reviewer reference)",
199
- "",
200
- existingKnowledgeContent,
201
- ].join("\n");
202
- }
203
- return { resolvedContent: resolvedPromotionContent };
204
- }
205
- /**
206
- * Run the memory→knowledge promotion branch. Returns the finished distill
207
- * result when promotion fired (all paths terminal), or `null` when the ref is
208
- * not a promotion candidate and the caller should continue to the ordinary
209
- * lesson/knowledge distillation path.
210
- */
211
- export async function promoteMemoryToKnowledge(ctx, planned) {
212
- const { inputRef, assetContent, config, chat, stash, fetchSimilarLessonsFn, existingRefVocabulary, outcomeWeightEnabled, eligMeta, exclusionSetSize, filteredFeedbackCount, feedbackFullyFiltered, } = ctx;
213
- const durableInputRef = ctx.durableInputRef ?? inputRef;
214
- const promotionPlan = planned === undefined ? await planMemoryKnowledgePromotion(ctx) : planned;
215
- if (!promotionPlan)
216
- return null;
217
- const promotion = promotionPlan.promotion;
218
- // D-1 / #369: When the destination knowledge file already exists, route
219
- // through the LLM for contradiction resolution instead of silently
220
- // overwriting. Follows mem0 ADD/UPDATE/DELETE/NOOP pattern (arXiv:2504.19413 §3.2)
221
- // and A-MEM dynamic linking (arXiv:2502.12110).
222
- const merged = await resolveKnowledgePromotionContent(ctx, promotionPlan);
223
- if ("earlyResult" in merged)
224
- return merged.earlyResult;
225
- const resolvedPromotionContent = merged.resolvedContent;
226
- // Apply quality gate to fast-path knowledge promotion (Risk 4 fix).
227
- // D-5 / #388: Three-band system — review_needed band queues to proposal
228
- // queue with review_needed outcome rather than auto-rejecting.
229
- let knowledgeJudgeConfidence;
230
- if (ctx.strategy?.processes?.distill?.qualityGate?.enabled ?? true) {
231
- // D-4 / #390: retrieve top-3 similar lessons for dedup check in judge.
232
- const similarLessons = await fetchSimilarLessonsFn(resolvedPromotionContent.slice(0, 500), 3);
233
- const judgeResult = await runLessonQualityJudge(config, resolvedPromotionContent, assetContent ?? "", chat, {
234
- ...(similarLessons.length > 0 ? { similarLessons } : {}),
235
- ...(ctx.llmRunner ? { llmRunner: ctx.llmRunner } : {}),
236
- ...(ctx.lease ? { lease: ctx.lease } : {}),
237
- ...(ctx.signal ? { signal: ctx.signal } : {}),
238
- ...(ctx.onNotices ? { onNotices: ctx.onNotices } : {}),
239
- });
240
- if (!judgeResult.pass) {
241
- const proposalOpts = {
242
- ...(ctx.proposalsCtx ? { proposalsCtx: ctx.proposalsCtx } : {}),
243
- ...(ctx.sourceRun !== undefined ? { sourceRun: ctx.sourceRun } : {}),
244
- ...(ctx.llmRunner?.connection.model ? { modelId: ctx.llmRunner.connection.model } : {}),
245
- };
246
- if (judgeResult.reviewNeeded) {
247
- // Uncertainty band (2.5–3.5): queue as review_needed instead of rejecting.
248
- return writeQualityRejection(stash, inputRef, promotion.knowledgeRef, resolvedPromotionContent, judgeResult.score, judgeResult.reason, { reviewNeeded: true, ...(judgeResult.criteria ? { criteria: judgeResult.criteria } : {}) }, ctx.eligibilitySource, ctx.eventsCtx, proposalOpts);
249
- }
250
- return writeQualityRejection(stash, inputRef, promotion.knowledgeRef, resolvedPromotionContent, judgeResult.score, judgeResult.reason, judgeResult.criteria ? { criteria: judgeResult.criteria } : {}, ctx.eligibilitySource, ctx.eventsCtx, proposalOpts);
251
- }
252
- // Normalize 1-5 judge score to [0, 1]. Only a real passing verdict reaches
253
- // here (07 P0-2: the judge now fails CLOSED on no-LLM / timeout / parse
254
- // failure, so those return pass:false and early-return above). The score>0
255
- // guard defensively leaves confidence undefined for any non-positive score.
256
- if (judgeResult.score > 0)
257
- knowledgeJudgeConfidence = judgeResult.score / 5;
258
- }
259
- const knowledgeParsed = parseFrontmatter(resolvedPromotionContent);
260
- const proposalResult = emitProposal({ stashDir: stash, proposalsCtx: ctx.proposalsCtx }, {
261
- ref: promotion.knowledgeRef,
262
- source: "distill",
263
- // §23.6 fingerprint model-id term (WI-6.4).
264
- ...(ctx.llmRunner?.connection.model ? { modelId: ctx.llmRunner.connection.model } : {}),
265
- ...(ctx.sourceRun !== undefined ? { sourceRun: ctx.sourceRun } : {}),
266
- payload: {
267
- content: resolvedPromotionContent,
268
- ...(Object.keys(knowledgeParsed.data).length > 0 ? { frontmatter: knowledgeParsed.data } : {}),
269
- },
270
- ...(knowledgeJudgeConfidence !== undefined ? { confidence: knowledgeJudgeConfidence } : {}),
271
- // Attribution tagging: persist the eligibility lane on the proposal.
272
- ...(ctx.eligibilitySource ? { eligibilitySource: ctx.eligibilitySource } : {}),
273
- });
274
- if (isProposalSkipped(proposalResult)) {
275
- appendEvent({
276
- eventType: "distill_invoked",
277
- // Use item_ref when resolved, otherwise the input conceptId.
278
- ref: ctx.itemRef ?? durableInputRef,
279
- metadata: {
280
- outcome: "skipped",
281
- proposalRef: promotion.knowledgeRef,
282
- message: proposalResult.message,
283
- skipReason: proposalResult.reason,
284
- ...eligMeta,
285
- },
286
- }, ctx.eventsCtx);
287
- return {
288
- schemaVersion: 1,
289
- ok: true,
290
- outcome: "skipped",
291
- inputRef,
292
- proposalRef: promotion.knowledgeRef,
293
- skipReason: proposalResult.reason,
294
- message: proposalResult.message,
295
- };
296
- }
297
- const proposal = proposalResult;
298
- // G4: content-score the distilled OUTPUT so it carries a real encoding
299
- // salience (encoding_source='content') from creation.
300
- persistOutputEncodingSalience(durableImproveRef(promotion.knowledgeRef), resolvedPromotionContent, existingRefVocabulary, outcomeWeightEnabled);
301
- appendEvent({
302
- eventType: "distill_invoked",
303
- // Use item_ref when resolved, otherwise the input conceptId.
304
- ref: ctx.itemRef ?? durableInputRef,
305
- metadata: {
306
- outcome: "queued",
307
- proposalRef: promotion.knowledgeRef,
308
- proposalKind: "knowledge",
309
- proposalId: proposal.id,
310
- // R3: judge verdicts are longitudinally queryable, not just a one-shot
311
- // proposal.confidence write (normalized 1–5 score / 5).
312
- ...(knowledgeJudgeConfidence !== undefined ? { judgeConfidence: knowledgeJudgeConfidence } : {}),
313
- ...(ctx.sourceRun !== undefined ? { sourceRun: ctx.sourceRun } : {}),
314
- ...(exclusionSetSize > 0 ? { filteredFeedbackCount } : {}),
315
- ...eligMeta,
316
- },
317
- }, ctx.eventsCtx);
318
- return {
319
- schemaVersion: 1,
320
- ok: true,
321
- outcome: "queued",
322
- inputRef,
323
- proposalRef: promotion.knowledgeRef,
324
- proposalKind: "knowledge",
325
- proposalId: proposal.id,
326
- proposal,
327
- ...(exclusionSetSize > 0 ? { filteredFeedbackCount, feedbackFullyFiltered } : {}),
328
- };
329
- }