akm-cli 0.9.0-rc.8 → 0.9.0

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 (450) hide show
  1. package/CHANGELOG.md +1063 -44
  2. package/README.md +51 -25
  3. package/SECURITY.md +14 -1
  4. package/STABILITY.md +497 -0
  5. package/dist/akm +148 -35
  6. package/dist/{akm-migrate-storage → akm-migrate} +6 -9
  7. package/dist/assets/hints/cli-hints-full.md +223 -95
  8. package/dist/assets/hints/cli-hints-short.md +85 -22
  9. package/dist/assets/improve-strategies/default.json +1 -1
  10. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  11. package/dist/assets/prompts/memory-infer-user.md +2 -3
  12. package/dist/assets/stash-skeleton/README.md +6 -5
  13. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
  14. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
  15. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
  16. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
  17. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
  18. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
  19. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
  20. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
  21. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
  22. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
  23. package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
  24. package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
  25. package/dist/assets/tasks/core/extract.yml +1 -1
  26. package/dist/assets/tasks/core/version-check.yml +1 -1
  27. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
  28. package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
  29. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
  30. package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
  31. package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
  32. package/dist/assets/templates/html/health.html +1 -3
  33. package/dist/assets/workflows/workflow-template.md +32 -15
  34. package/dist/cli/invocation.js +40 -15
  35. package/dist/cli/parse-args.js +0 -22
  36. package/dist/cli/retired-commands.js +121 -0
  37. package/dist/cli/shared.js +154 -22
  38. package/dist/cli/unknown-flags.js +236 -0
  39. package/dist/cli-node.mjs +2 -1
  40. package/dist/cli.js +696 -258
  41. package/dist/commands/agent/agent-dispatch.js +14 -3
  42. package/dist/commands/agent/contribute-cli.js +73 -88
  43. package/dist/commands/completions.js +79 -22
  44. package/dist/commands/config-cli.js +17 -150
  45. package/dist/commands/env/env-cli.js +59 -143
  46. package/dist/commands/env/env.js +12 -163
  47. package/dist/commands/env/marker-path.js +6 -0
  48. package/dist/commands/env/secret-cli.js +36 -66
  49. package/dist/commands/env/secret.js +24 -57
  50. package/dist/commands/feedback-cli.js +141 -87
  51. package/dist/commands/health/accept-rate.js +58 -0
  52. package/dist/commands/health/advisories.js +3 -4
  53. package/dist/commands/health/checks.js +85 -23
  54. package/dist/commands/health/html-report.js +7 -10
  55. package/dist/commands/health/improve-metrics.js +25 -83
  56. package/dist/commands/health/md-report.js +5 -9
  57. package/dist/commands/health/metrics.js +62 -20
  58. package/dist/commands/health/renderers.js +47 -0
  59. package/dist/commands/health/report-view-model.js +4 -5
  60. package/dist/commands/health/stash-exposure.js +1 -1
  61. package/dist/commands/health/surfaces.js +3 -48
  62. package/dist/commands/health/task-runs.js +3 -67
  63. package/dist/commands/health/types-improve.js +7 -0
  64. package/dist/commands/health.js +99 -28
  65. package/dist/commands/improve/anti-collapse.js +2 -2
  66. package/dist/commands/improve/autonomy-gate.js +68 -0
  67. package/dist/commands/improve/collapse-detector.js +41 -40
  68. package/dist/commands/improve/consolidate/eligibility.js +1 -23
  69. package/dist/commands/improve/consolidate/merge.js +4 -0
  70. package/dist/commands/improve/consolidate.js +140 -1000
  71. package/dist/commands/improve/distill/promote-memory.js +12 -12
  72. package/dist/commands/improve/distill/quality-gate.js +6 -6
  73. package/dist/commands/improve/distill.js +58 -69
  74. package/dist/commands/improve/eligibility.js +105 -57
  75. package/dist/commands/improve/extract-cli.js +14 -133
  76. package/dist/commands/improve/improve-cli.js +98 -114
  77. package/dist/commands/improve/improve-result-file.js +1 -28
  78. package/dist/commands/improve/improve-strategies.js +8 -5
  79. package/dist/commands/improve/improve.js +128 -91
  80. package/dist/commands/improve/loop-stages.js +182 -20
  81. package/dist/commands/improve/memory/derived-ref.js +45 -43
  82. package/dist/commands/improve/memory/memory-belief.js +1 -1
  83. package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
  84. package/dist/commands/improve/memory/memory-improve.js +6 -5
  85. package/dist/commands/improve/outcome-loop.js +22 -65
  86. package/dist/commands/improve/preparation.js +114 -123
  87. package/dist/commands/improve/proactive-maintenance.js +2 -5
  88. package/dist/commands/improve/reflect.js +56 -160
  89. package/dist/commands/improve/salience.js +11 -122
  90. package/dist/commands/improve/source-identity.js +10 -38
  91. package/dist/commands/lint/base-linter.js +20 -124
  92. package/dist/commands/lint/env-key-rules.js +31 -47
  93. package/dist/commands/lint/index.js +249 -43
  94. package/dist/commands/{events.js → log.js} +33 -38
  95. package/dist/commands/migrate-cli.js +92 -12
  96. package/dist/commands/migration-tool.js +46 -0
  97. package/dist/commands/observability-cli.js +70 -209
  98. package/dist/commands/proposal/drain.js +101 -29
  99. package/dist/commands/proposal/proposal-cli.js +76 -48
  100. package/dist/commands/proposal/proposal.js +54 -18
  101. package/dist/commands/proposal/propose-cli.js +88 -0
  102. package/dist/commands/proposal/propose.js +23 -15
  103. package/dist/commands/proposal/repository.js +701 -278
  104. package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
  105. package/dist/commands/proposal/validators/proposal-validators.js +55 -7
  106. package/dist/commands/proposal/validators/proposals.js +4 -7
  107. package/dist/commands/read/curate.js +34 -53
  108. package/dist/commands/read/knowledge.js +150 -95
  109. package/dist/commands/read/registry-search.js +2 -2
  110. package/dist/commands/read/remember-cli.js +42 -15
  111. package/dist/commands/read/search-cli.js +180 -78
  112. package/dist/commands/read/search.js +58 -43
  113. package/dist/commands/read/show.js +197 -141
  114. package/dist/commands/registry-cli.js +12 -51
  115. package/dist/commands/remember.js +14 -57
  116. package/dist/commands/sources/add-cli.js +100 -31
  117. package/dist/commands/sources/bundle-cli.js +166 -0
  118. package/dist/commands/sources/bundle-config-ops.js +7 -2
  119. package/dist/commands/sources/info.js +18 -5
  120. package/dist/commands/sources/init.js +12 -12
  121. package/dist/commands/sources/installed-stashes.js +382 -98
  122. package/dist/commands/sources/schema-repair.js +3 -2
  123. package/dist/commands/sources/self-update.js +131 -38
  124. package/dist/commands/sources/source-add.js +72 -17
  125. package/dist/commands/sources/source-clone.js +129 -45
  126. package/dist/commands/sources/source-manage.js +43 -23
  127. package/dist/commands/sources/sources-cli.js +57 -208
  128. package/dist/commands/sources/stash-cli.js +46 -53
  129. package/dist/commands/tasks/tasks-cli.js +91 -97
  130. package/dist/commands/tasks/tasks.js +276 -421
  131. package/dist/commands/workflow-cli.js +175 -450
  132. package/dist/core/adapter/adapters/akm-adapter.js +47 -28
  133. package/dist/core/adapter/adapters/akm-lint.js +42 -27
  134. package/dist/core/adapter/adapters/akm-metadata.js +15 -44
  135. package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
  136. package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
  137. package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
  138. package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
  139. package/dist/core/adapter/adapters/index.js +6 -6
  140. package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
  141. package/dist/core/adapter/adapters/okf-adapter.js +187 -19
  142. package/dist/core/adapter/adapters/shared.js +3 -19
  143. package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
  144. package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
  145. package/dist/core/adapter/detect-adapter.js +17 -0
  146. package/dist/core/adapter/recognize-match.js +6 -4
  147. package/dist/core/adapter/validate-context.js +214 -0
  148. package/dist/core/asset/akm-markdown.js +63 -0
  149. package/dist/core/asset/asset-placement.js +20 -6
  150. package/dist/core/asset/asset-ref.js +11 -9
  151. package/dist/core/asset/frontmatter-lint.js +30 -0
  152. package/dist/core/asset/frontmatter.js +37 -9
  153. package/dist/core/asset/markdown.js +40 -51
  154. package/dist/core/asset/resolve-ref.js +89 -18
  155. package/dist/core/asset/stash-meta.js +1 -1
  156. package/dist/core/bundle-id.js +51 -0
  157. package/dist/core/common.js +152 -38
  158. package/dist/core/config/config-io.js +12 -1
  159. package/dist/core/config/config-schema.js +35 -8
  160. package/dist/core/config/config-sources.js +55 -11
  161. package/dist/core/config/config-walker.js +25 -9
  162. package/dist/core/config/config.js +9 -48
  163. package/dist/core/config/experimental.js +21 -0
  164. package/dist/core/config/schema/embedding.js +5 -1
  165. package/dist/core/config/schema/experimental.js +30 -0
  166. package/dist/core/config/schema/improve-processes.js +0 -6
  167. package/dist/core/config/schema/improve.js +21 -3
  168. package/dist/core/config/schema/index-config.js +8 -15
  169. package/dist/core/config/schema/output.js +4 -1
  170. package/dist/core/config/schema/setup.js +9 -18
  171. package/dist/core/config/schema/sources-bundles.js +49 -33
  172. package/dist/core/config/schema/workflow.js +3 -3
  173. package/dist/core/env-secret-ref.js +76 -46
  174. package/dist/core/errors.js +18 -12
  175. package/dist/core/events.js +46 -128
  176. package/dist/core/file-change.js +6 -5
  177. package/dist/core/fs-txn.js +83 -7
  178. package/dist/core/git-message.js +2 -2
  179. package/dist/core/improve-result.js +1 -100
  180. package/dist/core/lesson-lint.js +1 -17
  181. package/dist/core/logs-db.js +2 -1
  182. package/dist/core/migration-operation.js +16 -0
  183. package/dist/core/mutation-target.js +78 -0
  184. package/dist/core/parse.js +4 -1
  185. package/dist/core/paths.js +17 -20
  186. package/dist/core/recognition-util.js +12 -14
  187. package/dist/core/redaction.js +34 -0
  188. package/dist/core/standards/resolve-standards-context.js +2 -14
  189. package/dist/core/standards/resolve-stash-standards.js +2 -2
  190. package/dist/core/standards/resolve-type-conventions.js +2 -2
  191. package/dist/core/state/migrations.js +41 -18
  192. package/dist/core/state-db.js +5 -14
  193. package/dist/core/structured.js +1 -1
  194. package/dist/core/subprocess.js +6 -4
  195. package/dist/core/text-truncation.js +9 -5
  196. package/dist/core/type-presentation.js +3 -3
  197. package/dist/core/warn.js +0 -3
  198. package/dist/core/write-source.js +771 -95
  199. package/dist/indexer/bundle-identity-guard.js +3 -2
  200. package/dist/indexer/db/graph-db.js +0 -24
  201. package/dist/indexer/ensure-index.js +1 -0
  202. package/dist/indexer/graph/graph-boost.js +9 -34
  203. package/dist/indexer/graph/graph-extraction.js +8 -5
  204. package/dist/indexer/index-writer-lock.js +53 -17
  205. package/dist/indexer/index-written-assets.js +16 -22
  206. package/dist/indexer/indexer.js +497 -239
  207. package/dist/indexer/installations.js +14 -96
  208. package/dist/indexer/passes/dir-staleness.js +16 -9
  209. package/dist/indexer/passes/memory-inference.js +11 -9
  210. package/dist/indexer/passes/metadata.js +113 -47
  211. package/dist/indexer/scan/doc-to-entry.js +38 -1
  212. package/dist/indexer/scan/drain-dir.js +13 -23
  213. package/dist/indexer/search/db-search.js +99 -54
  214. package/dist/indexer/search/fts-query.js +47 -24
  215. package/dist/indexer/search/ranking-contributors.js +42 -20
  216. package/dist/indexer/search/ranking.js +18 -99
  217. package/dist/indexer/search/search-fields.js +7 -2
  218. package/dist/indexer/search/search-source.js +82 -93
  219. package/dist/indexer/usage/usage-events.js +0 -89
  220. package/dist/indexer/walk/file-context.js +2 -1
  221. package/dist/indexer/walk/matchers.js +30 -43
  222. package/dist/indexer/walk/path-resolver.js +7 -2
  223. package/dist/indexer/walk/walker.js +38 -12
  224. package/dist/integrations/agent/builders.js +0 -6
  225. package/dist/integrations/agent/config.js +2 -2
  226. package/dist/integrations/agent/detect.js +49 -19
  227. package/dist/integrations/agent/engine-fallback.js +76 -0
  228. package/dist/integrations/agent/profiles.js +14 -0
  229. package/dist/integrations/agent/prompts.js +12 -8
  230. package/dist/integrations/agent/runner-dispatch.js +4 -2
  231. package/dist/integrations/agent/runner.js +0 -1
  232. package/dist/integrations/agent/spawn.js +5 -6
  233. package/dist/integrations/github.js +1 -1
  234. package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
  235. package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
  236. package/dist/integrations/harnesses/claude/session-log.js +0 -10
  237. package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
  238. package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
  239. package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
  240. package/dist/integrations/harnesses/index.js +3 -7
  241. package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
  242. package/dist/integrations/harnesses/opencode/session-log.js +0 -15
  243. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
  244. package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
  245. package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
  246. package/dist/integrations/lockfile.js +101 -6
  247. package/dist/integrations/session-logs/index.js +3 -28
  248. package/dist/llm/client.js +136 -100
  249. package/dist/llm/embedders/remote.js +13 -5
  250. package/dist/llm/feature-gate.js +4 -12
  251. package/dist/llm/graph-extract.js +5 -11
  252. package/dist/llm/memory-infer.js +144 -1
  253. package/dist/llm/metadata-enhance.js +5 -7
  254. package/dist/llm/structured-call.js +1 -1
  255. package/dist/llm/usage-persist.js +26 -5
  256. package/dist/llm/usage-telemetry.js +25 -2
  257. package/dist/output/cli-hints.js +1 -2
  258. package/dist/output/context.js +22 -7
  259. package/dist/output/format-exempt.js +80 -0
  260. package/dist/output/generic-render.js +259 -0
  261. package/dist/output/render-registry.js +57 -0
  262. package/dist/output/renderers.js +14 -36
  263. package/dist/output/shapes/curate.js +10 -1
  264. package/dist/output/shapes/events.js +12 -7
  265. package/dist/output/shapes/helpers.js +56 -83
  266. package/dist/output/shapes/migrate.js +8 -0
  267. package/dist/output/shapes/passthrough.js +7 -41
  268. package/dist/output/shapes/proposal/producer.js +15 -7
  269. package/dist/output/shapes.js +2 -9
  270. package/dist/output/text/{init.js → bundle-create.js} +3 -1
  271. package/dist/output/text/bundle-show.js +7 -0
  272. package/dist/output/text/command-format.js +164 -96
  273. package/dist/output/text/env.js +1 -3
  274. package/dist/output/text/events.js +8 -7
  275. package/dist/output/text/health-format.js +103 -0
  276. package/dist/output/text/health.js +7 -0
  277. package/dist/output/text/helpers.js +10 -8
  278. package/dist/output/text/lint-format.js +43 -0
  279. package/dist/output/text/{save.js → lint.js} +2 -2
  280. package/dist/output/text/migrate.js +88 -0
  281. package/dist/output/text/proposal/producer.js +4 -2
  282. package/dist/output/text/proposal-format.js +44 -72
  283. package/dist/output/text/registry-commands.js +1 -2
  284. package/dist/output/text/show-directives.js +15 -7
  285. package/dist/output/text/status-list.js +32 -0
  286. package/dist/output/text/sync.js +5 -0
  287. package/dist/output/text/workflow-format.js +24 -203
  288. package/dist/output/text/workflow.js +1 -7
  289. package/dist/output/text.js +16 -17
  290. package/dist/registry/factory.js +4 -6
  291. package/dist/registry/origin-resolve.js +16 -27
  292. package/dist/registry/providers/skills-sh.js +3 -3
  293. package/dist/registry/providers/static-index.js +13 -23
  294. package/dist/registry/resolve.js +42 -7
  295. package/dist/registry/semver.js +34 -84
  296. package/dist/runtime.js +2 -23
  297. package/dist/scripts/akm-migrate-node.js +60290 -0
  298. package/dist/scripts/akm-migrate.js +59628 -0
  299. package/dist/setup/detect.js +42 -15
  300. package/dist/setup/registry-stash-loader.js +2 -2
  301. package/dist/setup/setup.js +236 -136
  302. package/dist/setup/steps/connection.js +7 -9
  303. package/dist/setup/steps/platforms.js +9 -9
  304. package/dist/setup/steps/semantic.js +15 -3
  305. package/dist/setup/steps/sources.js +12 -13
  306. package/dist/setup/steps/stashdir.js +2 -3
  307. package/dist/setup/steps/tasks.js +237 -120
  308. package/dist/sources/freshness.js +1 -1
  309. package/dist/sources/provider-factory.js +11 -17
  310. package/dist/sources/providers/filesystem.js +2 -3
  311. package/dist/sources/providers/git-install.js +278 -34
  312. package/dist/sources/providers/git-provider.js +25 -23
  313. package/dist/sources/providers/git-stash.js +395 -106
  314. package/dist/sources/providers/git.js +2 -2
  315. package/dist/sources/providers/npm.js +16 -19
  316. package/dist/sources/providers/provider-utils.js +7 -4
  317. package/dist/sources/providers/sync-from-ref.js +3 -9
  318. package/dist/sources/providers/website.js +6 -1
  319. package/dist/sources/resolve.js +6 -5
  320. package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
  321. package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
  322. package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
  323. package/dist/sources/snapshot-fetchers/github.js +100 -0
  324. package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
  325. package/dist/sources/snapshot-fetchers/registry.js +17 -1
  326. package/dist/sources/snapshot-fetchers/robots.js +348 -0
  327. package/dist/sources/snapshot-fetchers/rss.js +282 -0
  328. package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
  329. package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
  330. package/dist/sources/snapshot-fetchers/x.js +910 -0
  331. package/dist/storage/database.js +7 -0
  332. package/dist/storage/engines/sqlite-migrations.js +23 -111
  333. package/dist/storage/managed-db.js +2 -2
  334. package/dist/storage/repositories/canaries-repository.js +1 -1
  335. package/dist/storage/repositories/events-repository.js +27 -11
  336. package/dist/storage/repositories/improve-runs-repository.js +6 -12
  337. package/dist/storage/repositories/index-connection.js +17 -6
  338. package/dist/storage/repositories/index-entries-repository.js +151 -240
  339. package/dist/storage/repositories/index-entry-mapper.js +15 -11
  340. package/dist/storage/repositories/index-fts-repository.js +5 -2
  341. package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
  342. package/dist/storage/repositories/index-meta-repository.js +2 -3
  343. package/dist/storage/repositories/index-schema.js +10 -25
  344. package/dist/storage/repositories/index-utility-repository.js +15 -28
  345. package/dist/storage/repositories/index-vec-repository.js +6 -1
  346. package/dist/storage/repositories/outcome-repository.js +119 -0
  347. package/dist/storage/repositories/proposals-repository.js +296 -59
  348. package/dist/storage/repositories/registry-cache.js +19 -0
  349. package/dist/storage/repositories/salience-repository.js +172 -0
  350. package/dist/storage/repositories/task-history-repository.js +15 -13
  351. package/dist/storage/repositories/workflow-runs-repository.js +52 -40
  352. package/dist/tasks/backends/cron.js +105 -15
  353. package/dist/tasks/backends/index.js +1 -1
  354. package/dist/tasks/backends/launchd.js +85 -38
  355. package/dist/tasks/backends/schtasks.js +135 -15
  356. package/dist/tasks/embedded.js +56 -40
  357. package/dist/tasks/parser.js +7 -157
  358. package/dist/tasks/resolve-akm-bin.js +137 -59
  359. package/dist/tasks/runner.js +79 -42
  360. package/dist/tasks/scheduler-invocation.js +220 -10
  361. package/dist/tasks/schema.js +24 -1
  362. package/dist/tasks/task-id.js +1 -3
  363. package/dist/tasks/validator.js +20 -6
  364. package/dist/workflows/authoring/authoring.js +94 -143
  365. package/dist/workflows/authoring/scope-key.js +1 -1
  366. package/dist/workflows/exec/frozen-judge.js +28 -2
  367. package/dist/workflows/exec/native-executor.js +77 -57
  368. package/dist/workflows/exec/param-secrets.js +9 -9
  369. package/dist/workflows/exec/run-workflow.js +133 -79
  370. package/dist/workflows/exec/step-work.js +219 -346
  371. package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
  372. package/dist/workflows/ir/compile.js +141 -270
  373. package/dist/workflows/ir/freeze.js +40 -30
  374. package/dist/workflows/ir/params.js +135 -11
  375. package/dist/workflows/ir/plan-hash.js +1 -1
  376. package/dist/workflows/ir/schema.js +25 -26
  377. package/dist/workflows/parser.js +872 -307
  378. package/dist/workflows/program/expressions.js +20 -208
  379. package/dist/workflows/program/schema.js +7 -10
  380. package/dist/workflows/renderer.js +95 -68
  381. package/dist/workflows/resource-limits.js +2 -0
  382. package/dist/workflows/runtime/checkin.js +3 -3
  383. package/dist/workflows/runtime/plan-classifier.js +16 -75
  384. package/dist/workflows/runtime/runs.js +186 -127
  385. package/dist/workflows/runtime/unit-checkin.js +1 -1
  386. package/dist/workflows/runtime/unit-phases.js +2 -2
  387. package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
  388. package/dist/workflows/schema.js +1 -11
  389. package/dist/workflows/validate-summary.js +30 -36
  390. package/dist/workflows/validator.js +21 -62
  391. package/docs/README.md +68 -0
  392. package/docs/migration/README.md +8 -0
  393. package/docs/migration/release-notes/0.7.0.md +11 -11
  394. package/docs/migration/release-notes/0.9.0.md +208 -27
  395. package/docs/migration/v0.7-to-v0.8.md +46 -47
  396. package/docs/migration/v0.8-to-v0.9.md +564 -208
  397. package/docs/migration/v0.9.0-troubleshooting.md +561 -0
  398. package/docs/reference/README.md +12 -0
  399. package/docs/reference/cli.md +2253 -0
  400. package/docs/reference/configuration.md +358 -0
  401. package/docs/reference/data-and-telemetry.md +105 -42
  402. package/docs/reference/workflows.md +647 -0
  403. package/package.json +22 -11
  404. package/schemas/akm-asset-envelope.json +93 -0
  405. package/schemas/akm-config.json +81 -128
  406. package/schemas/akm-workflow.json +74 -73
  407. package/dist/assets/tasks/core/backup.yml +0 -5
  408. package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
  409. package/dist/cli/config-migrate.js +0 -1806
  410. package/dist/cli/config-validate.js +0 -41
  411. package/dist/commands/backup-cli.js +0 -56
  412. package/dist/commands/bundle/bundle-cli.js +0 -68
  413. package/dist/commands/bundle/bundle.js +0 -219
  414. package/dist/commands/graph/graph-cli.js +0 -124
  415. package/dist/commands/graph/graph.js +0 -489
  416. package/dist/commands/improve/extract-watch.js +0 -140
  417. package/dist/commands/mv-cli.js +0 -1221
  418. package/dist/commands/sources/history.js +0 -201
  419. package/dist/commands/tasks/default-tasks.js +0 -186
  420. package/dist/core/migration-backup.js +0 -1234
  421. package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
  422. package/dist/llm/memory-infer-impl.js +0 -138
  423. package/dist/migrate/legacy/config-source-migration.js +0 -223
  424. package/dist/migrate/legacy/content-migration.js +0 -305
  425. package/dist/migrate/legacy/legacy-layout.js +0 -779
  426. package/dist/migrate/legacy/legacy-paths.js +0 -25
  427. package/dist/migrate/legacy/legacy-stash-json.js +0 -72
  428. package/dist/migrate/legacy/proposal-fs-import.js +0 -168
  429. package/dist/migrate/legacy/task-target-ref-migration.js +0 -272
  430. package/dist/migrate/legacy/three-db-cutover.js +0 -841
  431. package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
  432. package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
  433. package/dist/migrate/legacy-ref-grammar.js +0 -214
  434. package/dist/output/shapes/distill.js +0 -14
  435. package/dist/output/shapes/history.js +0 -11
  436. package/dist/output/text/distill.js +0 -6
  437. package/dist/output/text/enable-disable.js +0 -8
  438. package/dist/output/text/history.js +0 -6
  439. package/dist/registry/build-index.js +0 -382
  440. package/dist/schemas/akm-config.json +0 -4704
  441. package/dist/schemas/akm-task.json +0 -87
  442. package/dist/schemas/akm-workflow.json +0 -372
  443. package/dist/scripts/migrate-storage.js +0 -3816
  444. package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
  445. package/dist/workflows/cli.js +0 -53
  446. package/dist/workflows/exec/brief.js +0 -481
  447. package/dist/workflows/exec/report.js +0 -1460
  448. package/dist/workflows/exec/watch.js +0 -116
  449. package/dist/workflows/program/parser.js +0 -813
  450. package/dist/workflows/program/project.js +0 -104
