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
@@ -16,6 +16,8 @@
16
16
  import fs from "node:fs";
17
17
  import { parseRefInput } from "../../core/asset/resolve-ref.js";
18
18
  import { NotFoundError, UsageError } from "../../core/errors.js";
19
+ import { warn } from "../../core/warn.js";
20
+ import { fallbackAnnouncement, NO_ENGINE_MESSAGE_SUFFIX, NO_ENGINE_REMEDY, withEngineFallback, } from "../../integrations/agent/engine-fallback.js";
19
21
  import { resolveEngine } from "../../integrations/agent/engine-resolution.js";
20
22
  import { executeRunner } from "../../integrations/agent/runner-dispatch.js";
21
23
  /**
@@ -60,10 +62,18 @@ async function resolveAssetBody(ref) {
60
62
  export async function akmAgentDispatch(options) {
61
63
  if (!options.agentConfig)
62
64
  throw new UsageError("agent requires a valid config with an agent engine.", "MISSING_REQUIRED_ARGUMENT");
63
- const engineName = options.engine ?? options.agentConfig.defaults?.engine;
65
+ // Same implicit opencode-sdk fallback the workflow and task surfaces apply,
66
+ // so an engine-less install is usable everywhere or nowhere — not a mix.
67
+ const { config: agentConfig, fallbackEngineName } = withEngineFallback(options.agentConfig);
68
+ const engineName = options.engine ?? agentConfig.defaults?.engine;
69
+ // Announced, never silent: `options.engine` outranks the default, so the
70
+ // fallback is only reportable when it is the engine actually selected.
71
+ const engineAnnouncement = fallbackAnnouncement(fallbackEngineName, engineName);
72
+ if (engineAnnouncement)
73
+ warn(engineAnnouncement);
64
74
  if (!engineName)
65
- throw new UsageError("agent requires --engine or defaults.engine.", "MISSING_REQUIRED_ARGUMENT");
66
- const runner = resolveEngine(engineName, options.agentConfig);
75
+ throw new UsageError(`agent ${NO_ENGINE_MESSAGE_SUFFIX} ${NO_ENGINE_REMEDY}`, "MISSING_REQUIRED_ARGUMENT");
76
+ const runner = resolveEngine(engineName, agentConfig);
67
77
  if (runner.kind === "llm") {
68
78
  throw new UsageError(`Engine "${engineName}" is an LLM engine; akm agent requires an agent engine.`, "INVALID_FLAG_VALUE");
69
79
  }
@@ -108,5 +118,6 @@ export async function akmAgentDispatch(options) {
108
118
  durationMs: result.durationMs,
109
119
  ...(result.error !== undefined ? { error: result.error } : {}),
110
120
  ...(result.reason !== undefined ? { reason: result.reason } : {}),
121
+ ...(engineAnnouncement ? { warnings: [engineAnnouncement] } : {}),
111
122
  };
112
123
  }
@@ -2,49 +2,56 @@
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
4
  /**
5
- * Contribution command cluster (`akm agent`, `akm lint`, `akm propose`) —
6
- * the asset authoring / validation / proposal-creation verbs. Extracted
7
- * verbatim from src/cli.ts (WS6) so the God Module shrinks; the
8
- * `main.subCommands.{agent,lint,propose}` keys and every command's args /
9
- * output shape stay byte-identical.
5
+ * Contribution command cluster (`akm agent`, `akm lint`) — the asset
6
+ * authoring / validation verbs. Extracted verbatim from src/cli.ts (WS6) so
7
+ * the God Module shrinks; the `main.subCommands.{agent,lint}` keys and every
8
+ * command's args / output shape stay byte-identical.
10
9
  *
11
- * These three handlers each branch on the result and call `process.exit`
12
- * conditionally (exit 1 on a failed dispatch / proposal, or on
13
- * `--fail-on-flagged` lint findings), so they keep the inline
14
- * `runWithJsonErrors` form rather than migrating to `defineJsonCommand`
15
- * (which is reserved for plain runWithJsonErrors+output handlers).
10
+ * These handlers branch on the result and set a non-zero `process.exitCode`
11
+ * conditionally (exit 1 on a failed dispatch, or on `--fail-on-flagged` lint
12
+ * findings) rather than emitting through the thrown-error path, so they keep
13
+ * the inline `runWithJsonErrors` form rather than migrating to
14
+ * `defineJsonCommand` (which is reserved for plain runWithJsonErrors+output
15
+ * handlers). `process.exitCode` (not `process.exit()`) so the process still
16
+ * exits via natural event-loop drain rather than skipping pending cleanup —
17
+ * see R-067 / F4.
16
18
  *
17
- * NOTE on `propose` vs `proposal`: the proposal MANAGEMENT family
18
- * (list/show/accept/reject/…) lives in src/commands/proposal-cli.ts. The
19
- * `propose` (create) verb here is the asset-authoring entry point and shares
20
- * no private helper with that module — its path/name helpers come from the
21
- * shared src/core/asset-create.ts module, imported below.
19
+ * NOTE: the asset-authoring `propose` verb (formerly here) moved to
20
+ * `akm proposal new` (0.9 CLI overhaul, S8) — see
21
+ * src/commands/proposal/propose-cli.ts.
22
22
  */
