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
@@ -11,6 +11,7 @@
11
11
  import fs from "node:fs";
12
12
  import path from "node:path";
13
13
  import { parse as yamlParse } from "yaml";
14
+ import { detectAdapterId } from "../../core/adapter/detect-adapter.js";
14
15
  import { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath } from "../../core/asset/asset-create.js";
15
16
  import { assetPathForName, stashDirFor } from "../../core/asset/asset-placement.js";
16
17
  import { assembleAsset } from "../../core/asset/asset-serialize.js";
@@ -19,11 +20,14 @@ import { conceptIdFromTypeName, parseRefInput } from "../../core/asset/resolve-r
19
20
  import { isHttpUrl, isWithin, resolveStashDir, tryReadStdinText } from "../../core/common.js";
20
21
  import { loadConfig } from "../../core/config/config.js";
21
22
  import { UsageError } from "../../core/errors.js";
23
+ import { resolveBundleWriteTarget, resolveMutationTarget } from "../../core/mutation-target.js";
22
24
  import { resolveStashStandards } from "../../core/standards/resolve-stash-standards.js";
23
25
  import { warn } from "../../core/warn.js";
24
26
  import { commitWriteTargetBoundary, formatRefForMessage, recordWriteTargetPath, resolveWriteTarget, writeAssetToSource, } from "../../core/write-source.js";
25
27
  import { indexWrittenAssets } from "../../indexer/index-written-assets.js";
28
+ import { deriveInstallations, slugForPath } from "../../indexer/installations.js";
26
29
  import { resolveSourceEntries } from "../../indexer/search/search-source.js";
30
+ import { storeSecretResolver } from "../../sources/snapshot-fetchers/secret-seam.js";
27
31
  import { fetchWebsiteMarkdownSnapshot, shouldAllowPrivateWebsiteUrlForTests, } from "../../sources/snapshot-fetchers/website-ingest.js";
28
32
  import { writeSupersededEdge } from "../improve/memory/memory-belief.js";
29
33
  import { refToRelPath, resolveRefPathInStash } from "../lint/base-linter.js";
@@ -116,19 +120,16 @@ export async function readKnowledgeInput(source, options) {
116
120
  return readKnowledgeContent(source);
117
121
  const snapshot = await fetchWebsiteMarkdownSnapshot(source, {
118
122
  stashDir: options?.stashDir,
123
+ resolveSecret: storeSecretResolver.resolveSecret,
119
124
  allowPrivateHosts: options?.allowPrivateHosts ?? shouldAllowPrivateWebsiteUrlForTests(source),
120
125
  });
121
126
  return { content: snapshot.content, preferredName: snapshot.preferredName };
122
127
  }
123
128
  /**
124
129
  * Parse a `--xref` / `--supersedes` value through the new-grammar input parser
125
- * (`parseRefInput`, the 0.9.0 `[bundle//]conceptId` grammar) so malformed and
126
- * origin-prefixed spellings get a structured error instead of a misleading "did
127
- * not resolve". Chunk-8 WI-8.5c: the legacy `[origin//]type:name` content-surface
128
- * arm is retired — `--xref`/`--supersedes` take the conceptId form. A `local//`
129
- * origin is accepted (it names the same local resolution this validator
130
- * performs, mirroring lint's `local//` strip); any other origin is rejected —
131
- * write-time validation only resolves local stash roots.
130
+ * (`parseRefInput`, the `[bundle//]conceptId` grammar) so malformed values get a
131
+ * structured error instead of a misleading "did not resolve". Bundle qualifiers
132
+ * are retained for exact source membership checks.
132
133
  */
133
134
  function parseWriteRef(raw, flag) {
134
135
  let parsed;
@@ -139,21 +140,21 @@ function parseWriteRef(raw, flag) {
139
140
  const message = error instanceof Error ? error.message : String(error);
140
141
  throw new UsageError(`${flag} "${raw}" is not a valid asset ref: ${message}`, "INVALID_FLAG_VALUE", `Refs use the conceptId form, e.g. ${flag} knowledge/auth-flow.`);
141
142
  }
142
- if (parsed.origin && parsed.origin !== "local") {
143
- throw new UsageError(`${flag} "${raw}" carries the origin prefix "${parsed.origin}//" — ${flag} only resolves refs in the write target, the working stash, and configured sources.`, "INVALID_FLAG_VALUE", `Pass the plain conceptId form, e.g. ${flag} ${conceptIdFromTypeName(parsed.type, parsed.name)}.`);
144
- }
145
- // Canonical bare conceptId: type alias resolved, name normalized, `local//`
146
- // dropped (it names the same local resolution this validator performs). The
147
- // bare `<stash-subdir>/<name>` short ref (WI-8.5a) is what lands in the
148
- // containing bundle's frontmatter (§11.1 short-ref rule); the name is already
149
- // normalized by the parser.
150
- return { ref: conceptIdFromTypeName(parsed.type, parsed.name), type: parsed.type, name: parsed.name };
143
+ // Bundle qualifiers remain explicit so duplicate names resolve in the named
144
+ // source.
145
+ const conceptId = conceptIdFromTypeName(parsed.type, parsed.name);
146
+ const origin = parsed.origin;
147
+ return {
148
+ ref: origin ? `${origin}//${conceptId}` : conceptId,
149
+ type: parsed.type,
150
+ name: parsed.name,
151
+ ...(origin ? { origin } : {}),
152
+ };
151
153
  }