@@ -53,114 +53,49 @@
53
53
  * the loose `akm` stash-shape probe.
54
54
  *
55
55
  * When NO adapter's probe fires (an empty or not-yet-materialized root), the
56
- * fallback is **`akm`** (see {@link FALLBACK_ADAPTER_ID}) a RECORDED DEVIATION
57
- * from spec §1.2(3), which specifies an `okf` fallback. See that constant's
58
- * comment for the rationale (workspace-root discipline in the pre-config-adapter
59
- * transitional model).
56
+ * fallback is **`akm`** (see {@link FALLBACK_ADAPTER_ID}), preserving workspace
57
+ * root behavior. Explicit configured ownership always wins over probing.
60
58
  */
61
- import crypto from "node:crypto";
62
- import path from "node:path";
63
59
  import { isSourceWriteActivated } from "../core/activation-policy.js";
64
- import { getAdapters } from "../core/adapter/registry.js";
60
+ import { detectAdapterId } from "../core/adapter/detect-adapter.js";
65
61
  import { stashDirFor } from "../core/asset/asset-placement.js";
66
- import { isBundleSlug } from "../core/asset/asset-ref.js";
62
+ import { deriveBundleId, deriveBundleIds, slugForPath } from "../core/bundle-id.js";
63
+ export { deriveBundleId, deriveBundleIds, slugForPath };
67
64
  /**
68
65
  * The no-probe-match fallback adapter id.
69
66
  *
70
- * RECORDED DEVIATION from spec §1.2(3) (which specifies an `okf` fallback),
71
- * kept as the status-quo-preserving choice pending 0.9.1:
67
+ * The status-quo-preserving default from spec §1.2(3):
72
68
  *
73
69
  * - Behavior discipline (spec line 267): the AKM workspace root's own indexing
74
70
  * MUST stay classified `akm`. In this transitional model there is no
75
- * config-driven adapter plumbing yet (§1.4) `deriveInstallations` derives
76
- * the adapter SOLELY from this probe, so the workspace-root classification
77
- * depends on either `akm.looksLikeRoot` firing (type dirs / `.stash` present)
78
- * OR this fallback. A genuinely empty / not-yet-materialized workspace root
79
- * (no type dirs) fires no probe; an `okf` fallback would misclassify it as
80
- * `okf`, violating that discipline. `akm` keeps it correct.
71
+ * depends on either explicit adapter configuration, `akm.looksLikeRoot`
72
+ * firing (type dirs / `.stash` present), or this fallback. A genuinely empty
73
+ * root fires no probe; `akm` keeps the implicit workspace root correct.
81
74
  * - Status quo: before the registry was wired, `getAdapters()` was empty in
82
75
  * production so EVERY source fell back here — this preserves that exact
83
76
  * fallback value while the probe now genuinely classifies the non-akm shapes.
84
- *
85
- * 0.9.1 should flip this to `okf` once the config-default adapter for the
86
- * workspace root is plumbed from config (§1.4 / spec line 267), which frees this
87
- * fallback to be the spec §1.2(3) `okf`.
88
77
  */
