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
@@ -0,0 +1,124 @@
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
+ * The single, keyed-on-ref implementation of "is this a derived memory?" and
6
+ * "which parent does it derive from?" (R12).
7
+ *
8
+ * Two divergent copies previously lived side by side — the CONSUMER
9
+ * (`memory-improve.ts`, keyed on the memory name) and the PRODUCER
10
+ * (`memory-contradiction-detect.ts`, keyed on the file path). The producer's
11
+ * copy was strictly narrower: it ignored `derivedFrom` entirely and matched
12
+ * `source:` through a separate parser. That let the producer and consumer
13
+ * disagree on a memory's parent — the exact defect plan §6 calls out
14
+ * ("producer/consumer cannot disagree").
15
+ *
16
+ * Both sides now share this one impl, keyed on the memory NAME (the stash-
17
+ * relative path without the `.md` extension, e.g. `nested/foo.derived`). The
18
+ * producer converts its file path to a name via `toMemoryRef` before calling
19
+ * in. Adopting it on the producer side is an INTENTIONAL widening, pinned by
20
+ * `tests/commands/improve/derived-ref.test.ts`:
21
+ * - `derivedFrom`-keyed families now resolve a parent (and so participate in
22
+ * contradiction detection); and
23
+ * - `source:` is parsed through `parseRefInput` so current bundle-qualified
24
+ * refs resolve consistently.
25
+ *
26
+ * Resolution order (source → derivedFrom → `.derived` suffix) matches the
27
+ * consumer's prior behaviour exactly, so the consumer side is a pure move.
28
+ */
29
+ import { conceptIdFromTypeName, parseRefInput } from "../../../core/asset/resolve-ref.js";
30
+ import { asNonEmptyString } from "../../../core/common.js";
31
+ import { DERIVED_SUFFIX } from "../../../core/recognition-util.js";
32
+ /**
33
+ * Parse a belief edge (`supersededBy` / `contradictedBy` / `currentBeliefRefs`)
34
+ * to the bare memory name the identity channel keys on.
35
+ *
36
+ * Accepts BOTH spellings, because both reach this function:
37
+ * - `memory:<name>` — the internal identity spelling, and what belief edges
38
+ * written before 0.9.0 carry on disk;
39
+ * - `memories/<name>` / `<bundle>//memories/<name>` — the conceptId grammar
40
+ * the current writers emit (`akm remember --supersedes` and `akm import
41
+ * --supersedes` go through `writeSupersededEdge` with the write result's
42
+ * `ref`, which is fully qualified).
43
+ *
44
+ * Accepting only the first spelling silently reduced every edge written by the
45
+ * current code path to nothing, so a superseded memory read back as active.
46
+ * Both normalize to the bare name; the caller re-mints the internal
47
+ * `memory:<name>` form via {@link memoryIdentityRef}, so there is still exactly
48
+ * one identity spelling downstream.
49
+ */
50
+ export function parseMemoryName(value) {
51
+ if (!value)
52
+ return undefined;
53
+ const trimmed = value.trim();
54
+ const MEMORY_PREFIX = "memory:";
55
+ if (trimmed.startsWith(MEMORY_PREFIX)) {
56
+ const name = trimmed.slice(MEMORY_PREFIX.length);
57
+ return name.length > 0 ? name : undefined;
58
+ }
59
+ try {
60
+ const parsed = parseRefInput(trimmed);
61
+ return parsed.type === "memory" && parsed.name.length > 0 ? parsed.name : undefined;
62
+ }
63
+ catch {
64
+ return undefined;
65
+ }
66
+ }
67
+ /**
68
+ * Parse a current `source:` backref and return its canonical memory conceptId,
69
+ * or `undefined` when it is empty, invalid, or not a memory ref.
70
+ */
71
+ export function parseMemoryRef(value) {
72
+ if (!value)
73
+ return undefined;
74
+ try {
75
+ const parsed = parseRefInput(value.trim());
76
+ return parsed.type === "memory" ? conceptIdFromTypeName("memory", parsed.name) : undefined;
77
+ }
78
+ catch {
79
+ return undefined;
80
+ }
81
+ }
82
+ /**
83
+ * Format a bare memory name into the belief-edge IDENTITY channel ref
84
+ * `memory:<name>` — the ONE implementation of that spelling.
85
+ *
86
+ * Belief-edge / identity
87
+ * channel (`contradictedBy` / `supersededBy` / `currentBeliefRefs`, and a derived
88
+ * memory's own `record.ref`) uses `memory:<name>` and is compared against a
89
+ * derived memory's identity ref. This channel is separate from `source:` asset
90
+ * refs, which use `memories/<name>`. Both `memory-improve.ts` (`refArray`) and
91
+ * `memory-contradiction-detect.ts` (`toMemoryRef`) emit through here so the
92
+ * identity spelling has one implementation.
93
+ */
94
+ export function memoryIdentityRef(name) {
95
+ return `memory:${name}`;
96
+ }
97
+ /**
98
+ * True when the named memory is a derived/inferred child — either it carries
99
+ * `inferred: true` in its frontmatter or its name ends with the structural
100
+ * `.derived` suffix.
101
+ */
102
+ export function isDerivedMemory(name, frontmatter) {
103
+ return frontmatter.inferred === true || name.endsWith(DERIVED_SUFFIX);
104
+ }
105
+ /**
106
+ * Resolve the parent (source) memory ref for a derived memory as a canonical
107
+ * `memories/<name>` conceptId, or `undefined` when none
108
+ * can be determined. Precedence:
109
+ * 1. `frontmatter.source` (normalised through {@link parseMemoryRef});
110
+ * 2. `frontmatter.derivedFrom` (a bare memory name → `memories/<name>`);
111
+ * 3. the `.derived` name suffix, stripped → `memories/<name>`.
112
+ */
113
+ export function resolveParentRef(name, frontmatter) {
114
+ const fromSource = parseMemoryRef(asNonEmptyString(frontmatter.source));
115
+ if (fromSource)
116
+ return fromSource;
117
+ const derivedFrom = asNonEmptyString(frontmatter.derivedFrom);
118
+ if (derivedFrom)
119
+ return conceptIdFromTypeName("memory", derivedFrom);
120
+ if (name.endsWith(DERIVED_SUFFIX)) {
121
+ return conceptIdFromTypeName("memory", name.slice(0, -DERIVED_SUFFIX.length));
122
+ }
123
+ return undefined;
124
+ }
@@ -28,6 +28,25 @@
28
28
  * - MemOS (arXiv:2507.03724) — formal archive/merge/transition with shared state model
