akm-cli 0.9.0-rc.9 → 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 +95 -55
  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 +25 -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 +88 -7
  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 -1878
  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 -1231
  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 -257
  424. package/dist/migrate/legacy/content-migration.js +0 -350
  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 -80
  428. package/dist/migrate/legacy/proposal-fs-import.js +0 -168
  429. package/dist/migrate/legacy/task-target-ref-migration.js +0 -278
  430. package/dist/migrate/legacy/three-db-cutover.js +0 -845
  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
@@ -16,25 +16,28 @@
16
16
  * 3. Render the file via the matcher/renderer pipeline.
17
17
  */
18
18
  import fs from "node:fs";
19
- import { findCittyTopLevelCommandIndex } from "../../cli/parse-args.js";
19
+ import path from "node:path";
20
20
  import { recognizeMatch } from "../../core/adapter/recognize-match.js";
21
+ import { makeBundleRef, parseBundleRef } from "../../core/asset/asset-ref.js";
21
22
  import { parseFrontmatter } from "../../core/asset/frontmatter.js";
22
- import { displayRef, parseQualifiedRefInput } from "../../core/asset/resolve-ref.js";
23
+ import { extractSection, markdownFragmentSlugs } from "../../core/asset/markdown.js";
24
+ import { displayRef, typeNameFromConceptId } from "../../core/asset/resolve-ref.js";
23
25
  import { META_DIR, parseMetaRef, resolveMetaFilePath } from "../../core/asset/stash-meta.js";
24
26
  import { asNonEmptyString } from "../../core/common.js";
25
27
  import { getIndexPassConfig, loadConfig } from "../../core/config/config.js";