89
78
  const FALLBACK_ADAPTER_ID = "akm";
90
- /**
91
- * Deterministic, filesystem-safe bundle slug from a source path. Sanitizes the
92
- * path's basename to the ref bundle-slug charset (spec §1.3: no `/`, `:`, `.`,
93
- * `#`); an empty result (e.g. a root path) falls back to a short path hash.
94
- * Pure function of the resolved path — the same path always slugs the same.
95
- */
96
- export function slugForPath(sourcePath) {
97
- const resolved = path.resolve(sourcePath);
98
- const base = path
99
- .basename(resolved)
100
- .toLowerCase()
101
- .replace(/[^a-z0-9]+/g, "-")
102
- .replace(/^-+|-+$/g, "");
103
- if (base.length > 0)
104
- return base;
105
- return `bundle-${shortHash(resolved)}`;
106
- }
107
- /** First 8 hex chars of the sha256 of the input — a stable disambiguator. */
108
- function shortHash(input) {
109
- return crypto.createHash("sha256").update(input).digest("hex").slice(0, 8);
110
- }
111
- /**
112
- * Derive the batch-unique bundle id for a source (D-R5, ref-grammar decision):
113
- *
114
- * 1. `registryId` — WHEN it is a legal bundle slug (spec §11.1 charset). A
115
- * non-slug-legal registry id (`github:owner/repo`, `npm:@scope/pkg` — they
116
- * carry `:` / `/`) CANNOT be a bundle prefix (it would break the
117
- * `bundle//conceptId` grammar), so it falls through to (2).
118
- * 2. `slugForPath(sourcePath)` — the basename slug fallback.
119
- *
120
- * The result is made unique WITHIN a derivation batch by `ensureUniqueId`, and
121
- * the chosen id is added to `usedIds`. This is the ONE derivation the Chunk-8
122
- * config migrator ({@link import("../migrate/legacy/config-source-migration.js")})
123
- * and {@link deriveInstallations} share, so a migrated `bundles` key equals the
124
- * runtime installation id by construction (D-R5 no-identity-shift proof).
125
- */
126
- export function deriveBundleId(registryId, sourcePath, usedIds) {
127
- const preferred = registryId && registryId.length > 0 && isBundleSlug(registryId) ? registryId : slugForPath(sourcePath);
128
- const id = ensureUniqueId(preferred, sourcePath, usedIds);
129
- usedIds.add(id);
130
- return id;
131
- }
132
79
  /**
133
80
  * Resolve the adapter id for a component root via the ordered `looksLikeRoot`
134
81
  * probe (spec §1.2), first match wins; falls back to `akm` when no probe fires.
135
82
  */
