akm-cli 0.9.30 → 0.10.261001-beta

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 (384) hide show
  1. package/CHANGELOG.md +438 -0
  2. package/README.md +10 -10
  3. package/ROADMAP.md +112 -0
  4. package/STABILITY.md +99 -57
  5. package/dist/api-node.mjs +20 -0
  6. package/dist/api.d.ts +23 -0
  7. package/dist/api.js +45 -0
  8. package/dist/assets/hints/cli-hints-full.md +15 -29
  9. package/dist/assets/hints/cli-hints-short.md +2 -2
  10. package/dist/assets/improve-strategies/default.json +3 -3
  11. package/dist/assets/prompts/consolidate-pair.md +9 -7
  12. package/dist/assets/stash-skeleton/README.md +1 -1
  13. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
  14. package/dist/cli/shared.js +31 -48
  15. package/dist/cli/unknown-flags.js +6 -43
  16. package/dist/cli.js +8 -34
  17. package/dist/commands/agent/contribute-cli.js +1 -1
  18. package/dist/commands/completions.js +1 -2
  19. package/dist/commands/config-cli.js +5 -28
  20. package/dist/commands/env/env-cli.js +5 -5
  21. package/dist/commands/env/secret-cli.js +2 -2
  22. package/dist/commands/feedback-cli.js +75 -49
  23. package/dist/commands/health/checks.js +41 -16
  24. package/dist/commands/health/plugin-staleness.js +52 -22
  25. package/dist/commands/improve/autonomy-gate.js +5 -3
  26. package/dist/commands/improve/consolidate/chunking.js +3 -10
  27. package/dist/commands/improve/consolidate/continuity-check.js +4 -4
  28. package/dist/commands/improve/consolidate/pair-pass.js +29 -10
  29. package/dist/commands/improve/consolidate.js +10 -65
  30. package/dist/commands/improve/distill/lesson-update.js +91 -0
  31. package/dist/commands/improve/distill-guards.js +1 -43
  32. package/dist/commands/improve/distill.js +148 -21
  33. package/dist/commands/improve/eligibility.js +14 -1
  34. package/dist/commands/improve/extract-cli.js +1 -1
  35. package/dist/commands/improve/extract-prompt.js +17 -7
  36. package/dist/commands/improve/extract.js +5 -7
  37. package/dist/commands/improve/improve-cli.js +125 -118
  38. package/dist/commands/improve/improve-strategies.js +8 -12
  39. package/dist/commands/improve/improve.js +134 -52
  40. package/dist/commands/improve/loop-stages.js +18 -5
  41. package/dist/commands/improve/planner.js +0 -1
  42. package/dist/commands/improve/preparation.js +40 -99
  43. package/dist/commands/improve/proactive-maintenance.js +2 -2
  44. package/dist/commands/improve/reflect-noise.js +3 -55
  45. package/dist/commands/improve/reflect.js +29 -34
  46. package/dist/commands/improve/retrieval-queries.js +37 -0
  47. package/dist/commands/improve/retrieval-scope.js +2 -2
  48. package/dist/commands/improve/salience.js +2 -9
  49. package/dist/commands/improve/session-asset.js +4 -1
  50. package/dist/commands/improve/stage.js +23 -12
  51. package/dist/commands/lint/index.js +5 -20
  52. package/dist/commands/observability-cli.js +3 -9
  53. package/dist/commands/proposal/drain.js +43 -6
  54. package/dist/commands/proposal/proposal-cli.js +11 -31
  55. package/dist/commands/proposal/repository.js +20 -14
  56. package/dist/commands/proposal/validators/proposal-quality-validators.js +0 -3
  57. package/dist/commands/read/knowledge.js +3 -3
  58. package/dist/commands/read/remember-cli.js +0 -13
  59. package/dist/commands/read/search-cli.js +29 -97
  60. package/dist/commands/read/search.js +0 -11
  61. package/dist/commands/read/show.js +0 -19
  62. package/dist/commands/sources/plugin-upgrade.js +164 -101
  63. package/dist/commands/sources/sources-cli.js +1 -15
  64. package/dist/commands/sources/stash-cli.js +6 -14
  65. package/dist/commands/tasks/tasks-cli.js +4 -115
  66. package/dist/commands/workflow/plan.js +11 -33
  67. package/dist/commands/workflow-cli.js +2 -7
  68. package/dist/core/adapter/adapter-ids.js +1 -2
  69. package/dist/core/adapter/adapters/agent-skills-adapter.js +0 -4
  70. package/dist/core/adapter/adapters/akm-adapter.js +9 -48
  71. package/dist/core/adapter/adapters/akm-lint.js +10 -26
  72. package/dist/core/adapter/adapters/akm-metadata.js +2 -72
  73. package/dist/core/adapter/adapters/akm-task-adapter.js +0 -5
  74. package/dist/core/adapter/adapters/akm-workflow-adapter.js +9 -28
  75. package/dist/core/adapter/adapters/dotenv-adapter.js +1 -20
  76. package/dist/core/adapter/adapters/generic-files-adapter.js +0 -10
  77. package/dist/core/adapter/adapters/llm-wiki-adapter.js +0 -4
  78. package/dist/core/adapter/adapters/tool-dir-shared.js +0 -24
  79. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -4
  80. package/dist/core/adapter/recognize-match.js +3 -4
  81. package/dist/core/common.js +18 -2
  82. package/dist/core/config/config-schema.js +12 -15
  83. package/dist/core/config/config-types.js +6 -15
  84. package/dist/core/config/config-walker.js +6 -23
  85. package/dist/core/config/config.js +17 -80
  86. package/dist/core/config/engine-semantics.js +7 -3
  87. package/dist/core/config/schema/engines.js +7 -7
  88. package/dist/core/config/schema/improve-processes.js +10 -63
  89. package/dist/core/config/schema/improve.js +2 -21
  90. package/dist/core/config/schema/index-config.js +6 -39
  91. package/dist/core/env-secret-ref.js +2 -45
  92. package/dist/core/errors.js +1 -2
  93. package/dist/core/extra-params.js +2 -86
  94. package/dist/core/file-lock.js +12 -7
  95. package/dist/core/improve-result.js +13 -1
  96. package/dist/core/mutation-target.js +2 -2
  97. package/dist/core/paths.js +4 -0
  98. package/dist/core/recognition-util.js +4 -5
  99. package/dist/core/run-lock.js +1 -1
  100. package/dist/core/subprocess.js +49 -0
  101. package/dist/core/warn.js +21 -4
  102. package/dist/core/write-source.js +3 -3
  103. package/dist/execution/target-ref.js +1 -2
  104. package/dist/indexer/indexer.js +15 -6
  105. package/dist/indexer/passes/memory-inference.js +15 -6
  106. package/dist/indexer/search/db-search.js +49 -36
  107. package/dist/indexer/search/fts-query.js +0 -19
  108. package/dist/indexer/search/ranking.js +29 -1
  109. package/dist/indexer/usage/usage-events.js +21 -16
  110. package/dist/integrations/agent/engine-resolution.js +5 -2
  111. package/dist/integrations/agent/index.js +1 -1
  112. package/dist/integrations/agent/profiles.js +41 -98
  113. package/dist/integrations/agent/request-lowering.js +3 -3
  114. package/dist/integrations/harnesses/aider/index.js +5 -0
  115. package/dist/integrations/harnesses/amazonq/index.js +1 -0
  116. package/dist/integrations/harnesses/claude/config-import.js +2 -3
  117. package/dist/integrations/harnesses/claude/index.js +5 -0
  118. package/dist/integrations/harnesses/codex/index.js +1 -0
  119. package/dist/integrations/harnesses/copilot/index.js +1 -0
  120. package/dist/integrations/harnesses/gemini/index.js +1 -0
  121. package/dist/integrations/harnesses/index.js +18 -39
  122. package/dist/integrations/harnesses/opencode/agent-builder.js +60 -35
  123. package/dist/integrations/harnesses/opencode/config-import.js +121 -52
  124. package/dist/integrations/harnesses/opencode/index.js +22 -0
  125. package/dist/integrations/harnesses/opencode/plugin-layout.js +68 -0
  126. package/dist/integrations/harnesses/opencode/session-log-types.js +12 -0
  127. package/dist/integrations/harnesses/opencode/session-log-v1.js +72 -0
  128. package/dist/integrations/harnesses/opencode/session-log-v2.js +140 -0
  129. package/dist/integrations/harnesses/opencode/session-log.js +104 -115
  130. package/dist/integrations/harnesses/opencode/version.js +98 -0
  131. package/dist/integrations/harnesses/opencode-sdk/{harness.js → index.js} +5 -17
  132. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +105 -206
  133. package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +199 -0
  134. package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +254 -0
  135. package/dist/integrations/harnesses/opencode-sdk/wire.js +66 -0
  136. package/dist/integrations/harnesses/openhands/index.js +1 -0
  137. package/dist/integrations/harnesses/pi/index.js +1 -0
  138. package/dist/integrations/harnesses/shared.js +2 -0
  139. package/dist/integrations/harnesses/types.js +2 -0
  140. package/dist/llm/client.js +74 -14
  141. package/dist/output/cli-hints.js +1 -1
  142. package/dist/output/context.js +10 -19
  143. package/dist/output/format-exempt.js +5 -8
  144. package/dist/output/shapes/helpers.js +1 -22
  145. package/dist/output/shapes/passthrough.js +0 -1
  146. package/dist/output/shapes.js +3 -31
  147. package/dist/output/stdout.js +5 -1
  148. package/dist/output/text/command-format.js +6 -1
  149. package/dist/output/text/workflow-format.js +4 -22
  150. package/dist/scripts/akm-migrate-node.js +15769 -16731
  151. package/dist/scripts/akm-migrate.js +16339 -17297
  152. package/dist/setup/detect.js +10 -4
  153. package/dist/setup/harness-config-import.js +5 -14
  154. package/dist/setup/setup.js +1 -1
  155. package/dist/setup/steps/tasks.js +12 -13
  156. package/dist/sources/providers/git-stash.js +94 -13
  157. package/dist/storage/repositories/index-utility-repository.js +2 -32
  158. package/dist/storage/repositories/index-vec-repository.js +4 -0
  159. package/dist/storage/repositories/task-history-repository.js +0 -5
  160. package/dist/storage/repositories/workflow-runs-repository.js +5 -15
  161. package/dist/tasks/embedded.js +2 -1
  162. package/dist/tasks/run/run-command-task.js +9 -1
  163. package/dist/tasks/run/run-workflow-task.js +4 -3
  164. package/dist/tasks/run/task-history.js +0 -2
  165. package/dist/tasks/run/task-log.js +38 -1
  166. package/dist/tasks/schedule-gates.js +39 -0
  167. package/dist/tasks/scheduler-binding.js +0 -16
  168. package/dist/tasks/scheduler-sync.js +3 -97
  169. package/dist/tasks/source/bounded-document.js +1 -1
  170. package/dist/tasks/source/task-source-v4.js +2 -12
  171. package/dist/tasks/task-run-reserved-flags.js +2 -31
  172. package/dist/workflows/authoring/authoring.js +6 -6
  173. package/dist/workflows/compile.js +8 -65
  174. package/dist/workflows/exec/child-workflow.js +22 -3
  175. package/dist/workflows/exec/native-executor.js +12 -147
  176. package/dist/workflows/exec/run-workflow.js +31 -103
  177. package/dist/workflows/exec/step-work.js +9 -178
  178. package/dist/workflows/exec/unit-dispatch.js +0 -10
  179. package/dist/workflows/freeze/environment.js +3 -44
  180. package/dist/workflows/freeze/freeze.js +8 -41
  181. package/dist/workflows/freeze/targets/child-workflow.js +27 -63
  182. package/dist/workflows/freeze/targets/command.js +2 -16
  183. package/dist/workflows/freeze/targets/shell.js +0 -2
  184. package/dist/workflows/freeze/task-bindings.js +2 -28
  185. package/dist/workflows/ir/params.js +12 -2
  186. package/dist/workflows/parser.js +82 -232
  187. package/dist/workflows/plan.js +1 -1
  188. package/dist/workflows/renderer.js +10 -19
  189. package/dist/workflows/runtime/run-plan.js +11 -53
  190. package/dist/workflows/runtime/runs.js +4 -27
  191. package/dist/workflows/source-files.js +12 -16
  192. package/dist/workflows/source-semantics.js +1 -93
  193. package/docs/README.md +43 -42
  194. package/docs/agents/README.md +15 -0
  195. package/docs/agents/agent-install.md +14 -0
  196. package/docs/architecture/0.10-process-rules.md +827 -0
  197. package/docs/architecture/README.md +67 -0
  198. package/docs/architecture/adapters.md +258 -0
  199. package/docs/architecture/akm-architecture-decision-history.md +2055 -0
  200. package/docs/architecture/akm-core-principles.md +126 -0
  201. package/docs/architecture/architecture.md +578 -0
  202. package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +550 -0
  203. package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +72 -0
  204. package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +142 -0
  205. package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +189 -0
  206. package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +97 -0
  207. package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +108 -0
  208. package/docs/architecture/decisions/0006-task-source-version-routing.md +124 -0
  209. package/docs/architecture/decisions/0007-workflow-composition-bounds.md +83 -0
  210. package/docs/architecture/decisions/0008-task-binding-normalization.md +88 -0
  211. package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +80 -0
  212. package/docs/architecture/decisions/0010-driver-protocol-cut.md +36 -0
  213. package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +125 -0
  214. package/docs/architecture/decisions/README.md +62 -0
  215. package/docs/architecture/improvement.md +479 -0
  216. package/docs/architecture/internals/classification.md +154 -0
  217. package/docs/architecture/internals/fresh-host-rebuild-runbook.md +40 -0
  218. package/docs/architecture/internals/functional-contract-patterns.md +340 -0
  219. package/docs/architecture/internals/health-advisories.md +110 -0
  220. package/docs/architecture/internals/improve-workflow.md +719 -0
  221. package/docs/architecture/internals/indexing.md +498 -0
  222. package/docs/architecture/internals/registry-network-boundary.md +57 -0
  223. package/docs/architecture/internals/search.md +248 -0
  224. package/docs/architecture/internals/storage-locations.md +943 -0
  225. package/docs/architecture/persisted-data-compat.md +68 -0
  226. package/docs/architecture/reviews/env-secret-access.md +319 -0
  227. package/docs/architecture/runtime-boundary-design.md +153 -0
  228. package/docs/architecture/specs/0.9.0-close-out-plan.md +361 -0
  229. package/docs/architecture/specs/0.9.0-decisions.md +532 -0
  230. package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +745 -0
  231. package/docs/architecture/specs/0.9.0-open-items-register.md +135 -0
  232. package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +740 -0
  233. package/docs/architecture/specs/0.9.0-release-surface-review.md +636 -0
  234. package/docs/architecture/specs/agent-command-engine-model-design.md +513 -0
  235. package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +501 -0
  236. package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +291 -0
  237. package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +2059 -0
  238. package/docs/architecture/specs/di-seams-plan.md +539 -0
  239. package/docs/architecture/specs/driver-protocol-keep-or-cut.md +275 -0
  240. package/docs/architecture/specs/fact-asset-type.md +142 -0
  241. package/docs/architecture/specs/improve-collapse-churn-detector-design.md +634 -0
  242. package/docs/architecture/specs/okf-support.md +148 -0
  243. package/docs/architecture/specs/ref.md +329 -0
  244. package/docs/architecture/specs/reviews/task-workflow-unification/README.md +72 -0
  245. package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +152 -0
  246. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +352 -0
  247. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +300 -0
  248. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +402 -0
  249. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +758 -0
  250. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +645 -0
  251. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +602 -0
  252. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +27 -0
  253. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +27 -0
  254. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +74 -0
  255. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +15 -0
  256. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +132 -0
  257. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +147 -0
  258. package/docs/architecture/specs/stash-conventions-code-spec.md +275 -0
  259. package/docs/architecture/specs/stash-organization-conventions.md +377 -0
  260. package/docs/architecture/specs/task-workflow-format-unification.md +721 -0
  261. package/docs/architecture/specs/workflow-engine-buy-vs-build.md +231 -0
  262. package/docs/architecture/specs/workflow-format-unification.md +432 -0
  263. package/docs/architecture/testing/manual-testing-checklist.md +3411 -0
  264. package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +924 -0
  265. package/docs/architecture/testing/task-workflow-manual-tests.md +1720 -0
  266. package/docs/architecture/testing/testing-workflow.md +446 -0
  267. package/docs/architecture/workflow-engine.md +223 -0
  268. package/docs/guides/README.md +33 -0
  269. package/docs/guides/author-bundles.md +310 -0
  270. package/docs/guides/author-workflows.md +490 -0
  271. package/docs/guides/bundles.md +323 -0
  272. package/docs/guides/capture-knowledge.md +136 -0
  273. package/docs/guides/claude-code-vs-akm-workflows.md +29 -0
  274. package/docs/guides/concepts.md +93 -0
  275. package/docs/guides/discover-and-load.md +158 -0
  276. package/docs/guides/getting-started.md +240 -0
  277. package/docs/guides/improve-the-library.md +247 -0
  278. package/docs/guides/knowledge-management.md +18 -0
  279. package/docs/guides/recipes/headless-install.md +97 -0
  280. package/docs/guides/recipes/website-source.md +28 -0
  281. package/docs/guides/run-workflows.md +279 -0
  282. package/docs/guides/scheduling.md +131 -0
  283. package/docs/guides/use-with-any-agent.md +174 -0
  284. package/docs/guides/wikis.md +81 -0
  285. package/docs/integration/bundling-akm.md +7 -6
  286. package/docs/maintainers/README.md +19 -0
  287. package/docs/maintainers/curate-workmap.md +335 -0
  288. package/docs/maintainers/eval.md +3 -0
  289. package/docs/maintainers/local-development.md +108 -0
  290. package/docs/maintainers/release-checklist.md +135 -0
  291. package/docs/migration/README.md +4 -2
  292. package/docs/migration/release-notes/0.0.13.md +1 -1
  293. package/docs/migration/release-notes/0.1.0.md +1 -1
  294. package/docs/migration/release-notes/0.10.0.md +201 -0
  295. package/docs/migration/release-notes/0.2.0.md +1 -1
  296. package/docs/migration/release-notes/0.3.0.md +1 -1
  297. package/docs/migration/release-notes/0.5.0.md +1 -1
  298. package/docs/migration/release-notes/0.6.0.md +1 -1
  299. package/docs/migration/release-notes/0.7.0.md +1 -1
  300. package/docs/migration/release-notes/0.7.3.md +2 -2
  301. package/docs/migration/release-notes/0.7.4.md +1 -1
  302. package/docs/migration/release-notes/0.7.5.md +1 -1
  303. package/docs/migration/release-notes/0.8.0.md +1 -1
  304. package/docs/migration/release-notes/0.9.0.md +1 -1
  305. package/docs/migration/release-notes/0.9.14.md +1 -1
  306. package/docs/migration/release-notes/0.9.15.md +1 -1
  307. package/docs/migration/release-notes/0.9.16.md +1 -1
  308. package/docs/migration/release-notes/0.9.17.md +1 -1
  309. package/docs/migration/release-notes/0.9.19.md +1 -1
  310. package/docs/migration/release-notes/0.9.2.md +1 -1
  311. package/docs/migration/release-notes/README.md +28 -31
  312. package/docs/migration/v0.5-to-v0.6.md +759 -0
  313. package/docs/migration/v0.8-to-v0.9.md +1 -1
  314. package/docs/migration/v0.9-to-v0.10.md +507 -0
  315. package/docs/plans/0.9.2-agent-command-workflow-plan.md +423 -0
  316. package/docs/posts/README.md +30 -0
  317. package/docs/posts/akm-command-tour.md +495 -0
  318. package/docs/posts/akm-logo-sized.webp +0 -0
  319. package/docs/posts/belief-aware-memory-12.md +139 -0
  320. package/docs/posts/config-v2-lessons-16.md +191 -0
  321. package/docs/posts/improve-loop-autonomous-10.md +225 -0
  322. package/docs/posts/improve-pipeline-debugging-0803.md +179 -0
  323. package/docs/posts/intro-part-01.md +76 -0
  324. package/docs/posts/intro-part-02.md +221 -0
  325. package/docs/posts/intro-part-03.md +190 -0
  326. package/docs/posts/intro-part-04.md +221 -0
  327. package/docs/posts/llm-mode-reflect-13.md +166 -0
  328. package/docs/posts/openpalm-built-on-akm.md +86 -0
  329. package/docs/posts/progressive-disclosure-06.md +129 -0
  330. package/docs/posts/proposal-safety-net-15.md +112 -0
  331. package/docs/posts/release-0.5.0.md +247 -0
  332. package/docs/posts/release-0.6.0.md +117 -0
  333. package/docs/posts/release-0.7.0.md +159 -0
  334. package/docs/posts/release-0.8.0.md +332 -0
  335. package/docs/posts/scattered-skills-05.md +100 -0
  336. package/docs/posts/task-assets-persistent-workflows-11.md +222 -0
  337. package/docs/posts/team-skills-07.md +198 -0
  338. package/docs/posts/wiki-agent-knowledge-08.md +223 -0
  339. package/docs/posts/workflows-vaults-09.md +321 -0
  340. package/docs/product-surface.md +54 -0
  341. package/docs/reference/README.md +2 -2
  342. package/docs/reference/api.md +65 -0
  343. package/docs/reference/asset-types.md +166 -0
  344. package/docs/reference/bundle-types.md +2 -4
  345. package/docs/reference/cli.md +163 -192
  346. package/docs/reference/configuration.md +101 -20
  347. package/docs/reference/data-and-telemetry.md +2 -2
  348. package/docs/reference/env-and-secrets.md +126 -0
  349. package/docs/reference/memory.md +124 -0
  350. package/docs/reference/refs.md +156 -0
  351. package/docs/reference/registry.md +489 -0
  352. package/docs/reference/supported-formats.md +3 -4
  353. package/docs/reference/tasks.md +12 -19
  354. package/docs/reference/website-sources.md +141 -0
  355. package/docs/reference/workflow-schema.md +89 -317
  356. package/docs/reference/workflows.md +20 -48
  357. package/package.json +23 -16
  358. package/schemas/akm-config.json +2 -243
  359. package/schemas/akm-task.json +2 -3
  360. package/schemas/akm-workflow.json +47 -84
  361. package/dist/assets/improve-strategies/catchup.json +0 -41
  362. package/dist/assets/improve-strategies/proactive-maintenance.json +0 -24
  363. package/dist/assets/improve-strategies/quick.json +0 -17
  364. package/dist/assets/improve-strategies/reflect-distill.json +0 -29
  365. package/dist/assets/improve-strategies/thorough.json +0 -49
  366. package/dist/assets/prompts/retrieval-relevance-judge.md +0 -6
  367. package/dist/assets/tasks/improve/akm-improve-catchup.yml +0 -6
  368. package/dist/assets/tasks/improve/akm-improve-frequent.yml +0 -4
  369. package/dist/assets/tasks/improve/akm-improve-nightly.yml +0 -4
  370. package/dist/cli/retired-commands.js +0 -118
  371. package/dist/commands/improve/retrieval-gate.js +0 -132
  372. package/dist/commands/tasks/validate.js +0 -176
  373. package/dist/core/config/legacy-source-shape-shim.js +0 -117
  374. package/dist/indexer/feedback/utility-policy.js +0 -75
  375. package/dist/integrations/harnesses/ids.js +0 -28
  376. package/dist/tasks/source/task-source-v3-frozen.js +0 -424
  377. package/dist/tasks/source/task-to-v4.js +0 -863
  378. package/dist/workflows/exec/worktree.js +0 -372
  379. package/dist/workflows/freeze/child-output-references.js +0 -83
  380. package/dist/workflows/freeze/identity.js +0 -22
  381. package/dist/workflows/freeze/targets/script.js +0 -50
  382. package/dist/workflows/freeze/targets/task.js +0 -124
  383. package/dist/workflows/github-yaml.js +0 -506
  384. package/dist/workflows/runtime/run-outputs.js +0 -80