26
28
  import { NotFoundError, rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
27
29
  import { appendEvent, readEvents } from "../../core/events.js";
28
30
  import { withStateDbTelemetry } from "../../core/state-db.js";
31
+ import { presentationFor } from "../../core/type-presentation.js";
29
32
  import { hasGraphData } from "../../indexer/db/graph-db.js";
30
33
  import { listRelatedPathsForFile } from "../../indexer/graph/graph-boost.js";
31
34
  import { extractGraphForSingleFile } from "../../indexer/graph/graph-extraction.js";
32
- import { lookup } from "../../indexer/indexer.js";
35
+ import { lookupBundleRef } from "../../indexer/indexer.js";
33
36
  import { ensurePrimaryIndexForRead, resolveReadSources } from "../../indexer/read-preflight.js";
34
37
  import { usageEventAttributionMetadata } from "../../indexer/search/search-attribution.js";
35
38
  import { buildEditHint, findSourceForPath, isEditable, resolveSourceEntries } from "../../indexer/search/search-source.js";
36
39
  import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
37
- import { buildFileContext, buildRenderContext, getRenderer } from "../../indexer/walk/file-context.js";
40
+ import { buildFileContext, buildRenderContext, getRenderer, } from "../../indexer/walk/file-context.js";
38
41
  import { resolveAssetPath } from "../../indexer/walk/path-resolver.js";
39
42
  import { resolveIndexPassLLM } from "../../llm/index-passes.js";
40
43
  import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
@@ -46,6 +49,7 @@ import { computeBodyHash } from "../../storage/repositories/index-llm-cache-repo
46
49
  // Eagerly import source providers to trigger self-registration.
47
50
  import "../../sources/providers/index.js";
48
51
  import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
52
+ import { buildWorkflowAction } from "../../workflows/renderer.js";
49
53
  import { getActiveWorkflowRun } from "../../workflows/runtime/runs.js";
50
54
  /**
51
55
  * Unified show: queries the local FTS5 index, then falls back to on-disk
@@ -60,8 +64,7 @@ export async function akmShowUnified(input) {
60
64
  // 0a. Stash `.meta/` convention: `[origin//]meta[:name]` direct-reads a
61
65
  // human-authored orientation doc from the stash's `.meta/` directory.
62
66
  // These files are not indexed (the walker skips dot-dirs), so they are
63
- // resolved here before the index lookup and the `type:name` parser,
64
- // which would otherwise reject the non-asset-type `meta`.
67
+ // resolved here before the index lookup; meta docs are not asset refs.
65
68
  {
66
69
  const metaRef = parseMetaRef(ref);
67
70
  if (metaRef)
@@ -72,17 +75,18 @@ export async function akmShowUnified(input) {
72
75
  await ensurePrimaryIndexForRead(primarySource);
73
76
  // Try local filesystem (FTS5 index lookup)
74
77
  const result = await showLocal(input);
75
- // Scope filter narrows resolution: if --scope was supplied, the asset's
76
- // frontmatter scope must satisfy every supplied key. We re-read the file
77
- // (cheap — already on the show hot path) so we don't have to thread scope
78
- // through the renderer chain just for one verification step.
78
+ // Scope filter narrows resolution: if a scope filter was supplied, the
79
+ // asset's frontmatter scope must satisfy every supplied key. We re-read the
80
+ // file (cheap — already on the show hot path) so we don't have to thread
81
+ // scope through the renderer chain just for one verification step.
79
82
  if (input.scope && hasAnyScopeKey(input.scope) && result.path) {
80
83
  enforceScopeOrThrow(result.path, ref, input.scope);
81
84
  }
82
85
  // Count prior shows of this ref before logging the current one.
83
86
  if (!input.skipLogging) {
84
- const priorShowCount = recentShowCount(ref);
85
- logShowEvent(ref, input.eventSource, result.path, result.origin);
87
+ const consumedRef = result.ref ?? makeBundleRef(undefined, parseBundleRef(ref).conceptId);
88
+ const priorShowCount = recentShowCount(consumedRef);
89
+ logShowEvent(consumedRef, result.type, result.name, input.eventSource, result.path);
86
90
  if (priorShowCount >= 2) {
87
91
  // Agent has shown this same asset 3+ times — inject a loop-break hint.
88
92
  result.showLoopWarning = priorShowCount + 1;
@@ -103,7 +107,7 @@ async function showStashMeta(metaRef) {
103
107
  const sources = resolveSourcesForOrigin(metaRef.origin, allSources);
104
108
  if (metaRef.origin && sources.length === 0) {
105
109
  throw new NotFoundError(`Stash "${metaRef.origin}" is not installed, so its ${META_DIR}/ docs are unavailable. ` +
106
- `Run: akm add ${metaRef.origin}`);
110
+ `Run: akm bundle add ${metaRef.origin}`);
107
111
  }
108
112
  const config = loadConfig();
109
113
  for (const source of sources) {
@@ -111,12 +115,13 @@ async function showStashMeta(metaRef) {
111
115
  if (!filePath)
112
116
  continue;
113
117
  const content = fs.readFileSync(filePath, "utf8");
114
- const editable = isEditable(filePath, config);
118
+ const editable = isEditable(filePath, config, allSources);
115
119
  appendEvent({ eventType: "show", ref: `meta:${metaRef.name}`, metadata: { type: "meta", name: metaRef.name } });
116
120
  return {
117
121
  type: "meta",
118
122
  name: metaRef.name,
119
123
  path: filePath,
124
+ ref: `meta:${metaRef.name}`,
120
125
  content,
121
126
  origin: source.registryId ?? null,
122
127
  editable,
@@ -180,14 +185,11 @@ function recentShowCount(ref) {
180
185
  return 0;
181
186
  }
182
187
  }
183
- function logShowEvent(ref, eventSource = "user", filePath, origin) {
188
+ function logShowEvent(ref, type, name, eventSource = "user", filePath) {
184
189
  // Emit a structured event to events.jsonl so workflow-trace consumers
185
190
  // detect akm show invocations without relying on stdout scraping.
186
- const parsed = parseQualifiedRefInput(ref);
187
- // New-grammar display ref: also the lookup key below, which `findEntryIdByRef`
188
- // resolves against `item_ref`.
189
- const eventRef = displayRef({ type: parsed.type, name: parsed.name, bundleId: parsed.origin ?? origin ?? undefined });
190
- appendEvent({ eventType: "show", ref: eventRef, metadata: { type: parsed.type, name: parsed.name } });
191
+ const eventRef = makeBundleRef(parseBundleRef(ref).bundle, parseBundleRef(ref).conceptId);
192
+ appendEvent({ eventType: "show", ref: eventRef, metadata: { type, name } });
191
193
  // Detect if this show is a selection from a recent search result.
192
194
  try {
193
195
  // D7: bound the query to the last 60 s so we never scan unbounded history
@@ -220,12 +222,15 @@ function logShowEvent(ref, eventSource = "user", filePath, origin) {
220
222
  try {
221
223
  withIndexDb((db) => {
222
224
  const entryId = filePath ? getEntryIdByFilePath(db, filePath) : findEntryIdByRef(db, eventRef);
223
- // The DURABLE usage-event key is the resolved entry's fully-qualified
224
- // `item_ref`; the new-grammar `eventRef` is the fallback for an
225
- // unresolved / not-yet-indexed show. entry_id/item_ref resolve from
226
- // index.db (`db`); the usage_events write lands in state.db (WI-8.3).
227
- const entryRef = (entryId !== undefined ? getItemRefById(db, entryId) : null) ?? eventRef;
228
- const entry = entryId !== undefined ? getEntryById(db, entryId) : undefined;
225
+ if (entryId === undefined)
226
+ return;
227
+ // Usage events carry only the resolved row's fully-qualified item_ref.
228
+ // A disk-only show has no durable indexed identity yet, so it does not
229
+ // create a per-entry usage row.
230
+ const entryRef = getItemRefById(db, entryId);
231
+ if (!entryRef)
232
+ return;
233
+ const entry = getEntryById(db, entryId);
229
234
  withStateDbTelemetry((stateDb) => {
230
235
  insertUsageEvent(stateDb, {
231
236
  event_type: "show",
@@ -244,44 +249,102 @@ function logShowEvent(ref, eventSource = "user", filePath, origin) {
244
249
  }
245
250
  /** @internal Use akmShowUnified() for all external callers. */
246
251
  export async function showLocal(input) {
247
- const parsed = parseQualifiedRefInput(input.ref);
248
- const displayType = parsed.type;
252
+ const parsed = parseBundleRef(input.ref);
253
+ const assetParts = typeNameFromConceptId(parsed.conceptId);
249
254
  const config = loadConfig();
250
255
  const allSources = resolveSourceEntries(input.stashDir);
251
- const searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
256
+ const searchSources = resolveSourcesForOrigin(parsed.bundle, allSources);
252
257
  const allSourceDirs = searchSources.map((s) => s.path);
253
- const resolvedAssetPath = await resolveAssetPath(parsed, {
254
- stashDir: input.stashDir,
255
- mode: "index-first",
256
- });
258
+ let indexedEntry = null;
259
+ try {
260
+ indexedEntry = await lookupBundleRef(parsed);
261
+ }
262
+ catch (err) {
263
+ rethrowIfTestIsolationError(err);
264
+ indexedEntry = null;
265
+ }
266
+ const resolvedAssetPath = indexedEntry?.filePath ??
267
+ (assetParts
268
+ ? await resolveAssetPath({ type: assetParts.type, name: assetParts.name, origin: parsed.bundle }, {
269
+ stashDir: input.stashDir,
270
+ mode: "disk-only",
271
+ })
272
+ : null);
257
273
  const assetPath = resolvedAssetPath ?? undefined;
258
- if (!assetPath && parsed.origin && searchSources.length === 0) {
259
- const installCmd = `akm add ${parsed.origin}`;
260
- throw new NotFoundError(`Stash asset not found for ref: ${displayType}:${parsed.name}. ` +
261
- `Stash "${parsed.origin}" is not installed. Run: ${installCmd}`);
274
+ const displayType = indexedEntry?.type ?? assetParts?.type ?? "asset";
275
+ const displayName = indexedEntry?.name ?? assetParts?.name ?? parsed.conceptId;
276
+ if (!assetPath && parsed.bundle && searchSources.length === 0) {
277
+ const installCmd = `akm bundle add ${parsed.bundle}`;
278
+ throw new NotFoundError(`Stash asset not found for ref: ${makeBundleRef(parsed.bundle, parsed.conceptId)}. ` +
279
+ `Stash "${parsed.bundle}" is not installed. Run: ${installCmd}`);
262
280
  }
263
281
  if (!assetPath) {
264
- throw new NotFoundError(`Stash asset not found for ref: ${displayType}:${parsed.name}. ` +
282
+ throw new NotFoundError(`Stash asset not found for ref: ${makeBundleRef(parsed.bundle, parsed.conceptId)}. ` +
265
283
  "Check the name with `akm search` or verify the asset exists in your stash.");
266
284
  }
285
+ if (indexedEntry) {
286
+ try {
287
+ fs.accessSync(assetPath, fs.constants.R_OK);
288
+ }
289
+ catch (error) {
290
+ throwIndexedPathNotFound(error, input.ref);
291
+ }
292
+ }
267
293
  const source = findSourceForPath(assetPath, allSources);
268
294
  const sourceStashDir = source?.path ?? allSourceDirs[0];
269
295
  if (!sourceStashDir) {
270
- throw new UsageError(`Could not determine stash root for asset: ${displayType}:${parsed.name}. ` +
271
- "Run `akm init` to create the stash directory, or check `akm stash list` for configured paths.");
296
+ throw new UsageError(`Could not determine stash root for asset: ${makeBundleRef(parsed.bundle, parsed.conceptId)}. ` +
297
+ "Run `akm bundle create` to create the stash directory, or check `akm bundle list` for configured paths.");
272
298
  }
273
299
  const fileCtx = buildFileContext(sourceStashDir, assetPath);
274
- const match = recognizeMatch(fileCtx);
275
- if (!match) {
276
- throw new UsageError(`Could not display asset "${displayType}:${parsed.name}" — unsupported file type or unrecognized layout`);
300
+ const indexedRenderer = indexedEntry ? rendererForIndexedEntry(indexedEntry, fileCtx) : undefined;
301
+ let response;
302
+ try {
303
+ if (indexedEntry && indexedRenderer === null) {
304
+ response = buildIndexedProjectionResponse(indexedEntry, assetPath, parsed.fragment);
305
+ }
306
+ else {
307
+ const match = indexedEntry && typeof indexedRenderer === "string"
308
+ ? indexedMatch(indexedEntry, indexedRenderer)
309
+ : recognizeMatch(fileCtx);
310
+ if (!match) {
311
+ throw new UsageError(`Could not display asset "${makeBundleRef(parsed.bundle, parsed.conceptId)}" — unsupported file type or unrecognized layout`);
312
+ }
313
+ match.meta = { ...match.meta, name: displayName };
314
+ const renderer = await getRenderer(match.renderer);
315
+ if (!renderer) {
316
+ throw new UsageError(`Renderer "${match.renderer}" not found for asset: ${makeBundleRef(parsed.bundle, parsed.conceptId)}`);
317
+ }
318
+ const renderBundle = indexedEntry ? indexedEntry.bundleId : source?.registryId;
319
+ const renderDefaultBundle = config.defaultBundle ?? (source?.path === allSources[0]?.path ? renderBundle : undefined);
320
+ const renderCtx = buildRenderContext(fileCtx, match, allSourceDirs, renderBundle, renderDefaultBundle);
321
+ response = renderer.buildShowResponse(renderCtx);
322
+ if (parsed.fragment !== undefined) {
323
+ if (!match.renderer.endsWith("-md")) {
324
+ throw new UsageError(`Fragments are not supported for ${makeBundleRef(parsed.bundle, parsed.conceptId)}. Only Markdown documents support heading fragments.`, "INVALID_FLAG_VALUE");
325
+ }
326
+ applyMarkdownFragment(response, fileCtx.content(), parsed.fragment, displayName);
327
+ }
328
+ }
329
+ }
330
+ catch (error) {
331
+ if (indexedEntry)
332
+ throwIndexedPathNotFound(error, input.ref);
333
+ throw error;
277
334
  }
278
- match.meta = { ...match.meta, name: parsed.name, view: input.view };
279
- const renderer = await getRenderer(match.renderer);
280
- if (!renderer) {
281
- throw new UsageError(`Renderer "${match.renderer}" not found for asset: ${displayType}:${parsed.name}`);
335
+ if (indexedEntry) {
336
+ response.type = indexedEntry.type;
337
+ response.name = indexedEntry.name;
282
338
  }
283
- const renderCtx = buildRenderContext(fileCtx, match, allSourceDirs, source?.registryId);
284
- const response = renderer.buildShowResponse(renderCtx);
339
+ const isPrimaryStash = source !== undefined && source.path === allSources[0]?.path;
340
+ const canonicalRef = displayRef({
341
+ type: displayType,
342
+ name: displayName,
343
+ conceptId: indexedEntry?.conceptId,
344
+ bundleId: indexedEntry ? indexedEntry.bundleId : source?.registryId,
345
+ }, config.defaultBundle ?? (isPrimaryStash ? indexedEntry?.bundleId : undefined));
346
+ if (response.type === "workflow")
347
+ response.action = buildWorkflowAction(canonicalRef);
285
348
  // 07 P1-D: provenance-aware toolPolicy CEILING. An agent's self-declared
286
349
  // `tools` frontmatter is honoured ONLY for the operator's own PRIMARY stash —
287
350
  // the assets they authored. Every other source is content pulled from
@@ -293,16 +356,16 @@ export async function showLocal(input) {
293
356
  // `allSources[0]` is always the primary (search-source.ts) — not a
294
357
  // name-derived registryId or the orthogonal `writable` bit. `source` undefined
295
358
  // (unresolved path) also fails closed.
296
- const isPrimaryStash = source !== undefined && source.path === allSources[0]?.path;
297
359
  if (response.toolPolicy !== undefined && !isPrimaryStash) {
298
360
  delete response.toolPolicy;
299
361
  }
300
- const editable = isEditable(assetPath, config);
362
+ const editable = isEditable(assetPath, config, allSources);
301
363
  const fullResponse = {
302
364
  ...response,
365
+ ref: canonicalRef,
303
366
  origin: source?.registryId ?? null,
304
367
  editable,
305
- ...(!editable ? { editHint: buildEditHint(assetPath, parsed.type, parsed.name, source?.registryId) } : {}),
368
+ ...(!editable ? { editHint: buildEditHint(canonicalRef) } : {}),
306
369
  related: (() => {
307
370
  try {
308
371
  return withIndexDb((db) => {
@@ -395,14 +458,87 @@ async function maybeExtractGraphInline(config, sourceStashDir, assetPath) {
395
458
  * renderer graph. Spec §6.2's literal flow.
396
459
  */
397
460
  export async function showByRef(ref) {
398
- const parsed = parseQualifiedRefInput(ref);
399
- const entry = await lookup(parsed);
461
+ const parsed = parseBundleRef(ref);
462
+ if (parsed.fragment !== undefined) {
463
+ throw new UsageError(`Fragments are not accepted by raw show: ${ref}`, "INVALID_FLAG_VALUE");
464
+ }
465
+ const entry = await lookupBundleRef(parsed);
400
466
  if (!entry) {
401
- throw new NotFoundError(`Asset not found for ref: ${parsed.type}:${parsed.name}`);
467
+ throw new NotFoundError(`Asset not found for ref: ${makeBundleRef(parsed.bundle, parsed.conceptId)}`);
468
+ }
469
+ let body;
470
+ try {
471
+ body = await fs.promises.readFile(entry.filePath, "utf8");
472
+ }
473
+ catch (error) {
474
+ throwIndexedPathNotFound(error, ref);
402
475
  }
403
- const body = await fs.promises.readFile(entry.filePath, "utf8");
404
476
  return { filePath: entry.filePath, body };
405
477
  }
478
+ function throwIndexedPathNotFound(error, ref) {
479
+ const code = error?.code;
480
+ if (code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "EPERM") {
481
+ throw new NotFoundError(`The indexed file for ${ref} is missing or unreadable. The search index may be stale.`, "ASSET_NOT_FOUND", "Run `akm index` to reconcile indexed paths, then retry `akm show`.");
482
+ }
483
+ throw error;
484
+ }
485
+ /** `null` selects adapter-owned projection; a string selects a core renderer. */
486
+ function rendererForIndexedEntry(entry, _file) {
487
+ if (entry.document?.ownsPresentation === true)
488
+ return null;
489
+ switch (entry.adapterId) {
490
+ case null:
491
+ case undefined:
492
+ case "akm":
493
+ return undefined;
494
+ case "akm-workflow":
495
+ return "workflow-md";
496
+ default:
497
+ return presentationFor(entry.type).renderer;
498
+ }
499
+ }
500
+ function indexedMatch(entry, renderer) {
501
+ return { type: entry.type, specificity: Number.MAX_SAFE_INTEGER, renderer, meta: { name: entry.name } };
502
+ }
503
+ function buildIndexedProjectionResponse(entry, assetPath, fragment) {
504
+ if (fragment !== undefined && path.extname(assetPath).toLowerCase() !== ".md") {
505
+ throw new UsageError(`Fragments are not supported for ${entry.conceptId}. Only Markdown documents support heading fragments.`, "INVALID_FLAG_VALUE");
506
+ }
507
+ const raw = fs.readFileSync(assetPath, "utf8");
508
+ const parsed = parseFrontmatter(raw);
509
+ const content = fragment ? requireMarkdownSection(parsed.content, fragment, entry.name).content : parsed.content;
510
+ const description = entry.document?.description ?? asNonEmptyString(parsed.data.description);
511
+ const tags = entry.document?.tags ??
512
+ (Array.isArray(parsed.data.tags)
513
+ ? parsed.data.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0)
514
+ : undefined);
515
+ return {
516
+ type: entry.type,
517
+ name: entry.name,
518
+ path: assetPath,
519
+ action: "Read the content below.",
520
+ content,
521
+ ...(description ? { description } : {}),
522
+ ...(tags && tags.length > 0 ? { tags } : {}),
523
+ };
524
+ }
525
+ function applyMarkdownFragment(response, raw, fragment, name) {
526
+ const section = requireMarkdownSection(parseFrontmatter(raw).content, fragment, name).content;
527
+ if (response.template !== undefined)
528
+ response.template = section;
529
+ else if (response.prompt !== undefined)
530
+ response.prompt = section;
531
+ else
532
+ response.content = section;
533
+ }
534
+ function requireMarkdownSection(content, fragment, name) {
535
+ const section = extractSection(content, fragment);
536
+ if (section)
537
+ return section;
538
+ const available = markdownFragmentSlugs(content);
539
+ throw new NotFoundError(`Fragment "#${fragment}" not found in ${name}.` +
540
+ (available.length > 0 ? ` Available fragments: ${available.map((slug) => `#${slug}`).join(", ")}.` : ""));
541
+ }
406
542
  /**
407
543
  * Build a reduced brief response from a full ShowResponse.
408
544
  *
@@ -414,11 +550,13 @@ function buildBriefResponse(full, assetPath) {
414
550
  type: summary.type,
415
551
  name: summary.name,
416
552
  path: summary.path,
553
+ ...(summary.ref ? { ref: summary.ref } : {}),
417
554
  ...(summary.description ? { description: summary.description } : {}),
418
555
  ...(summary.action ? { action: summary.action } : {}),
419
556
  ...(summary.run ? { run: summary.run } : {}),
420
557
  ...(summary.origin !== undefined ? { origin: summary.origin } : {}),
421
558
  ...(full.editable !== undefined ? { editable: full.editable } : {}),
559
+ ...(full.editHint ? { editHint: full.editHint } : {}),
422
560
  };
423
561
  }
424
562
  /**
@@ -444,6 +582,7 @@ function buildSummaryResponse(full, assetPath) {
444
582
  type: full.type,
445
583
  name: full.name,
446
584
  path: full.path,
585
+ ...(full.ref ? { ref: full.ref } : {}),
447
586
  ...(description ? { description } : {}),
448
587
  ...(tags && tags.length > 0 ? { tags } : {}),
449
588
  ...(full.parameters ? { parameters: full.parameters } : {}),
@@ -451,91 +590,8 @@ function buildSummaryResponse(full, assetPath) {
451
590
  ...(full.action ? { action: full.action } : {}),
452
591
  ...(full.run ? { run: full.run } : {}),
453
592
  ...(full.origin !== undefined ? { origin: full.origin } : {}),
593
+ ...(full.editable !== undefined ? { editable: full.editable } : {}),
594
+ ...(full.editHint ? { editHint: full.editHint } : {}),
454
595
  };
455
596
  return summary;
456
597
  }
457
- // ── argv normalisation ───────────────────────────────────────────────────────
458
- const SHOW_VIEW_MODES = new Set(["toc", "frontmatter", "full", "section", "lines"]);
459
- const SHOW_ARGV_TOP_LEVEL_ARGS = {
460
- format: { type: "string" },
461
- output: { type: "string" },
462
- detail: { type: "string" },
463
- shape: { type: "string" },
464
- quiet: { type: "boolean", alias: "q" },
465
- verbose: { type: "boolean" },
466
- };
467
- /**
468
- * Normalize argv so positional view-mode arguments after the asset ref
469
- * are rewritten into internal flags that citty can parse.
470
- *
471
- * Converts:
472
- * akm show knowledge:guide.md toc → akm show knowledge:guide.md --akmView toc
473
- * akm show knowledge:guide.md section Auth → akm show knowledge:guide.md --akmView section --akmHeading Auth
474
- * akm show knowledge:guide.md lines 1 50 → akm show knowledge:guide.md --akmView lines --akmStart 1 --akmEnd 50
475
- *
476
- * Legacy `--view` is intentionally unsupported.
477
- * Returns a new array; the input is never modified.
478
- */
479
- export function normalizeShowArgv(argv) {
480
- const rawArgs = argv.slice(2);
481
- const commandIndex = findCittyTopLevelCommandIndex(rawArgs, SHOW_ARGV_TOP_LEVEL_ARGS);
482
- if (commandIndex < 0 || rawArgs[commandIndex] !== "show")
483
- return argv;
484
- const commandArgs = rawArgs.slice(commandIndex + 1);
485
- if (commandArgs.includes("--view") ||
486
- commandArgs.includes("--heading") ||
487
- commandArgs.includes("--start") ||
488
- commandArgs.includes("--end")) {
489
- throw new UsageError('Legacy show flags are no longer supported. Use positional syntax like `akm show knowledge:guide toc` or `akm show knowledge:guide section "Auth"`.');
490
- }
491
- // Separate global flags from positional/show-specific args
492
- const prefix = [...argv.slice(0, 2), ...rawArgs.slice(0, commandIndex + 1)];
493
- const rest = commandArgs;
494
- const globalFlags = [];
495
- const showArgs = [];
496
- for (let i = 0; i < rest.length; i++) {
497
- const arg = rest[i];
498
- if (arg === "--quiet" || arg === "-q" || arg === "--verbose") {
499
- globalFlags.push(arg);
500
- continue;
501
- }
502
- if (arg.startsWith("--format=") || arg.startsWith("--detail=") || arg.startsWith("--shape=")) {
503
- globalFlags.push(arg);
504
- continue;
505
- }
506
- if (arg === "--format" || arg === "--detail" || arg === "--shape") {
507
- globalFlags.push(arg);
508
- const nextArg = rest[i + 1];
509
- if (nextArg !== undefined) {
510
- globalFlags.push(nextArg);
511
- i++;
512
- }
513
- continue;
514
- }
515
- showArgs.push(arg);
516
- }
517
- // showArgs[0] = ref, showArgs[1] = potential view mode, showArgs[2..] = view params
518
- const ref = showArgs[0];
519
- const viewMode = showArgs[1];
520
- if (!ref || !viewMode || !SHOW_VIEW_MODES.has(viewMode)) {
521
- return argv;
522
- }
523
- const result = [...prefix, ref, "--akmView", viewMode];
524
- if (viewMode === "section") {
525
- // Next arg is the heading name; pass empty string when missing so the
526
- // show handler can produce a clear "section not found" error.
527
- const heading = showArgs[2] ?? "";
528
- result.push("--akmHeading", heading);
529
- }
530
- else if (viewMode === "lines") {
531
- // Next two args are start and end
532
- const start = showArgs[2];
533
- const end = showArgs[3];
534
- if (start)
535
- result.push("--akmStart", start);
536
- if (end)
537
- result.push("--akmEnd", end);
538
- }
539
- result.push(...globalFlags);
540
- return result;
541
- }
@@ -1,23 +1,20 @@
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 { defineCommand } from "citty";
5
- import { parsePositiveIntFlag } from "../cli/parse-args.js";
6
- import { defineJsonCommand, output } from "../cli/shared.js";
7
- import { DEFAULT_CONFIG, loadUserConfig, mutateConfig } from "../core/config/config.js";
8
- import { UsageError } from "../core/errors.js";
4
+ import { defineGroupCommand, defineJsonCommand, output } from "../cli/shared.js";
5
+ import { getEffectiveRegistries, loadUserConfig, mutateConfig } from "../core/config/config.js";
6
+ import { NotFoundError, UsageError } from "../core/errors.js";
9
7
  import { warn } from "../core/warn.js";
10
- import { buildRegistryIndex, writeRegistryIndex } from "../registry/build-index.js";
11
- import { searchRegistry } from "./read/registry-search.js";
12
- export const registryCommand = defineCommand({
13
- meta: { name: "registry", description: "Manage stash registries" },
8
+ export const registryCommand = defineGroupCommand({
9
+ meta: { name: "registry", description: "Manage bundle registries" },
14
10
  subCommands: {
15
11
  list: defineJsonCommand({
16
12
  meta: { name: "list", description: "List configured registries" },
17
13
  async run() {
18
14
  const config = loadUserConfig();
19
- const registries = config.registries ?? DEFAULT_CONFIG.registries;
20
- output("registry-list", { registries });
15
+ // R-066 #5: mirror the shared config↔default-fallback helper instead
16
+ // of re-deriving it inline.
17
+ output("registry-list", { registries: getEffectiveRegistries(config) });
21
18
  },
22
19
  }),
23
20
  add: defineJsonCommand({
@@ -85,8 +82,10 @@ export const registryCommand = defineCommand({
85
82
  const registries = [...(config.registries ?? [])];
86
83
  const idx = registries.findIndex((r) => r.url === args.target || r.name === args.target);
87
84
  if (idx === -1) {
88
- output("registry-remove", { registries, removed: false, message: "No matching registry found" });
89
- return;
85
+ // Was a success envelope with `removed: false` and exit 0, so
86
+ // `akm registry remove typo && ...` proceeded as if it had removed
87
+ // something. A missing target is exit 1, like every other not-found.
88
+ throw new NotFoundError(`No registry matching "${args.target}" is configured.`, "SOURCE_NOT_FOUND", "Run `akm registry list` to see configured registries.");
90
89
  }
91
90
  const { confirmDestructive } = await import("../cli/confirm.js");
92
91
  const confirmed = await confirmDestructive(`Remove registry "${args.target}"? This cannot be undone.`, {
@@ -112,43 +111,5 @@ export const registryCommand = defineCommand({
112
111
  });
113
112
  },
114
113
  }),
115
- search: defineJsonCommand({
116
- meta: { name: "search", description: "Search enabled registries for stashes" },
117
- args: {
118
- query: { type: "positional", description: "Search query", required: true },
119
- limit: { type: "string", description: "Maximum number of results" },
120
- assets: { type: "boolean", description: "Include asset-level search results", default: false },
121
- },
122
- async run({ args }) {
123
- const limitRaw = parsePositiveIntFlag(args.limit ?? undefined);
124
- const result = await searchRegistry(args.query, { limit: limitRaw, includeAssets: args.assets });
125
- output("registry-search", result);
126
- },
127
- }),
128
- "build-index": defineJsonCommand({
129
- meta: { name: "build-index", description: "Build a v2 registry index from discovery and manual entries" },
130
- args: {
131
- out: { type: "string", description: "Output path for the generated index" },
132
- manual: { type: "string", description: "Manual entries JSON file" },
133
- "npm-registry": { type: "string", description: "Override npm registry base URL" },
134
- "github-api": { type: "string", description: "Override GitHub API base URL" },
135
- },
136
- async run({ args }) {
137
- const result = await buildRegistryIndex({
138
- manualEntriesPath: args.manual,
139
- npmRegistryBase: args["npm-registry"],
140
- githubApiBase: args["github-api"],
141
- });
142
- const outPath = writeRegistryIndex(result.index, args.out);
143
- output("registry-build-index", {
144
- outPath,
145
- version: result.index.version,
146
- updatedAt: result.index.updatedAt,
147
- totalKits: result.counts.total,
148
- counts: result.counts,
149
- manualEntriesPath: result.paths.manualEntriesPath,
150
- });
151
- },
152
- }),
153
114
  },
154
115
  });