136
- function detectAdapterId(root) {
137
- for (const adapter of getAdapters()) {
138
- try {
139
- if (adapter.looksLikeRoot?.(root) === true)
140
- return adapter.id;
141
- }
142
- catch {
143
- // A probe that throws (unreadable root, race) does not claim the root —
144
- // fall through to the next adapter, ultimately to the akm fallback.
145
- }
146
- }
147
- return FALLBACK_ADAPTER_ID;
148
- }
83
+ export { detectAdapterId } from "../core/adapter/detect-adapter.js";
149
84
  /**
150
85
  * Derive the durable `BundleInstallation[]` from the transitional
151
86
  * `SearchSource[]`. Order is preserved (source priority = installation
152
87
  * priority). Bundle ids are unique within the returned batch.
153
88
  */
154
89
  export function deriveInstallations(sources) {
155
- const usedIds = new Set();
90
+ const ids = deriveBundleIds(sources);
156
91
  const installations = [];
157
- for (const source of sources) {
92
+ for (const [index, source] of sources.entries()) {
158
93
  // D-R5 rule 1: when the source carries its config bundle key (a slug-legal
159
94
  // registryId), that key IS the installation id — equal by construction to
160
95
  // this derivation. A non-slug-legal registryId slugs from the path instead.
161
- const id = deriveBundleId(source.registryId, source.path, usedIds);
96
+ const id = ids[index];
162
97
  const writable = isSourceWriteActivated(source);
163
- const adapter = detectAdapterId(source.path);
98
+ const adapter = source.adapterId ?? detectAdapterId(source.path, FALLBACK_ADAPTER_ID);
164
99
  installations.push({
165
100
  id,
166
101
  trusted: writable,
@@ -205,20 +140,3 @@ adapterConceptId) {
205
140
  adapterId: bundle.adapterId,
206
141
  };
207
142
  }
208
- /**
209
- * Guarantee a batch-unique id. The preferred id (registryId or path slug) is
210
- * used as-is when free; on collision a short path-hash suffix disambiguates
211
- * (deterministic in the resolved path), and the unlikely second-order collision
212
- * appends a numeric counter.
213
- */
214
- function ensureUniqueId(preferred, sourcePath, used) {
215
- if (!used.has(preferred))
216
- return preferred;
217
- const suffixed = `${preferred}-${shortHash(path.resolve(sourcePath))}`;
218
- if (!used.has(suffixed))
219
- return suffixed;
220
- let n = 2;
221
- while (used.has(`${suffixed}-${n}`))
222
- n++;
223
- return `${suffixed}-${n}`;
224
- }
@@ -21,15 +21,22 @@ import fs from "node:fs";
21
21
  import path from "node:path";
22
22
  import { getEntriesByDir } from "../../storage/repositories/index-entries-repository.js";
23
23
  import { getIndexDirState } from "../../storage/repositories/index-meta-repository.js";
24
- export function getDirIndexState(db, dirPath, files, builtAtMs) {
24
+ export function getDirIndexState(db, dirPath, files, builtAtMs, indexVariant = "") {
25
25
  const prevEntries = getEntriesByDir(db, dirPath);
26
- const fingerprint = computeDirFingerprint(dirPath, files);
26
+ const fingerprint = computeDirFingerprint(dirPath, files, indexVariant);
27
27
  if (prevEntries.length > 0) {
28
28
  const staleReason = getDirStaleReason(dirPath, files, prevEntries, builtAtMs);
29
- if (!staleReason) {
30
- return { stale: false, reason: { kind: "unchanged" }, persistedRowCount: prevEntries.length };
29
+ if (staleReason)
30
+ return { stale: true, reason: staleReason, persistedRowCount: prevEntries.length };
31
+ const cachedState = getIndexDirState(db, dirPath);
32
+ if (!cachedState || cachedState.fileSetHash !== fingerprint.fileSetHash) {
33
+ return {
34
+ stale: true,
35
+ reason: { kind: "index-context-changed", detail: indexVariant },
36
+ persistedRowCount: prevEntries.length,
37
+ };
31
38
  }
32
- return { stale: true, reason: staleReason, persistedRowCount: prevEntries.length };
39
+ return { stale: false, reason: { kind: "unchanged" }, persistedRowCount: prevEntries.length };
33
40
  }
34
41
  const cachedState = getIndexDirState(db, dirPath);
35
42
  if (cachedState &&
@@ -47,8 +54,8 @@ export function getDirIndexState(db, dirPath, files, builtAtMs) {
47
54
  persistedRowCount: 0,
48
55
  };
49
56
  }
50
- export function getCachedZeroRowDirState(db, dirPath, files, builtAtMs, priorDirsChanged) {
51
- const state = getDirIndexState(db, dirPath, files, builtAtMs);
57
+ export function getCachedZeroRowDirState(db, dirPath, files, builtAtMs, priorDirsChanged, indexVariant = "") {
58
+ const state = getDirIndexState(db, dirPath, files, builtAtMs, indexVariant);
52
59
  if (state.stale || state.reason.kind !== "cached-zero-row-state")
53
60
  return undefined;
54
61
  if (!canUseIncrementalSkip(state, priorDirsChanged))
@@ -60,7 +67,7 @@ export function canUseIncrementalSkip(state, priorDirsChanged) {
60
67
  state.reason.kind === "cached-zero-row-state" &&
61
68
  state.reason.detail === "deduped-zero-row");
62
69
  }
63
- export function computeDirFingerprint(_dirPath, files) {
70
+ export function computeDirFingerprint(_dirPath, files, indexVariant = "") {
64
71
  const normalizedFiles = [...new Set(files.map((file) => path.basename(file)))].sort();
65
72
  let fileMtimeMaxMs = 0;
66
73
  for (const file of files) {
@@ -73,7 +80,7 @@ export function computeDirFingerprint(_dirPath, files) {
73
80
  }
74
81
  }
75
82
  return {
76
- fileSetHash: normalizedFiles.join("\0"),
83
+ fileSetHash: [indexVariant, ...normalizedFiles].join("\0"),
77
84
  fileMtimeMaxMs,
78
85
  };
79
86
  }
@@ -36,9 +36,11 @@
36
36
  */
37
37
  import fs from "node:fs";
38
38
  import path from "node:path";
39
+ import { detectAdapterId } from "../../core/adapter/detect-adapter.js";
39
40
  import { assembleAsset } from "../../core/asset/asset-serialize.js";
40
41
  import { parseFrontmatter, parseFrontmatterBlock } from "../../core/asset/frontmatter.js";
41
42
  import { conceptIdFromTypeName, parseRefInput } from "../../core/asset/resolve-ref.js";
43
+ import { todayIso } from "../../core/common.js";
42
44
  import { concurrentMap } from "../../core/concurrent.js";
43
45
  import { warn } from "../../core/warn.js";
44
46
  import { writeAssetToSource } from "../../core/write-source.js";
@@ -107,7 +109,7 @@ export async function runMemoryInferencePass(ctx) {
107
109
  // (git, npm, website) are deliberately untouched — writing inferred
108
110
  // children there would be clobbered by the next sync().
109
111
  const primary = sources[0];
110
- if (!primary)
112
+ if (!primary || (primary.adapterId ?? detectAdapterId(primary.path)) !== "akm")
111
113
  return result;
112
114
  const pending = collectPendingMemories(primary.path).filter((record) => !options.candidateRefs || options.candidateRefs.has(record.ref));
113
115
  result.considered = pending.length;
@@ -179,7 +181,7 @@ export async function runMemoryInferencePass(ctx) {
179
181
  const derived = db
180
182
  ? await withLlmCache(db, record.filePath, record.body, reEnrich ?? false, () => compressMemoryToDerivedMemory(llmConfig, record.body, signal, featureConfig, (evt) => {
181
183
  warn(`[akm] LLM fallback for ${evt.feature}: ${evt.reason}`);
182
- }, inferTelemetry, onRetryAttempt), validate, undefined, "", {
184
+ }, inferTelemetry, onRetryAttempt), validate, undefined, "memory-inference-v2", {
183
185
  onCacheHit: () => {
184
186
  fromCache = true;
185
187
  },
@@ -221,8 +223,8 @@ export async function runMemoryInferencePass(ctx) {
221
223
  precheck: false,
222
224
  };
223
225
  },
224
- // Default concurrency of 4 for cloud APIs. Set `llm.concurrency: 1`
225
- // in config.json for local model servers (LM Studio, Ollama).
226
+ // Caller-set connection concurrency or 1: `resolveLlmEngineUse` does
227
+ // not forward `engines.<name>.concurrency`, so config cannot raise this.
226
228
  llmConfig.concurrency ?? 1);
227
229
  for (let i = 0; i < perRecordResults.length; i++) {
228
230
  const res = perRecordResults[i];
@@ -314,7 +316,7 @@ export function collectPendingMemories(stashRoot) {
314
316
  out.push({
315
317
  filePath,
316
318
  stashRoot,
317
- ref: `memory:${relName}`,
319
+ ref: conceptIdFromTypeName("memory", relName),
318
320
  data: parsed.data,
319
321
  body: parsed.content,
320
322
  name: relName,
@@ -374,6 +376,7 @@ async function writeDerivedMemory(parent, derived) {
374
376
  kind: "filesystem",
375
377
  name: "stash",
376
378
  path: parent.stashRoot,
379
+ adapterId: "akm",
377
380
  };
378
381
  const writeConfig = {
379
382
  type: "filesystem",
@@ -407,16 +410,15 @@ function renderDerivedMemory(parent, derived) {
407
410
  const fm = {
408
411
  [FM_INFERRED]: true,
409
412
  [FM_CAPTURE_MODE]: "background",
410
- // Group-C item 2: the `source:` backref (the `derived_from` channel) is now
411
- // written in the 0.9.0 `memories/<name>` conceptId grammar, not the legacy
412
- // `memory:<name>`. `parent.ref` stays the legacy identity ref used internally
413
- // for candidate/progress bookkeeping; only the on-disk backref is flipped.
413
+ // The `source:` backref and internal candidate identity use the same current
414
+ // `memories/<name>` conceptId spelling.
414
415
  [FM_SOURCE]: conceptIdFromTypeName("memory", parent.name),
415
416
  description: derived.description,
416
417
  tags: derived.tags,
417
418
  searchHints: derived.searchHints,
418
419
  title: derived.title,
419
420
  derivedFrom: parent.name,
421
+ updated: todayIso(),
420
422
  };
421
423
  return assembleAsset(fm, `# ${derived.title.trim()}\n\n${derived.content.trim()}\n`);
422
424
  }
@@ -3,10 +3,10 @@
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 { parseBundleRef } from "../../core/asset/asset-ref.js";
6
7
  import { parseFrontmatter } from "../../core/asset/frontmatter.js";
7
8
  import { asNonEmptyString } from "../../core/common.js";
8
9
  import { loadUserConfig } from "../../core/config/config.js";
9
- import { DEPRECATED_REJECTED_TYPES } from "../../core/recognition-util.js";
10
10
  import { isVerbose, warn } from "../../core/warn.js";
11
11
  export const SCOPE_KEYS = ["user", "agent", "run", "channel"];
12
12
  // ── Quality semantics (v1 spec §4.2) ────────────────────────────────────────
@@ -50,11 +50,9 @@ export function isProposedQuality(quality) {
50
50
  /**
51
51
  * Validate and normalize a raw object into a `IndexDocument`.
52
52
  *
53
- * Open type token (chunk 1.5, D1.5-1/D1.5-6): `entry.type` accepts any
54
- * non-empty string foreign/adapter types are valid `IndexDocument` data, not
55
- * just AKM's own built-in set EXCEPT `DEPRECATED_REJECTED_TYPES`
56
- * (`tool`/`vault`), which stay rejected so a hand-edited legacy sidecar can't
57
- * silently resurrect a deliberately-retired type.
53
+ * Open type token: `entry.type` accepts any non-empty string. Type ownership
54
+ * and capability decisions belong to the adapter; this format-neutral
55
+ * projection must not reject a value merely because AKM does not own it.
58
56
  */
59
57
  export function validateStashEntry(entry) {
60
58
  if (typeof entry !== "object" || entry === null)
@@ -62,7 +60,7 @@ export function validateStashEntry(entry) {
62
60
  const e = entry;
63
61
  if (typeof e.name !== "string" || !e.name)
64
62
  return null;
65
- if (typeof e.type !== "string" || !e.type || DEPRECATED_REJECTED_TYPES.has(e.type))
63
+ if (typeof e.type !== "string" || !e.type)
66
64
  return null;
67
65
  const result = {
68
66
  name: e.name,
@@ -144,9 +142,8 @@ export function validateStashEntry(entry) {
144
142
  const sources = normalizeNonEmptyStringList(e.sources);
145
143
  if (sources)
146
144
  result.sources = sources;
147
- // SPEC-6: `category` must survive the whitelist or legacy-sidecar-declared
148
- // facts lose their convention/meta marker on the round-trip. Non-string
149
- // values are dropped, not coerced.
145
+ // SPEC-6: `category` must survive the projection. Non-string values are
146
+ // dropped, not coerced.
150
147
  if (typeof e.category === "string" && e.category.trim().length > 0) {
151
148
  result.category = e.category.trim();
152
149
  }
@@ -165,9 +162,6 @@ export function validateStashEntry(entry) {
165
162
  if (typeof e.generation === "number" && Number.isFinite(e.generation) && e.generation > 0) {
166
163
  result.generation = Math.floor(e.generation);
167
164
  }
168
- const sourceRefs = normalizeNonEmptyStringList(e.sourceRefs);
169
- if (sourceRefs)
170
- result.sourceRefs = sourceRefs;
171
165
  const currentBeliefRefs = normalizeNonEmptyStringList(e.currentBeliefRefs);
172
166
  if (currentBeliefRefs)
173
167
  result.currentBeliefRefs = currentBeliefRefs;
@@ -186,9 +180,8 @@ export function validateStashEntry(entry) {
186
180
  if (typeof e.derivedFrom === "string" && e.derivedFrom.trim().length > 0) {
187
181
  result.derivedFrom = e.derivedFrom.trim();
188
182
  }
189
- // SPEC-8: `bodyOpening` must survive the whitelist so entries round-tripped
190
- // through the legacy sidecar keep their captured opening. Preserved verbatim —
191
- // the extractor already trimmed and capped it at capture time.
183
+ // SPEC-8: `bodyOpening` must survive the projection. The extractor already
184
+ // trimmed and capped it at capture time.
192
185
  if (typeof e.bodyOpening === "string" && e.bodyOpening.trim().length > 0) {
193
186
  result.bodyOpening = e.bodyOpening;
194
187
  }
@@ -283,40 +276,43 @@ function normalizeStringListOrUndefined(value) {
283
276
  return normalizeNonEmptyStringList(value);
284
277
  }
285
278
  /**
286
- * Normalise one derived-memory parent backref to the 0.9.0 `memories/<name>`
287
- * conceptId for the `derived_from` column (Group-C item 2 flip), tolerant of
288
- * BOTH the flipped `[bundle//]memories/<name>` producer output and the legacy
289
- * `[origin//]memory:<name>` spelling still on disk pre content-migration.
290
- * Returns `undefined` for a non-memory / bare value so the caller can fall back
291
- * to the bare `derivedFrom` key. Kept inline (a two-branch pure string op) so
292
- * the indexer stays self-contained and does not import the commands-layer
293
- * reader — the two normalisers agree on output by construction.
279
+ * Normalize a current derived-memory parent ref to its `memories/<name>`
280
+ * conceptId for the `derived_from` column. Returns `undefined` for a non-memory
281
+ * or bare value so the caller can inspect the current `derivedFrom` key.
294
282
  */
295
283
  function normalizeMemoryBackref(value) {
296
284
  if (!value)
297
285
  return undefined;
298
- const trimmed = value.trim();
299
- const boundary = trimmed.indexOf("//");
300
- const body = boundary >= 0 ? trimmed.slice(boundary + 2) : trimmed;
301
- const MEMORY_PREFIX = "memory:";
302
- if (body.startsWith(MEMORY_PREFIX))
303
- return `memories/${body.slice(MEMORY_PREFIX.length)}`;
304
- if (body.startsWith("memories/"))
305
- return body;
306
- return undefined;
286
+ try {
287
+ const parsed = parseBundleRef(value);
288
+ return parsed.fragment === undefined && parsed.conceptId.startsWith("memories/") ? parsed.conceptId : undefined;
289
+ }
290
+ catch {
291
+ return undefined;
292
+ }
307
293
  }
308
294
  /**
309
- * Resolve a derived memory's parent conceptId from its `source:` backref (new or
310
- * legacy grammar) or, failing that, its bare `derivedFrom: <name>` frontmatter
311
- * key (promoted to `memories/<name>`). `undefined` when neither yields a parent.
295
+ * Resolve a derived memory's parent conceptId from its current `source:` backref
296
+ * or, failing that, its bare `derivedFrom: <name>` frontmatter key.
312
297
  */
313
298
  function derivedFromConceptId(source, derivedFrom) {
314
299
  const fromSource = normalizeMemoryBackref(source);
315
300
  if (fromSource)
316
301
  return fromSource;
317
- if (derivedFrom)
318
- return normalizeMemoryBackref(derivedFrom) ?? `memories/${derivedFrom}`;
319
- return undefined;
302
+ const rawDerivedFrom = derivedFrom?.trim();
303
+ if (!rawDerivedFrom)
304
+ return undefined;
305
+ const qualified = normalizeMemoryBackref(rawDerivedFrom);
306
+ if (qualified)
307
+ return qualified;
308
+ if (rawDerivedFrom.includes(":") || rawDerivedFrom.includes("//"))
309
+ return undefined;
310
+ try {
311
+ return parseBundleRef(`memories/${rawDerivedFrom}`).conceptId;
312
+ }
313
+ catch {
314
+ return undefined;
315
+ }
320
316
  }
321
317
  export function applyCuratedFrontmatter(entry, fmData) {
322
318
  const description = asNonEmptyString(fmData.description);
@@ -367,17 +363,12 @@ export function applyCuratedFrontmatter(entry, fmData) {
367
363
  const contradictedBy = normalizeStringListOrUndefined(fmData.contradictedBy);
368
364
  if (contradictedBy)
369
365
  entry.contradictedBy = contradictedBy;
370
- // R5 — consolidation provenance. `generation` (merge depth counter) and
371
- // `source_refs` (merge/distill provenance pointers) are written by the
372
- // improve pipeline; captured into the index so the collapse detector can
373
- // count over-generation assets and follow merges without filesystem reads.
366
+ // R5 — consolidation generation depth is captured so the collapse detector
367
+ // can count over-generation assets without filesystem reads.
374
368
  const generation = fmData.generation;
375
369
  if (typeof generation === "number" && Number.isFinite(generation) && generation > 0) {
376
370
  entry.generation = Math.floor(generation);
377
371
  }
378
- const sourceRefs = normalizeStringListOrUndefined(fmData.source_refs);
379
- if (sourceRefs)
380
- entry.sourceRefs = sourceRefs;
381
372
  const currentBeliefRefs = normalizeStringListOrUndefined(fmData.currentBeliefRefs);
382
373
  if (currentBeliefRefs)
383
374
  entry.currentBeliefRefs = currentBeliefRefs;
@@ -493,6 +484,80 @@ export function applyWikiFrontmatter(entry, fmData) {
493
484
  entry.sources = filtered;
494
485
  }
495
486
  }
487
+ /**
488
+ * Parse one `verified:` family value into the `IndexDocument.provenance` shape.
489
+ * Accepts OKF v0.2's list form and its documented single-mapping shorthand
490
+ * ("consumers MUST treat a bare mapping as a one-element list", SPEC §5.2).
491
+ * Tolerant: an entry without a usable `by` is dropped individually.
492
+ */
493
+ function parseVerifiedFamily(value) {
494
+ const entries = Array.isArray(value) ? value : [value];
495
+ return entries
496
+ .filter((v) => v !== null && typeof v === "object" && !Array.isArray(v))
497
+ .map((v) => {
498
+ const by = asNonEmptyString(v.by);
499
+ if (!by)
500
+ return undefined;
501
+ const at = asNonEmptyString(v.at);
502
+ return at ? { by, at } : { by };
503
+ })
504
+ .filter((v) => v !== undefined);
505
+ }
506
+ /**
507
+ * Extract the OKF v0.2 provenance families that `promoteProposal` stamps onto
508
+ * accepted AKM-native proposals (D2, #730), and apply them to the entry.
509
+ *
510
+ * The on-disk shape is deliberately **hybrid** (owner decision, #730 review):
511
+ * `generated:` and `verified:` are stamped BARE at the top level, exactly as
512
+ * OKF v0.2 spells them, because neither has any pre-existing AKM consumer — so
513
+ * a third-party OKF v0.2 reader treating an AKM stash as an OKF bundle sees
514
+ * spec-conformant trust metadata, which is what `okf-support.md`'s
515
+ * "AKM Markdown is an OKF-compatible superset" positioning promises. Only
516
+ * `sources` stays namespaced under `provenance:`, because a bare top-level
517
+ * `sources:` genuinely collides with {@link applyWikiFrontmatter}'s
518
+ * pre-existing citation-**string** convention (which silently drops
519
+ * non-strings).
520
+ *
521
+ * The nested `provenance.generatedBy` / `.generatedAt` / `.verified` spellings
522
+ * are still read as a fallback so assets stamped by an earlier build of this
523
+ * branch keep resolving. Tolerant throughout: any malformed sub-field is
524
+ * dropped individually rather than rejecting the whole block.
525
+ */
526
+ export function applyProvenanceFrontmatter(entry, fmData) {
527
+ const provenance = fmData.provenance;
528
+ const nested = provenance !== null && typeof provenance === "object" && !Array.isArray(provenance)
529
+ ? provenance
530
+ : {};
531
+ const result = {};
532
+ // Bare `generated: {by, at}` (OKF v0.2 §5.3) wins; nested is the fallback.
533
+ const generatedMapping = fmData.generated !== null && typeof fmData.generated === "object" && !Array.isArray(fmData.generated)
534
+ ? fmData.generated
535
+ : undefined;
536
+ const generatedBy = asNonEmptyString(generatedMapping?.by) ?? asNonEmptyString(nested.generatedBy);
537
+ if (generatedBy)
538
+ result.generatedBy = generatedBy;
539
+ const generatedAt = asNonEmptyString(generatedMapping?.at) ?? asNonEmptyString(nested.generatedAt);
540
+ if (generatedAt)
541
+ result.generatedAt = generatedAt;
542
+ // Bare `verified:` (list or single mapping) wins; nested is the fallback.
543
+ const verified = fmData.verified !== undefined ? parseVerifiedFamily(fmData.verified) : parseVerifiedFamily(nested.verified);
544
+ if (verified.length > 0)
545
+ result.verified = verified;
546
+ // `sources` is namespaced-only — see the collision note above.
547
+ if (Array.isArray(nested.sources)) {
548
+ const sources = nested.sources
549
+ .filter((s) => s !== null && typeof s === "object" && !Array.isArray(s))
550
+ .map((s) => {
551
+ const resource = asNonEmptyString(s.resource);
552
+ return resource ? { resource } : undefined;
553
+ })
554
+ .filter((s) => s !== undefined);
555
+ if (sources.length > 0)
556
+ result.sources = sources;
557
+ }
558
+ if (Object.keys(result).length > 0)
559
+ entry.provenance = result;
560
+ }
496
561
  // AKM-stash indexing policy (env/vaults/secrets sensitive-marker + wiki-infra
497
562
  // exclusions) moved to the `akm` adapter's `recognize` as path/stat-based
498
563
  // abstention (owner ruling 2026-07-21 — adapter-owned filtering). See
@@ -763,7 +828,6 @@ function mergeAliases(existing, generated) {
763
828
  *
764
829
  * This predicate is used by `enhanceDirsWithLlm` to skip the LLM call for
765
830
  * entries that were previously enriched and already carry all three fields.
766
- * Pass `reEnrich = true` in the caller to bypass this check.
767
831
  */
768
832
  export function isEnrichmentComplete(entry) {
769
833
  const hasDescription = typeof entry.description === "string" && entry.description.trim().length > 0;
@@ -994,6 +1058,8 @@ export function applyPreContributorFields(entry, file, ctx, pkgMeta) {
994
1058
  entry.parameters = fmParams;
995
1059
  // Pass wiki-pattern frontmatter through onto the entry
996
1060
  applyWikiFrontmatter(entry, parsed.data);
1061
+ // D2 (#730): reread the namespaced `provenance:` block promoteProposal stamps.
1062
+ applyProvenanceFrontmatter(entry, parsed.data);
997
1063
  // Stash-organization conventions (SPEC-8): config-gated capture of the
998
1064
  // self-situating body opening. Default off — enabling it changes indexed
999
1065
  // text (collapse-detector canary baselines shift, and embeddings for
@@ -58,10 +58,39 @@ export function indexDocumentToStashEntry(doc) {
58
58
  entry.description = doc.description;
59
59
  if (doc.tags !== undefined)
60
60
  entry.tags = doc.tags;
61
+ if (doc.content !== undefined)
62
+ entry.content = doc.content;
63
+ if (doc.ownsPresentation !== undefined)
64
+ entry.ownsPresentation = doc.ownsPresentation;
65
+ if (doc.updated !== undefined)
66
+ entry.updated = doc.updated;
67
+ if (doc.links !== undefined)
68
+ entry.links = doc.links;
69
+ if (doc.adapterId === "okf") {
70
+ if (doc.documentJson !== undefined)
71
+ entry.documentJson = doc.documentJson;
72
+ // OKF v0.2 trust/provenance/lifecycle family (okf-support.md v0.2 note).
73
+ // These are first-class IndexDocument members the okf adapter sets
74
+ // directly (never routed through documentJson), so — unlike the akm
75
+ // adapter's DOCUMENT_JSON_CARRIED_FIELDS reconstruction below — they need
76
+ // an explicit carry here too, or persistence silently drops them even
77
+ // though `recognize()` itself returns them correctly.
78
+ if (doc.provenance !== undefined)
79
+ entry.provenance = doc.provenance;
80
+ if (doc.lifecycleStatus !== undefined)
81
+ entry.lifecycleStatus = doc.lifecycleStatus;
82
+ if (doc.staleAfter !== undefined)
83
+ entry.staleAfter = doc.staleAfter;
84
+ if (doc.okfVersion !== undefined)
85
+ entry.okfVersion = doc.okfVersion;
86
+ return entry;
87
+ }
61
88
  if (doc.aliases !== undefined)
62
89
  entry.aliases = doc.aliases;
63
90
  if (doc.searchHints !== undefined)
64
91
  entry.searchHints = doc.searchHints;
92
+ if (doc.hints !== undefined)
93
+ entry.hints = doc.hints;
65
94
  if (doc.quality !== undefined)
66
95
  entry.quality = doc.quality;
67
96
  if (doc.confidence !== undefined)
@@ -78,6 +107,8 @@ export function indexDocumentToStashEntry(doc) {
78
107
  entry.lessonStrength = doc.lessonStrength;
79
108
  if (doc.derivedFrom !== undefined)
80
109
  entry.derivedFrom = doc.derivedFrom;
110
+ if (doc.pinned !== undefined)
111
+ entry.pinned = doc.pinned;
81
112
  // ── documentJson-carried extras (DOCUMENT_JSON_CARRIED_FIELDS) ──
82
113
  // The `renderer` key on documentJson is adapter-internal (WI-C presentation),
83
114
  // NOT a IndexDocument field — deliberately not restored.
@@ -106,8 +137,14 @@ export function indexDocumentToStashEntry(doc) {
106
137
  assignStringList(entry, "sources", dj.sources);
107
138
  if (typeof dj.generation === "number")
108
139
  entry.generation = dj.generation;
109
- assignStringList(entry, "sourceRefs", dj.sourceRefs);
110
140
  assignStringList(entry, "evidenceSources", dj.evidenceSources);
141
+ // D2 (#730): OKF v0.2 provenance promoteProposal stamps onto AKM-native
142
+ // writes, carried via DOCUMENT_JSON_CARRIED_FIELDS (akm-adapter.ts) —
143
+ // unpacked back to a first-class member here exactly like `sources`/
144
+ // `generation`/`evidenceSources` above, so it round-trips to the top level
145
+ // of the persisted entry rather than staying nested under `documentJson`.
146
+ if (dj.provenance !== undefined)
147
+ entry.provenance = dj.provenance;
111
148
  return entry;
112
149
  }
113
150
  function assignStringList(entry, key, value) {