@@ -13,13 +13,14 @@ import * as childProcess from "node:child_process";
13
13
  import fs from "node:fs";
14
14
  import os from "node:os";
15
15
  import path from "node:path";
16
- import { IS_WINDOWS, stripJsonComments } from "../../core/common.js";
16
+ import { IS_WINDOWS, parseJsonc } from "../../core/common.js";
17
17
  import { moveToTrash } from "../../core/trash.js";
18
+ import { OPENCODE_SDK_SERVER_BIN } from "../../integrations/agent/profiles.js";
19
+ import { OPENCODE_V1, OPENCODE_V2, readPackageVersion, } from "../../integrations/harnesses/opencode/plugin-layout.js";
20
+ import { detectOpencodeMajor, resolveOpencodeBin } from "../../integrations/harnesses/opencode/version.js";
18
21
  import { semverOrder } from "../../runtime.js";
19
22
  const MARKETPLACE = "akm-plugins";
20
23
  const PLUGIN_ID = `akm@${MARKETPLACE}`;
21
- const OPENCODE_PACKAGE = "akm-opencode";
22
- const OPENCODE_NEXT_SPEC = `${OPENCODE_PACKAGE}@next`;
23
24
  const READ_TIMEOUT_MS = 30_000;
24
25
  const REFRESH_TIMEOUT_MS = 120_000;