23
23
  import fs from "node:fs";
24
- import path from "node:path";
25
24
  import { defineCommand } from "citty";
26
25
  import { getStringArg, parsePositiveIntFlag } from "../../cli/parse-args.js";
27
- import { EXIT_CODES, output, runWithJsonErrors } from "../../cli/shared.js";
28
- import { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath } from "../../core/asset/asset-create.js";
26
+ import { EXIT_CODES, GLOBAL_OUTPUT_ARGS, output, runWithJsonErrors } from "../../cli/shared.js";
29
27
  import { loadConfig } from "../../core/config/config.js";
30
28
  import { UsageError } from "../../core/errors.js";
31
29
  import { resolveUsageEventSource } from "../../indexer/usage/usage-events.js";
30
+ import { getHyphenatedBoolean } from "../../output/context.js";
32
31
  import { akmLint } from "../lint/index.js";
33
- import { akmPropose } from "../proposal/propose.js";
34
32
  import { akmAgentDispatch } from "./agent-dispatch.js";
35
33
  const EXIT_GENERAL = EXIT_CODES.GENERAL;
34
+ export function readPromptStdin(read = () => fs.readFileSync(0, "utf8")) {
35
+ return read();
36
+ }
36
37
  export const agentCommand = defineCommand({
37
38
  meta: {
38
39
  name: "agent",
39
- description: "Dispatch an agent CLI (opencode, claude, …) with an optional agent asset that provides the system prompt, model, and tool policy. Use <agent-ref> to embody a stash agent, --model to override the model, and --prompt/--command/--workflow to provide the task.",
40
+ description: "Dispatch an agent CLI (opencode, claude, …) with an optional agent asset that provides the system prompt, model, and tool policy. Use <agent-ref> to embody a bundle agent, --model to override the model, and --prompt/--command/--workflow to provide the task.",
40
41
  },
41
42
  args: {
43
+ ...GLOBAL_OUTPUT_ARGS,
42
44
  "agent-ref": {
43
45
  type: "positional",
44
- description: "Optional agent asset ref (e.g. agents/code-reviewer). Loads system prompt, model, and tool policy from the stash asset.",
46
+ description: "Optional agent asset ref (e.g. agents/code-reviewer). Loads system prompt, model, and tool policy from the bundle asset.",
45
47
  required: false,
46
48
  },
47
49
  prompt: { type: "string", description: "Task prompt to pass to the agent" },
50
+ "prompt-stdin": {
51
+ type: "boolean",
52
+ description: "Read the task prompt from stdin (mutually exclusive with --prompt, --command, and --workflow)",
53
+ default: false,
54
+ },
48
55
  engine: { type: "string", description: "Agent engine to use (default: defaults.engine)" },
49
56
  command: { type: "string", description: "Load prompt from a command asset" },
50
57
  workflow: { type: "string", description: "Load prompt from a workflow asset" },
@@ -71,7 +78,10 @@ export const agentCommand = defineCommand({
71
78
  if (agentRef) {
72
79
  const { akmShowUnified } = await import("../read/show.js");
73
80
  const asset = await akmShowUnified({ ref: agentRef, detail: "full", eventSource: resolveUsageEventSource() });
74
- systemPrompt = typeof asset.content === "string" ? asset.content : undefined;
81
+ if (asset.type !== "agent") {
82
+ throw new UsageError(`Asset ref "${agentRef}" resolves to type "${asset.type}", expected "agent".`, "INVALID_FLAG_VALUE");
83
+ }
84
+ systemPrompt = typeof asset.prompt === "string" ? asset.prompt : undefined;
75
85
  assetModel = typeof asset.modelHint === "string" ? asset.modelHint : undefined;
76
86
  assetTools = asset.toolPolicy;
77
87
  }
@@ -80,22 +90,27 @@ export const agentCommand = defineCommand({
80
90
  const promptText = getStringArg(args, "prompt");
81
91
  const commandRef = getStringArg(args, "command");
82
92
  const workflowRef = getStringArg(args, "workflow");
93
+ const promptStdin = args["prompt-stdin"] === true;
94
+ if (promptStdin && (promptText !== undefined || commandRef !== undefined || workflowRef !== undefined)) {
95
+ throw new UsageError("--prompt-stdin cannot be combined with --prompt, --command, or --workflow.", "INVALID_FLAG_VALUE");
96
+ }
97
+ const stdinPrompt = promptStdin ? readPromptStdin() : undefined;
83
98
  const cwd = getStringArg(args, "cwd");
84
99
  // Only build a dispatch request when there is something to dispatch — a
85
100
  // prompt, an agent asset, or a model override. When none of these are
86
101
  // present the agent is launched interactively (no injected prompt, no
87
102
  // platform-specific flags beyond the profile's base args).
88
- const hasDispatchContent = !!(promptText ?? commandRef ?? workflowRef ?? systemPrompt ?? model ?? assetTools);
103
+ const hasDispatchContent = stdinPrompt !== undefined || !!(promptText ?? commandRef ?? workflowRef ?? systemPrompt ?? model ?? assetTools);
89
104
  const result = await akmAgentDispatch({
90
105
  engine: getStringArg(args, "engine"),
91
- prompt: promptText,
106
+ prompt: stdinPrompt ?? promptText,
92
107
  commandRef,
93
108
  workflowRef,
94
109
  agentConfig,
95
110
  ...(hasDispatchContent
96
111
  ? {
97
112
  dispatch: {
98
- prompt: promptText ?? "",
113
+ prompt: stdinPrompt ?? promptText ?? "",
99
114
  systemPrompt,
100
115
  model,
101
116
  tools: assetTools,
@@ -108,7 +123,16 @@ export const agentCommand = defineCommand({
108
123
  });
109
124
  output("agent-result", result);
110
125
  if (!result.ok) {
111
- process.exit(EXIT_GENERAL);
126
+ // R-067-style fix: this used to call `process.exit(EXIT_GENERAL)`
127
+ // directly, which terminates synchronously and skips any pending
128
+ // `finally`/cleanup up the call stack (including the dispatched
129
+ // agent process' own bookkeeping). `output()` has already run above,
130
+ // so there is nothing left in this handler that depends on
131
+ // terminating immediately — `process.exitCode` + `return` (this is
132
+ // the last statement anyway) lets the process exit naturally once
133
+ // the event loop drains.
134
+ process.exitCode = EXIT_GENERAL;
135
+ return;
112
136
  }
113
137
  });
114
138
  },
@@ -116,16 +140,33 @@ export const agentCommand = defineCommand({
116
140
  export const lintCommand = defineCommand({
117
141
  meta: {
118
142
  name: "lint",
119
- description: "Scan stash .md files for structural issues (unquoted colons, missing updated field, orphaned stubs, placeholder stubs, missing name/type, stale paths, broken refs in body text and in refs/xrefs/supersededBy/contradictedBy frontmatter). Use --fix to auto-fix Tier 1 issues. Exits 0 on success regardless of findings; use --fail-on-flagged for CI fail-on-finding behavior.",
143
+ description: "Scan bundle .md files for structural issues (unquoted colons, missing updated field, orphaned stubs, placeholder stubs, missing name/type, stale paths, broken refs in body text and in refs/xrefs/supersededBy/contradictedBy frontmatter). Use --fix to auto-fix Tier 1 issues. Exits 0 on success regardless of findings; use --fail-on-flagged for CI fail-on-finding behavior.",
120
144
  },
121
145
  args: {
146
+ // R-051: `lint` is a raw `defineCommand` (not `defineJsonCommand`), so it
147
+ // does not get `GLOBAL_OUTPUT_ARGS` for free. `--format`/`--detail`/
148
+ // `--shape`/`--output` already parsed correctly here (this command has no
149
+ // positional for a stray value to fall into), so this is purely a
150
+ // `--help` visibility / consistency fix, not a behavior change.
151
+ ...GLOBAL_OUTPUT_ARGS,
122
152
  fix: {
123
153
  type: "boolean",
124
- alias: "auto-fix",
125
- description: "Apply auto-fixes in place (alias: --auto-fix)",
154
+ description: "Apply auto-fixes in place",
126
155
  default: false,
127
156
  },
128
- dir: { type: "string", description: "Override stash root directory (default: from config)" },
157
+ // Declared as its own arg rather than `alias: "auto-fix"`: citty's alias
158
+ // handling (node:util parseArgs `short` options) only supports
159
+ // SINGLE-character aliases. A
160
+ // multi-char alias rendered in help as `-auto-fix` (one dash) and parsed
161
+ // as a pile of junk single-char flags, so BOTH advertised spellings —
162
+ // `-auto-fix` and `--auto-fix` — silently ran a plain lint while claiming
163
+ // to fix. Two real boolean args, OR'd at the call site, work and render.
164
+ "auto-fix": {
165
+ type: "boolean",
166
+ description: "Apply auto-fixes in place (same as --fix)",
167
+ default: false,
168
+ },
169
+ dir: { type: "string", description: "Override bundle root directory (default: from config)" },
129
170
  "fail-on-flagged": {
130
171
  type: "boolean",
131
172
  description: "Exit non-zero when summary.flagged > 0 (CI-friendly). Default: exit 0 regardless of findings.",
@@ -139,8 +180,8 @@ export const lintCommand = defineCommand({
139
180
  },
140
181
  async run({ args }) {
141
182
  await runWithJsonErrors(async () => {
142
- const result = akmLint({
143
- fix: args.fix ?? false,
183
+ const result = await akmLint({
184
+ fix: args.fix === true || getHyphenatedBoolean(args, "auto-fix"),
144
185
  dir: getStringArg(args, "dir"),
145
186
  typeFilter: getStringArg(args, "type"),
146
187
  });
@@ -152,59 +193,3 @@ export const lintCommand = defineCommand({
152
193
  });
153
194
  },
154
195
  });
155
- export const proposeCommand = defineCommand({
156
- meta: {
157
- name: "propose",
158
- description: "Ask the configured agent CLI to author a brand-new asset and queue it as a proposal",
159
- },
160
- args: {
161
- // Optional in citty so run() is invoked when omitted; we re-validate
162
- // below to surface a structured UsageError (exit 2) instead of citty's
163
- // default help-banner exit-0.
164
- type: { type: "positional", description: "Asset type (skill, command, knowledge, lesson, ...)", required: false },
165
- name: {
166
- type: "positional",
167
- description: "Asset name (flat, no '/'; use --path for a subdirectory)",
168
- required: false,
169
- },
170
- path: {
171
- type: "string",
172
- description: "Relative subdirectory under the type dir to place the proposed asset in (e.g. 'release'). The filename comes from the name.",
173
- },
174
- task: { type: "string", description: "Task description for the agent (what should the asset do?)" },
175
- file: { type: "string", description: "Read the task or prompt text from a UTF-8 file" },
176
- engine: { type: "string", description: "Engine to use (defaults to defaults.engine)" },
177
- "timeout-ms": { type: "string", description: "Override the agent CLI timeout in milliseconds" },
178
- },
179
- async run({ args }) {
180
- await runWithJsonErrors(async () => {
181
- // citty silently shows help and exits 0 when required positionals are
182
- // omitted. Re-validate explicitly so the exit code is 2 (USAGE) and a
183
- // structured JSON error reaches scripted callers.
184
- const taskFromFlag = typeof args.task === "string" ? args.task : undefined;
185
- const fileFromFlag = typeof args.file === "string" ? args.file : undefined;
186
- if (!args.type || !args.name || (!taskFromFlag && !fileFromFlag)) {
187
- throw new UsageError("Usage: akm propose <type> <name> (--task '<task>' | --file <path>).", "MISSING_REQUIRED_ARGUMENT", "Provide the asset type, name, and exactly one of --task or --file.");
188
- }
189
- if (taskFromFlag && fileFromFlag) {
190
- throw new UsageError("Pass exactly one of --task or --file.", "INVALID_FLAG_VALUE");
191
- }
192
- // `name` is flat; subdirectory placement is `--path`'s job.
193
- assertFlatAssetName(String(args.name));
194
- const proposedName = combineCreatePath(normalizeCreateSubPath(getStringArg(args, "path")), String(args.name));
195
- const taskText = fileFromFlag ? fs.readFileSync(path.resolve(fileFromFlag), "utf8") : (taskFromFlag ?? "");
196
- const timeoutMs = parsePositiveIntFlag(args["timeout-ms"], "--timeout-ms");
197
- const result = await akmPropose({
198
- type: String(args.type),
199
- name: proposedName,
200
- task: taskText,
201
- engine: getStringArg(args, "engine"),
202
- ...(timeoutMs !== undefined ? { timeoutMs } : {}),
203
- });
204
- output("propose", result);
205
- if (result.ok === false) {
206
- process.exit(EXIT_GENERAL);
207
- }
208
- });
209
- },
210
- });
@@ -5,32 +5,72 @@ import fs from "node:fs";
5
5
  import os from "node:os";
6
6
  import path from "node:path";
7
7
  import { placementTypes } from "../core/asset/asset-placement.js";
8
- // ── Known flag values ────────────────────────────────────────────────────────
9
8
  const FLAG_VALUES = {
10
- "--format": ["json", "text", "yaml", "jsonl"],
11
- "--detail": ["brief", "normal", "full", "summary"],
12
- "--type": () => [...placementTypes(), "any"],
13
- "--source": ["stash", "registry", "both"],
14
- "--shell": ["bash"],
9
+ "--format": [{ values: ["json", "jsonl", "yaml", "text", "md", "html"] }],
10
+ "--detail": [{ values: ["brief", "normal", "full"] }],
11
+ "--shape": [{ values: ["human", "agent", "summary"] }],
12
+ "--type": [{ values: () => [...placementTypes(), "any"] }],
13
+ "--shell": [{ values: ["bash"] }],
14
+ "--from": [{ paths: ["akm search", "akm curate"], values: ["local", "registry", "all"] }],
15
15
  };
16
+ function resolveRuleValues(rule) {
17
+ return typeof rule.values === "function" ? rule.values() : rule.values;
18
+ }
19
+ /**
20
+ * Build the `${prev}`-case body for one flag. When the flag has no
21
+ * path-scoped rules, every command shares one value set (unchanged from
22
+ * before R-052a). When it does (currently only `--from`), nest a
23
+ * `${cmd_path}` match inside the flag's case so the suggestion depends on
24
+ * which command is being completed — with a `*)` fallback to any
25
+ * unscoped/global rule declared alongside the scoped ones, or no suggestion
26
+ * at all when every rule for that flag is scoped.
27
+ */
28
+ function buildFlagValueCaseBody(rules) {
29
+ const scoped = rules.filter((rule) => rule.paths && rule.paths.length > 0);
30
+ const global = rules.find((rule) => !rule.paths || rule.paths.length === 0);
31
+ if (scoped.length === 0) {
32
+ return ` COMPREPLY=( $(compgen -W "${resolveRuleValues(global).join(" ")}" -- "\${cur}") )`;
33
+ }
34
+ const branches = scoped
35
+ .map((rule) => ` ${rule.paths.map((p) => `"${p}"`).join("|")})
36
+ COMPREPLY=( $(compgen -W "${resolveRuleValues(rule).join(" ")}" -- "\${cur}") )
37
+ ;;`)
38
+ .join("\n");
39
+ const fallback = global
40
+ ? ` *)
41
+ COMPREPLY=( $(compgen -W "${resolveRuleValues(global).join(" ")}" -- "\${cur}") )
42
+ ;;`
43
+ : "";
44
+ return ` case "\${cmd_path}" in
45
+ ${branches}
46
+ ${fallback}
47
+ esac`;
48
+ }
16
49
  function walkCommandTree(cmd, parentPath = "") {
17
50
  const name = cmd.meta?.name ?? "";
18
51
  const currentPath = parentPath ? `${parentPath} ${name}` : name;
19
52
  const result = [];
20
- const subcommands = Object.keys(cmd.subCommands ?? {});
53
+ // `meta.hidden` (e.g. `migrate`, S11) is excluded from completion the same
54
+ // way citty's own `renderUsage` excludes it from a rendered COMMANDS list —
55
+ // a hidden command still runs, it just isn't suggested.
56
+ const visibleSubEntries = Object.entries((cmd.subCommands ?? {})).filter(([, sub]) => !sub.meta?.hidden);
57
+ const subcommands = visibleSubEntries.map(([key]) => key);
21
58
  const flags = [];
59
+ const valueFlags = [];
22
60
  if (cmd.args) {
23
61
  for (const [flagName, arg] of Object.entries(cmd.args)) {
24
62
  if (arg.type === "positional")
25
63
  continue;
26
64
  flags.push(`--${flagName}`);
65
+ if (arg.type === "boolean" && arg.default === true)
66
+ flags.push(`--no-${flagName}`);
67
+ if (arg.type !== "boolean")
68
+ valueFlags.push(`--${flagName}`);
27
69
  }
28
70
  }
29
- result.push({ path: currentPath, subcommands, flags });
30
- if (cmd.subCommands) {
31
- for (const sub of Object.values(cmd.subCommands)) {
32
- result.push(...walkCommandTree(sub, currentPath));
33
- }
71
+ result.push({ path: currentPath, subcommands, flags, valueFlags });
72
+ for (const [, sub] of visibleSubEntries) {
73
+ result.push(...walkCommandTree(sub, currentPath));
34
74
  }
35
75
  return result;
36
76
  }
@@ -41,6 +81,7 @@ export function generateBashCompletions(cmd) {
41
81
  // Collect global flags from root command
42
82
  const rootInfo = commands.find((c) => c.path === rootName);
43
83
  const globalFlags = rootInfo?.flags ?? [];
84
+ const valueFlags = [...new Set(commands.flatMap((info) => info.valueFlags))];
44
85
  // Build the case blocks for subcommand completion
45
86
  const caseBlocks = [];
46
87
  for (const info of commands) {
@@ -61,10 +102,9 @@ export function generateBashCompletions(cmd) {
61
102
  }
62
103
  // Build flag-value completion cases
63
104
  const valueCases = [];
64
- for (const [flag, valuesOrFn] of Object.entries(FLAG_VALUES)) {
65
- const values = typeof valuesOrFn === "function" ? valuesOrFn() : valuesOrFn;
105
+ for (const [flag, rules] of Object.entries(FLAG_VALUES)) {
66
106
  valueCases.push(` ${flag})
67
- COMPREPLY=( $(compgen -W "${values.join(" ")}" -- "\${cur}") )
107
+ ${buildFlagValueCaseBody(rules)}
68
108
  return 0
69
109
  ;;`);
70
110
  }
@@ -83,20 +123,37 @@ _${rootName}() {
83
123
  cword=\${COMP_CWORD}
84
124
  fi
85
125
 
86
- # Complete flag values
87
- case "\${prev}" in
88
- ${valueCases.join("\n")}
89
- esac
90
-
91
- # Build the command path from COMP_WORDS
126
+ # Build the command path from recognized subcommand transitions only. Positional
127
+ # arguments and option values cannot extend the path, so completion remains
128
+ # command-aware after either one.
92
129
  local cmd_path="${rootName}"
130
+ local skip_value=0
93
131
  for (( i=1; i < cword; i++ )); do
132
+ if (( skip_value )); then
133
+ skip_value=0
134
+ continue
135
+ fi
94
136
  case "\${words[i]}" in
137
+ --) break ;;
138
+ --*=*) continue ;;
139
+ ${valueFlags.join("|")}) skip_value=1; continue ;;
95
140
  -*) continue ;;
96
- *) cmd_path="\${cmd_path} \${words[i]}" ;;
141
+ *)
142
+ case "\${cmd_path}:\${words[i]}" in
143
+ ${commands
144
+ .filter((info) => info.subcommands.length > 0)
145
+ .flatMap((info) => info.subcommands.map((subcommand) => ` "${info.path}:${subcommand}") cmd_path="${info.path} ${subcommand}" ;;`))
146
+ .join("\n")}
147
+ esac
148
+ ;;
97
149
  esac
98
150
  done
99
151
 
152
+ # Complete flag values
153
+ case "\${prev}" in
154
+ ${valueCases.join("\n")}
155
+ esac
156
+
100
157
  # Complete based on current command path
101
158
  case "\${cmd_path}" in
102
159
  ${caseBlocks.join("\n")}