29
29
  */
30
30
  import { mutateFrontmatter } from "../../../core/asset/frontmatter.js";
31
+ // ── Shared edge-list reader ───────────────────────────────────────────────────
32
+ /**
33
+ * Read a frontmatter edge value (`supersededBy` / `contradictedBy`) as a
34
+ * string list, promoting a scalar string to a one-element list.
35
+ *
36
+ * Scalar edges are LIVE data: the indexer's `normalizeNonEmptyStringList`
37
+ * accepts them and lint deliberately never flags them. An Array.isArray-only
38
+ * read treats a scalar as "no existing edges" and silently destroys the edge
39
+ * on the next merge — mirror `mergeXrefsIntoContent`'s scalar promotion
40
+ * instead.
41
+ */
42
+ function readEdgeList(value) {
43
+ if (Array.isArray(value)) {
44
+ return value.filter((v) => typeof v === "string" && v.trim().length > 0);
45
+ }
46
+ if (typeof value === "string" && value.trim())
47
+ return [value.trim()];
48
+ return [];
49
+ }
31
50
  // ── Contradiction edge writer ─────────────────────────────────────────────────
32
51
  /**
33
52
  * Write `contradictedBy` and `beliefState: contradicted` edges to a memory
@@ -38,24 +57,77 @@ import { mutateFrontmatter } from "../../../core/asset/frontmatter.js";
38
57
  * - `memory-contradiction-detect.ts` for the M-1 automated contradiction pass
39
58
  * - `resolveFamilyContradictions` in `memory-improve.ts` for SCC resolution
40
59
  *
41
- * Idempotent: if the `contradictedByRef` is already in `contradictedBy`,
42
- * the file is not rewritten.
60
+ * Idempotent: if the `contradictedByRef` is already in `contradictedBy` AND
61
+ * the file already carries the demotion state, the file is not rewritten. The
62
+ * guard is state-aware like its sibling {@link writeSupersededEdge}: an edge
63
+ * present WITHOUT the demotion (e.g. a hand-written `contradictedBy:` line,
64
+ * or a beliefState lost to a partial edit) is repaired, not skipped — an
65
+ * edge-only guard would make such a file a permanent no-op while
66
+ * contradiction writers report the contradiction as applied.
67
+ *
68
+ * Never weakens a stronger demotion: `archived` ranks BELOW `contradicted`
69
+ * (see `BELIEF_STATE_SCORE_CEILINGS` in
70
+ * src/indexer/search/ranking-contributors.ts), so contradicting an archived
71
+ * memory keeps `archived` and only appends the edge.
43
72
  *
44
73
  * @param filePath - Absolute path to the memory markdown file.
45
74
  * @param contradictedByRef - The ref that contradicts this memory.
46
75
  */