25
26
  const PREFETCH_TIMEOUT_MS = 180_000;
@@ -137,20 +138,33 @@ function upgradeCodex(dryRun) {
137
138
  const after = codexPluginVersion();
138
139
  return refreshed("codex", before.version, "version" in after ? after.version : undefined);
139
140
  }
141
+ // ── OpenCode ────────────────────────────────────────────────────────────────
142
+ const nextSpec = (flavor) => `${flavor.pkg}@next`;
140
143
  function homeDir() {
141
144
  return process.env.HOME?.trim() || process.env.USERPROFILE?.trim() || os.homedir();
142
145
  }
146
+ function openCodeCacheHome() {
147
+ const cacheHome = process.env.XDG_CACHE_HOME?.trim() || path.join(homeDir(), ".cache");
148
+ return path.join(cacheHome, "opencode");
149
+ }
150
+ /** The spec in a config's plugin entry (a spec string or a `[spec, options]` pair). */
151
+ function entrySpec(entry) {
152
+ const spec = Array.isArray(entry) ? entry[0] : entry;
153
+ return typeof spec === "string" ? spec : undefined;
154
+ }
155
+ const namesPackage = (spec, pkg) => spec === pkg || spec.startsWith(`${pkg}@`);
143
156
  /**
144
- * The `akm-opencode` spec the user's global OpenCode config names (bare,
145
- * `@latest`, `@next`, an exact version, ...), or undefined when none does.
146
- * OpenCode caches each spec in its own folder, so this says which cache it
147
- * loads. The config is only read, never written; project configs are not
148
- * looked at (akm does not know which project OpenCode runs in).
157
+ * The plugin spec the user's global OpenCode config names for this flavor's
158
+ * package (bare, `@latest`, `@next`, an exact version, ...), with the config key
159
+ * it sits under, or undefined when none does. OpenCode caches each spec in its
160
+ * own folder, so this says which cache it loads. The config is only read, never
161
+ * written; project configs are not looked at (akm does not know which project
162
+ * OpenCode runs in).
149
163
  */