152
154
  /**
153
155
  * Trim, parse, and dedupe `--xref` / `--supersedes` flag values, in argv
154
- * order. Parsing comes BEFORE deduplication so two alias spellings of the
155
- * same asset (`environment:prod` and `env:prod`, `local//knowledge:x` and
156
- * `knowledge:x`) collapse into one canonical entry.
156
+ * order. Parsing comes before deduplication so normalized spellings collapse
157
+ * into one canonical entry.
157
158
  */
158
159
  function parseWriteRefs(rawRefs, flag) {
159
160
  const parsedRefs = [];
@@ -167,26 +168,26 @@ function parseWriteRefs(rawRefs, flag) {
167
168
  }
168
169
  return parsedRefs;
169
170
  }
170
- /**
171
- * The ONE root set write-time ref validation resolves against, shared by
172
- * `resolveXrefsForWrite` and `resolveSupersedesForWrite` so the two flags can
173
- * never disagree on what a ref resolves to:
174
- *
175
- * 1. the resolved write target (mutable),
176
- * 2. the primary working stash when it is a different directory (mutable) —
177
- * a `--target`/`defaultWriteTarget` write must still see working-stash
178
- * assets, which `resolveSourceEntries(writeTarget)` alone omits,
179
- * 3. every other configured source (read-only for demotion purposes).
180
- *
181
- * NOTE: this is deliberately a superset of lint's root set (lint roots at the
182
- * working stash; this roots at the write target AND the working stash).
183
- */
184
171
  function resolveWriteRefRoots(target) {
185
172
  const cfg = loadConfig();
186
- const stashRoot = resolveWriteTarget(cfg, target).source.path;
173
+ let writeTarget;
174
+ try {
175
+ writeTarget = resolveWriteTarget(cfg, target);
176
+ }
177
+ catch (error) {
178
+ if (!target)
179
+ throw error;
180
+ try {
181
+ writeTarget = resolveBundleWriteTarget(cfg, target);
182
+ }
183
+ catch {
184
+ throw error;
185
+ }
186
+ }
187
+ const stashRoot = writeTarget.source.path;
187
188
  let workingStash;
188
189
  try {
189
- workingStash = resolveStashDir({ readOnly: true });
190
+ workingStash = resolveStashDir();
190
191
  }
191
192
  catch {
192
193
  // No working stash configured — the write target alone.
@@ -194,15 +195,51 @@ function resolveWriteRefRoots(target) {
194
195
  const mutableRoots = [stashRoot];
195
196
  if (workingStash && path.resolve(workingStash) !== path.resolve(stashRoot))
196
197
  mutableRoots.push(workingStash);
197
- const otherSources = resolveSourceEntries(stashRoot, cfg).filter((s) => !mutableRoots.some((m) => path.resolve(m) === path.resolve(s.path)) && fs.existsSync(s.path));
198
- return { mutableRoots: mutableRoots.filter((p) => fs.existsSync(p)), otherSources };
198
+ const namedSources = resolveSourceEntries(undefined, cfg);
199
+ const installations = deriveInstallations(namedSources);
200
+ const bundleByPath = new Map(namedSources.flatMap((source, index) => {
201
+ const bundleId = installations[index]?.id;
202
+ return bundleId ? [[path.resolve(source.path), bundleId]] : [];
203
+ }));
204
+ const otherSources = namedSources.filter((s) => !mutableRoots.some((m) => path.resolve(m) === path.resolve(s.path)) && fs.existsSync(s.path));
205
+ const roots = [
206
+ ...mutableRoots
207
+ .filter((p) => fs.existsSync(p))
208
+ .map((p) => {
209
+ const source = namedSources.find((candidate) => path.resolve(candidate.path) === path.resolve(p));
210
+ const mutable = path.resolve(p) === path.resolve(stashRoot)
211
+ ? writeTarget.source.adapterId === "akm"
212
+ : source?.writable === true && (source.adapterId ?? detectAdapterId(p)) === "akm";
213
+ return {
214
+ path: p,
215
+ source,
216
+ bundleId: bundleByPath.get(path.resolve(p)) ?? slugForPath(p),
217
+ mutable,
218
+ };
219
+ }),
220
+ ...otherSources.map((source) => ({
221
+ path: source.path,
222
+ source,
223
+ bundleId: bundleByPath.get(path.resolve(source.path)) ?? slugForPath(source.path),
224
+ mutable: false,
225
+ })),
226
+ ];
227
+ return { roots };
228
+ }
229
+ function rootsForWriteRef(parsed, roots) {
230
+ if (!parsed.origin)
231
+ return roots;
232
+ return roots.filter((root) => root.bundleId === parsed.origin);
233
+ }
234
+ function canonicalWriteRef(parsed, bundleId) {
235
+ return `${bundleId}//${conceptIdFromTypeName(parsed.type, parsed.name)}`;
199
236
  }
200
237
  /**
201
238
  * True when write-time validation must FAIL OPEN for this ref type — exactly
202
239
  * lint's `checkMissingRefs` policy (`if (relPath === null) continue`,
203
- * base-linter.ts): a type the slug resolver cannot map to a path (`script:` is
204
- * contract-pinned to return null) is accepted without an existence check
205
- * rather than being unwinnable. `workflow:` never fails open — it resolves
240
+ * base-linter.ts): a type the slug resolver cannot map to a path (script refs
241
+ * are contract-pinned to return null) is accepted without an existence check
242
+ * rather than being unwinnable. Workflow refs never fail open — they resolve
206
243
  * stash-rooted via {@link locateWriteRefInRoot}.
207
244
  */
208
245
  function isFailOpenRefType(type, name) {
@@ -210,7 +247,7 @@ function isFailOpenRefType(type, name) {
210
247
  }
211
248
  /**
212
249
  * Resolve a write-time ref to its primary on-disk file within a single stash
213
- * root. Wraps lint's `resolveRefPathInStash` with one addition: `workflow:`
250
+ * root. Wraps lint's `resolveRefPathInStash` with one addition: workflow
214
251
  * refs are probed against the ROOT's workflows/ dir first (every recognized
215
252
  * workflow extension), because `workflowSpec.toAssetPath` inside
216
253
  * `refToRelPath` probes the CWD — and write validation must not depend on the
@@ -230,8 +267,9 @@ function locateWriteRefInRoot(type, name, root) {
230
267
  }
231
268
  /** Build the shared exit-2 error for refs that resolved in no root. */
232
269
  function unresolvedRefsError(flag, unresolved) {
233
- const first = unresolved[0];
234
- return new UsageError(`${flag} ref${unresolved.length > 1 ? "s" : ""} did not resolve in the write target or any configured source: ${unresolved.map((u) => u.ref).join(", ")}`, "INVALID_FLAG_VALUE", `Find the intended asset with \`akm search "${first.name}" --type ${first.type}\`. Refs use the form [bundle//]conceptId (e.g. knowledge/guide.md).`);
270
+ const firstName = unresolved[0]?.name ?? "asset";
271
+ const firstType = unresolved[0]?.type ?? "knowledge";
272
+ return new UsageError(`${flag} ref${unresolved.length > 1 ? "s" : ""} did not resolve in the write target or any configured source: ${unresolved.map((u) => u.ref).join(", ")}`, "INVALID_FLAG_VALUE", `Find the intended asset with \`akm search "${firstName}" --type ${firstType}\`. Refs use the form [bundle//]conceptId (e.g. knowledge/guide.md).`);
235
273
  }
236
274
  // ── Cross-references (--xref) ────────────────────────────────────────────────
237
275
  /**
@@ -243,7 +281,7 @@ export const XREF_SOFT_CAP = 5;
243
281
  /**
244
282
  * Validate `--xref` flag values before ANY write happens.
245
283
  *
246
- * Each ref (`type:name`) must resolve to a real asset in the write-ref root
284
+ * Each `[bundle//]conceptId` must resolve to a real asset in the write-ref root
247
285
  * set (write target + working stash + configured sources — see
248
286
  * {@link resolveWriteRefRoots}; cross-stash provenance refs into read-only
249
287
  * sources are accepted). An unresolvable ref is input validation of an
@@ -252,33 +290,36 @@ export const XREF_SOFT_CAP = 5;
252
290
  * validation leaves the stash untouched. Resolution reuses the lint
253
291
  * ref-resolver helpers (`refToRelPath` / `resolveRefPathInStash`) — do not
254
292
  * fork a second resolver — and mirrors lint's fail-open policy: a type the
255
- * resolver cannot map to a path (`script:`) is accepted without an existence
256
- * check.
293
+ * resolver cannot map to a path (for example a script concept) is accepted
294
+ * without an existence check.
257
295
  *
258
- * Returns the CANONICAL `type:name` spellings (alias types resolved, names
259
- * normalized, `local//` stripped see {@link ParsedWriteRef}), deduplicated
260
- * in argv order. More than {@link XREF_SOFT_CAP} refs emits a stderr warning
261
- * (soft cap) but still returns them all.
296
+ * Returns fully-qualified durable refs, deduplicated in argv order. More than
297
+ * {@link XREF_SOFT_CAP} refs emits a stderr warning (soft cap) but still
298
+ * returns them all.
262
299
  */
263
300
  export function resolveXrefsForWrite(rawXrefs, target) {
264
301
  const parsedRefs = parseWriteRefs(rawXrefs, "--xref");
265
302
  if (parsedRefs.length === 0)
266
303
  return [];
267
- const { mutableRoots, otherSources } = resolveWriteRefRoots(target);
268
- const allRoots = [...mutableRoots, ...otherSources.map((s) => s.path)];
304
+ const { roots } = resolveWriteRefRoots(target);
269
305
  const unresolved = [];
306
+ const xrefs = [];
270
307
  for (const parsed of parsedRefs) {
271
- if (isFailOpenRefType(parsed.type, parsed.name))
272
- continue;
273
- if (!allRoots.some((root) => locateWriteRefInRoot(parsed.type, parsed.name, root) !== null)) {
308
+ const candidates = rootsForWriteRef(parsed, roots);
309
+ const resolvedRoot = isFailOpenRefType(parsed.type, parsed.name)
310
+ ? candidates[0]
311
+ : candidates.find((root) => locateWriteRefInRoot(parsed.type, parsed.name, root.path) !== null);
312
+ if (!resolvedRoot) {
274
313
  unresolved.push(parsed);
314
+ continue;
275
315
  }
316
+ const ref = canonicalWriteRef(parsed, resolvedRoot.bundleId);
317
+ if (!xrefs.includes(ref))
318
+ xrefs.push(ref);
276
319
  }
277
320
  if (unresolved.length > 0) {
278
321
  throw unresolvedRefsError("--xref", unresolved);
279
322
  }
280
- // The CANONICAL spellings are what land in frontmatter (see ParsedWriteRef).
281
- const xrefs = parsedRefs.map((p) => p.ref);
282
323
  if (xrefs.length > XREF_SOFT_CAP) {
283
324
  warn(`Warning: ${xrefs.length} xrefs exceeds the ~${XREF_SOFT_CAP} soft cap from the back-linking conventions. ` +
284
325
  "Each xref folds into this asset's search hints, so extras blur its ranking signal. Writing anyway.");
@@ -300,8 +341,9 @@ export function resolveXrefsForWrite(rawXrefs, target) {
300
341
  * scanner and re-serializing that lossy result would destroy list/nested
301
342
  * values (`tags: [a, b]` → `tags: ""`). Rather than corrupt data the caller
302
343
  * asked to preserve, a block that is not a parseable YAML mapping throws
303
- * {@link UsageError} (exit 2, before any write) fix the frontmatter or run
304
- * the command without `--xref`, which keeps the file verbatim. Known
344
+ * {@link UsageError} (exit 2, before any write). The AKM write boundary also
345
+ * rejects malformed frontmatter without `--xref` because it cannot safely add
346
+ * required type metadata. Known
305
347
  * cosmetic limitation: YAML comments and anchors in a VALID block do not
306
348
  * survive the round-trip (values are preserved).
307
349
  */
@@ -311,7 +353,7 @@ export function mergeXrefsIntoContent(content, xrefs) {
311
353
  const parsed = parseFrontmatter(content);
312
354
  if (parsed.frontmatter?.trim()) {
313
355
  if (!isParseableYamlMapping(parsed.frontmatter)) {
314
- throw new UsageError("--xref cannot merge into this document: its frontmatter is not a parseable YAML mapping, and rewriting it would drop the values the parser could not read.", "INVALID_FLAG_VALUE", "Fix the document's frontmatter (e.g. an unterminated quote) and retry, or run the command without --xref to keep the file verbatim.");
356
+ throw new UsageError("--xref cannot merge into this document: its frontmatter is not a parseable YAML mapping, and rewriting it would drop the values the parser could not read.", "INVALID_FLAG_VALUE", "Fix the document's frontmatter (e.g. an unterminated quote) and retry.");
315
357
  }
316
358
  }
317
359
  const existingValue = parsed.data.xrefs;
@@ -343,6 +385,18 @@ function isParseableYamlMapping(frontmatter) {
343
385
  return false;
344
386
  }
345
387
  }
388
+ /** Resolve any qualified supersedes ref as the mutation target for remember/import. */
389
+ export function resolveSupersedesWriteTarget(rawRefs, target) {
390
+ const config = loadConfig();
391
+ let effectiveTarget = target;
392
+ for (const parsed of parseWriteRefs(rawRefs, "--supersedes")) {
393
+ if (!parsed.origin)
394
+ continue;
395
+ const resolved = resolveMutationTarget(config, { type: parsed.type, name: parsed.name, origin: parsed.origin }, effectiveTarget).target;
396
+ effectiveTarget = resolved.selector ?? resolved.source.name;
397
+ }
398
+ return effectiveTarget;
399
+ }
346
400
  /**
347
401
  * Asset types `--supersedes` must refuse to demote: the demotion writes a YAML
348
402
  * frontmatter block onto the target file, and these types are RAW files whose
@@ -366,7 +420,7 @@ const SUPERSEDE_REJECTED_TYPES = new Set(["secret", "env", "task", "script"]);
366
420
  * Because the demotion PREPENDS a YAML frontmatter block when the target file
367
421
  * has none, only markdown assets may be demoted: refs of a raw asset type
368
422
  * ({@link SUPERSEDE_REJECTED_TYPES}) and refs resolving to any non-`.md` file
369
- * (e.g. a YAML workflow program) are rejected with {@link UsageError} BEFORE
423
+ * (for example a task YAML file) are rejected with {@link UsageError} BEFORE
370
424
  * any write — never silently corrupted.
371
425
  *
372
426
  * Demotion targets must live under the resolved write target's source path or
@@ -384,30 +438,28 @@ export function resolveSupersedesForWrite(rawRefs, target) {
384
438
  const parsedRefs = parseWriteRefs(rawRefs, "--supersedes");
385
439
  if (parsedRefs.length === 0)
386
440
  return [];
387
- const { mutableRoots, otherSources } = resolveWriteRefRoots(target);
388
- // Mutable roots first: when a ref resolves in several roots, demote the copy
389
- // this command is allowed to mutate. Non-mutable roots keep their SearchSource
390
- // so the skip reason can distinguish "re-run with --target" (a configured
391
- // writable source that simply is not this write's target) from genuinely
392
- // read-only sources.
393
- const orderedRoots = [
394
- ...mutableRoots.map((p) => ({ path: p })),
395
- ...otherSources.map((s) => ({ path: s.path, source: s })),
396
- ];
441
+ const { roots } = resolveWriteRefRoots(target);
397
442
  const plan = [];
398
443
  const unresolved = [];
399
444
  for (const parsed of parsedRefs) {
445
+ const orderedRoots = rootsForWriteRef(parsed, roots);
400
446
  // Data-corruption gate (SPEC-5): demotion is a frontmatter write; a raw
401
447
  // asset type must be rejected up front — resolving it and mutating the
402
448
  // file would prepend a YAML block over its raw bytes.
403
449
  if (SUPERSEDE_REJECTED_TYPES.has(parsed.type)) {
404
- throw new UsageError(`--supersedes cannot demote ${parsed.ref}: "${parsed.type}:" assets are raw files, and the demotion writes YAML frontmatter that would corrupt them.`, "INVALID_FLAG_VALUE", "Only markdown assets (e.g. memory:, knowledge:, fact:) can carry the beliefState/supersededBy demotion. Replace or delete the raw asset instead.");
450
+ throw new UsageError(`--supersedes cannot demote ${parsed.ref}: asset type "${parsed.type}" uses raw files, and the demotion writes YAML frontmatter that would corrupt them.`, "INVALID_FLAG_VALUE", "Only markdown assets (e.g. memories/note, knowledge/guide, facts/team/tool-stack) can carry the beliefState/supersededBy demotion. Replace or delete the raw asset instead.");
405
451
  }
406
452
  let located = null;
407
453
  for (const root of orderedRoots) {
408
454
  const filePath = locateWriteRefInRoot(parsed.type, parsed.name, root.path);
409
455
  if (filePath !== null) {
410
- located = { root: root.path, source: root.source, filePath };
456
+ located = {
457
+ root: root.path,
458
+ source: root.source,
459
+ bundleId: root.bundleId,
460
+ mutable: root.mutable,
461
+ filePath,
462
+ };
411
463
  break;
412
464
  }
413
465
  }
@@ -416,20 +468,21 @@ export function resolveSupersedesForWrite(rawRefs, target) {
416
468
  continue;
417
469
  }
418
470
  // Belt-and-suspenders for the same corruption class: whatever the type,
419
- // the demotion may only touch a markdown file. Rejects e.g. a YAML
420
- // workflow program (`workflow:deploy` resolving to workflows/deploy.yaml,
421
- // or the explicit `workflow:deploy.yaml` spelling).
471
+ // the demotion may only touch a markdown file. Rejects, for example, a task
472
+ // YAML file reached through a malformed or stale ref.
422
473
  if (!located.filePath.toLowerCase().endsWith(".md")) {
423
474
  throw new UsageError(`--supersedes ${parsed.ref} resolves to a non-markdown file (${located.filePath}) — the demotion writes YAML frontmatter and would corrupt it.`, "INVALID_FLAG_VALUE", "Only markdown assets can carry the beliefState/supersededBy demotion. Replace or delete the file instead.");
424
475
  }
425
- const { root, source, filePath } = located;
426
- const writable = source === undefined;
476
+ const { root, source, bundleId, mutable: writable, filePath } = located;
427
477
  // The eligibility rule is write-target-or-working-stash, NOT source
428
478
  // writability: mutating a non-target writable source would leave it dirty
429
479
  // outside any boundary commit. Name the remedy when one exists.
430
480
  const namedWritableSource = source?.writable === true ? source.registryId : undefined;
481
+ const canonicalRef = canonicalWriteRef(parsed, bundleId);
482
+ if (plan.some((item) => item.ref === canonicalRef))
483
+ continue;
431
484
  plan.push({
432
- ref: parsed.ref,
485
+ ref: canonicalRef,
433
486
  filePath,
434
487
  stashRoot: root,
435
488
  writable,
@@ -460,14 +513,15 @@ export function resolveSupersedesForWrite(rawRefs, target) {
460
513
  */
461
514
  export async function writeMarkdownAsset(options) {
462
515
  const cfg = loadConfig();
463
- const target = resolveWriteTarget(cfg, options.target);
464
- const { source, config } = target;
465
- const typeRoot = path.join(source.path, options.type === "knowledge" ? "knowledge" : "memories");
466
516
  // `--name` is the flat asset name; `--path` is the subdirectory under the
467
517
  // type root. Combine them into the nested name the path resolver expects.
468
518
  const subPath = normalizeCreateSubPath(options.path);
469
519
  const baseName = normalizeMarkdownAssetName(options.name, inferAssetName(options.content, options.fallbackPrefix, options.preferredName));
470
520
  const normalizedName = combineCreatePath(subPath, baseName);
521
+ const resolved = resolveMutationTarget(cfg, { type: options.type, name: normalizedName }, options.target);
522
+ const { target } = resolved;
523
+ const { source, config } = target;
524
+ const typeRoot = path.join(source.path, options.type === "knowledge" ? "knowledge" : "memories");
471
525
  // Pre-flight: existence + force semantics. The helper itself overwrites
472
526
  // unconditionally; the CLI surfaces a friendlier UsageError before any
473
527
  // disk activity when --force is absent.
@@ -485,11 +539,12 @@ export async function writeMarkdownAsset(options) {
485
539
  // Input validation: exit 2, before any write, nothing demoted.
486
540
  for (const item of options.supersedes ?? []) {
487
541
  if (path.resolve(item.filePath) === path.resolve(assetPath)) {
488
- throw new UsageError(`--supersedes ${item.ref} resolves to the asset being written ("${options.type}:${normalizedName}") — a correction cannot supersede itself.`, "INVALID_FLAG_VALUE", "Write the correction under a different --name, or drop --supersedes when overwriting an asset in place with --force.");
542
+ throw new UsageError(`--supersedes ${item.ref} resolves to the asset being written ("${resolved.displayRef}") — a correction cannot supersede itself.`, "INVALID_FLAG_VALUE", "Write the correction under a different --name, or drop --supersedes when overwriting an asset in place with --force.");
489
543
  }
490
544
  }
491
- const ref = { type: options.type, name: normalizedName };
492
- const result = await writeAssetToSource(source, config, ref, options.content);
545
+ const result = await writeAssetToSource(source, config, resolved.ref, options.content);
546
+ const durableRef = result.ref;
547
+ result.ref = resolved.displayRef;
493
548
  // SPEC-5 (--supersedes): demote each superseded asset by mutating its
494
549
  // frontmatter (`beliefState: superseded` + sorted-set-append `supersededBy`;
495
550
  // every other key and the body are preserved). Ordered BEFORE
@@ -532,12 +587,9 @@ export async function writeMarkdownAsset(options) {
532
587
  // on a git target, uncommitted (and a re-run hits RESOURCE_ALREADY_EXISTS).
533
588
  // Degrade to the same applied:false report the non-writable path uses.
534
589
  try {
535
- // supersededBy points at the correction's canonical write ref (F4b-flipped
536
- // display spelling), keeping it in lockstep with the reported `result.ref`.
537
- // The --xref/--supersedes input path (resolveXrefsForWrite/parseWriteRef)
538
- // is now the new-grammar conceptId surface too (WI-8.5c).
539
- writeSupersededEdge(item.filePath, result.ref);
540
- if (path.resolve(item.stashRoot) === path.resolve(source.path)) {
590
+ const sameSource = path.resolve(item.stashRoot) === path.resolve(source.path);
591
+ writeSupersededEdge(item.filePath, durableRef);
592
+ if (sameSource) {
541
593
  recordWriteTargetPath(source, item.filePath);
542
594
  }
543
595
  }
@@ -555,7 +607,7 @@ export async function writeMarkdownAsset(options) {
555
607
  }
556
608
  // 0.9.0 (issue #507): single batch commit at the write boundary for git
557
609
  // targets. No-op for filesystem/primary-stash targets.
558
- commitWriteTargetBoundary(target, `Update ${formatRefForMessage(ref)}`);
610
+ commitWriteTargetBoundary(target, `Update ${formatRefForMessage(resolved.ref)}`);
559
611
  // Write-path indexing: the asset is searchable immediately. Fail-open; reads
560
612
  // no longer trigger reindexes, so keeping the index current is the writer's
561
613
  // job. Demoted files reindex under their own containing root (usually the
@@ -564,9 +616,12 @@ export async function writeMarkdownAsset(options) {
564
616
  // effect without waiting for the next full index.
565
617
  const demotedInTargetRoot = demotedByRoot.get(source.path) ?? [];
566
618
  demotedByRoot.delete(source.path);
567
- await indexWrittenAssets(source.path, [result.path, ...demotedInTargetRoot]);
619
+ await indexWrittenAssets(source.path, [result.path, ...demotedInTargetRoot], { bundleId: resolved.ref.origin });
620
+ const sourceEntries = resolveSourceEntries(undefined, cfg);
621
+ const sourceInstallations = deriveInstallations(sourceEntries);
568
622
  for (const [root, files] of demotedByRoot) {
569
- await indexWrittenAssets(root, files);
623
+ const sourceIndex = sourceEntries.findIndex((entry) => path.resolve(entry.path) === path.resolve(root));
624
+ await indexWrittenAssets(root, files, { bundleId: sourceInstallations[sourceIndex]?.id });
570
625
  }
571
626
  // Placement hint (stash-organization conventions): CLI writers never receive
572
627
  // the resolveStashStandards prompt injection LLM flows get, so a type-root
@@ -582,7 +637,7 @@ export async function writeMarkdownAsset(options) {
582
637
  // and a dead `akm show` pointer is worse than generic wording.
583
638
  const orgFactPath = path.join(source.path, "facts", "conventions", "organization.md");
584
639
  hint = fs.existsSync(orgFactPath)
585
- ? `Wrote to the ${options.type} root. This stash has placement conventions — see \`akm show fact:conventions/organization\`.`
640
+ ? `Wrote to the ${options.type} root. This stash has placement conventions — see \`akm show facts/conventions/organization\`.`
586
641
  : `Wrote to the ${options.type} root. This stash has placement conventions — see the convention facts under its facts/ directory.`;
587
642
  }
588
643
  }
@@ -4,7 +4,7 @@
4
4
  import { toErrorMessage } from "../../core/common.js";
5
5
  import { DEFAULT_CONFIG } from "../../core/config/config.js";
6
6
  import { warn } from "../../core/warn.js";
7
- import { resolveProviderFactory } from "../../registry/factory.js";
7
+ import { resolveRegistryProviderFactory } from "../../registry/factory.js";
8
8
  // ── Eagerly import providers to trigger self-registration ───────────────────
9
9
  import "../../registry/providers/index.js";
10
10
  // ── Public API ──────────────────────────────────────────────────────────────
@@ -142,7 +142,7 @@ export function resolveRegistries(configRegistries) {
142
142
  // ── Provider resolution ─────────────────────────────────────────────────────
143
143
  function createProvider(entry, warnings) {
144
144
  const providerType = entry.provider ?? "static-index";
145
- const factory = resolveProviderFactory(providerType);
145
+ const factory = resolveRegistryProviderFactory(providerType);
146
146
  if (!factory) {
147
147
  const label = entry.name ? `${entry.name} (${entry.url})` : entry.url;
148
148
  warnings.push(`Registry ${label}: unknown provider type "${providerType}"`);
@@ -1,13 +1,14 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ import { getParsedInvocation } from "../../cli/invocation.js";
4
5
  import { getStringArg } from "../../cli/parse-args.js";
5
6
  import { defineJsonCommand, output, parseAllFlagValues } from "../../cli/shared.js";
6
7
  import { UsageError } from "../../core/errors.js";
7
8
  import { appendEvent } from "../../core/events.js";
8
9
  import { resolveUsageEventSource } from "../../indexer/usage/usage-events.js";
9
- import { buildMemoryFrontmatter, parseDuration, readMemoryContent, resolveRememberContentArg, runAutoHeuristics, runLlmEnrich, } from "../remember.js";
10
- import { assertFlatAssetName, inferAssetName, resolveSupersedesForWrite, resolveXrefsForWrite, writeMarkdownAsset, } from "./knowledge.js";
10
+ import { buildMemoryFrontmatter, parseDuration, readMemoryContent, runAutoHeuristics, runLlmEnrich } from "../remember.js";
11
+ import { assertFlatAssetName, inferAssetName, resolveSupersedesForWrite, resolveSupersedesWriteTarget, resolveXrefsForWrite, writeMarkdownAsset, } from "./knowledge.js";
11
12
  import { akmSearch } from "./search.js";
12
13
  // ── Helper: similar memory search ────────────────────────────────────────────
13
14
  /**
@@ -32,11 +33,22 @@ async function fetchSimilarMemories(query, excludeRef, eventSource) {
32
33
  return [];
33
34
  }
34
35
  }
36
+ /**
37
+ * `--target` was renamed to `--bundle` on `remember` in 0.9 (S8). citty is
38
+ * non-strict, so the retired spelling is silently absorbed rather than
39
+ * rejected — the memory then lands in the default bundle instead of the one
40
+ * the caller named, with exit 0 and no error. Reject it explicitly instead.
41
+ */
42
+ function rejectRetiredTargetFlag() {
43
+ if (!getParsedInvocation().hasFlag("--target"))
44
+ return;
45
+ throw new UsageError("`akm remember --target` was renamed to `--bundle` in 0.9. Use `--bundle <name>` instead.", "INVALID_FLAG_VALUE");
46
+ }
35
47
  // ── Command definition ────────────────────────────────────────────────────────
36
48
  export const rememberCommand = defineJsonCommand({
37
49
  meta: {
38
50
  name: "remember",
39
- description: "Record a memory in the default stash",
51
+ description: "Record a memory in the default bundle",
40
52
  },
41
53
  args: {
42
54
  content: {
@@ -75,11 +87,11 @@ export const rememberCommand = defineJsonCommand({
75
87
  },
76
88
  xref: {
77
89
  type: "string",
78
- description: "Cross-reference ref recorded in the memory's `xrefs:` frontmatter (repeatable: --xref knowledge:auth-flow --xref memory:vpn-note). Each ref must resolve in the write target or a configured source; an unresolvable ref aborts the write.",
90
+ description: "Cross-reference ref recorded in the memory's `xrefs:` frontmatter (repeatable: --xref knowledge/auth-flow --xref memories/vpn-note). Each ref must resolve in the write target or a configured source; an unresolvable ref aborts the write.",
79
91
  },
80
92
  supersedes: {
81
93
  type: "string",
82
- description: "Ref of an existing asset this memory corrects (repeatable: --supersedes memory:projectA/old-note). Writes the correction with an xref to the old asset AND demotes the old asset (`beliefState: superseded` + `supersededBy`, a metadata-only edit) so ranking prefers the correction and `--belief current` hides the stale version. An unresolvable or self-referencing ref aborts the write; a ref outside the write target and working stash still writes the correction but skips the demotion (reported as applied: false).",
94
+ description: "Ref of an existing asset this memory corrects (repeatable: --supersedes memories/projectA/old-note). Writes the correction with an xref to the old asset AND demotes the old asset (`beliefState: superseded` + `supersededBy`, a metadata-only edit) so ranking prefers the correction and `--belief current` hides the stale version. An unresolvable or self-referencing ref aborts the write; a ref outside the write target and working bundle still writes the correction but skips the demotion (reported as applied: false).",
83
95
  },
84
96
  auto: {
85
97
  type: "boolean",
@@ -91,9 +103,9 @@ export const rememberCommand = defineJsonCommand({
91
103
  description: "Call the configured LLM to propose tags and description (requires LLM config)",
92
104
  default: false,
93
105
  },
94
- target: {
106
+ bundle: {
95
107
  type: "string",
96
- description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working stash.",
108
+ description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working bundle.",
97
109
  },
98
110
  user: {
99
111
  type: "string",
@@ -111,13 +123,23 @@ export const rememberCommand = defineJsonCommand({
111
123
  type: "string",
112
124
  description: "Scope this memory to a channel name (persisted as `scope_channel` frontmatter)",
113
125
  },
114
- showSimilar: {
126
+ "show-similar": {
115
127
  type: "boolean",
116
- description: "Return top-3 similar existing memories in output (opt-in)",
128
+ // R-062: canonical spelling is kebab-case, matching every other
129
+ // multi-word flag in the CLI (--fail-on-flagged, --auto-fix, …).
130
+ // `--showSimilar` (the pre-rename spelling) is kept as an explicit,
131
+ // documented alias rather than a silent citty auto-alias — citty
132
+ // registers BOTH the camelCase and kebab-case spelling of any
133
+ // declared flag name automatically, so this is a rename, not a
134
+ // breaking change: both spellings already worked, and both keep
135
+ // working.
136
+ alias: "showSimilar",
137
+ description: "Return top-3 similar existing memories in output (opt-in). Alias: --showSimilar.",
117
138
  },
118
139
  },
119
140
  async run({ args }) {
120
- const body = readMemoryContent(resolveRememberContentArg(args.content));
141
+ rejectRetiredTargetFlag();
142
+ const body = readMemoryContent(args.content);
121
143
  const eventSource = resolveUsageEventSource();
122
144
  // `--name` is a flat name; subdirectory placement is `--path`'s job.
123
145
  assertFlatAssetName(args.name);
@@ -130,7 +152,9 @@ export const rememberCommand = defineJsonCommand({
130
152
  // input validation (UsageError → exit 2) and must leave the stash
131
153
  // untouched. Refs resolvable only in a configured extra stash source are
132
154
  // accepted (cross-stash provenance).
133
- const xrefs = resolveXrefsForWrite(parseAllFlagValues("--xref"), args.target);
155
+ const rawSupersedes = parseAllFlagValues("--supersedes");
156
+ const writeTarget = resolveSupersedesWriteTarget(rawSupersedes, args.bundle);
157
+ const xrefs = resolveXrefsForWrite(parseAllFlagValues("--xref"), writeTarget);
134
158
  // Collect and validate --supersedes occurrences (repeatable). Same
135
159
  // before-any-write validation contract: an unresolvable ref exits 2 with
136
160
  // nothing written AND nothing demoted (no partial correction). The
@@ -138,7 +162,7 @@ export const rememberCommand = defineJsonCommand({
138
162
  // (correction provenance per the back-linking conventions); the demotion
139
163
  // itself runs inside writeMarkdownAsset, ordered before the git boundary
140
164
  // commit.
141
- const supersedes = resolveSupersedesForWrite(parseAllFlagValues("--supersedes"), args.target);
165
+ const supersedes = resolveSupersedesForWrite(rawSupersedes, writeTarget);
142
166
  for (const s of supersedes) {
143
167
  if (!xrefs.includes(s.ref))
144
168
  xrefs.push(s.ref);
@@ -157,7 +181,10 @@ export const rememberCommand = defineJsonCommand({
157
181
  // --xref counts as structured metadata (it must land in frontmatter) but,
158
182
  // like scope, does NOT trigger the tags-required check — provenance
159
183
  // without tags is a valid write.
160
- const hasStructuredArgs = hasTagRequiringArgs || hasScope || args.auto || xrefs.length > 0;
184
+ // --enrich is structured (it must reach the Mode-3 dispatch below, not the
185
+ // zero-flag hot path) but, like --auto, never tag-requiring: enrichment is
186
+ // fail-soft and a zero-tag outcome still writes.
187
+ const hasStructuredArgs = hasTagRequiringArgs || hasScope || args.auto || args.enrich || xrefs.length > 0;
161
188
  if (!hasStructuredArgs) {
162
189
  // Phase 1B / Rec 7: even the zero-flag hot-path emits
163
190
  // `captureMode: hot` + `beliefState: asserted` so user-supplied
@@ -176,7 +203,7 @@ export const rememberCommand = defineJsonCommand({
176
203
  fallbackPrefix: "memory",
177
204
  preferredName: inferAssetName(body, "memory"),
178
205
  force: args.force,
179
- target: args.target,
206
+ target: writeTarget,
180
207
  path: args.path,
181
208
  supersedes,
182
209
  });
@@ -278,7 +305,7 @@ export const rememberCommand = defineJsonCommand({
278
305
  fallbackPrefix: "memory",
279
306
  preferredName: inferAssetName(body, "memory"),
280
307
  force: args.force,
281
- target: args.target,
308
+ target: writeTarget,
282
309
  path: args.path,
283
310
  supersedes,
284
311
  });