47
76
  export function writeContradictEdge(filePath, contradictedByRef) {
48
77
  mutateFrontmatter(filePath, (parsed) => {
49
- const existing = Array.isArray(parsed.data.contradictedBy)
50
- ? parsed.data.contradictedBy
51
- : [];
52
- if (existing.includes(contradictedByRef))
78
+ const existing = readEdgeList(parsed.data.contradictedBy);
79
+ const currentState = parsed.data.beliefState;
80
+ const nextState = currentState === "archived" ? currentState : "contradicted";
81
+ if (existing.includes(contradictedByRef) && currentState === nextState) {
53
82
  return null; // Already written — idempotent.
83
+ }
54
84
  const nextContradictedBy = [...new Set([...existing, contradictedByRef])].sort();
55
85
  return {
56
86
  ...parsed.data,
57
87
  contradictedBy: nextContradictedBy,
58
- beliefState: "contradicted",
88
+ beliefState: nextState,
89
+ };
90
+ });
91
+ }
92
+ // ── Supersession edge writer ─────────────────────────────────────────────────
93
+ /**
94
+ * Write `supersededBy` and `beliefState: superseded` edges to an asset file's
95
+ * frontmatter (SPEC-5, stash-conventions-code-spec.md).
96
+ *
97
+ * Sibling of {@link writeContradictEdge}: the shared primitive for the
98
+ * conventions' corrections pattern — when a new asset supersedes an old one,
99
+ * the old asset gets a METADATA-ONLY demotion edit (every other frontmatter
100
+ * key and the body are preserved) so the ranker's beliefStateBoost demotes the
101
+ * stale incumbent and `--belief current` hides it. Used by
102
+ * `akm remember --supersedes` / `akm import --supersedes`.
103
+ *
104
+ * Idempotent: if `supersededByRef` is already in `supersededBy` and the file
105
+ * is already demoted, the file is not rewritten. Multiple corrections
106
+ * sorted-set-append their refs.
107
+ *
108
+ * Never WEAKENS an existing demotion: `contradicted` and `archived` rank
109
+ * BELOW `superseded` (severity order deprecated > superseded > contradicted >
110
+ * archived — see `BELIEF_STATE_SCORE_CEILINGS` in
111
+ * src/indexer/search/ranking-contributors.ts), so superseding an already
112
+ * contradicted/archived asset keeps the stronger state and only appends the
113
+ * `supersededBy` edge.
114
+ *
115
+ * @param filePath - Absolute path to the asset markdown file.
116
+ * @param supersededByRef - The ref of the correction that supersedes this asset.
117
+ */
118
+ export function writeSupersededEdge(filePath, supersededByRef) {
119
+ mutateFrontmatter(filePath, (parsed) => {
120
+ const existing = readEdgeList(parsed.data.supersededBy);
121
+ const currentState = parsed.data.beliefState;
122
+ const nextState = currentState === "contradicted" || currentState === "archived" ? currentState : "superseded";
123
+ if (existing.includes(supersededByRef) && currentState === nextState) {
124
+ return null; // Already written — idempotent.
125
+ }
126
+ const nextSupersededBy = [...new Set([...existing, supersededByRef])].sort();
127
+ return {
128
+ ...parsed.data,
129
+ supersededBy: nextSupersededBy,
130
+ beliefState: nextState,
59
131
  };
60
132
  });
61
133
  }