150
- export function openCodeConfigSpec() {
164
+ export function openCodeConfigSpec(flavor) {
151
165
  const configHome = process.env.XDG_CONFIG_HOME?.trim() || path.join(homeDir(), ".config");
152
166
  const files = [
153
- process.env.OPENCODE_CONFIG?.trim(),
167
+ flavor.globalConfigOnly ? undefined : process.env.OPENCODE_CONFIG?.trim(),
154
168
  path.join(configHome, "opencode", "opencode.json"),
155
169
  path.join(configHome, "opencode", "opencode.jsonc"),
156
170
  ];
@@ -158,14 +172,15 @@ export function openCodeConfigSpec() {
158
172
  if (!file)
159
173
  continue;
160
174
  try {
161
- const config = JSON.parse(stripJsonComments(fs.readFileSync(file, "utf8")));
162
- if (!Array.isArray(config.plugin))
163
- continue;
164
- // An entry is a spec string or a `[spec, options]` pair.
165
- for (const entry of config.plugin) {
166
- const spec = Array.isArray(entry) ? entry[0] : entry;
167
- if (typeof spec === "string" && (spec === OPENCODE_PACKAGE || spec.startsWith(`${OPENCODE_PACKAGE}@`))) {
168
- return spec;
175
+ const config = parseJsonc(fs.readFileSync(file, "utf8"));
176
+ for (const key of flavor.configKeys) {
177
+ const entries = config[key];
178
+ if (!Array.isArray(entries))
179
+ continue;
180
+ for (const entry of entries) {
181
+ const spec = entrySpec(entry);
182
+ if (spec !== undefined && namesPackage(spec, flavor.pkg))
183
+ return { spec, key };
169
184
  }
170
185
  }
171
186
  }
@@ -175,30 +190,32 @@ export function openCodeConfigSpec() {
175
190
  }
176
191
  return undefined;
177
192
  }
193
+ /** Whether OpenCode 2 has ever cached `akm-opencode-v2` on this host. */
194
+ function openCodeV2Cached() {
195
+ try {
196
+ return fs
197
+ .readdirSync(path.join(openCodeCacheHome(), OPENCODE_V2.cacheFolder("")))
198
+ .some((name) => name.startsWith(`${OPENCODE_V2.pkg}@`));
199
+ }
200
+ catch {
201
+ return false;
202
+ }
203
+ }
178
204
  /**
179
- * The cached `akm-opencode` OpenCode installed on first use, or undefined when
180
- * there is none. OpenCode names the folder after the spec it resolved, so a
181
- * bare `akm-opencode` lands in `@latest` and `akm-opencode@next` in `@next`.
205
+ * The cached plugin OpenCode installed on first use, or undefined when there is
206
+ * none. OpenCode names the folder after the spec it resolved, so a bare package
207
+ * lands in `@latest` and `<pkg>@next` in `@next`.
182
208
  */
183
- export function detectOpenCodeCache(tag = "latest") {
184
- const cacheHome = process.env.XDG_CACHE_HOME?.trim() || path.join(homeDir(), ".cache");
185
- const dir = path.join(cacheHome, "opencode", "packages", `${OPENCODE_PACKAGE}@${tag}`);
209
+ export function detectOpenCodeCache(tag, flavor) {
210
+ const dir = path.join(openCodeCacheHome(), flavor.cacheFolder(`${flavor.pkg}@${tag}`));
186
211
  if (!fs.existsSync(dir))
187
212
  return undefined;
188
- const readVersion = (file) => {
189
- try {
190
- const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
191
- return typeof pkg.version === "string" ? pkg.version : undefined;
192
- }
193
- catch {
194
- return undefined;
195
- }
196
- };
197
- return { dir, version: readVersion(path.join(dir, "node_modules", OPENCODE_PACKAGE, "package.json")) };
213
+ const nodeModules = flavor.nodeModulesDir(dir);
214
+ return { dir, version: nodeModules && readPackageVersion(path.join(nodeModules, flavor.pkg, "package.json")) };
198
215
  }
199
- /** What npm's `akm-opencode@<tag>` is, and which akm-cli it pins. */
200
- export function lookupOpenCodeLatest(tag = "latest") {
201
- const spec = `${OPENCODE_PACKAGE}@${tag}`;
216
+ /** What npm's `<pkg>@<tag>` is, and which akm-cli it pins. */
217
+ export function lookupOpenCodeLatest(tag, flavor) {
218
+ const spec = `${flavor.pkg}@${tag}`;
202
219
  const view = runCommand(IS_WINDOWS ? "npm.cmd" : "npm", ["view", spec, "version", "dependencies.akm-cli", "--json"], READ_TIMEOUT_MS);
203
220
  if (!view.ok)
204
221
  return { error: view.error };
@@ -209,7 +226,7 @@ export function lookupOpenCodeLatest(tag = "latest") {
209
226
  return { version: parsed.version, akmCli: typeof akmCli === "string" ? akmCli : undefined };
210
227
  }
211
228
  /**
212
- * `akm-opencode@next`, which must exist and pin an akm-cli no older than the one
229
+ * `<pkg>@next`, which must exist and pin an akm-cli no older than the one
213
230
  * `@latest` pins: a prerelease channel that trails the stable one is not a target.
214
231
  *
215
232
  * The two builds are compared by their akm-cli pins, never by their own
@@ -220,23 +237,23 @@ export function lookupOpenCodeLatest(tag = "latest") {
220
237
  * (#1089). For the same reason plugin versions are only ever tested for
221
238
  * equality (is the cache already this build?), never ordered.
222
239
  */
223
- export function lookupOpenCodeNext() {
224
- const next = lookupOpenCodeLatest("next");
240
+ export function lookupOpenCodeNext(flavor) {
241
+ const next = lookupOpenCodeLatest("next", flavor);
225
242
  if ("error" in next)
226
243
  return next;
227
- const latest = lookupOpenCodeLatest("latest");
244
+ const latest = lookupOpenCodeLatest("latest", flavor);
228
245
  if ("error" in latest)
229
- return { error: `could not compare with ${OPENCODE_PACKAGE}@latest: ${latest.error}` };
246
+ return { error: `could not compare with ${flavor.pkg}@latest: ${latest.error}` };
230
247
  // No pin on @next: returned as is, and the lockstep holds the CLI and says why.
231
248
  if (!next.akmCli)
232
249
  return next;
233
250
  if (!latest.akmCli) {
234
- return { error: `could not compare with ${OPENCODE_PACKAGE}@latest: it declares no akm-cli dependency` };
251
+ return { error: `could not compare with ${flavor.pkg}@latest: it declares no akm-cli dependency` };
235
252
  }
236
253
  if (semverOrder(next.akmCli, latest.akmCli) < 0) {
237
254
  return {
238
- error: `${OPENCODE_NEXT_SPEC} (${next.version}) pins akm-cli ${next.akmCli}, older than the ` +
239
- `${latest.akmCli} that ${OPENCODE_PACKAGE}@latest (${latest.version}) pins`,
255
+ error: `${nextSpec(flavor)} (${next.version}) pins akm-cli ${next.akmCli}, older than the ` +
256
+ `${latest.akmCli} that ${flavor.pkg}@latest (${latest.version}) pins`,
240
257
  };
241
258
  }
242
259
  return next;
@@ -296,28 +313,31 @@ function openCodeRunning() {
296
313
  return undefined;
297
314
  }
298
315
  }
299
- const NOT_FOLLOWING_NEXT = `--next: OpenCode resolves a bare "${OPENCODE_PACKAGE}" to @latest, so it is not updated to a prerelease; ` +
300
- `set "plugin": ["${OPENCODE_NEXT_SPEC}"] in your OpenCode config to follow prereleases`;
316
+ const notFollowingNext = (flavor) => `--next: OpenCode resolves a bare "${flavor.pkg}" to @latest, so it is not updated to a prerelease; ` +
317
+ `set "${flavor.configKeys[0]}": ["${nextSpec(flavor)}"] in your OpenCode config to follow prereleases`;
301
318
  /** Why a run leaves alone an OpenCode whose config names a spec this run does not refresh (#1115, #1117). */
302
- function otherSpecNote(spec) {
319
+ function otherSpecNote(flavor, spec) {
303
320
  const loads = `OpenCode loads "${spec}" (your OpenCode config), so this upgrade leaves it alone`;
304
- return spec === OPENCODE_NEXT_SPEC
305
- ? `${loads}; run \`akm upgrade --next\` to update it, or set "plugin": ["${OPENCODE_PACKAGE}"] to follow stable releases`
306
- : `${loads}; set "plugin": ["${OPENCODE_PACKAGE}"] to have \`akm upgrade\` keep it current`;
321
+ const key = flavor.configKeys[0];
322
+ return spec === nextSpec(flavor)
323
+ ? `${loads}; run \`akm upgrade --next\` to update it, or set "${key}": ["${flavor.pkg}"] to follow stable releases`
324
+ : `${loads}; set "${key}": ["${flavor.pkg}"] to have \`akm upgrade\` keep it current`;
307
325
  }
308
- function upgradeOpenCode(dryRun, cache, latest, tag, notFollowingNext, otherSpec) {
326
+ function upgradeOpenCode(dryRun, target) {
327
+ const { flavor, cache, latest, tag, skip } = target;
328
+ const harness = flavor.harness;
309
329
  // Refreshing a cache OpenCode does not load would trash one it never re-creates (#1115, #1117).
310
- if (otherSpec)
311
- return skipped("opencode", otherSpecNote(otherSpec));
330
+ if (skip)
331
+ return skipped(harness, skip);
312
332
  if (!cache || !latest)
313
- return skipped("opencode", `no cached ${OPENCODE_PACKAGE}@${tag} plugin`);
333
+ return skipped(harness, `no cached ${flavor.pkg}@${tag} plugin`);
314
334
  if ("error" in latest)
315
- return failed("opencode", latest.error);
316
- if (notFollowingNext)
317
- return skipped("opencode", NOT_FOLLOWING_NEXT);
335
+ return failed(harness, latest.error);
336
+ if (target.notFollowingNext)
337
+ return skipped(harness, notFollowingNext(flavor));
318
338
  if (cache.version === latest.version)
319
- return { harness: "opencode", outcome: "current", from: cache.version, to: latest.version };
320
- const base = { harness: "opencode", from: cache.version, to: latest.version };
339
+ return { harness, outcome: "current", from: cache.version, to: latest.version };
340
+ const base = { harness, from: cache.version, to: latest.version };
321
341
  const running = openCodeRunning();
322
342
  if (running !== false) {
323
343
  return {
@@ -330,30 +350,39 @@ function upgradeOpenCode(dryRun, cache, latest, tag, notFollowingNext, otherSpec
330
350
  }
331
351
  if (dryRun)
332
352
  return { ...base, outcome: "pending" };
333
- // OpenCode must be runnable before the cache goes: it does the prefetch.
334
- const probe = runCommand("opencode", ["--version"], READ_TIMEOUT_MS);
335
- if (!probe.ok)
336
- return skipped("opencode", probe.missing ? "opencode is not on PATH" : probe.error);
353
+ // OpenCode must be runnable before the cache goes: it does the prefetch, and only the major
354
+ // that owns this plugin's cache can re-create it. akm never installs or replaces the binary.
355
+ // OpenCode 2 may sit beside an OpenCode 1 `opencode` as `opencode2`; OpenCode 1 is only ever `opencode`.
356
+ const bin = flavor.major === 2 ? resolveOpencodeBin() : OPENCODE_SDK_SERVER_BIN;
357
+ const detected = detectOpencodeMajor(bin);
358
+ if (!detected.runnable)
359
+ return skipped(harness, `${bin} is not on PATH or \`${bin} --version\` failed`);
360
+ const major = detected.reportedMajor;
361
+ // OpenCode 1 keeps its long-standing behavior when the version cannot be read; OpenCode 2's
362
+ // refresh needs a command only OpenCode 2 has, so it must be sure.
363
+ if (major === undefined ? flavor.major === 2 : major !== flavor.major) {
364
+ return skipped(harness, `\`${bin}\` on PATH is ${major === undefined ? "of an unknown version" : `OpenCode ${major}`}, ` +
365
+ `not OpenCode ${flavor.major}, so it cannot re-create the ${flavor.pkg} cache; the cache is left alone`);
366
+ }
337
367
  try {
338
368
  moveToTrash(cache.dir);
339
369
  }
340
370
  catch (error) {
341
- return failed("opencode", `could not move ${cache.dir} to the trash: ${error instanceof Error ? error.message : String(error)}`);
371
+ return failed(harness, `could not move ${cache.dir} to the trash: ${error instanceof Error ? error.message : String(error)}`);
342
372
  }
343
- // Any OpenCode command that resolves the config installs the plugin again;
344
- // from a temp dir, so no project's opencode.json is read.
373
+ // From a temp dir, so no project's opencode.json is read.
345
374
  const workDir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-opencode-prefetch-"));
346
375
  try {
347
- const prefetch = runCommand("opencode", ["debug", "config"], PREFETCH_TIMEOUT_MS, { cwd: workDir });
376
+ const prefetch = runCommand(bin, flavor.prefetch(target.spec), PREFETCH_TIMEOUT_MS, { cwd: workDir });
348
377
  if (!prefetch.ok)
349
- return failed("opencode", `${prefetch.error} (the old cache is in the trash)`);
378
+ return failed(harness, `${prefetch.error} (the old cache is in the trash)`);
350
379
  }
351
380
  finally {
352
381
  fs.rmSync(workDir, { recursive: true, force: true });
353
382
  }
354
- const after = detectOpenCodeCache(tag);
383
+ const after = detectOpenCodeCache(tag, flavor);
355
384
  if (!after)
356
- return failed("opencode", "opencode did not re-create the plugin cache (the old cache is in the trash)");
385
+ return failed(harness, "opencode did not re-create the plugin cache (the old cache is in the trash)");
357
386
  return { ...base, outcome: "updated", to: after.version ?? latest.version };
358
387
  }
359
388
  // ── Orchestration ───────────────────────────────────────────────────────────
@@ -365,18 +394,17 @@ function withNextNote(entry) {
365
394
  return { ...entry, message: entry.message ? `${entry.message}; ${NO_PRERELEASE_CHANNEL}` : NO_PRERELEASE_CHANNEL };
366
395
  }
367
396
  export function upgradePlugins(opts) {
368
- const { cache, latest, tag, notFollowingNext, otherSpec } = opts.openCode;
369
397
  const claude = upgradeClaudeCode(opts.dryRun);
370
398
  const codex = upgradeCodex(opts.dryRun);
371
399
  return [
372
400
  opts.next ? withNextNote(claude) : claude,
373
401
  opts.next ? withNextNote(codex) : codex,
374
- upgradeOpenCode(opts.dryRun, cache, latest, tag, notFollowingNext, otherSpec),
402
+ ...opts.openCode.map((target) => upgradeOpenCode(opts.dryRun, target)),
375
403
  ];
376
404
  }
377
405
  /**
378
- * When the OpenCode plugin is present the CLI target is the akm-cli that
379
- * `akm-opencode@latest` pins, not the newest release: the plugin runs that
406
+ * When an OpenCode plugin is present the CLI target is the akm-cli that
407
+ * `<pkg>@latest` pins, not the newest release: the plugin runs that
380
408
  * exact akm in-process, against databases a newer CLI may already have
381
409
  * migrated. The CLI never moves backwards to meet the pin.
382
410
  *
@@ -386,7 +414,7 @@ export function upgradePlugins(opts) {
386
414
  * `lockstep.reason` says why. Moving the CLI ahead of a pin nobody could read is
387
415
  * what lockstep exists to prevent; the OpenCode entry reports the failure.
388
416
  */
389
- export function applyLockstep(check, latest, tag = "latest") {
417
+ export function applyLockstep(check, latest, tag, pkg) {
390
418
  if (!latest)
391
419
  return check;
392
420
  // Held back only when there is a release this upgrade would otherwise install.
@@ -394,14 +422,14 @@ export function applyLockstep(check, latest, tag = "latest") {
394
422
  const pinned = "error" in latest ? undefined : latest.akmCli;
395
423
  if (!pinned) {
396
424
  const reason = "error" in latest
397
- ? `could not read the akm-cli pin of ${OPENCODE_PACKAGE}@${tag}: ${latest.error}`
398
- : `${OPENCODE_PACKAGE}@${tag} declares no akm-cli dependency`;
425
+ ? `could not read the akm-cli pin of ${pkg}@${tag}: ${latest.error}`
426
+ : `${pkg}@${tag} declares no akm-cli dependency`;
399
427
  return {
400
428
  ...check,
401
429
  latestVersion: check.currentVersion,
402
430
  updateAvailable: false,
403
431
  lockstep: {
404
- plugin: OPENCODE_PACKAGE,
432
+ plugin: pkg,
405
433
  pinnedVersion: null,
406
434
  newestVersion: check.latestVersion,
407
435
  heldBack: wouldInstall,
@@ -411,7 +439,7 @@ export function applyLockstep(check, latest, tag = "latest") {
411
439
  }
412
440
  const heldBack = semverOrder(pinned, check.latestVersion) < 0 && wouldInstall;
413
441
  const lockstep = {
414
- plugin: OPENCODE_PACKAGE,
442
+ plugin: pkg,
415
443
  pinnedVersion: pinned,
416
444
  newestVersion: check.latestVersion,
417
445
  heldBack,
@@ -426,40 +454,75 @@ export function applyLockstep(check, latest, tag = "latest") {
426
454
  };
427
455
  }
428
456
  /**
429
- * Which OpenCode plugin build the CLI is held to, and which cache refreshes.
430
- * Under `--next` that is `akm-opencode@next`, but only when the user's OpenCode
457
+ * The plugin the CLI is held to when several are present: one whose pin could not be read (the
458
+ * CLI stays put), else the one pinning the oldest akm-cli, since every plugin runs the CLI that is installed.
459
+ */
460
+ function lockstepSource(targets) {
461
+ const readable = (t) => t.latest !== undefined && !("error" in t.latest) && typeof t.latest.akmCli === "string";
462
+ const pinned = targets.filter((t) => t.latest);
463
+ return (pinned.find((t) => !readable(t)) ??
464
+ pinned.filter(readable).sort((a, b) => semverOrder(a.latest.akmCli, b.latest.akmCli))[0]);
465
+ }
466
+ /**
467
+ * Which build of one OpenCode plugin the CLI is held to, and which cache refreshes.
468
+ * Under `--next` that is `<pkg>@next`, but only when the user's OpenCode
431
469
  * config names that tag: a bare one keeps resolving `@latest`, so the lockstep
432
470
  * stays against the `@latest` pin and the entry is reported as skipped. A config
433
471
  * naming any other spec (an exact version, or `@next` on a plain run) is left
434
472
  * alone, with no lockstep.
435
473
  */
436
- function resolveOpenCodeTarget(next) {
437
- // No config entry behaves like a bare one: OpenCode would resolve @latest.
438
- const spec = openCodeConfigSpec() ?? OPENCODE_PACKAGE;
439
- const followsLatest = spec === OPENCODE_PACKAGE || spec === `${OPENCODE_PACKAGE}@latest`;
440
- const followNext = next && spec === OPENCODE_NEXT_SPEC;
441
- // Any other spec loads a cache this run does not refresh, and pins no akm-cli it should be held to.
442
- if (!followsLatest && !followNext) {
443
- return {
444
- cache: undefined,
445
- latest: undefined,
446
- tag: next ? "next" : "latest",
447
- notFollowingNext: false,
448
- otherSpec: spec,
449
- };
474
+ function resolveOpenCodeTarget(next, flavor, configured) {
475
+ // OpenCode 1 with no config entry behaves like a bare one: it would resolve @latest. OpenCode 2's
476
+ // re-fetch writes the config, so its plugin is only refreshed where the config already names it.
477
+ const spec = configured?.spec ?? flavor.pkg;
478
+ const leftAlone = (skip) => ({
479
+ flavor,
480
+ cache: undefined,
481
+ latest: undefined,
482
+ tag: next ? "next" : "latest",
483
+ spec,
484
+ notFollowingNext: false,
485
+ skip,
486
+ });
487
+ if (flavor.globalConfigOnly) {
488
+ if (!configured) {
489
+ return leftAlone(`OpenCode's global config does not name ${flavor.pkg}; this upgrade only refreshes a plugin it names`);
490
+ }
491
+ if (configured.key !== flavor.configKeys[0]) {
492
+ return leftAlone(`OpenCode loads "${spec}" from the "${configured.key}" key of your config; move it to "${flavor.configKeys[0]}" ` +
493
+ "to have `akm upgrade` keep it current");
494
+ }
450
495
  }
496
+ const followsLatest = spec === flavor.pkg || spec === `${flavor.pkg}@latest`;
497
+ const followNext = next && spec === nextSpec(flavor);
498
+ // Any other spec loads a cache this run does not refresh, and pins no akm-cli it should be held to.
499
+ if (!followsLatest && !followNext)
500
+ return leftAlone(otherSpecNote(flavor, spec));
451
501
  const tag = followNext ? "next" : "latest";
452
- const cache = detectOpenCodeCache(tag);
453
- const latest = cache ? (followNext ? lookupOpenCodeNext() : lookupOpenCodeLatest()) : undefined;
454
- return { cache, latest, tag, notFollowingNext: next && !followNext };
502
+ const cache = detectOpenCodeCache(tag, flavor);
503
+ const latest = cache ? (followNext ? lookupOpenCodeNext(flavor) : lookupOpenCodeLatest("latest", flavor)) : undefined;
504
+ return { flavor, cache, latest, tag, spec, notFollowingNext: next && !followNext };
505
+ }
506
+ /**
507
+ * The OpenCode plugins this host has: OpenCode 1's always, OpenCode 2's only when the global config
508
+ * names `akm-opencode-v2` or OpenCode 2 has cached it, so a host with just OpenCode 1 sees the same
509
+ * output as before.
510
+ */
511
+ function resolveOpenCodeTargets(next) {
512
+ const targets = [resolveOpenCodeTarget(next, OPENCODE_V1, openCodeConfigSpec(OPENCODE_V1))];
513
+ const v2 = openCodeConfigSpec(OPENCODE_V2);
514
+ if (v2 || openCodeV2Cached())
515
+ targets.push(resolveOpenCodeTarget(next, OPENCODE_V2, v2));
516
+ return targets;
455
517
  }
456
518
  /** `akm upgrade`: the CLI step (held to the OpenCode plugin's akm), then the plugins. */
457
519
  export async function runUpgrade(args, currentVersion, deps) {
458
520
  const next = args.next === true;
459
521
  const channel = next ? "next" : "latest";
460
- const openCode = resolveOpenCodeTarget(next);
522
+ const openCode = resolveOpenCodeTargets(next);
523
+ const held = lockstepSource(openCode);
461
524
  const check = {
462
- ...applyLockstep(await deps.checkForUpdate(currentVersion, channel), openCode.latest, openCode.tag),
525
+ ...applyLockstep(await deps.checkForUpdate(currentVersion, channel), held?.latest, held?.tag ?? "latest", held?.flavor.pkg ?? OPENCODE_V1.pkg),
463
526
  channel,
464
527
  };
465
528
  if (args.check) {
@@ -26,10 +26,8 @@
26
26
  * `akm sync` directly).
27
27
  */
28
28
  import { defineCommand } from "citty";
29
- import { getParsedInvocation } from "../../cli/invocation.js";
30
29
  import { defineJsonCommand, EXIT_CODES, GLOBAL_OUTPUT_ARGS, output, outputWithExitCode, runWithJsonErrors, } from "../../cli/shared.js";
31
30
  import { loadConfig } from "../../core/config/config.js";
32
- import { UsageError } from "../../core/errors.js";
33
31
  import { appendEvent } from "../../core/events.js";
34
32
  import { resolveWritableOverride, saveGitStash } from "../../sources/providers/git.js";
35
33
  import { pkgVersion } from "../../version.js";
@@ -40,7 +38,7 @@ export const upgradeCommand = defineJsonCommand({
40
38
  meta: {
41
39
  name: "upgrade",
42
40
  description: "Upgrade akm to the latest release, then update the akm plugin of each installed harness " +
43
- "(Claude Code, Codex, OpenCode). With the OpenCode plugin installed, akm moves to the version that plugin pins.",
41
+ "(Claude Code, Codex, OpenCode 1 and 2). With an OpenCode plugin installed, akm moves to the version that plugin pins.",
44
42
  },
45
43
  args: {
46
44
  check: {
@@ -126,17 +124,6 @@ export const syncCommand = defineCommand({
126
124
  await runSyncBody(args);
127
125
  },
128
126
  });
129
- /**
130
- * `--target` was renamed to `--bundle` on `clone` in 0.9 (S8). citty is
131
- * non-strict, so the retired spelling is silently absorbed rather than
132
- * rejected — the asset then lands in the default bundle instead of the one
133
- * the caller named, with exit 0 and no error. Reject it explicitly instead.
134
- */
135
- function rejectRetiredCloneTargetFlag() {
136
- if (!getParsedInvocation().hasFlag("--target"))
137
- return;
138
- throw new UsageError("`akm clone --target` was renamed to `--bundle` in 0.9. Use `--bundle <name>` instead.", "INVALID_FLAG_VALUE");
139
- }
140
127
  export const cloneCommand = defineJsonCommand({
141
128
  meta: {
142
129
  name: "clone",
@@ -153,7 +140,6 @@ export const cloneCommand = defineJsonCommand({
153
140
  dest: { type: "string", description: "Unmanaged destination directory (cannot be combined with --bundle)" },
154
141
  },
155
142
  async run({ args }) {
156
- rejectRetiredCloneTargetFlag();
157
143
  const result = await akmClone({
158
144
  sourceRef: args.ref,
159
145
  newName: args.name,
@@ -30,22 +30,20 @@
30
30
  import path from "node:path";
31
31
  import { defineCommand } from "citty";
32
32
  import * as p from "../../cli/clack.js";
33
- import { getParsedInvocation } from "../../cli/invocation.js";
34
33
  import { defineJsonCommand, GLOBAL_OUTPUT_ARGS, output, parseAllFlagValues, runWithJsonErrors } from "../../cli/shared.js";
35
34
  import { assertFlatAssetName } from "../../core/asset/asset-create.js";
36
35
  import { placementTypes } from "../../core/asset/asset-placement.js";
37
36
  import { parseFrontmatter } from "../../core/asset/frontmatter.js";
38
37
  import { isHttpUrl, resolveStashDir } from "../../core/common.js";
39
38
  import { loadConfig } from "../../core/config/config.js";
40
- import { UsageError } from "../../core/errors.js";
41
39
  import { appendEvent } from "../../core/events.js";
42
40
  import { resolveBundleWriteTarget } from "../../core/mutation-target.js";
43
- import { getCacheDir } from "../../core/paths.js";
41
+ import { getRunLogDir } from "../../core/paths.js";
44
42
  import { clearLogFile, info, isVerbose, setLogFile } from "../../core/warn.js";
45
43
  import { resolveWriteTarget } from "../../core/write-source.js";
46
44
  import { releaseIndexRebuildLock, tryAcquireIndexRebuildLock } from "../../indexer/index-rebuild-lock.js";
47
45
  import { akmIndex } from "../../indexer/indexer.js";
48
- import { getHyphenatedBoolean, getOutputMode } from "../../output/context.js";
46
+ import { getOutputMode } from "../../output/context.js";
49
47
  import { pkgVersion } from "../../version.js";
50
48
  import { inferAssetName, mergeXrefsIntoContent, readKnowledgeInput, resolveSupersedesForWrite, resolveSupersedesWriteTarget, resolveXrefsForWrite, writeMarkdownAsset, } from "../read/knowledge.js";
51
49
  import { assembleInfo } from "./info.js";
@@ -56,7 +54,7 @@ export const indexCommand = defineCommand({
56
54
  args: {
57
55
  // R-051: `index` is a raw `defineCommand` (not `defineJsonCommand`), so it
58
56
  // does not get `GLOBAL_OUTPUT_ARGS` for free. `--format`/`--detail`/
59
- // `--shape`/`--output` already parsed correctly here (this command has no
57
+ // `--output` already parsed correctly here (this command has no
60
58
  // extra positional for a stray value to fall into), so this is purely a
61
59
  // `--help` visibility / consistency fix, not a behavior change.
62
60
  ...GLOBAL_OUTPUT_ARGS,
@@ -84,12 +82,6 @@ export const indexCommand = defineCommand({
84
82
  },
85
83
  async run({ args }) {
86
84
  await runWithJsonErrors(async () => {
87
- if (getHyphenatedBoolean(args, "enrich") || getParsedInvocation().getFlagValue("--enrich") !== undefined) {
88
- throw new UsageError("`akm index --enrich` has been removed. Metadata enrichment during indexing is retired; it never runs.");
89
- }
90
- if (getHyphenatedBoolean(args, "re-enrich") || getParsedInvocation().getFlagValue("--re-enrich") !== undefined) {
91
- throw new UsageError("`akm index --re-enrich` has been removed. Metadata enrichment during indexing is retired; there is nothing to re-enrich.");
92
- }
93
85
  // #956: opt-in, non-blocking rebuild lock — never gates a human-typed
94
86
  // `akm index` (it only warns and contends), but a scheduled/opportunistic
95
87
  // caller can pass --skip-if-locked to step aside instead of piling up
@@ -116,7 +108,7 @@ export const indexCommand = defineCommand({
116
108
  const abort = () => controller.abort(new Error("index interrupted"));
117
109
  process.once("SIGINT", abort);
118
110
  process.once("SIGTERM", abort);
119
- const indexLogFile = path.join(getCacheDir(), "logs", "index", `${new Date().toISOString().replace(/[:.]/g, "-")}.log`);
111
+ const indexLogFile = path.join(getRunLogDir("index"), `${new Date().toISOString().replace(/[:.]/g, "-")}.log`);
120
112
  setLogFile(indexLogFile);
121
113
  const verbose = isVerbose();
122
114
  const spin = !verbose && outputMode.format === "text" ? p.spinner() : null;
@@ -229,7 +221,7 @@ export const importKnowledgeCommand = defineJsonCommand({
229
221
  description: "Overwrite an existing knowledge document with the same name",
230
222
  default: false,
231
223
  },
232
- target: {
224
+ bundle: {
233
225
  type: "string",
234
226
  description: "Override the write destination. Accepts a source name from your config; falls back to defaultWriteTarget then the working bundle.",
235
227
  },
@@ -250,7 +242,7 @@ export const importKnowledgeCommand = defineJsonCommand({
250
242
  // read/write so an unresolvable ref (UsageError → exit 2) leaves the
251
243
  // stash untouched.
252
244
  const rawSupersedes = parseAllFlagValues("--supersedes");
253
- const writeTarget = resolveSupersedesWriteTarget(rawSupersedes, args.target);
245
+ const writeTarget = resolveSupersedesWriteTarget(rawSupersedes, args.bundle);
254
246
  const xrefs = resolveXrefsForWrite(parseAllFlagValues("--xref"), writeTarget);
255
247
  // Collect and validate --supersedes occurrences (repeatable). Same
256
248
  // before-any-read/write contract: an unresolvable ref exits 2 with nothing