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
@@ -0,0 +1,446 @@
1
+ # Testing Workflow
2
+
3
+ This project is a CLI with three risk-heavy areas:
4
+
5
+ - command behavior across real files, config, and cache directories
6
+ - managed-source install/update flows
7
+ - binary deployment and self-upgrade behavior
8
+
9
+ The safest way to test it is in layers: fast local checks first, then end-to-end
10
+ CLI coverage, then Docker-based deployment and upgrade validation. This document
11
+ owns automated test workflow and test-authoring guidance only. The authoritative
12
+ manual setup, command matrix, expected behavior, release gates, evidence, and
13
+ cleanup live in [AKM Manual Testing Runbook](./manual-testing-checklist.md).
14
+
15
+ ## What To Validate
16
+
17
+ - core CLI flows: `setup`, `index`, `search`, `show`, `info`, `bundle list`, `config`
18
+ - asset lifecycle: add assets, re-index, search, show, and incremental refresh
19
+ - managed-source lifecycle: `akm bundle add`, `akm bundle list`, `akm bundle update`, `akm bundle remove`
20
+ - binary lifecycle: install, run, `akm upgrade --check`, `akm upgrade`
21
+ - cross-environment behavior on Ubuntu, Debian, Alpine, and Fedora containers
22
+
23
+ ## Test Layers In This Repo
24
+
25
+ ### 1. Fast local correctness
26
+
27
+ Run these before any release candidate or merge:
28
+
29
+ ```sh
30
+ bun run test:unit
31
+ bunx biome check --write src/ tests/
32
+ bunx tsc --noEmit
33
+ ```
34
+
35
+ Use this when you want the shortest full-project signal:
36
+
37
+ ```sh
38
+ bun run check
39
+ ```
40
+
41
+ Relevant coverage:
42
+
43
+ - `tests/integration/self-update.test.ts` - self-upgrade detection and checksum enforcement
44
+ - `tests/integration/registry-*.test.ts`, `tests/provider-registry.test.ts` - `list`, `remove`, `update`, cache cleanup, install resolution, tar safety, local/git/npm paths
45
+ - `tests/integration/setup-run.test.ts` - full setup wizard orchestration and failure handling
46
+ - `tests/integration/install-script.test.ts` - repeatable `install.sh` edge cases and permission paths
47
+
48
+ ### Writing deterministic, isolated tests
49
+
50
+ Both `scripts/test-unit.sh` (`bun run test:unit`) and `scripts/test-integration.sh`
51
+ (`bun run test:integration`) shard their target across up to `min(nproc, 8)`
52
+ concurrent `bun test` processes, splitting the file list round-robin — neither
53
+ runner is a single shared process, and neither is "the unit suite" alone.
54
+ Within one shard, every file assigned to that process still runs in **one
55
+ shared process**: one `process.env`, one module-singleton namespace, and
56
+ (under fake timers) one global clock for every file in that shard. A test that
57
+ mutates shared state without restoring it, or that asserts on a wall-clock
58
+ measurement, can pass on one scheduling and
59
+ fail on another — the two release/0.8.0 flakes (scoring-pipeline Issue #14
60
+ reading the wrong index DB after a sibling mutated `XDG_DATA_HOME`; the
61
+ llm-client timeout test racing real timers) were both this class.
62
+
63
+ Rules (conventions, not statically enforced — the lint script that policed
64
+ them was deleted in 0.9.8; the runtime guard in `src/core/paths.ts` throws
65
+ `TEST_ISOLATION_MISSING` and the preload tripwire catches leaks):
66
+
67
+ 1. **Never mutate `AKM_*` / `XDG_*` / `HOME` on `process.env` directly.** Use the
68
+ sanctioned helpers in `tests/_helpers/sandbox.ts`:
69
+ - `sandboxStashDir`, `sandboxXdgConfigHome`, `sandboxXdgDataHome`,
70
+ `sandboxXdgCacheHome`, `sandboxXdgStateHome`, `sandboxHome` — set the env var
71
+ to an isolated temp dir and return a `cleanup` that restores the prior value.
72
+ Chain them and call `cleanup()` in `afterEach`.
73
+ - `withEnv({ AKM_BUNDLE_DIR }, async () => …)` — scoped override that always
74
+ restores in a `finally`, even on throw. Use this for per-call overrides
75
+ around an in-process CLI invocation.
76
+ - `makeStashDir` / `makeSandboxDir` — temp dirs that are NOT wired into env
77
+ (pass them to `withEnv` or a subprocess env object yourself).
78
+
79
+ The DB path resolves from `XDG_DATA_HOME`; if you `akmIndex` then `akmSearch`,
80
+ both must see the **same** sandboxed `XDG_DATA_HOME` or the search reads a
81
+ different (empty/stale) DB. Sandbox it in `beforeEach`.
82
+
83
+ 2. **Do not assert on a measured wall-clock delta.** `expect(Date.now() - start)
84
+ .toBeLessThan(N)` races the scheduler. Assert the *observable result* instead
85
+ (e.g. `result.reason === "timeout"`), or drive time deterministically with
86
+ `jest.useFakeTimers()` + `jest.advanceTimersByTime(...)` and a fetch/spawn stub.
87
+ Asserting on a `durationMs` field computed from injected fixture timestamps is
88
+ fine (it is deterministic).
89
+
90
+ 3. **Sort/compare on the value the user sees.** When a test asserts ordering,
91
+ make the production sort key the same quantized value that is displayed
92
+ (`db-search.ts` sorts on the clamped+rounded score, then breaks ties by name),
93
+ so an invisible sub-display-precision epsilon can never reorder visible ties.
94
+
95
+ 4. **Avoid stateful feedback within one test.** Re-running `akmSearch` without
96
+ `skipLogging: true` writes utility/recency rows that perturb the next search's
97
+ ranking. Pass `skipLogging: true` when you need repeatable ranking across
98
+ calls in a single test.
99
+
100
+ If a file legitimately needs a literal env value (e.g. pure path-resolution unit
101
+ tests) and restores via its own save/restore wrapper, add it to the linter's
102
+ `ENV_ASSIGN_ALLOWED` set with a one-line justification — the list may only shrink.
103
+
104
+ ### 2. End-to-end CLI validation
105
+
106
+ Run the full integration suite when changing CLI behavior, indexing, search,
107
+ config, source management, or output shaping:
108
+
109
+ ```sh
110
+ bun run test:integration
111
+ ```
112
+
113
+ Collectively, these suites (`tests/integration/`) exercise real flows,
114
+ including:
115
+
116
+ - fallback search without an index
117
+ - `index -> search -> show`
118
+ - CLI subprocess execution through `src/cli.ts`
119
+ - config read/write behavior
120
+ - registry-source compatibility
121
+ - progressive indexing and re-indexing
122
+ - update and upgrade command error paths
123
+ - knowledge `#fragment` selection and mixed asset discovery
124
+
125
+ ## Semantic Search States
126
+
127
+ Semantic search does not behave as a simple on/off feature at runtime. Testing
128
+ should distinguish between saved-config state and actual readiness.
129
+
130
+ ### Config intent
131
+
132
+ Semantic search intent is saved independently as `semanticSearchMode`:
133
+
134
+ - `off` when the user opts out explicitly
135
+ - `auto` when the user wants semantic search enabled
136
+
137
+ Setup should not flip intent from `auto` back to `off` because preparation or
138
+ verification fails transiently.
139
+
140
+ ### Runtime readiness
141
+
142
+ Actual semantic readiness is tracked separately from config intent. Runtime state
143
+ can be:
144
+
145
+ - `pending` when semantic search is enabled but not yet verified
146
+ - `ready-js` when every entry has a vector (the name is historical; there is no other vector path)
147
+ - `blocked` when semantic search cannot run with the current provider/setup
148
+
149
+ These cases are covered by `tests/integration/setup-run.test.ts` and the focused
150
+ semantic/config suites.
151
+
152
+ The real-model gate (`AKM_SEMANTIC_TESTS=1`) honors an explicit `HF_HOME` and
153
+ otherwise uses the ignored, repo-local `.ci-cache/huggingface` directory. That
154
+ path is outside the preload's disposable test `HOME`, so a second local run
155
+ reuses the model without exposing the developer's normal AKM cache. Gated CI
156
+ sets the same path and restores it from a model/source-identified Actions
157
+ cache. Candidate tags and manual runs are restore-only; only the scheduled
158
+ default-branch run may save a cache entry.
159
+
160
+ The same gate runs real semantic index/search round-trips against the declared
161
+ external dependency. Package acceptance separately verifies the ordinary npm
162
+ package surface; there is no installed-consumer compatibility architecture or
163
+ copied semantic runtime to audit.
164
+
165
+ ### What to test explicitly
166
+
167
+ - config stays `off` only when the user disables semantic search intentionally
168
+ - config stays `auto` when preparation is skipped intentionally
169
+ - config stays `auto` when preparation fails but runtime status becomes `blocked`
170
+ - runtime status becomes `pending`, `ready-js`, or `blocked` as appropriate
171
+ - index and info output report readiness state instead of only config intent
172
+
173
+ ### 3. Docker deployment validation
174
+
175
+ Run the Docker matrix when changing install, packaging, startup, runtime
176
+ dependencies, or platform behavior:
177
+
178
+ ```sh
179
+ AKM_DOCKER_TESTS=1 bun test tests/integration/docker-install.test.ts
180
+ ```
181
+
182
+ Or run the shell orchestrator directly:
183
+
184
+ ```sh
185
+ ./tests/docker/run-docker-tests.sh
186
+ ```
187
+
188
+ This validates two deployment methods across four Linux families:
189
+
190
+ - bun-based install: Ubuntu, Debian, Alpine, Fedora
191
+ - compiled binary install: Ubuntu, Debian, Fedora
192
+
193
+ Binary validation currently excludes Alpine. The compiled Linux binary used in
194
+ this repo's Docker tests is not packaged for Alpine/musl compatibility, so the
195
+ binary deployment gate focuses on the glibc-based targets we currently support.
196
+
197
+ The Docker smoke test in `tests/docker/smoke-test.sh` verifies:
198
+
199
+ - `akm --help`
200
+ - `akm bundle create`
201
+ - bundle directory creation
202
+ - `akm index`
203
+ - `akm search`
204
+ - `akm show`
205
+ - `akm info`
206
+ - `akm bundle list`
207
+ - incremental re-index after adding a new asset
208
+
209
+ ### 4. Benchmark (agent utility)
210
+
211
+ The LLM-provider-driven, multi-seed agent-utility benchmark (`akm-bench`) now
212
+ lives in the standalone repo **[itlackey/akm-bench](https://github.com/itlackey/akm-bench)**.
213
+ Run it from there after any change to `src/output/`, `src/commands/read/show.ts`,
214
+ APPLY directives, or other content that affects what agents see.
215
+
216
+ For curate/search ranking quality, run the retrieval eval of
217
+ **[itlackey/akm-eval](https://github.com/itlackey/akm-eval)**
218
+ (`evals/retrieval/run --corpus public`, with `AKM_BIN` naming the build under
219
+ test). It scores `akm search` and `akm curate` against graded judgments and
220
+ calls no model service. The in-repo curate benchmark that used to do this,
221
+ `akm-eval-curate-bench`, left with the rest of `scripts/akm-eval/`; see
222
+ `docs/maintainers/eval.md`.
223
+
224
+ ## Recommended Workflow
225
+
226
+ ### Normal change
227
+
228
+ Use this for most code changes:
229
+
230
+ ```sh
231
+ bun run test:unit
232
+ bun run test:integration
233
+ bunx biome check --write src/ tests/
234
+ bunx tsc --noEmit
235
+ ```
236
+
237
+ ### Install, packaging, or release-related change
238
+
239
+ Use this when touching `src/cli.ts`, `src/commands/sources/self-update.ts`, install flows,
240
+ source management, or Docker assets:
241
+
242
+ ```sh
243
+ bun run test:unit
244
+ bun test tests/integration/self-update.test.ts tests/integration/setup-run.test.ts tests/integration/install-script.test.ts
245
+ ./tests/docker/run-docker-tests.sh
246
+ bunx biome check --write src/ tests/
247
+ bunx tsc --noEmit
248
+ ```
249
+
250
+ ### Release gate
251
+
252
+ Use this before publishing a release:
253
+
254
+ ```sh
255
+ bun run release:check
256
+ ```
257
+
258
+ If Docker is available, prefer `./tests/docker/run-docker-tests.sh` over a
259
+ single-variant container run so both bun and binary installs are covered.
260
+
261
+ For a local release gate without Docker, use:
262
+
263
+ ```sh
264
+ ./tests/release-check.sh --skip-docker
265
+ ```
266
+
267
+ That script now runs a dedicated install/setup regression suite before the full
268
+ test run so first-run, installer, and wizard failures surface early.
269
+
270
+ The local script is only one half of release validation. Follow the
271
+ [maintainer release checklist](../../maintainers/release-checklist.md) to
272
+ run **Gated CI** from a `gated-ci/candidate-*` tag targeting the exact candidate
273
+ commit, or manually dispatch it with the full candidate
274
+ SHA after the workflow reaches the default branch. Its real-embedding, Docker,
275
+ and Linux/macOS/Windows scheduler jobs must all succeed, and the release PR
276
+ must link the resulting Actions run. The weekly scheduled run detects
277
+ default-branch drift; it cannot attest a different release-candidate commit.
278
+
279
+ ## Manual QA Authority
280
+
281
+ Use [AKM Manual Testing Runbook](./manual-testing-checklist.md) for every manual
282
+ flow. Its full sandbox is mandatory; the smaller historical XDG-only setup is
283
+ unsafe because `AKM_CONFIG_DIR` can bypass it. The runbook also owns expected
284
+ exits/channels, fixtures, release evidence, platform gates, and cleanup.
285
+
286
+ ## Docker Deployment Validation
287
+
288
+ ### Automated matrix
289
+
290
+ The repo already contains Dockerfiles for:
291
+
292
+ - `tests/docker/Dockerfile.ubuntu-bun`
293
+ - `tests/docker/Dockerfile.debian-bun`
294
+ - `tests/docker/Dockerfile.alpine-bun`
295
+ - `tests/docker/Dockerfile.fedora-bun`
296
+ - `tests/docker/Dockerfile.ubuntu-binary`
297
+ - `tests/docker/Dockerfile.debian-binary`
298
+ - `tests/docker/Dockerfile.fedora-binary`
299
+
300
+ `Dockerfile.alpine-binary` does not exist and is deliberately not part of this
301
+ matrix: binary validation excludes Alpine (see above) because the compiled
302
+ binary targets glibc and Alpine is musl-based.
303
+
304
+ Run one variant if you need a focused repro:
305
+
306
+ ```sh
307
+ ./tests/docker/run-docker-tests.sh ubuntu-binary
308
+ ./tests/docker/run-docker-tests.sh --bun-only
309
+ ./tests/docker/run-docker-tests.sh --binary-only
310
+ ```
311
+
312
+ ### What the Docker matrix proves
313
+
314
+ - the CLI starts in minimal Linux images
315
+ - runtime dependencies are sufficient for `bundle create`, `index`, `search`, and `show`
316
+ - bun-linked installs work after building from source
317
+ - compiled Linux binaries run correctly when copied into the image
318
+ - the CLI can create a fresh bundle, build an index, and discover new assets
319
+
320
+ Treat this matrix as a release gate for shell-level regressions too. The Docker
321
+ smoke path exercises real entrypoint scripts and container command execution,
322
+ which can catch failures that unit and subprocess tests miss.
323
+
324
+ ### What it does not prove by itself
325
+
326
+ - that the published release artifact matches the local compiled binary
327
+ - that `install.sh` works against a real GitHub release
328
+ - that self-upgrade can replace the running binary in-place
329
+
330
+ Those should be validated in disposable containers as described next.
331
+
332
+ ## Published Artifact Acceptance
333
+
334
+ Published binary, installer, checksum, native-platform, and self-upgrade
335
+ procedures are release-facing manual gates. Run sections 21-22 of the
336
+ [manual runbook](./manual-testing-checklist.md); do not validate release bytes
337
+ with an installer fetched from raw `main`.
338
+
339
+ ## Upgrade Regression Coverage
340
+
341
+ Managed-source updates and CLI self-upgrade are separate implementations.
342
+ Provider/registry suites cover source add/update/remove/cache behavior;
343
+ `tests/integration/self-update.test.ts` covers install-method detection,
344
+ orchestration, checksum, and failure paths. Real managed-source and self-upgrade
345
+ acceptance is manual and lives in section 21 of the
346
+ [manual runbook](./manual-testing-checklist.md).
347
+
348
+ ### Upgrade rehearsal gate
349
+
350
+ `tests/integration/upgrade-rehearsal/` installs the PREVIOUS published stable
351
+ `akm-cli` release as a real global npm package (real `npm pack` / `npm
352
+ install --global` into a throwaway prefix — see `scripts/package-install.ts`)
353
+ under the label `live`, drives it to build a realistic home — a filesystem
354
+ bundle, a git bundle (with an in-bundle symlink at its root), a website
355
+ bundle, an npm bundle, three scheduled tasks (two granted, one left
356
+ ungranted) plus a manual task, and a synced native (fake) crontab — then
357
+ installs the CANDIDATE build OVER `live`, in the SAME prefix: an in-place
358
+ swap, the same thing a real `npm i -g akm-cli@…`/`bun add -g` upgrade does,
359
+ not a side-by-side install. It then runs the CANDIDATE against that home
360
+ (`migrate status`/`apply`, `bundle list` with every bundle confirmed enabled,
361
+ `search`/`show`, `task sync` dry-run and real — plain, no `--rebind`, as an
362
+ upgrading user actually runs it — executing the generated cron command and
363
+ confirming it ran the candidate, `task run`, `health`, `improve --dry-run`), and
364
+ finally installs a separate untouched copy of the PREVIOUS release and runs
365
+ it back against the candidate-written home to prove read-back still works.
366
+ It exists because no other suite drives a real prior release against a real
367
+ candidate build: the symlink-abort regression fixed in 0.9.17-alpha.3
368
+ (`d76af0a7b`) went undetected by the full unit/integration suite,
369
+ `tests/release-check.sh`, and the Docker matrix, because no fixture combined
370
+ a git bundle with an in-bundle symlink, a website bundle, an npm bundle, an
371
+ ungranted task, and a real crontab row in one home. Plain `task sync` proves
372
+ clean specifically because the candidate lands inside the SAME prefix the
373
+ previous release's scheduler rows already point at — no launcher path moves,
374
+ so nothing needs rebinding; a side-by-side install (a separate prefix) would
375
+ need `--rebind` instead, which is not what an in-place package-manager
376
+ upgrade does. `tests/integration/previous-release-corpus.test.ts` covers
377
+ persisted-data shapes read in isolation; this gate covers the whole CLI
378
+ surface driven end to end across two real installed releases.
379
+
380
+ Run it locally with:
381
+
382
+ ```sh
383
+ bun run build
384
+ AKM_UPGRADE_REHEARSAL=1 TMPDIR=/tmp bun test --timeout=900000 tests/integration/upgrade-rehearsal/
385
+ ```
386
+
387
+ Unset (the default), the suite logs one line and skips — it never fails
388
+ "inconclusively" (#795): every missing capability (no `npm` on `PATH`, no
389
+ network reachable to resolve/fetch the previous release, no candidate build)
390
+ throws naming the fix instead. Env overrides:
391
+
392
+ - `AKM_UPGRADE_FROM=<version>` — pin the previous release instead of
393
+ resolving the highest published stable version below the candidate's
394
+ `package.json` version.
395
+ - `AKM_CANDIDATE_TARBALL=<path>` — use an already-packed candidate tarball
396
+ (`tests/release-check.sh` passes `$PACKAGE_CANDIDATE`) instead of running
397
+ `npm pack` on the working tree (which requires `dist/cli.js` — run
398
+ `bun run build` first).
399
+
400
+ Fetched previous-release tarballs are cached under
401
+ `${TMPDIR:-/tmp}/akm-upgrade-rehearsal/previous-release/<version>/` so repeat
402
+ runs do not re-hit the network. It is wired into CI as the `upgrade-rehearsal`
403
+ job (`.github/workflows/ci.yml`) and into `tests/release-check.sh` right
404
+ after packing the release candidate.
405
+
406
+ ## Coverage Gap Guide
407
+
408
+ This repo now has broad coverage across the major CLI, indexing, registry, and
409
+ semantic-search paths. Use this file as a current gap guide, not a greenfield
410
+ test plan.
411
+
412
+ ### Areas With Strong Existing Coverage
413
+
414
+ - database and scoring (`tests/integration/db.test.ts`, `tests/integration/db-scoring.test.ts`, `tests/integration/fts-field-weighting.test.ts`)
415
+ - search/show CLI surfaces (`tests/integration/commands/search-cli-envelope.test.ts`, `tests/integration/commands/show.test.ts`, and the other `search-*`/`show-*` suites under `tests/integration/`)
416
+ - registry install/search/update/list flows
417
+ - workflow, vault, and wiki behavior
418
+ - semantic status, vector search, and embedding config behavior
419
+ - CLI error handling and output shaping
420
+ - Docker install validation
421
+
422
+ ### Highest-Value Remaining Gaps
423
+
424
+ 1. corrupt or version-mismatched DB fallback behavior during search
425
+ 2. local model download and ONNX startup failures
426
+ 3. partial embedding-generation failures during indexing
427
+ 4. concurrent search/embedder behavior under load
428
+ 5. semantic readiness reporting parity between `setup`, `search`, and `info`
429
+ 6. broader platform CI for Alpine/musl, ARM, and Windows edge cases
430
+
431
+ ### When Adding Tests
432
+
433
+ - prefer focused `bun:test` files under `tests/`
434
+ - use isolated temp config/cache/stash dirs
435
+ - cover the user-visible CLI behavior when the risk is output shaping or command routing
436
+ - cover internal units directly when the risk is scoring, metadata extraction, or persistence
437
+
438
+ ### Useful Existing Suites To Extend
439
+
440
+ - `tests/integration/commands/search-cli-envelope.test.ts`
441
+ - `tests/integration/commands/show.test.ts`
442
+ - `tests/integration/vector-search.test.ts`
443
+ - `tests/integration/semantic-status.test.ts`
444
+ - `tests/setup-wizard.test.ts`, `tests/setup-scheduled-tasks.test.ts`
445
+ - `tests/integration/info-command.test.ts`
446
+ - `tests/integration/docker-install.test.ts`
@@ -0,0 +1,223 @@
1
+ # Architecture: The Workflow Engine
2
+
3
+ A workflow compiles to a frozen plan, persists run and unit state, dispatches
4
+ its work, verifies declared gates, and resumes without replaying completed
5
+ units. This page is the architecture-level reference for that engine — how a
6
+ run's plan is frozen and stored, how dispatch and resume actually work, how
7
+ one engine owns a run, and how isolated file-mutating units execute. For the
8
+ exact frontmatter/body syntax that produces the plan, see
9
+ [Workflow Schema](../reference/workflow-schema.md). For the day-to-day
10
+ commands that drive a run, see [Running Workflows](../guides/run-workflows.md).
11
+
12
+ > **`akm workflow run` is Experimental (see `STABILITY.md`), ungated, and the only
13
+ > execution surface.** It is the canonical start/resume/execute command; there is
14
+ > no separate external-driver protocol.
15
+
16
+ ## Frozen plans
17
+
18
+ The first `akm workflow run <ref>` compiles either peer source format
19
+ (Markdown or GitHub-Actions-style YAML) straight to the one plan type and
20
+ stores it as durable plan **`irVersion` 6** on the run row (`plan_json` +
21
+ `plan_hash`); a new start never emits an older version. `plan_ir_version` and
22
+ `plan_hash` are recorded provenance, not gates: a stored plan is decoded as it
23
+ is — irVersion 4 and 5 plans included — and one frozen by an older or newer
24
+ akm that still decodes simply runs (with one warning). A newer akm's plan that
25
+ does not decode is refused with a message naming "Upgrade akm".
26
+
27
+ The durable plan records `sourceHash`, the sha256 of the workflow source file
28
+ at freeze. It is used only for the resume warning below, never to refuse a
29
+ run.
30
+
31
+ Dispatch-significant material is immutable. The resolved request is frozen,
32
+ the resolved target is frozen, and runner selection is frozen.
33
+ Working directory (`cwd`) identity is frozen.
34
+ Git identity and its commit OID are frozen. The executable a unit runs is
35
+ resolved at dispatch, so upgrading a CLI (say, `claude`) never strands a run.
36
+ Exact models, inference, tools and authorization,
37
+ execution limits, parameter snapshots, command/script bytes, and verifier
38
+ selection therefore cannot drift under an in-flight run.
39
+
40
+ Workflow environment asset values are the narrow live-value exception within
41
+ authored workflow inputs.
42
+ The environment owner key set and secret-token topology are frozen.
43
+ Literal values remain frozen. Pass-through bindings
44
+ materialize at dispatch from the current process, and env/secret references
45
+ materialize their current values only after owner/topology checks. Durable
46
+ plans never store secret values or enable whole-process `inheritEnv`.
47
+
48
+ **A run executes the plan compiled at creation; edits to source need a new
49
+ run.** Resuming a run re-reads its workflow source only to warn, once, when
50
+ the source changed since the freeze — the run continues on the frozen plan.
51
+ Orchestration decisions are pure functions of the frozen plan, run params,
52
+ and journaled results.
53
+
54
+ ## Child workflows
55
+
56
+ A step that composes another workflow — directly (`uses: workflows/<ref>`)
57
+ or through a task whose own target is a workflow (`uses: tasks/<ref>`) —
58
+ freezes to a `child-workflow` frozen target. Unlike the `command`/`shell`/
59
+ `script` targets, a `child-workflow` target carries the child's **complete
60
+ frozen plan, embedded**: compiling the parent recursively compiles,
61
+ validates, and freezes each child in full — depth-first, all of it — before
62
+ the parent run is ever published. Nothing about a child is re-read at
63
+ dispatch time; the embedded plan is authoritative. See
64
+ [Workflow Schema: Child workflows](../reference/workflow-schema.md#child-workflows)
65
+ for the authoring-side view, including the three composition bounds (depth,
66
+ cycle, aggregate embedded bytes) enforced at freeze.
67
+
68
+ **Decoding.** An embedded child plan is decoded by the same structural
69
+ decoder as its parent, recursively. Its `planHash` and the target's
70
+ `contentHash` are recorded provenance, carried as data and never re-verified
71
+ against the bytes.
72
+
73
+ **The dispatch seam.** Dispatching a step whose target is
74
+ `kind: "child-workflow"` is the one branch point in
75
+ `dispatchJournaledAttempt` (`src/workflows/exec/native-executor.ts`) that
76
+ does not call the ordinary unit dispatcher: it calls
77
+ `driveChildWorkflowUnit` instead, with everything the composing unit already
78
+ resolved — the frozen target, the parent's dispatch context, the child's
79
+ resolved params, and the unit input hash. The branch sits **inside** the
80
+ existing retry loop, after the parent unit's attempt row is already claimed
81
+ `running` (so a crash between claiming that row and publishing the child
82
+ leaves a recoverable `running` parent unit and no orphaned child) and
83
+ **before** the ordinary post-dispatch journaling (redaction, attempt
84
+ finishing), which runs unchanged either way — a
85
+ child-workflow unit is journaled exactly like any other.
86
+
87
+ **The drive contract.** `driveChildWorkflowUnit` validates and resolves the
88
+ child's params through the same input-binding
89
+ resolution every frozen target uses, computes the child's identity key from
90
+ `{parentRunId, parentUnitId, unitInputHash}`, and publishes the child run —
91
+ idempotently: the same three inputs always resolve to the same child row,
92
+ so a retried or resumed composing step re-drives the run it already started
93
+ rather than starting a new one, and only a change to the composing step's
94
+ own inputs (params, an upstream step output it reads, or gate feedback from
95
+ a rejected verification loop) produces a different child. A child found
96
+ already `blocked` or `failed` is not re-driven — driving happens once per
97
+ call, and a terminal-but-unhealthy child surfaces through the status mapping
98
+ below instead. The child's final status maps onto the composing unit, and
99
+ from there onto the parent step and run, exactly as described in [Workflow
100
+ Schema: Child execution](../reference/workflow-schema.md#child-execution).
101
+
102
+ **Why `runWorkflowSteps` is reused, not a second executor.** The child drive
103
+ calls the exact same exported entry point `akm workflow run` calls —
104
+ `runWorkflowSteps(options)`, pointed at the child's run id as `target` —
105
+ with no special-casing for "this target is a child": resolving a run id,
106
+ decoding the stored plan, taking that run's own lock, and walking its spine
107
+ through `completeWorkflowStep` are identical to the top-level path. That
108
+ reuse is what makes child run locks arbitrate two-parent contention with no
109
+ new mechanism, and what makes a resumed parent skip a completed child step
110
+ with zero dispatcher calls. The child drive passes a no-op
111
+ `disposeDispatchResources` (the parent's `finally` remains the sole owner of
112
+ the process-lifecycle drain for the whole process) and no `maxSteps` or
113
+ `maxRetries` (the parent's own budgets count only its own spine steps). The
114
+ lower-level `driveRun` that `runWorkflowSteps` wraps stays module-private —
115
+ reaching for it directly, instead of the public entry point, would be
116
+ exactly the second executor this design avoids.
117
+
118
+ **Why `hashVersion` is 7, and why child composition did not move it.** The
119
+ version prefix mixed into a unit's input hash is 7
120
+ (`src/workflows/exec/step-work.ts`); 0.9.2 bumped it — a single, durable
121
+ 5 → 7 step, since every released tag on the line carries 5 — when
122
+ `taskInputs`, the resolved values of a composed task's reference-kind
123
+ `inputBindings`, joined the preimage (see [ADR
124
+ 0002](decisions/0002-unit-reuse-and-input-hash-scope.md)). Child composition
125
+ itself contributed nothing to that bump: the parent unit's input-hash
126
+ preimage already covers everything the child drive depends on — the frozen
127
+ target carries the child's ref, plan hash, content hash, binding mode, and
128
+ its entire embedded plan, so any change anywhere in the child changes the
129
+ parent unit's own input hash transitively. The child run id (minted at
130
+ dispatch) and its result (the child's last step output) are unit *outputs*, not inputs, so neither
131
+ belongs in the preimage — adding either would be a hashing-boundary
132
+ violation, not a fix.
133
+
134
+ ## Resume skips completed units
135
+
136
+ Resume never re-reads config or the asset index, and reads the workflow
137
+ source only for the drift warning above. It consumes the frozen plan plus
138
+ the journaled attempts and results. A stored plan that this akm cannot
139
+ decode is not an error to fix in place: `akm workflow run` marks such a run
140
+ abandoned (status `failed`) and says to start a new run with
141
+ `akm workflow run <ref>`; `akm workflow status`, `list`, and `abandon` never
142
+ read the plan at all. A plan frozen by a newer akm that this one cannot
143
+ decode is left untouched, and the message names upgrading akm.
144
+
145
+ Every dispatched unit is journaled under a content-derived identity — the
146
+ node id plus a hash of its item for a map unit (`<node>:solo` otherwise) —
147
+ together with an input hash over everything the unit was asked to do (its
148
+ frozen instructions and target, declared `inputs:` artifacts, the params
149
+ snapshot, gate feedback). On
150
+ re-run, a unit whose journal row is `completed` is **reused**, never
151
+ re-dispatched; a failed or missing unit is dispatched live. The recorded
152
+ input hash is informational: a completed unit stays completed even when the
153
+ params row or an upstream artifact changed since — a fresh run is what
154
+ recomputes it.
155
+
156
+ ## Durable attempts and at-least-once dispatch
157
+
158
+ Workflow dispatch is at-least-once. Every unit has a stable content-derived
159
+ unit id and an append-only sequence of attempts.
160
+ A crash reclaim reuses the same stable dispatchId for the interrupted attempt.
161
+ An explicit retry gets a new dispatchId under one stable unit id and increments the attempt number.
162
+
163
+ One driver per run (below) keeps a second engine off a run, and a finished
164
+ attempt accepts no second terminal write, but neither can prove whether an
165
+ external process completed immediately before a crash. An ambiguous crash
166
+ outcome may re-run and can produce a duplicate side effect. Workflow actions
167
+ should be idempotent or use the stable dispatch identity as their own
168
+ deduplication key.
169
+
170
+ ## One engine drives a run (the run lock)
171
+
172
+ `akm workflow run` takes the run's **lock file** before reading the plan or
173
+ dispatching anything: one `O_EXCL` file per run id under the data directory
174
+ (`workflow-run-locks/<run id>.lock`, next to `state.db`), recording the
175
+ holder's pid, released when the invocation exits. A second `workflow run`
176
+ against a run another live process holds refuses up front with
177
+ `RUN_LEASE_HELD` (exit 75), naming the holder pid. A lock whose holder pid is
178
+ dead is reclaimed at once, so a crashed engine never wedges a run; nothing
179
+ expires by age and nothing renews. `workflow status` and `list` never take
180
+ the lock.
181
+
182
+ ## Concurrency limits
183
+
184
+ Native fan-out (`akm workflow run`) uses the minimum of four limits: the
185
+ map's declared `concurrency`, the run's frozen `workflow.maxConcurrency`, the
186
+ selected frozen LLM engine's `concurrency` (including an SDK engine's
187
+ fallback LLM), and the current host's CPU-derived safety limit. Reapplying
188
+ host safety keeps a run safe when it resumes on a smaller machine.
189
+
190
+ - **Unset (default):** the CPU-derived value `min(16, max(1, cores − 2))` — a
191
+ conservative default that leaves headroom on the host and matches the
192
+ original Claude-Code cap.
193
+ - **Set:** an explicit positive integer, clamped when frozen to `[1, 64]`
194
+ (values above 64 are clamped down, never rejected, so one config shared
195
+ across machines with different core counts never hard-fails).
196
+
197
+ ```console
198
+ $ akm config set workflow.maxConcurrency 8 # raise the frozen workflow limit
199
+ $ akm config get workflow.maxConcurrency
200
+ 8
201
+ ```
202
+
203
+ A workflow that fans out is authorizing **N parallel agents**, not one — see
204
+ [Running Workflows: workflow sources are executed code](../guides/run-workflows.md#security-workflow-sources-are-executed-code)
205
+ for what that means for trust.
206
+
207
+ ## Run scope and persistence
208
+
209
+ Run state (`plan_json`, `plan_hash`, step statuses, and the unit journal)
210
+ persists in the project's `state.db`; the per-run lock file sits beside it. Run state is scoped to
211
+ the current project directory — the nearest `.akm/config.json`, git root,
212
+ bundle root, or current directory — so the same workflow can run
213
+ independently in separate projects, and `akm workflow list`/`status` without
214
+ an explicit run id only ever see runs in that scope.
215
+
216
+ ## See also
217
+
218
+ - [Workflow Schema](../reference/workflow-schema.md) — exact frontmatter,
219
+ refs, gates, and outputs syntax
220
+ - [Running Workflows](../guides/run-workflows.md) — start, inspect, resume,
221
+ and abandon a run
222
+ - [Author's Guide: Writing Workflows](../guides/author-workflows.md) — writing
223
+ and testing a workflow definition