@@ -22,7 +22,7 @@
22
22
  *
23
23
  * # LLM Feature Gate
24
24
  *
25
- * The pass is gated behind `profiles.improve.default.processes.consolidate.contradictionDetection.enabled`.
25
+ * The pass is gated by the selected strategy's consolidate contradiction setting.
26
26
  * When the gate is disabled or no LLM is configured,
27
27
  * the pass is a no-op and `analyzeMemoryCleanup` proceeds with only manually
28
28
  * annotated edges.
@@ -37,9 +37,12 @@ import fs from "node:fs";
37
37
  import path from "node:path";
38
38
  import contradictionJudgeTemplate from "../../../assets/prompts/contradiction-judge.md" with { type: "text" };
39
39
  import { mutateFrontmatter, parseFrontmatter } from "../../../core/asset/frontmatter.js";
40
- import { getDefaultLlmConfig } from "../../../core/config/config.js";
41
- import { chatCompletion, parseEmbeddedJsonResponse } from "../../../llm/client.js";
42
- import { tryLlmFeature } from "../../../llm/feature-gate.js";
40
+ import { parseEmbeddedJsonResponse } from "../../../core/parse.js";
41
+ import { getDefaultLlmConfig } from "../../../integrations/agent/engine-resolution.js";
42
+ import { materializeLlmRunnerConnection, resolveImproveProcessRunner } from "../../../integrations/agent/runner.js";
43
+ import { chatCompletion } from "../../../llm/client.js";
44
+ import { callStructured } from "../../../llm/structured-call.js";
45
+ import { isDerivedMemory, memoryIdentityRef, resolveParentRef } from "./derived-ref.js";
43
46
  // ── Constants ────────────────────────────────────────────────────────────────
44
47
  /**
45
48
  * Maximum family size for pairwise contradiction checking. Families larger
@@ -54,8 +57,7 @@ const MAX_PAIRS_PER_RUN = 20;
54
57
  /**
55
58
  * Minimum confidence required to write a contradiction edge. Below this
56
59
  * threshold the LLM may be flagging topic-overlap rather than genuine logical
57
- * exclusivity (investigation 2026-06-18). Absent confidence fields default to
58
- * 1.0 for backward compatibility with older judge responses.
60
+ * exclusivity (investigation 2026-06-18).
59
61
  */
60
62
  const CONTRADICT_CONFIDENCE_THRESHOLD = 0.92;
61
63
  /**
@@ -85,37 +87,17 @@ function* walkMarkdownFilesLocal(root) {
85
87
  yield full;
86
88
  }
87
89
  }
90
+ // Build the derived memory's own belief-edge IDENTITY ref from its file path.
91
+ // Emits through the shared {@link memoryIdentityRef} so this — the former THIRD
92
+ // hand-rolled copy of the identity-channel spelling — no longer diverges from
93
+ // memory-improve's `refArray` (ref-grammar decision D-R3 identity-channel
94
+ // exception, documented at `memoryIdentityRef`).
88
95
  function toMemoryRef(memoriesDir, filePath) {
89
96
  const rel = path.relative(memoriesDir, filePath);
90
97
  if (!rel || rel.startsWith(".."))
91
98
  return undefined;
92
99
  const name = rel.replace(/\\/g, "/").replace(/\.md$/i, "");
93
- return `memory:${name}`;
94
- }
95
- function isDerivedMemory(filePath, frontmatter) {
96
- // Name-based guard (M-2): the .derived suffix is structural and immutable.
97
- const base = path.basename(filePath, ".md");
98
- if (base.endsWith(".derived"))
99
- return true;
100
- // Frontmatter-based guard: inferred: true marks explicit child memories.
101
- return frontmatter.inferred === true;
102
- }
103
- function resolveParentRef(filePath, frontmatter, memoriesRootDir) {
104
- // Prefer the explicit source: frontmatter.
105
- const source = frontmatter.source;
106
- if (typeof source === "string" && source.startsWith("memory:"))
107
- return source;
108
- // Fall back to deriving parent from the file name (strip .derived suffix).
109
- const base = path.basename(filePath, ".md");
110
- if (base.endsWith(".derived")) {
111
- const parentName = base.slice(0, -".derived".length);
112
- // Use the stash memories root so nested paths (e.g. memories/nested/foo.derived.md)
113
- // resolve to the correct relative ref (memory:nested/foo, not memory:foo).
114
- const rootDir = memoriesRootDir ?? path.dirname(filePath);
115
- const rel = path.relative(rootDir, path.join(path.dirname(filePath), parentName));
116
- return `memory:${rel.replace(/\\/g, "/")}`;
117
- }
118
- return undefined;
100
+ return memoryIdentityRef(name);
119
101
  }
120
102
  // ── Edge writing ─────────────────────────────────────────────────────────────
121
103
  /**
@@ -173,14 +155,20 @@ function pickContradictionLoser(a, b) {
173
155
  * @param config - Loaded AKM config (used to access LLM settings).
174
156
  * @param chat - Optional chat seam for testing (defaults to chatCompletion).
175
157
  */
