akm-cli 0.9.0-rc.0 → 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 (598) hide show
  1. package/CHANGELOG.md +1283 -22
  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/prompts/workflow-unit-preamble.md +26 -0
  26. package/dist/assets/stash-skeleton/README.md +38 -10
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
  39. package/dist/assets/tasks/core/extract.yml +3 -2
  40. package/dist/assets/tasks/core/improve.yml +2 -1
  41. package/dist/assets/tasks/core/index-refresh.yml +1 -0
  42. package/dist/assets/tasks/core/sync.yml +1 -0
  43. package/dist/assets/tasks/core/version-check.yml +2 -1
  44. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  45. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  46. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  47. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  48. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  49. package/dist/assets/templates/html/health.html +5 -4
  50. package/dist/assets/workflows/workflow-template.md +31 -15
  51. package/dist/cli/invocation.js +279 -0
  52. package/dist/cli/parse-args.js +5 -90
  53. package/dist/cli/retired-commands.js +78 -0
  54. package/dist/cli/shared.js +158 -48
  55. package/dist/cli-node.mjs +2 -1
  56. package/dist/cli.js +747 -293
  57. package/dist/commands/agent/agent-dispatch.js +19 -18
  58. package/dist/commands/agent/agent-support.js +0 -24
  59. package/dist/commands/agent/contribute-cli.js +43 -97
  60. package/dist/commands/completions.js +80 -23
  61. package/dist/commands/config-cli.js +44 -281
  62. package/dist/commands/env/env-binding.js +99 -0
  63. package/dist/commands/env/env-cli.js +84 -224
  64. package/dist/commands/env/env.js +12 -163
  65. package/dist/commands/env/marker-path.js +6 -0
  66. package/dist/commands/env/secret-cli.js +45 -61
  67. package/dist/commands/env/secret.js +32 -62
  68. package/dist/commands/feedback-cli.js +179 -85
  69. package/dist/commands/health/accept-rate.js +58 -0
  70. package/dist/commands/health/advisories.js +7 -8
  71. package/dist/commands/health/checks.js +279 -94
  72. package/dist/commands/health/html-report.js +197 -578
  73. package/dist/commands/health/improve-metrics.js +277 -246
  74. package/dist/commands/health/llm-usage.js +19 -19
  75. package/dist/commands/health/md-report.js +16 -7
  76. package/dist/commands/health/metrics.js +67 -32
  77. package/dist/commands/health/renderers.js +47 -0
  78. package/dist/commands/health/report-view-model.js +508 -0
  79. package/dist/commands/health/stash-exposure.js +1 -1
  80. package/dist/commands/health/surfaces.js +16 -56
  81. package/dist/commands/health/task-runs.js +3 -67
  82. package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
  83. package/dist/commands/health/types-improve.js +29 -0
  84. package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
  85. package/dist/commands/health/types-result.js +7 -0
  86. package/dist/commands/health/types-runs.js +4 -0
  87. package/dist/commands/health/types-session-log.js +4 -0
  88. package/dist/commands/health/types-windows.js +4 -0
  89. package/dist/commands/health/types.js +26 -21
  90. package/dist/commands/health/windows.js +2 -3
  91. package/dist/commands/health.js +296 -167
  92. package/dist/commands/improve/anti-collapse.js +5 -5
  93. package/dist/commands/improve/autonomy-gate.js +68 -0
  94. package/dist/commands/improve/collapse-detector.js +65 -52
  95. package/dist/commands/improve/consolidate/chunking.js +9 -7
  96. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  97. package/dist/commands/improve/consolidate/merge.js +4 -0
  98. package/dist/commands/improve/consolidate.js +454 -1354
  99. package/dist/commands/improve/content-hash.js +39 -0
  100. package/dist/commands/improve/distill/content-repair.js +4 -10
  101. package/dist/commands/improve/distill/promote-memory.js +89 -64
  102. package/dist/commands/improve/distill/quality-gate.js +118 -42
  103. package/dist/commands/improve/distill-guards.js +1 -1
  104. package/dist/commands/improve/distill-promotion-policy.js +33 -888
  105. package/dist/commands/improve/distill.js +607 -363
  106. package/dist/commands/improve/eligibility.js +165 -79
  107. package/dist/commands/improve/extract-cli.js +35 -126
  108. package/dist/commands/improve/extract-prompt.js +6 -35
  109. package/dist/commands/improve/extract.js +640 -391
  110. package/dist/commands/improve/feedback-valence.js +2 -12
  111. package/dist/commands/improve/improve-cli.js +134 -135
  112. package/dist/commands/improve/improve-result-file.js +30 -50
  113. package/dist/commands/improve/improve-run-types.js +4 -0
  114. package/dist/commands/improve/improve-strategies.js +135 -0
  115. package/dist/commands/improve/improve.js +904 -701
  116. package/dist/commands/improve/locks.js +64 -111
  117. package/dist/commands/improve/loop-stages.js +1110 -923
  118. package/dist/commands/improve/memory/derived-ref.js +124 -0
  119. package/dist/commands/improve/memory/memory-belief.js +79 -7
  120. package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
  121. package/dist/commands/improve/memory/memory-improve.js +25 -37
  122. package/dist/commands/improve/outcome-loop.js +25 -88
  123. package/dist/commands/improve/preparation.js +1034 -813
  124. package/dist/commands/improve/proactive-maintenance.js +34 -9
  125. package/dist/commands/improve/proposal-envelope.js +31 -0
  126. package/dist/commands/improve/reflect.js +983 -794
  127. package/dist/commands/improve/run-context.js +119 -0
  128. package/dist/commands/improve/salience.js +24 -127
  129. package/dist/commands/improve/session-asset.js +7 -3
  130. package/dist/commands/improve/shared.js +14 -34
  131. package/dist/commands/improve/source-identity.js +28 -0
  132. package/dist/commands/improve/triage.js +20 -17
  133. package/dist/commands/lint/base-linter.js +340 -313
  134. package/dist/commands/lint/env-key-rules.js +31 -47
  135. package/dist/commands/lint/index.js +185 -30
  136. package/dist/commands/{events.js → log.js} +28 -38
  137. package/dist/commands/migrate-cli.js +54 -0
  138. package/dist/commands/migration-tool.js +55 -0
  139. package/dist/commands/observability-cli.js +70 -208
  140. package/dist/commands/proposal/diff-format.js +50 -0
  141. package/dist/commands/proposal/drain-policies.js +0 -6
  142. package/dist/commands/proposal/drain.js +91 -40
  143. package/dist/commands/proposal/proposal-cli.js +134 -132
  144. package/dist/commands/proposal/proposal-types.js +56 -0
  145. package/dist/commands/proposal/proposal.js +83 -65
  146. package/dist/commands/proposal/propose-cli.js +88 -0
  147. package/dist/commands/proposal/propose.js +105 -88
  148. package/dist/commands/proposal/repository.js +1303 -278
  149. package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
  150. package/dist/commands/proposal/validators/proposal-validators.js +61 -12
  151. package/dist/commands/proposal/validators/proposals.js +6 -8
  152. package/dist/commands/read/curate.js +78 -73
  153. package/dist/commands/read/knowledge.js +510 -13
  154. package/dist/commands/read/registry-search.js +2 -2
  155. package/dist/commands/read/remember-cli.js +84 -15
  156. package/dist/commands/read/search-cli.js +203 -96
  157. package/dist/commands/read/search.js +126 -94
  158. package/dist/commands/read/show.js +226 -250
  159. package/dist/commands/registry-cli.js +34 -60
  160. package/dist/commands/remember.js +18 -57
  161. package/dist/commands/sources/add-cli.js +104 -49
  162. package/dist/commands/sources/bundle-cli.js +166 -0
  163. package/dist/commands/sources/bundle-config-ops.js +63 -0
  164. package/dist/commands/sources/info.js +27 -15
  165. package/dist/commands/sources/init.js +30 -40
  166. package/dist/commands/sources/installed-stashes.js +469 -172
  167. package/dist/commands/sources/migration-help.js +7 -4
  168. package/dist/commands/sources/schema-repair.js +10 -9
  169. package/dist/commands/sources/self-update.js +182 -121
  170. package/dist/commands/sources/source-add.js +169 -178
  171. package/dist/commands/sources/source-clone.js +144 -41
  172. package/dist/commands/sources/source-manage.js +94 -59
  173. package/dist/commands/sources/sources-cli.js +64 -205
  174. package/dist/commands/sources/stash-cli.js +91 -54
  175. package/dist/commands/sources/stash-skeleton.js +1 -1
  176. package/dist/commands/tasks/tasks-cli.js +106 -104
  177. package/dist/commands/tasks/tasks.js +445 -262
  178. package/dist/commands/workflow-cli.js +232 -121
  179. package/dist/core/action-contributors.js +1 -1
  180. package/dist/core/activation-policy.js +49 -0
  181. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  182. package/dist/core/adapter/adapters/akm-adapter.js +528 -0
  183. package/dist/core/adapter/adapters/akm-lint.js +392 -0
  184. package/dist/core/adapter/adapters/akm-metadata.js +387 -0
  185. package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
  186. package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
  187. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  188. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  189. package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
  190. package/dist/core/adapter/adapters/index.js +80 -0
  191. package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
  192. package/dist/core/adapter/adapters/okf-adapter.js +391 -0
  193. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  194. package/dist/core/adapter/adapters/shared.js +286 -0
  195. package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
  196. package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
  197. package/dist/core/adapter/bundle-adapter.js +4 -0
  198. package/dist/core/adapter/detect-adapter.js +17 -0
  199. package/dist/core/adapter/recognize-match.js +44 -0
  200. package/dist/core/adapter/registry.js +56 -0
  201. package/dist/core/adapter/types.js +4 -0
  202. package/dist/core/asset/akm-markdown.js +30 -0
  203. package/dist/core/asset/asset-placement.js +243 -0
  204. package/dist/core/asset/asset-ref.js +110 -79
  205. package/dist/core/asset/asset-serialize.js +20 -0
  206. package/dist/core/asset/frontmatter.js +28 -12
  207. package/dist/core/asset/markdown.js +40 -51
  208. package/dist/core/asset/resolve-ref.js +274 -0
  209. package/dist/core/asset/stash-meta.js +2 -2
  210. package/dist/core/bundle-id.js +51 -0
  211. package/dist/core/common.js +281 -86
  212. package/dist/core/config/config-io.js +42 -128
  213. package/dist/core/config/config-schema.js +233 -834
  214. package/dist/core/config/config-sources.js +162 -39
  215. package/dist/core/config/config-types.js +16 -11
  216. package/dist/core/config/config-version.js +29 -0
  217. package/dist/core/config/config-walker.js +126 -37
  218. package/dist/core/config/config.js +154 -331
  219. package/dist/core/config/deep-merge.js +41 -0
  220. package/dist/core/config/engine-semantics.js +28 -0
  221. package/dist/core/config/experimental.js +21 -0
  222. package/dist/core/config/schema/embedding.js +38 -0
  223. package/dist/core/config/schema/engines.js +116 -0
  224. package/dist/core/config/schema/experimental.js +47 -0
  225. package/dist/core/config/schema/feedback.js +31 -0
  226. package/dist/core/config/schema/improve-processes.js +389 -0
  227. package/dist/core/config/schema/improve.js +94 -0
  228. package/dist/core/config/schema/index-config.js +176 -0
  229. package/dist/core/config/schema/output.js +18 -0
  230. package/dist/core/config/schema/primitives.js +94 -0
  231. package/dist/core/config/schema/search.js +30 -0
  232. package/dist/core/config/schema/setup.js +18 -0
  233. package/dist/core/config/schema/sources-bundles.js +169 -0
  234. package/dist/core/config/schema/workflow.js +29 -0
  235. package/dist/core/env-secret-ref.js +155 -20
  236. package/dist/core/errors.js +17 -15
  237. package/dist/core/events-types.js +4 -0
  238. package/dist/core/events.js +46 -128
  239. package/dist/core/extra-params.js +62 -0
  240. package/dist/core/file-change.js +17 -0
  241. package/dist/core/file-lock.js +202 -57
  242. package/dist/core/fs-txn.js +392 -0
  243. package/dist/core/git-message.js +59 -0
  244. package/dist/core/improve-result.js +167 -0
  245. package/dist/core/json-schema.js +142 -0
  246. package/dist/core/lesson-lint.js +1 -17
  247. package/dist/core/logs-db.js +1 -1
  248. package/dist/core/maintenance-barrier.js +135 -0
  249. package/dist/core/migration-operation.js +44 -0
  250. package/dist/core/mutation-target.js +78 -0
  251. package/dist/core/paths.js +22 -25
  252. package/dist/core/platform.js +10 -0
  253. package/dist/core/recognition-util.js +128 -0
  254. package/dist/core/redaction.js +392 -0
  255. package/dist/core/standards/resolve-standards-context.js +36 -65
  256. package/dist/core/standards/resolve-stash-standards.js +2 -2
  257. package/dist/core/standards/resolve-type-conventions.js +5 -5
  258. package/dist/core/state/migrations.js +242 -11
  259. package/dist/core/state-db.js +98 -10
  260. package/dist/core/structured.js +1 -1
  261. package/dist/core/subprocess.js +303 -0
  262. package/dist/core/text-truncation.js +9 -5
  263. package/dist/core/time.js +20 -0
  264. package/dist/core/type-presentation.js +130 -0
  265. package/dist/core/warn.js +0 -3
  266. package/dist/core/write-source.js +834 -118
  267. package/dist/indexer/bundle-identity-guard.js +92 -0
  268. package/dist/indexer/db/graph-db.js +1 -25
  269. package/dist/indexer/db/llm-cache.js +1 -1
  270. package/dist/indexer/ensure-index.js +30 -9
  271. package/dist/indexer/graph/graph-boost.js +9 -30
  272. package/dist/indexer/graph/graph-extraction.js +41 -27
  273. package/dist/indexer/graph/graph-types.js +4 -0
  274. package/dist/indexer/index-writer-lock.js +93 -49
  275. package/dist/indexer/index-written-assets.js +100 -53
  276. package/dist/indexer/indexer.js +746 -329
  277. package/dist/indexer/init.js +18 -25
  278. package/dist/indexer/installations.js +142 -0
  279. package/dist/indexer/passes/dir-staleness.js +18 -10
  280. package/dist/indexer/passes/memory-inference.js +25 -15
  281. package/dist/indexer/passes/metadata.js +412 -243
  282. package/dist/indexer/scan/doc-to-entry.js +160 -0
  283. package/dist/indexer/scan/drain-dir.js +134 -0
  284. package/dist/indexer/search/db-search.js +292 -108
  285. package/dist/indexer/search/fts-query.js +64 -0
  286. package/dist/indexer/search/ranking-contributors.js +145 -25
  287. package/dist/indexer/search/ranking-types.js +4 -0
  288. package/dist/indexer/search/ranking.js +28 -71
  289. package/dist/indexer/search/search-attribution.js +67 -0
  290. package/dist/indexer/search/search-fields.js +18 -3
  291. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  292. package/dist/indexer/search/search-source.js +157 -111
  293. package/dist/indexer/search/semantic-status.js +4 -1
  294. package/dist/indexer/usage/usage-events.js +10 -30
  295. package/dist/indexer/walk/file-context.js +3 -45
  296. package/dist/indexer/walk/matchers.js +42 -34
  297. package/dist/indexer/walk/path-resolver.js +11 -5
  298. package/dist/indexer/walk/walker.js +42 -14
  299. package/dist/integrations/agent/builder-shared.js +7 -0
  300. package/dist/integrations/agent/builders.js +5 -56
  301. package/dist/integrations/agent/config.js +3 -143
  302. package/dist/integrations/agent/detect.js +17 -2
  303. package/dist/integrations/agent/engine-resolution.js +231 -0
  304. package/dist/integrations/agent/index.js +1 -2
  305. package/dist/integrations/agent/model-aliases.js +16 -2
  306. package/dist/integrations/agent/profiles.js +36 -62
  307. package/dist/integrations/agent/prompts.js +46 -18
  308. package/dist/integrations/agent/runner-dispatch.js +93 -4
  309. package/dist/integrations/agent/runner.js +76 -208
  310. package/dist/integrations/agent/spawn.js +88 -196
  311. package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
  312. package/dist/integrations/harnesses/aider/index.js +48 -0
  313. package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
  314. package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
  315. package/dist/integrations/harnesses/amazonq/index.js +45 -0
  316. package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
  317. package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
  318. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  319. package/dist/integrations/harnesses/claude/index.js +24 -35
  320. package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
  321. package/dist/integrations/harnesses/claude/session-log.js +27 -75
  322. package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
  323. package/dist/integrations/harnesses/codex/index.js +52 -0
  324. package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
  325. package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
  326. package/dist/integrations/harnesses/copilot/index.js +48 -0
  327. package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
  328. package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
  329. package/dist/integrations/harnesses/gemini/index.js +48 -0
  330. package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
  331. package/dist/integrations/harnesses/ids.js +24 -0
  332. package/dist/integrations/harnesses/index.js +54 -34
  333. package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
  334. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  335. package/dist/integrations/harnesses/opencode/index.js +14 -32
  336. package/dist/integrations/harnesses/opencode/session-log.js +67 -125
  337. package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
  338. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
  339. package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
  340. package/dist/integrations/harnesses/openhands/index.js +48 -0
  341. package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
  342. package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
  343. package/dist/integrations/harnesses/pi/index.js +45 -0
  344. package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
  345. package/dist/integrations/harnesses/shared.js +17 -0
  346. package/dist/integrations/harnesses/types.js +43 -32
  347. package/dist/integrations/lockfile.js +211 -24
  348. package/dist/integrations/session-logs/index.js +36 -39
  349. package/dist/integrations/session-logs/provider-base.js +113 -0
  350. package/dist/llm/client.js +182 -110
  351. package/dist/llm/embedders/deterministic.js +2 -2
  352. package/dist/llm/embedders/remote.js +21 -9
  353. package/dist/llm/feature-gate.js +17 -57
  354. package/dist/llm/graph-extract.js +12 -13
  355. package/dist/llm/index-passes.js +8 -42
  356. package/dist/llm/memory-infer.js +144 -1
  357. package/dist/llm/metadata-enhance.js +45 -30
  358. package/dist/llm/structured-call.js +16 -8
  359. package/dist/llm/usage-persist.js +30 -5
  360. package/dist/llm/usage-telemetry.js +59 -6
  361. package/dist/output/cli-hints.js +1 -2
  362. package/dist/output/command-registry.js +27 -0
  363. package/dist/output/context.js +22 -7
  364. package/dist/output/format-exempt.js +80 -0
  365. package/dist/output/generic-render.js +251 -0
  366. package/dist/output/html-render.js +11 -16
  367. package/dist/output/render-registry.js +57 -0
  368. package/dist/output/renderers.js +14 -279
  369. package/dist/output/shapes/curate.js +10 -1
  370. package/dist/output/shapes/events.js +12 -7
  371. package/dist/output/shapes/helpers.js +58 -84
  372. package/dist/output/shapes/passthrough.js +11 -39
  373. package/dist/output/shapes/proposal/producer.js +15 -7
  374. package/dist/output/shapes/registry.js +12 -6
  375. package/dist/output/shapes.js +0 -9
  376. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  377. package/dist/output/text/bundle-show.js +7 -0
  378. package/dist/output/text/command-format.js +562 -0
  379. package/dist/output/text/env.js +1 -3
  380. package/dist/output/text/events.js +8 -7
  381. package/dist/output/text/helpers.js +15 -1164
  382. package/dist/output/text/proposal/producer.js +4 -2
  383. package/dist/output/text/proposal-format.js +202 -0
  384. package/dist/output/text/registry-commands.js +1 -2
  385. package/dist/output/text/registry.js +12 -6
  386. package/dist/output/text/show-directives.js +117 -0
  387. package/dist/output/text/show-format.js +103 -0
  388. package/dist/output/text/sync.js +5 -0
  389. package/dist/output/text/workflow-format.js +332 -0
  390. package/dist/output/text/workflow.js +3 -2
  391. package/dist/output/text.js +10 -19
  392. package/dist/registry/factory.js +4 -6
  393. package/dist/registry/origin-resolve.js +16 -27
  394. package/dist/registry/providers/skills-sh.js +3 -3
  395. package/dist/registry/providers/static-index.js +15 -25
  396. package/dist/registry/resolve.js +43 -94
  397. package/dist/registry/semver.js +43 -0
  398. package/dist/runtime.js +81 -12
  399. package/dist/scripts/akm-migrate.js +35529 -0
  400. package/dist/setup/detect.js +5 -7
  401. package/dist/setup/detected-engines.js +136 -0
  402. package/dist/setup/engine-config.js +100 -0
  403. package/dist/setup/registry-stash-loader.js +3 -3
  404. package/dist/setup/semantic-assets.js +12 -9
  405. package/dist/setup/setup.js +444 -208
  406. package/dist/setup/steps/connection-shared.js +120 -0
  407. package/dist/setup/steps/connection.js +108 -305
  408. package/dist/setup/steps/platforms.js +13 -12
  409. package/dist/setup/steps/semantic.js +15 -3
  410. package/dist/setup/steps/sources.js +21 -15
  411. package/dist/setup/steps/stashdir.js +6 -4
  412. package/dist/setup/steps/tasks.js +236 -119
  413. package/dist/setup/steps.js +3 -2
  414. package/dist/sources/freshness.js +39 -0
  415. package/dist/sources/provider-factory.js +11 -17
  416. package/dist/sources/providers/filesystem.js +2 -3
  417. package/dist/sources/providers/git-install.js +278 -34
  418. package/dist/sources/providers/git-provider.js +54 -56
  419. package/dist/sources/providers/git-stash.js +420 -91
  420. package/dist/sources/providers/git.js +2 -2
  421. package/dist/sources/providers/npm.js +16 -19
  422. package/dist/sources/providers/provider-utils.js +47 -22
  423. package/dist/sources/providers/sync-from-ref.js +3 -9
  424. package/dist/sources/providers/website.js +2 -2
  425. package/dist/sources/resolve.js +11 -10
  426. package/dist/sources/snapshot-fetchers/types.js +4 -0
  427. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
  428. package/dist/storage/database.js +60 -4
  429. package/dist/storage/engines/sqlite-migrations.js +156 -5
  430. package/dist/storage/locations.js +1 -2
  431. package/dist/storage/repositories/canaries-repository.js +1 -1
  432. package/dist/storage/repositories/events-repository.js +51 -11
  433. package/dist/storage/repositories/improve-runs-repository.js +6 -32
  434. package/dist/storage/repositories/index-connection.js +79 -0
  435. package/dist/storage/repositories/index-db.js +4 -3
  436. package/dist/storage/repositories/index-entries-repository.js +863 -0
  437. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
  438. package/dist/storage/repositories/index-entry-types.js +4 -0
  439. package/dist/storage/repositories/index-fts-repository.js +167 -0
  440. package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
  441. package/dist/storage/repositories/index-meta-repository.js +49 -0
  442. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
  443. package/dist/storage/repositories/index-sql.js +12 -0
  444. package/dist/storage/repositories/index-utility-repository.js +356 -0
  445. package/dist/storage/repositories/index-vec-repository.js +250 -0
  446. package/dist/storage/repositories/outcome-repository.js +119 -0
  447. package/dist/storage/repositories/proposals-repository.js +317 -75
  448. package/dist/storage/repositories/registry-cache.js +1 -1
  449. package/dist/storage/repositories/salience-repository.js +172 -0
  450. package/dist/storage/repositories/task-history-repository.js +110 -3
  451. package/dist/storage/repositories/workflow-runs-repository.js +240 -19
  452. package/dist/tasks/backends/cron.js +169 -46
  453. package/dist/tasks/backends/exec-utils.js +76 -3
  454. package/dist/tasks/backends/index.js +6 -9
  455. package/dist/tasks/backends/launchd.js +292 -55
  456. package/dist/tasks/backends/schtasks.js +557 -70
  457. package/dist/tasks/backends/types.js +4 -0
  458. package/dist/tasks/command-executable.js +93 -0
  459. package/dist/tasks/embedded.js +56 -38
  460. package/dist/tasks/parser.js +156 -64
  461. package/dist/tasks/resolve-akm-bin.js +144 -51
  462. package/dist/tasks/runner.js +377 -209
  463. package/dist/tasks/schedule.js +108 -19
  464. package/dist/tasks/scheduler-invocation.js +296 -0
  465. package/dist/tasks/schema.js +1 -1
  466. package/dist/tasks/task-id.js +35 -0
  467. package/dist/tasks/validator.js +30 -16
  468. package/dist/text-import-hook.mjs +1 -1
  469. package/dist/workflows/authoring/authoring.js +104 -43
  470. package/dist/workflows/authoring/scope-key.js +1 -1
  471. package/dist/workflows/cli.js +0 -16
  472. package/dist/workflows/concurrency-policy.js +15 -0
  473. package/dist/workflows/exec/brief.js +450 -0
  474. package/dist/workflows/exec/frozen-judge.js +47 -0
  475. package/dist/workflows/exec/native-executor.js +1038 -0
  476. package/dist/workflows/exec/param-secrets.js +115 -0
  477. package/dist/workflows/exec/report.js +1460 -0
  478. package/dist/workflows/exec/run-workflow.js +602 -0
  479. package/dist/workflows/exec/scheduler.js +71 -0
  480. package/dist/workflows/exec/step-work.js +1190 -0
  481. package/dist/workflows/exec/unit-writer.js +23 -0
  482. package/dist/workflows/exec/workflow-engine-gate.js +67 -0
  483. package/dist/workflows/exec/worktree.js +171 -0
  484. package/dist/workflows/ir/compile.js +246 -0
  485. package/dist/workflows/ir/freeze.js +233 -0
  486. package/dist/workflows/ir/params.js +54 -0
  487. package/dist/workflows/ir/plan-hash.js +68 -0
  488. package/dist/workflows/ir/schema.js +540 -0
  489. package/dist/workflows/parser.js +878 -304
  490. package/dist/workflows/program/expressions.js +181 -0
  491. package/dist/workflows/program/schema.js +51 -0
  492. package/dist/workflows/renderer.js +100 -45
  493. package/dist/workflows/resource-limits.js +22 -0
  494. package/dist/workflows/runtime/agent-identity.js +59 -14
  495. package/dist/workflows/runtime/checkin.js +1 -1
  496. package/dist/workflows/runtime/plan-classifier.js +131 -0
  497. package/dist/workflows/runtime/runs.js +376 -119
  498. package/dist/workflows/runtime/unit-checkin.js +45 -0
  499. package/dist/workflows/runtime/unit-phases.js +20 -0
  500. package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
  501. package/dist/workflows/schema.js +1 -11
  502. package/dist/workflows/validate-summary.js +2 -3
  503. package/dist/workflows/validator.js +52 -30
  504. package/docs/README.md +42 -78
  505. package/docs/migration/README.md +8 -0
  506. package/docs/migration/release-notes/0.6.0.md +1 -1
  507. package/docs/migration/release-notes/0.7.0.md +9 -8
  508. package/docs/migration/release-notes/0.9.0.md +158 -14
  509. package/docs/migration/v0.7-to-v0.8.md +46 -47
  510. package/docs/migration/v0.8-to-v0.9.md +844 -0
  511. package/docs/reference/README.md +12 -0
  512. package/docs/reference/data-and-telemetry.md +333 -0
  513. package/package.json +21 -17
  514. package/schemas/akm-asset-envelope.json +93 -0
  515. package/schemas/akm-config.json +4636 -0
  516. package/schemas/akm-task.json +87 -0
  517. package/schemas/akm-workflow.json +373 -0
  518. package/dist/akm-migrate-storage +0 -38
  519. package/dist/assets/help/help-accept.md +0 -12
  520. package/dist/assets/help/help-improve.md +0 -84
  521. package/dist/assets/help/help-proposals.md +0 -17
  522. package/dist/assets/help/help-propose.md +0 -17
  523. package/dist/assets/help/help-reject.md +0 -11
  524. package/dist/assets/profiles/frequent.json +0 -13
  525. package/dist/assets/profiles/recombine-only.json +0 -21
  526. package/dist/assets/profiles/reflect-distill.json +0 -30
  527. package/dist/assets/profiles/synthesize.json +0 -15
  528. package/dist/assets/prompts/procedural-system.md +0 -44
  529. package/dist/assets/prompts/recombine-system.md +0 -40
  530. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  531. package/dist/assets/tasks/core/backup.yml +0 -4
  532. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  533. package/dist/assets/templates/html/default.html +0 -78
  534. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  535. package/dist/assets/wiki/index-template.md +0 -12
  536. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  537. package/dist/assets/wiki/log-template.md +0 -8
  538. package/dist/assets/wiki/schema-template.md +0 -61
  539. package/dist/cli/config-migrate.js +0 -150
  540. package/dist/cli/config-validate.js +0 -39
  541. package/dist/commands/graph/graph-cli.js +0 -124
  542. package/dist/commands/graph/graph.js +0 -487
  543. package/dist/commands/improve/calibration.js +0 -161
  544. package/dist/commands/improve/dedup.js +0 -482
  545. package/dist/commands/improve/extract-watch.js +0 -140
  546. package/dist/commands/improve/hot-probation.js +0 -45
  547. package/dist/commands/improve/improve-auto-accept.js +0 -276
  548. package/dist/commands/improve/improve-profiles.js +0 -168
  549. package/dist/commands/improve/procedural.js +0 -398
  550. package/dist/commands/improve/recombine.js +0 -818
  551. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  552. package/dist/commands/lint/agent-linter.js +0 -44
  553. package/dist/commands/lint/command-linter.js +0 -44
  554. package/dist/commands/lint/default-linter.js +0 -16
  555. package/dist/commands/lint/fact-linter.js +0 -39
  556. package/dist/commands/lint/knowledge-linter.js +0 -16
  557. package/dist/commands/lint/memory-linter.js +0 -61
  558. package/dist/commands/lint/registry.js +0 -41
  559. package/dist/commands/lint/skill-linter.js +0 -45
  560. package/dist/commands/lint/task-linter.js +0 -50
  561. package/dist/commands/lint/workflow-linter.js +0 -81
  562. package/dist/commands/proposal/legacy-import.js +0 -115
  563. package/dist/commands/sources/history.js +0 -196
  564. package/dist/commands/tasks/default-tasks.js +0 -186
  565. package/dist/commands/wiki-cli.js +0 -292
  566. package/dist/core/asset/asset-registry.js +0 -76
  567. package/dist/core/asset/asset-spec.js +0 -259
  568. package/dist/core/config/config-migration.js +0 -602
  569. package/dist/core/deep-merge.js +0 -38
  570. package/dist/core/eval/rank-metrics.js +0 -113
  571. package/dist/core/ripgrep/install.js +0 -163
  572. package/dist/core/ripgrep/resolve.js +0 -81
  573. package/dist/indexer/db/db.js +0 -1413
  574. package/dist/indexer/manifest.js +0 -170
  575. package/dist/indexer/passes/metadata-contributors.js +0 -31
  576. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
  577. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
  578. package/dist/llm/call-ai.js +0 -62
  579. package/dist/llm/memory-infer-impl.js +0 -138
  580. package/dist/output/shapes/distill.js +0 -14
  581. package/dist/output/shapes/history.js +0 -11
  582. package/dist/output/text/distill.js +0 -6
  583. package/dist/output/text/enable-disable.js +0 -8
  584. package/dist/output/text/history.js +0 -6
  585. package/dist/output/text/wiki.js +0 -16
  586. package/dist/registry/build-index.js +0 -386
  587. package/dist/scripts/migrate-storage.js +0 -19108
  588. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
  589. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  590. package/dist/setup/legacy-config.js +0 -106
  591. package/dist/storage/repositories/consolidation-repository.js +0 -38
  592. package/dist/storage/repositories/recombine-repository.js +0 -213
  593. package/dist/wiki/wiki-templates.js +0 -15
  594. package/dist/wiki/wiki.js +0 -1012
  595. package/dist/workflows/db.js +0 -215
  596. package/docs/data-and-telemetry.md +0 -226
  597. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  598. /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),