176
- export async function detectAndWriteContradictions(stashDir, config, chat = chatCompletion) {
158
+ export async function detectAndWriteContradictions(stashDir, config, chat = chatCompletion, strategy, resolvedLlmConfig) {
177
159
  const result = {
178
160
  familiesExamined: 0,
179
161
  pairsChecked: 0,
180
162
  edgesWritten: 0,
181
163
  warnings: [],
182
164
  };
183
- const contradictionLlm = getDefaultLlmConfig(config);
165
+ const contradictionLlm = resolvedLlmConfig === null
166
+ ? undefined
167
+ : (resolvedLlmConfig ??
168
+ (() => {
169
+ const runner = resolveImproveProcessRunner(strategy, "consolidate", config);
170
+ return runner ? materializeLlmRunnerConnection(runner) : getDefaultLlmConfig(config);
171
+ })());
184
172
  if (!contradictionLlm)
185
173
  return result;
186
174
  // Collect derived memories grouped by parent.
@@ -195,14 +183,20 @@ export async function detectAndWriteContradictions(stashDir, config, chat = chat
195
183
  continue;
196
184
  }
197
185
  const parsed = parseFrontmatter(raw);
198
- if (!isDerivedMemory(filePath, parsed.data))
199
- continue;
200
- const parentRef = resolveParentRef(filePath, parsed.data, memoriesDir);
201
- if (!parentRef)
202
- continue;
203
186
  const ref = toMemoryRef(memoriesDir, filePath);
204
187
  if (!ref)
205
188
  continue;
189
+ // Key the shared derived-ref helpers on the memory NAME (stash-relative, no
190
+ // extension) — the same key the consumer uses — so producer and consumer
191
+ // resolve the identical parent (R12). This intentionally widens the producer
192
+ // to honour `derivedFrom` and normalised `source:` values it previously
193
+ // dropped (pinned by derived-ref.test.ts).
194
+ const name = ref.slice("memory:".length);
195
+ if (!isDerivedMemory(name, parsed.data))
196
+ continue;
197
+ const parentRef = resolveParentRef(name, parsed.data);
198
+ if (!parentRef)
199
+ continue;
206
200
  const entry = {
207
201
  filePath,
208
202
  ref,
@@ -236,11 +230,6 @@ export async function detectAndWriteContradictions(stashDir, config, chat = chat
236
230
  // edge already exists (no new information; avoids re-judging resolved
237
231
  // pairs across runs).
238
232
  //
239
- // Legacy mutual A↔B edges written by the pre-fix pass self-heal: the
240
- // skip fires this run, but the SCC resolver treats the 2-cycle as a sink
241
- // and refreshes both to active — DELETING both `contradictedBy` arrays
242
- // (memory-improve.ts persistBeliefStateTransition). The next detection
243
- // run then sees no edge, re-judges, and writes the single canonical edge.
244
233
  const aParsed = parseFrontmatter(fs.readFileSync(a.filePath, "utf8"));
245
234
  const bParsed = parseFrontmatter(fs.readFileSync(b.filePath, "utf8"));
246
235
  const { loser, winnerRef } = pickContradictionLoser(a, b);
@@ -249,12 +238,23 @@ export async function detectAndWriteContradictions(stashDir, config, chat = chat
249
238
  if (loserCB.includes(winnerRef))
250
239
  continue;
251
240
  const prompt = buildContradictionJudgePrompt(a, b);
252
- const judgeResult = await tryLlmFeature("memory_contradiction_detection", config, async () => {
253
- return chat(contradictionLlm, [
241
+ const judgeResult = await callStructured({
242
+ feature: "memory_contradiction_detection",
243
+ akmConfig: config,
244
+ // Resolver-less key: the strategy decision IS the gate (default-off).
245
+ enabled: strategy?.processes?.consolidate?.contradictionDetection?.enabled ?? false,
246
+ config: contradictionLlm,
247
+ messages: [
254
248
  { role: "system", content: "Return only valid JSON. No prose." },
255
249
  { role: "user", content: prompt },
256
- ]);
257
- }, null);
250
+ ],
251
+ request: { chat },
252
+ parse: (raw) => raw ?? null,
253
+ // A transport throw used to escape the gated fn into the gate's
254
+ // catch and take the null fallback ("skip"); onError reproduces it.
255
+ onError: () => null,
256
+ fallback: null, // null means "skip" — gate disabled or LLM call failed.
257
+ });
258
258
  totalPairsChecked++;
259
259
  result.pairsChecked++;
260
260
  if (!judgeResult)
@@ -269,10 +269,7 @@ export async function detectAndWriteContradictions(stashDir, config, chat = chat
269
269
  }
270
270
  if (!parsed?.contradicts)
271
271
  continue;
272
- // Confidence gate: absent field defaults to 1.0 (backward compat with
273
- // pre-confidence responses). Do NOT default to 0 — that would silently
274
- // disable all detection during the rollout period.
275
- const confidence = typeof parsed.confidence === "number" ? parsed.confidence : 1.0;
272
+ const confidence = typeof parsed.confidence === "number" ? parsed.confidence : 0;
276
273
  if (confidence < CONTRADICT_CONFIDENCE_THRESHOLD) {
277
274
  result.warnings.push(`Pair ${a.ref} / ${b.ref}: confidence ${confidence.toFixed(2)} below ${CONTRADICT_CONFIDENCE_THRESHOLD} threshold — skipped.`);
278
275
  continue;
@@ -3,11 +3,12 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
- import { makeAssetRef, parseAssetRef } from "../../../core/asset/asset-ref.js";
7
6
  import { assembleAsset } from "../../../core/asset/asset-serialize.js";
8
7
  import { mutateFrontmatter, parseFrontmatter } from "../../../core/asset/frontmatter.js";
8
+ import { conceptIdFromTypeName } from "../../../core/asset/resolve-ref.js";
9
9
  import { asNonEmptyString, groupBy, stringArray } from "../../../core/common.js";
10
- const DERIVED_SUFFIX = ".derived";
10
+ import { DERIVED_SUFFIX } from "../../../core/recognition-util.js";
11
+ import { isDerivedMemory, memoryIdentityRef, parseMemoryName, resolveParentRef } from "./derived-ref.js";
11
12
  export function analyzeMemoryCleanup(stashDir, options = {}) {
12
13
  const records = collectDerivedMemories(stashDir, options.parentRef);
13
14
  const byRef = new Map(records.map((record) => [record.ref, record]));
@@ -87,6 +88,8 @@ export function analyzeMemoryCleanup(stashDir, options = {}) {
87
88
  if (duplicates.length < 2)
88
89
  continue;
89
90
  const [survivor, ...rest] = sortRecordsForSurvival(duplicates);
91
+ if (survivor === undefined)
92
+ continue;
90
93
  for (const duplicate of rest) {
91
94
  planPrune(duplicate, "duplicate-derived", survivor.ref);
92
95
  }
@@ -587,7 +590,7 @@ function collectDerivedMemories(stashDir, parentRefFilter) {
587
590
  const body = parsed.content.trim();
588
591
  const signalKey = normalizeSignal(firstNonEmpty([title, description, searchHints[0]]));
589
592
  records.push({
590
- ref: makeAssetRef("memory", name),
593
+ ref: `memory:${name}`,
591
594
  name,
592
595
  filePath,
593
596
  parentRef,
@@ -596,7 +599,11 @@ function collectDerivedMemories(stashDir, parentRefFilter) {
596
599
  tags,
597
600
  searchHints,
598
601
  body,
599
- canonicalName: name === `${parentRef.slice("memory:".length)}${DERIVED_SUFFIX}`,
602
+ // parentRef is the 0.9.0 `memories/<name>` conceptId (Group-C item 2), so
603
+ // the canonical-child test compares the minted conceptId of the suffix-
604
+ // stripped name against it rather than slicing a fixed `memory:` prefix.
605
+ canonicalName: name.endsWith(DERIVED_SUFFIX) &&
606
+ parentRef === conceptIdFromTypeName("memory", name.slice(0, -DERIVED_SUFFIX.length)),
600
607
  signalScore: computeSignalScore(title, description, tags, searchHints, body),
601
608
  fingerprint: buildFingerprint(title, description, tags, searchHints, body),
602
609
  ...(signalKey ? { signalKey } : {}),
@@ -647,25 +654,19 @@ function resolveBeliefState(frontmatter) {
647
654
  }
648
655
  return "active";
649
656
  }
650
- function isDerivedMemory(name, frontmatter) {
651
- return frontmatter.inferred === true || name.endsWith(DERIVED_SUFFIX);
652
- }
653
- function resolveParentRef(name, frontmatter) {
654
- const fromSource = parseMemoryRef(asNonEmptyString(frontmatter.source));
655
- if (fromSource)
656
- return fromSource;
657
- const derivedFrom = asNonEmptyString(frontmatter.derivedFrom);
658
- if (derivedFrom)
659
- return makeAssetRef("memory", derivedFrom);
660
- if (name.endsWith(DERIVED_SUFFIX)) {
661
- return makeAssetRef("memory", name.slice(0, -DERIVED_SUFFIX.length));
662
- }
663
- return undefined;
664
- }
657
+ // Belief-edge refs (contradictedBy / supersededBy / currentBeliefRefs) are the
658
+ // IDENTITY channel: they are compared against a derived memory's own
659
+ // `memory:<name>` ref (resolveFamilyContradictions' familyRefSet,
660
+ // firstExistingRef's byRef map), so they are NORMALIZED to `memory:<name>` here.
661
+ // On disk they arrive in either spelling — `memory:<name>` from pre-0.9.0
662
+ // writes, or the `[<bundle>//]memories/<name>` conceptId that
663
+ // `writeSupersededEdge`/`writeContradictEdge` persist today — and
664
+ // `parseMemoryName` accepts both. Reading only the first spelling silently
665
+ // dropped every edge the current write path produces.
665
666
  function refArray(value) {
666
667
  if (typeof value === "string") {
667
- const parsed = parseMemoryRef(value);
668
- return parsed ? [parsed] : [];
668
+ const name = parseMemoryName(value);
669
+ return name === undefined ? [] : [memoryIdentityRef(name)];
669
670
  }
670
671
  if (!Array.isArray(value))
671
672
  return [];
@@ -673,25 +674,12 @@ function refArray(value) {
673
674
  for (const item of value) {
674
675
  if (typeof item !== "string")
675
676
  continue;
676
- const parsed = parseMemoryRef(item);
677
- if (parsed)
678
- refs.add(parsed);
677
+ const name = parseMemoryName(item);
678
+ if (name !== undefined)
679
+ refs.add(memoryIdentityRef(name));
679
680
  }
680
681
  return [...refs].sort();
681
682
  }
682
- function parseMemoryRef(value) {
683
- if (!value)
684
- return undefined;
685
- try {
686
- const parsed = parseAssetRef(value.trim());
687
- if (parsed.type !== "memory")
688
- return undefined;
689
- return makeAssetRef(parsed.type, parsed.name);
690
- }
691
- catch {
692
- return undefined;
693
- }
694
- }
695
683
  function buildFingerprint(title, description, tags, searchHints, body) {
696
684
  return JSON.stringify({
697
685
  title: normalizeSignal(title),