akm-cli 0.10.261012-beta → 0.10.261014-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 (518) hide show
  1. package/CHANGELOG.md +710 -3
  2. package/README.md +15 -0
  3. package/SECURITY.md +11 -10
  4. package/STABILITY.md +47 -51
  5. package/dist/assets/hints/cli-hints-full.md +21 -19
  6. package/dist/assets/hints/cli-hints-short.md +3 -4
  7. package/dist/assets/opencode/akm-plugin.js +177 -0
  8. package/dist/assets/stash-skeleton/README.md +1 -1
  9. package/dist/assets/tasks/core/improve.yml +1 -1
  10. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
  11. package/dist/assets/ui/config.js +27 -10
  12. package/dist/assets/workflows/workflow-template.md +2 -2
  13. package/dist/cli/clack.js +3 -1
  14. package/dist/cli/selection.js +33 -0
  15. package/dist/cli/shared.js +14 -1
  16. package/dist/cli/unknown-flags.js +6 -37
  17. package/dist/cli.js +69 -48
  18. package/dist/commands/agent/agent-dispatch.js +17 -25
  19. package/dist/commands/agent/contribute-cli.js +9 -8
  20. package/dist/commands/command/command-cli.js +4 -8
  21. package/dist/commands/command/command-execution.js +25 -39
  22. package/dist/commands/command/execution-source-loader.js +10 -14
  23. package/dist/commands/completions.js +1 -1
  24. package/dist/commands/config-cli.js +14 -5
  25. package/dist/commands/env/child-env.js +12 -14
  26. package/dist/commands/env/env-binding.js +47 -58
  27. package/dist/commands/env/env-cli.js +22 -24
  28. package/dist/commands/env/env.js +10 -58
  29. package/dist/commands/env/secret-cli.js +11 -29
  30. package/dist/commands/env/secret.js +3 -10
  31. package/dist/commands/health/checks.js +10 -849
  32. package/dist/commands/health/connections-and-harnesses-check.js +109 -0
  33. package/dist/commands/health/egress.js +3 -3
  34. package/dist/commands/health/html-report.js +9 -10
  35. package/dist/commands/health/plugin-staleness.js +18 -11
  36. package/dist/commands/health/report-view-model.js +16 -12
  37. package/dist/commands/health/scheduler-binary.js +1 -1
  38. package/dist/commands/health/semantic-search-check.js +85 -0
  39. package/dist/commands/health/type-directory-check.js +0 -3
  40. package/dist/commands/health.js +30 -42
  41. package/dist/commands/improve/consolidate/pair-pass.js +10 -25
  42. package/dist/commands/improve/consolidate.js +10 -15
  43. package/dist/commands/improve/distill.js +5 -17
  44. package/dist/commands/improve/eligibility.js +1 -3
  45. package/dist/commands/improve/execution.js +37 -40
  46. package/dist/commands/improve/extract-cli.js +6 -11
  47. package/dist/commands/improve/extract-prompt.js +2 -2
  48. package/dist/commands/improve/extract.js +67 -97
  49. package/dist/commands/improve/improve-cli.js +22 -128
  50. package/dist/commands/improve/improve-report.js +1 -1
  51. package/dist/commands/improve/improve-strategies.js +25 -108
  52. package/dist/commands/improve/improve.js +10 -14
  53. package/dist/commands/improve/loop-stages.js +3 -0
  54. package/dist/commands/improve/memory/memory-improve.js +1 -1
  55. package/dist/commands/improve/preparation.js +8 -13
  56. package/dist/commands/improve/reflect.js +203 -332
  57. package/dist/commands/improve/retrieval-scope.js +1 -1
  58. package/dist/commands/improve/session-asset.js +3 -2
  59. package/dist/commands/improve/stage.js +87 -115
  60. package/dist/commands/lint/base-linter.js +3 -3
  61. package/dist/commands/lint/env-key-rules.js +7 -6
  62. package/dist/commands/lint/index.js +3 -3
  63. package/dist/commands/models-cli.js +103 -63
  64. package/dist/commands/proposal/drain.js +26 -39
  65. package/dist/commands/proposal/proposal-cli.js +14 -18
  66. package/dist/commands/proposal/propose-cli.js +4 -2
  67. package/dist/commands/proposal/propose.js +37 -64
  68. package/dist/commands/proposal/repository.js +17 -17
  69. package/dist/commands/proposal/validators/proposal-validators.js +3 -6
  70. package/dist/commands/read/curate.js +10 -6
  71. package/dist/commands/read/registry-search.js +2 -48
  72. package/dist/commands/read/search-cli.js +1 -8
  73. package/dist/commands/read/search.js +5 -6
  74. package/dist/commands/read/show.js +6 -29
  75. package/dist/commands/remember.js +25 -40
  76. package/dist/commands/sources/add-cli.js +8 -63
  77. package/dist/commands/sources/bundle-cli.js +8 -9
  78. package/dist/commands/sources/bundle-config-ops.js +2 -2
  79. package/dist/commands/sources/info.js +12 -1
  80. package/dist/commands/sources/init.js +1 -1
  81. package/dist/commands/sources/installed-stashes.js +119 -63
  82. package/dist/commands/sources/migration-help.js +1 -1
  83. package/dist/commands/sources/plugin-upgrade.js +8 -15
  84. package/dist/commands/sources/schema-repair.js +4 -10
  85. package/dist/commands/sources/source-add.js +2 -2
  86. package/dist/commands/sources/source-clone.js +31 -7
  87. package/dist/commands/sources/source-manage.js +4 -4
  88. package/dist/commands/targets.js +175 -0
  89. package/dist/commands/tasks/explain.js +104 -69
  90. package/dist/commands/tasks/tasks-cli.js +9 -11
  91. package/dist/commands/tasks/tasks.js +75 -97
  92. package/dist/commands/ui/api.js +11 -3
  93. package/dist/commands/ui/redact.js +5 -31
  94. package/dist/commands/ui/workspace-actions.js +1 -1
  95. package/dist/commands/workflow/plan.js +48 -9
  96. package/dist/commands/workflow-cli.js +40 -45
  97. package/dist/core/adapter/adapters/agent-skills-adapter.js +10 -11
  98. package/dist/core/adapter/adapters/akm-adapter.js +36 -41
  99. package/dist/core/adapter/adapters/akm-lint.js +10 -12
  100. package/dist/core/adapter/adapters/akm-metadata.js +2 -2
  101. package/dist/core/adapter/adapters/akm-task-adapter.js +8 -9
  102. package/dist/core/adapter/adapters/akm-workflow-adapter.js +5 -5
  103. package/dist/core/adapter/adapters/claude-adapter.js +1 -1
  104. package/dist/core/adapter/adapters/dotenv-adapter.js +7 -6
  105. package/dist/core/adapter/adapters/generic-files-adapter.js +5 -5
  106. package/dist/core/adapter/adapters/index.js +3 -4
  107. package/dist/core/adapter/adapters/llm-wiki-adapter.js +12 -14
  108. package/dist/core/adapter/adapters/okf-adapter.js +8 -10
  109. package/dist/core/adapter/adapters/opencode-adapter.js +1 -1
  110. package/dist/core/adapter/adapters/shared.js +3 -3
  111. package/dist/core/adapter/adapters/tool-dir-shared.js +7 -25
  112. package/dist/core/adapter/adapters/website-snapshot-adapter.js +3 -3
  113. package/dist/core/adapter/detect-adapter.js +1 -1
  114. package/dist/core/adapter/execution-source.js +13 -35
  115. package/dist/core/adapter/registry.js +1 -1
  116. package/dist/core/adapter/validate-context.js +2 -4
  117. package/dist/core/asset/asset-placement.js +1 -1
  118. package/dist/core/asset/asset-ref.js +3 -3
  119. package/dist/core/asset/resolve-ref.js +5 -0
  120. package/dist/core/bundle-rename.js +12 -4
  121. package/dist/core/closest-match.js +37 -0
  122. package/dist/core/common.js +37 -57
  123. package/dist/core/config/config-io.js +26 -18
  124. package/dist/core/config/config-schema.js +19 -106
  125. package/dist/core/config/config-sources.js +3 -3
  126. package/dist/core/config/config-types.js +4 -4
  127. package/dist/core/config/config-walker.js +50 -77
  128. package/dist/core/config/config.js +438 -109
  129. package/dist/core/config/convert-engine-references.js +114 -0
  130. package/dist/core/config/convert-engines-shared.js +40 -0
  131. package/dist/core/config/convert-engines.js +300 -0
  132. package/dist/core/config/convert-models-overlay.js +137 -0
  133. package/dist/core/config/credentials.js +304 -0
  134. package/dist/core/config/engine-semantics.js +3 -3
  135. package/dist/core/config/migrate-keys.js +222 -0
  136. package/dist/core/config/model-aliases.js +37 -0
  137. package/dist/core/config/models-file.js +34 -0
  138. package/dist/core/config/retired-engines.js +53 -0
  139. package/dist/core/config/schema/connections.js +41 -0
  140. package/dist/core/config/schema/embedding.js +2 -2
  141. package/dist/core/config/schema/harnesses.js +41 -0
  142. package/dist/core/config/schema/improve-processes.js +9 -28
  143. package/dist/core/config/schema/improve.js +36 -1
  144. package/dist/core/config/schema/index-config.js +18 -20
  145. package/dist/core/config/schema/primitives.js +42 -17
  146. package/dist/core/config/schema/search.js +6 -11
  147. package/dist/core/config/schema/sources-bundles.js +9 -9
  148. package/dist/core/config/schema/workflow.js +2 -6
  149. package/dist/core/config/unusable-entries.js +66 -0
  150. package/dist/core/content-safety.js +3 -6
  151. package/dist/core/endpoint-url.js +47 -0
  152. package/dist/core/env-secret-ref.js +84 -73
  153. package/dist/core/errors.js +10 -16
  154. package/dist/core/extra-params.js +3 -3
  155. package/dist/core/improve-result.js +8 -9
  156. package/dist/core/json-schema.js +1 -1
  157. package/dist/core/lesson-lint.js +1 -1
  158. package/dist/core/llm-inference.js +80 -0
  159. package/dist/core/parse.js +2 -2
  160. package/dist/core/paths.js +33 -10
  161. package/dist/core/recognition-util.js +8 -10
  162. package/dist/core/redaction.js +94 -55
  163. package/dist/core/ref-token.js +82 -0
  164. package/dist/core/secret-value.js +14 -0
  165. package/dist/core/state/migrations.js +17 -22
  166. package/dist/core/structured.js +2 -68
  167. package/dist/core/subprocess.js +63 -22
  168. package/dist/core/type-presentation.js +10 -14
  169. package/dist/core/write-source.js +20 -4
  170. package/dist/execution/input-contract.js +3 -6
  171. package/dist/execution/notices.js +49 -0
  172. package/dist/execution/resolved-request.js +24 -40
  173. package/dist/execution/source.js +21 -45
  174. package/dist/execution/target-ref.js +2 -2
  175. package/dist/indexer/bundle-identity-guard.js +6 -5
  176. package/dist/indexer/ensure-index.js +1 -1
  177. package/dist/indexer/index-writer-lock.js +1 -1
  178. package/dist/indexer/indexer.js +46 -42
  179. package/dist/indexer/installations.js +12 -22
  180. package/dist/indexer/lookup/adapter-concept-owner.js +40 -14
  181. package/dist/indexer/materialize-embeddings.js +20 -16
  182. package/dist/indexer/passes/memory-inference.js +21 -50
  183. package/dist/indexer/passes/metadata.js +5 -5
  184. package/dist/indexer/scan/doc-to-entry.js +1 -1
  185. package/dist/indexer/scan/drain-dir.js +9 -11
  186. package/dist/indexer/search/db-search.js +9 -7
  187. package/dist/indexer/search/search-source.js +42 -22
  188. package/dist/indexer/usage/usage-events.js +2 -3
  189. package/dist/indexer/walk/index-context.js +2 -1
  190. package/dist/indexer/walk/matchers.js +3 -11
  191. package/dist/indexer/walk/path-resolver.js +13 -68
  192. package/dist/indexer/walk/walker.js +32 -26
  193. package/dist/integrations/agent/akm-read-tools.js +81 -0
  194. package/dist/integrations/agent/config.js +1 -1
  195. package/dist/integrations/agent/detect.js +32 -36
  196. package/dist/integrations/agent/execution.js +130 -428
  197. package/dist/integrations/agent/index.js +1 -1
  198. package/dist/integrations/agent/profiles.js +24 -28
  199. package/dist/integrations/agent/prompts.js +17 -30
  200. package/dist/integrations/agent/request-lowering.js +67 -101
  201. package/dist/integrations/agent/resolution.js +332 -0
  202. package/dist/integrations/agent/runner-dispatch.js +156 -181
  203. package/dist/integrations/agent/runner.js +20 -70
  204. package/dist/integrations/agent/runtime-port.js +4 -0
  205. package/dist/integrations/agent/runtime.js +10 -0
  206. package/dist/integrations/agent/spawn.js +65 -190
  207. package/dist/integrations/harnesses/aider/index.js +19 -39
  208. package/dist/integrations/harnesses/amazonq/index.js +17 -32
  209. package/dist/integrations/harnesses/claude/index.js +59 -28
  210. package/dist/integrations/harnesses/claude/session-log.js +7 -5
  211. package/dist/integrations/harnesses/codex/index.js +19 -31
  212. package/dist/integrations/harnesses/copilot/index.js +17 -35
  213. package/dist/integrations/harnesses/gemini/index.js +18 -34
  214. package/dist/integrations/harnesses/harness.js +36 -0
  215. package/dist/integrations/harnesses/index.js +20 -51
  216. package/dist/integrations/harnesses/opencode/agent-builder.js +132 -100
  217. package/dist/integrations/harnesses/opencode/index.js +11 -33
  218. package/dist/integrations/harnesses/opencode/roots.js +50 -0
  219. package/dist/integrations/harnesses/opencode/runtime/binary.js +206 -0
  220. package/dist/integrations/harnesses/opencode/runtime/command.js +152 -0
  221. package/dist/integrations/harnesses/opencode/runtime/index.js +177 -0
  222. package/dist/integrations/harnesses/opencode/runtime/tar.js +107 -0
  223. package/dist/integrations/harnesses/opencode/session-log-v1.js +15 -7
  224. package/dist/integrations/harnesses/opencode/session-log-v2.js +72 -48
  225. package/dist/integrations/harnesses/opencode/session-log.js +58 -137
  226. package/dist/integrations/harnesses/opencode/version.js +34 -53
  227. package/dist/integrations/harnesses/openhands/index.js +13 -37
  228. package/dist/integrations/harnesses/pi/index.js +21 -32
  229. package/dist/integrations/lockfile.js +1 -1
  230. package/dist/integrations/session-logs/index.js +11 -31
  231. package/dist/llm/client.js +93 -111
  232. package/dist/llm/embedder.js +19 -34
  233. package/dist/llm/embedders/connection.js +31 -0
  234. package/dist/llm/embedders/local-model-files.js +56 -0
  235. package/dist/llm/embedders/local.js +146 -115
  236. package/dist/llm/embedders/remote.js +26 -23
  237. package/dist/llm/embedders/types.js +1 -1
  238. package/dist/llm/index-passes.js +33 -39
  239. package/dist/llm/memory-infer.js +67 -77
  240. package/dist/llm/model-list.js +35 -0
  241. package/dist/llm/rerank-client.js +8 -14
  242. package/dist/llm/structured-call.js +45 -99
  243. package/dist/llm/structured.js +60 -0
  244. package/dist/output/renderers.js +2 -8
  245. package/dist/output/shapes/helpers.js +18 -44
  246. package/dist/output/shapes/passthrough.js +1 -0
  247. package/dist/output/shapes.js +1 -7
  248. package/dist/output/text/command-format.js +41 -39
  249. package/dist/output/text/health-format.js +8 -2
  250. package/dist/output/text/helpers.js +1 -1
  251. package/dist/output/text/migrate.js +12 -0
  252. package/dist/output/text/models.js +3 -2
  253. package/dist/output/text/registry-commands.js +1 -2
  254. package/dist/output/text/show-directives.js +16 -28
  255. package/dist/output/text/show-format.js +0 -2
  256. package/dist/output/text/targets-table.js +70 -0
  257. package/dist/output/text/workflow-format.js +44 -15
  258. package/dist/output/text.js +1 -1
  259. package/dist/registry/providers/skills-sh.js +1 -28
  260. package/dist/registry/providers/static-index.js +1 -71
  261. package/dist/runtime.js +6 -2
  262. package/dist/scripts/akm-migrate-node.js +47095 -44905
  263. package/dist/scripts/akm-migrate.js +46946 -44755
  264. package/dist/setup/detect.js +28 -273
  265. package/dist/setup/endpoint.js +36 -0
  266. package/dist/setup/semantic-assets.js +13 -19
  267. package/dist/setup/setup-flags.js +77 -0
  268. package/dist/setup/setup-plan.js +144 -0
  269. package/dist/setup/setup.js +134 -358
  270. package/dist/setup/steps/connection-shared.js +49 -101
  271. package/dist/setup/steps/connection.js +121 -524
  272. package/dist/setup/steps/embeddings.js +151 -0
  273. package/dist/setup/steps/harnesses.js +118 -0
  274. package/dist/setup/steps/platforms.js +2 -81
  275. package/dist/setup/steps/tasks.js +1 -2
  276. package/dist/setup/steps.js +10 -0
  277. package/dist/setup/summary.js +67 -0
  278. package/dist/sources/freshness.js +16 -21
  279. package/dist/sources/providers/git-provider.js +2 -9
  280. package/dist/sources/providers/provider-utils.js +13 -5
  281. package/dist/sources/resolve.js +12 -16
  282. package/dist/sources/snapshot-fetchers/robots.js +11 -12
  283. package/dist/sources/snapshot-fetchers/secret-seam.js +2 -4
  284. package/dist/sources/snapshot-fetchers/website-ingest.js +8 -15
  285. package/dist/sources/snapshot-fetchers/x.js +1 -1
  286. package/dist/standalone/onnxruntime-library.js +52 -0
  287. package/dist/storage/repositories/improve-ledger-repository.js +1 -1
  288. package/dist/storage/repositories/improve-runs-repository.js +0 -13
  289. package/dist/storage/repositories/index-entries-repository.js +2 -2
  290. package/dist/storage/repositories/proposals-repository.js +2 -2
  291. package/dist/storage/repositories/task-history-repository.js +2 -2
  292. package/dist/storage/repositories/workflow-runs-repository.js +44 -129
  293. package/dist/storage/sqlite-read-snapshot.js +33 -29
  294. package/dist/tasks/embedded.js +1 -1
  295. package/dist/tasks/log-redaction.js +7 -119
  296. package/dist/tasks/prepare/prepare-support.js +8 -7
  297. package/dist/tasks/prepare/prepare.js +8 -9
  298. package/dist/tasks/prepare/script-capture.js +9 -25
  299. package/dist/tasks/run/attempt-lifecycle.js +17 -35
  300. package/dist/tasks/run/load-task.js +54 -27
  301. package/dist/tasks/run/run-command-task.js +15 -10
  302. package/dist/tasks/run/run-native-task.js +8 -21
  303. package/dist/tasks/run/run-task.js +5 -8
  304. package/dist/tasks/run/run-workflow-task.js +14 -21
  305. package/dist/tasks/run/task-history.js +9 -17
  306. package/dist/tasks/run/task-log.js +1 -5
  307. package/dist/tasks/scheduler-invocation.js +13 -18
  308. package/dist/tasks/scheduler-sync.js +0 -1
  309. package/dist/tasks/source/bounded-document.js +31 -117
  310. package/dist/tasks/source/parse-task-source.js +0 -1
  311. package/dist/tasks/source/project-v4.js +5 -3
  312. package/dist/tasks/source/task-input-diagnostics.js +3 -4
  313. package/dist/tasks/source/task-source-v4.js +48 -72
  314. package/dist/tasks/source-v3.js +2 -5
  315. package/dist/tasks/task-run-reserved-flags.js +1 -2
  316. package/dist/workflows/authoring/authoring.js +2 -7
  317. package/dist/workflows/compile.js +1 -15
  318. package/dist/workflows/concurrency-policy.js +4 -4
  319. package/dist/workflows/exec/child-workflow.js +1 -4
  320. package/dist/workflows/exec/dispatch-redaction.js +35 -86
  321. package/dist/workflows/exec/environment.js +13 -77
  322. package/dist/workflows/exec/exec-unit.js +14 -55
  323. package/dist/workflows/exec/frozen-judge.js +26 -28
  324. package/dist/workflows/exec/native-executor.js +126 -71
  325. package/dist/workflows/exec/run-workflow.js +38 -42
  326. package/dist/workflows/exec/step-work.js +13 -17
  327. package/dist/workflows/exec/unit-dispatch.js +7 -21
  328. package/dist/workflows/freeze/environment.js +14 -119
  329. package/dist/workflows/freeze/freeze.js +14 -33
  330. package/dist/workflows/freeze/step-values.js +6 -13
  331. package/dist/workflows/freeze/targets/child-workflow.js +3 -5
  332. package/dist/workflows/freeze/targets/command.js +9 -15
  333. package/dist/workflows/freeze/targets/shell.js +0 -3
  334. package/dist/workflows/freeze/task-bindings.js +0 -1
  335. package/dist/workflows/parser.js +50 -59
  336. package/dist/workflows/plan.js +8 -2
  337. package/dist/workflows/renderer.js +83 -9
  338. package/dist/workflows/resource-limits.js +2 -2
  339. package/dist/workflows/runtime/run-plan.js +38 -23
  340. package/dist/workflows/runtime/runs.js +55 -93
  341. package/dist/workflows/runtime/workflow-asset-loader.js +55 -86
  342. package/dist/workflows/source-files.js +7 -19
  343. package/docs/README.md +10 -16
  344. package/docs/architecture/README.md +2 -37
  345. package/docs/architecture/adapters.md +2 -2
  346. package/docs/architecture/akm-core-principles.md +256 -118
  347. package/docs/architecture/architecture.md +283 -99
  348. package/docs/architecture/improvement.md +8 -2
  349. package/docs/architecture/internals/classification.md +1 -3
  350. package/docs/architecture/internals/fresh-host-rebuild-runbook.md +7 -6
  351. package/docs/architecture/internals/health-advisories.md +35 -74
  352. package/docs/architecture/internals/improve-workflow.md +27 -26
  353. package/docs/architecture/internals/indexing.md +3 -3
  354. package/docs/architecture/internals/storage-locations.md +48 -15
  355. package/docs/architecture/persisted-data-compat.md +10 -6
  356. package/docs/architecture/specs/okf-support.md +9 -11
  357. package/docs/architecture/specs/ref.md +7 -9
  358. package/docs/architecture/testing/testing-workflow.md +172 -52
  359. package/docs/architecture/workflow-engine.md +51 -34
  360. package/docs/guides/README.md +0 -1
  361. package/docs/guides/author-bundles.md +15 -20
  362. package/docs/guides/author-workflows.md +93 -71
  363. package/docs/guides/bundles.md +20 -16
  364. package/docs/guides/discover-and-load.md +1 -1
  365. package/docs/guides/getting-started.md +49 -3
  366. package/docs/guides/improve-the-library.md +10 -4
  367. package/docs/guides/recipes/headless-install.md +11 -16
  368. package/docs/guides/run-workflows.md +29 -20
  369. package/docs/guides/scheduling.md +2 -2
  370. package/docs/guides/use-with-any-agent.md +20 -22
  371. package/docs/integration/bundling-akm.md +19 -9
  372. package/docs/maintainers/README.md +2 -6
  373. package/docs/maintainers/release-checklist.md +73 -126
  374. package/docs/migration/README.md +10 -3
  375. package/docs/migration/release-notes/0.10.0.md +81 -16
  376. package/docs/migration/release-notes/0.6.0.md +1 -1
  377. package/docs/migration/release-notes/0.7.0.md +1 -1
  378. package/docs/migration/release-notes/0.9.0.md +1 -1
  379. package/docs/migration/release-notes/README.md +1 -1
  380. package/docs/migration/v0.9-to-v0.10.md +300 -60
  381. package/docs/migration/v0.9.1-to-v0.9.2.md +6 -5
  382. package/docs/posts/config-v2-lessons-16.md +1 -1
  383. package/docs/posts/llm-mode-reflect-13.md +1 -1
  384. package/docs/posts/release-0.6.0.md +11 -11
  385. package/docs/posts/release-0.8.0.md +4 -4
  386. package/docs/posts/workflows-vaults-09.md +1 -1
  387. package/docs/reference/README.md +1 -1
  388. package/docs/reference/asset-types.md +2 -2
  389. package/docs/reference/cli.md +477 -388
  390. package/docs/reference/configuration.md +569 -550
  391. package/docs/reference/data-and-telemetry.md +9 -6
  392. package/docs/reference/env-and-secrets.md +72 -15
  393. package/docs/reference/refs.md +3 -20
  394. package/docs/reference/registry.md +12 -38
  395. package/docs/reference/supported-formats.md +1 -1
  396. package/docs/reference/tasks.md +22 -11
  397. package/docs/reference/ui-api.md +14 -9
  398. package/docs/reference/workflow-schema.md +199 -154
  399. package/docs/reference/workflows.md +4 -6
  400. package/package.json +9 -11
  401. package/schemas/akm-config.json +1696 -2922
  402. package/schemas/akm-task.json +4 -4
  403. package/schemas/akm-workflow.json +36 -9
  404. package/ROADMAP.md +0 -112
  405. package/dist/assets/models.json +0 -35
  406. package/dist/commands/health/engine-usage.js +0 -45
  407. package/dist/commands/sources/dangerous-env-audit.js +0 -134
  408. package/dist/core/activation-policy.js +0 -67
  409. package/dist/core/config/schema/engines.js +0 -160
  410. package/dist/core/config/schema/execution.js +0 -23
  411. package/dist/core/spawn-env.js +0 -268
  412. package/dist/execution/directory-identity.js +0 -78
  413. package/dist/integrations/agent/builder-shared.js +0 -33
  414. package/dist/integrations/agent/builders.js +0 -43
  415. package/dist/integrations/agent/engine-fallback.js +0 -59
  416. package/dist/integrations/agent/engine-resolution.js +0 -333
  417. package/dist/integrations/agent/model-map.js +0 -475
  418. package/dist/integrations/harnesses/aider/agent-builder.js +0 -107
  419. package/dist/integrations/harnesses/aider/result-extractor.js +0 -53
  420. package/dist/integrations/harnesses/amazonq/agent-builder.js +0 -138
  421. package/dist/integrations/harnesses/amazonq/result-extractor.js +0 -48
  422. package/dist/integrations/harnesses/claude/agent-builder.js +0 -106
  423. package/dist/integrations/harnesses/claude/config-import.js +0 -67
  424. package/dist/integrations/harnesses/claude/result-extractor.js +0 -67
  425. package/dist/integrations/harnesses/codex/agent-builder.js +0 -150
  426. package/dist/integrations/harnesses/codex/result-extractor.js +0 -110
  427. package/dist/integrations/harnesses/copilot/agent-builder.js +0 -117
  428. package/dist/integrations/harnesses/copilot/result-extractor.js +0 -178
  429. package/dist/integrations/harnesses/gemini/agent-builder.js +0 -114
  430. package/dist/integrations/harnesses/gemini/result-extractor.js +0 -149
  431. package/dist/integrations/harnesses/opencode/config-import.js +0 -149
  432. package/dist/integrations/harnesses/opencode/model-config.js +0 -33
  433. package/dist/integrations/harnesses/opencode/model-work-agent.js +0 -115
  434. package/dist/integrations/harnesses/opencode/session-log-types.js +0 -12
  435. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -44
  436. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +0 -1052
  437. package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +0 -199
  438. package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +0 -254
  439. package/dist/integrations/harnesses/opencode-sdk/wire.js +0 -66
  440. package/dist/integrations/harnesses/openhands/agent-builder.js +0 -120
  441. package/dist/integrations/harnesses/openhands/result-extractor.js +0 -135
  442. package/dist/integrations/harnesses/pi/agent-builder.js +0 -89
  443. package/dist/integrations/harnesses/pi/result-extractor.js +0 -168
  444. package/dist/integrations/harnesses/shared.js +0 -18
  445. package/dist/integrations/harnesses/types.js +0 -55
  446. package/dist/llm/feature-gate.js +0 -115
  447. package/dist/output/shapes/models-list.js +0 -16
  448. package/dist/output/shapes/registry-search.js +0 -10
  449. package/dist/setup/detected-engines.js +0 -136
  450. package/dist/setup/engine-config.js +0 -97
  451. package/dist/setup/harness-config-import.js +0 -47
  452. package/dist/setup/providers.js +0 -14
  453. package/dist/setup/steps/semantic.js +0 -39
  454. package/dist/workflows/authoring/scope-key.js +0 -79
  455. package/dist/workflows/exec/lowering-notices.js +0 -23
  456. package/dist/workflows/source-semantics.js +0 -110
  457. package/docs/architecture/0.10-process-rules.md +0 -832
  458. package/docs/architecture/akm-architecture-decision-history.md +0 -2055
  459. package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +0 -550
  460. package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +0 -72
  461. package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +0 -142
  462. package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +0 -189
  463. package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +0 -97
  464. package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +0 -108
  465. package/docs/architecture/decisions/0006-task-source-version-routing.md +0 -124
  466. package/docs/architecture/decisions/0007-workflow-composition-bounds.md +0 -83
  467. package/docs/architecture/decisions/0008-task-binding-normalization.md +0 -88
  468. package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +0 -80
  469. package/docs/architecture/decisions/0010-driver-protocol-cut.md +0 -36
  470. package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +0 -125
  471. package/docs/architecture/decisions/README.md +0 -62
  472. package/docs/architecture/internals/functional-contract-patterns.md +0 -340
  473. package/docs/architecture/internals/registry-network-boundary.md +0 -57
  474. package/docs/architecture/internals/search.md +0 -248
  475. package/docs/architecture/reviews/env-secret-access.md +0 -319
  476. package/docs/architecture/runtime-boundary-design.md +0 -153
  477. package/docs/architecture/specs/0.9.0-close-out-plan.md +0 -361
  478. package/docs/architecture/specs/0.9.0-decisions.md +0 -532
  479. package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +0 -745
  480. package/docs/architecture/specs/0.9.0-open-items-register.md +0 -135
  481. package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +0 -740
  482. package/docs/architecture/specs/0.9.0-release-surface-review.md +0 -636
  483. package/docs/architecture/specs/agent-command-engine-model-design.md +0 -513
  484. package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +0 -501
  485. package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +0 -291
  486. package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +0 -2059
  487. package/docs/architecture/specs/di-seams-plan.md +0 -539
  488. package/docs/architecture/specs/driver-protocol-keep-or-cut.md +0 -275
  489. package/docs/architecture/specs/fact-asset-type.md +0 -142
  490. package/docs/architecture/specs/improve-collapse-churn-detector-design.md +0 -634
  491. package/docs/architecture/specs/reviews/task-workflow-unification/README.md +0 -72
  492. package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +0 -152
  493. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +0 -352
  494. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +0 -300
  495. package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +0 -402
  496. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +0 -758
  497. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +0 -645
  498. package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +0 -602
  499. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +0 -27
  500. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +0 -27
  501. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +0 -74
  502. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +0 -15
  503. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +0 -132
  504. package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +0 -147
  505. package/docs/architecture/specs/stash-conventions-code-spec.md +0 -275
  506. package/docs/architecture/specs/stash-organization-conventions.md +0 -377
  507. package/docs/architecture/specs/task-workflow-format-unification.md +0 -721
  508. package/docs/architecture/specs/workflow-engine-buy-vs-build.md +0 -231
  509. package/docs/architecture/specs/workflow-format-unification.md +0 -432
  510. package/docs/architecture/testing/manual-testing-checklist.md +0 -3411
  511. package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +0 -924
  512. package/docs/architecture/testing/task-workflow-manual-tests.md +0 -1720
  513. package/docs/guides/claude-code-vs-akm-workflows.md +0 -29
  514. package/docs/guides/knowledge-management.md +0 -18
  515. package/docs/maintainers/curate-workmap.md +0 -335
  516. package/docs/migration/v0.5-to-v0.6.md +0 -759
  517. package/docs/migration/v0.7-to-v0.8.md +0 -1378
  518. package/docs/plans/0.9.2-agent-command-workflow-plan.md +0 -423
@@ -4,12 +4,12 @@
4
4
  /**
5
5
  * Native executor — executes one frozen step subgraph (`WorkflowPlanStep.root`)
6
6
  * locally: fan-out through the scheduler, structured output through
7
- * `runStructured`, per-unit journaling through the serialized writer queue,
7
+ * `structuredLoop`, per-unit journaling through the serialized writer queue,
8
8
  * and `workflow_unit_*` events. It never writes step rows; advancing the spine
9
9
  * is `run-workflow.ts`'s job.
10
10
  *
11
11
  * - Data flow: instructions are the step's prose byte-exact; data reaches a
12
- * unit as attached context (docs/architecture/decisions/0001-…).
12
+ * unit as attached context.
13
13
  * - An empty successful free-text output is journaled as absent, so a live
14
14
  * run and a resume promote the same artifact.
15
15
  * - A declared step `output` schema is validated before the step completes;
@@ -23,26 +23,28 @@
23
23
  * - Run `budget` ceilings are consumed per actual dispatch and abort the step
24
24
  * when crossed, regardless of `on_error`.
25
25
  */
26
- import { appendEvent } from "../../core/events.js";
26
+ import { resolveRefToken } from "../../commands/env/env-binding.js";
27
+ import { isInstalledBundle } from "../../core/env-secret-ref.js";
28
+ import { NotFoundError } from "../../core/errors.js";
27
29
  import { validateJsonSchemaSubset } from "../../core/json-schema.js";
28
- import { runStructured } from "../../core/structured.js";
30
+ import { substituteRefTokens } from "../../core/ref-token.js";
29
31
  import { warn } from "../../core/warn.js";
30
- import { assertFrozenDirectoryContained } from "../../execution/directory-identity.js";
32
+ import { mergeNotices } from "../../execution/notices.js";
33
+ import { isRefused, jsonParser, structuredLoop } from "../../llm/structured.js";
31
34
  import { withWorkflowRunsConnection, withWorkflowRunsRepo, } from "../../storage/repositories/workflow-runs-repository.js";
32
35
  import { WORKFLOW_UNIT_DIAGNOSTIC_CLIP } from "../resource-limits.js";
36
+ import { resolveRunBundleRoot } from "../runtime/workflow-asset-loader.js";
33
37
  // The ONE child-workflow drive — publishes and drives a
34
38
  // `child-workflow`-targeted unit; this module's dispatch seam is its only
35
39
  // production caller.
36
40
  import { driveChildWorkflowUnit } from "./child-workflow.js";
37
- // The ONE dispatch redaction contract, shared with the gate-judge path
38
- // (exec/frozen-judge.ts). Consumers import the leaf directly — this module is
41
+ // The unit outcome scrub. Consumers import the leaf directly — this module is
39
42
  // not a second front door onto the seam.
40
43
  import { collectWorkflowDispatchSensitiveValues, redactUnitOutcome } from "./dispatch-redaction.js";
41
44
  import { materializeFrozenWorkflowEnvironment } from "./environment.js";
42
45
  // The exec (shell) unit runner — a leaf that owns argv spawning, containment,
43
46
  // and the process-outcome → failure-reason mapping.
44
47
  import { runExecUnit } from "./exec-unit.js";
45
- import { mergeLoweringNotices } from "./lowering-notices.js";
46
48
  import { secretShapedParamValues } from "./param-secrets.js";
47
49
  import { scheduleUnits } from "./scheduler.js";
48
50
  // Shared step semantics — the ONE implementation consumed by the engine
@@ -167,22 +169,28 @@ function openDispatchBudget(ctx, dispatched) {
167
169
  }
168
170
  /** Resolve the live-at-dispatch prerequisites once, after durable-row reuse is known. */
169
171
  async function prepareStepDispatchPrerequisites(input) {
170
- const { plan, workUnits, willDispatch, dispatched } = input;
172
+ const { plan, ctx, workUnits, willDispatch, dispatched } = input;
171
173
  let env;
172
174
  let sensitiveValues;
175
+ // The run's bundle is found again here, never frozen: a bundle update moves it to a new directory.
176
+ let cwd = ctx.bundleRootOverride;
177
+ if (willDispatch && cwd === undefined) {
178
+ try {
179
+ cwd = resolveRunBundleRoot(ctx.workflowRef);
180
+ }
181
+ catch (err) {
182
+ return {
183
+ ok: false,
184
+ result: failedStep(dispatched, `Step "${plan.stepId}" cannot run: ${message(err).replace(/\.$/, "")}.`),
185
+ };
186
+ }
187
+ }
173
188
  const frozenEnvironment = workUnits[0]?.environment;
174
189
  if (willDispatch && frozenEnvironment && frozenEnvironment.length > 0) {
175
190
  try {
176
191
  const materialized = materializeFrozenWorkflowEnvironment(frozenEnvironment);
177
192
  env = materialized.values;
178
193
  sensitiveValues = materialized.sensitiveValues;
179
- for (const audit of materialized.audits) {
180
- appendEvent({
181
- eventType: audit.eventType,
182
- ref: audit.ref,
183
- metadata: { keys: audit.keys, secretNames: audit.secretNames },
184
- });
185
- }
186
194
  }
187
195
  catch (err) {
188
196
  return {
@@ -193,6 +201,7 @@ async function prepareStepDispatchPrerequisites(input) {
193
201
  }
194
202
  return {
195
203
  ok: true,
204
+ ...(cwd !== undefined ? { cwd } : {}),
196
205
  ...(env ? { env } : {}),
197
206
  ...(sensitiveValues ? { sensitiveValues } : {}),
198
207
  };
@@ -229,13 +238,14 @@ async function executeStepPlanInConnection(plan, ctx) {
229
238
  const willDispatch = reuseDecisions.some((decision) => decision.kind === "dispatch");
230
239
  const prerequisites = await prepareStepDispatchPrerequisites({
231
240
  plan,
241
+ ctx,
232
242
  workUnits,
233
243
  willDispatch,
234
244
  dispatched,
235
245
  });
236
246
  if (!prerequisites.ok)
237
247
  return prerequisites.result;
238
- const { env, sensitiveValues } = prerequisites;
248
+ const { cwd, env, sensitiveValues } = prerequisites;
239
249
  // Budget ceilings + lifetime-cap accounting, and the budget-chained abort
240
250
  // signal they trip. Extracted verbatim (behavior-identical) — see
241
251
  // {@link openDispatchBudget}.
@@ -246,6 +256,7 @@ async function executeStepPlanInConnection(plan, ctx) {
246
256
  outcomes = await scheduleUnits(workUnits, (workUnit, index) => runUnit({
247
257
  plan,
248
258
  workUnit,
259
+ cwd,
249
260
  env,
250
261
  sensitiveValues,
251
262
  ctx,
@@ -267,7 +278,7 @@ async function executeStepPlanInConnection(plan, ctx) {
267
278
  // list with a failed-step envelope. Budget/cap and journal-write failures
268
279
  // must not erase notices already observed from real dispatches; durable row
269
280
  // reuses naturally contribute none.
270
- const notices = mergeLoweringNotices(...outcomes.map((outcome) => outcome?.notices));
281
+ const notices = mergeNotices(...outcomes.map((outcome) => outcome?.notices));
271
282
  // A declared budget ceiling is a hard backstop: a step that hit one FAILS
272
283
  // regardless of on_error policy (a capped run must never quietly pass its
273
284
  // gate). The budget message names WHICH ceiling tripped.
@@ -299,7 +310,7 @@ async function executeStepPlanInConnection(plan, ctx) {
299
310
  };
300
311
  }
301
312
  async function runUnit(input) {
302
- const { plan, workUnit, env, sensitiveValues, ctx, dispatcher } = input;
313
+ const { plan, workUnit, cwd, env, sensitiveValues, ctx, dispatcher } = input;
303
314
  const unitId = workUnit.unitId;
304
315
  // Target validity is a WHOLE-LIST invariant, never a per-unit condition:
305
316
  // computeStepWorkList rejects a step before building any unit when its sole
@@ -317,10 +328,7 @@ async function runUnit(input) {
317
328
  prompt,
318
329
  frozenTarget: workUnit.frozenTarget,
319
330
  ...(workUnit.execContext ? { execContext: workUnit.execContext } : {}),
320
- // An exec unit spawns in the engine invocation's working directory. Only
321
- // exec units get it: handing an agent unit a cwd it never had would change
322
- // harness behavior, and the agent path already takes its cwd from its profile.
323
- ...(workUnit.frozenTarget.kind !== "command" && ctx.workDir !== undefined ? { cwd: ctx.workDir } : {}),
331
+ ...(cwd !== undefined ? { cwd } : {}),
324
332
  timeoutMs: workUnit.timeoutMs,
325
333
  ...(workUnit.schema ? { schema: workUnit.schema } : {}),
326
334
  ...(env ? { env } : {}),
@@ -432,8 +440,8 @@ async function reserveJournaledDispatch(input, startedAt) {
432
440
  parentUnitId: workUnit.isFanOut ? `${plan.stepId}.map` : null,
433
441
  phase: "unit",
434
442
  runner: workUnit.runner,
435
- engine: target.kind === "command" ? target.request.engine.name : null,
436
- model: target.kind === "command" ? (target.request.model?.resolved ?? null) : null,
443
+ engine: target.kind === "command" ? target.request.target.name : null,
444
+ model: target.kind === "command" ? (target.request.model?.model ?? null) : null,
437
445
  inputHash,
438
446
  now: startedAt,
439
447
  }).attempt;
@@ -498,6 +506,7 @@ async function dispatchJournaledAttempt(input) {
498
506
  };
499
507
  // A child-workflow unit goes to the child executor instead of the
500
508
  // dispatcher, after its attempt row is reserved, so it journals like any unit.
509
+ const resolvedSecrets = new Set();
501
510
  const dispatched = request.frozenTarget.kind === "child-workflow"
502
511
  ? await driveChildWorkflowUnit({
503
512
  request,
@@ -507,17 +516,18 @@ async function dispatchJournaledAttempt(input) {
507
516
  inputHash: input.inputHash,
508
517
  dispatcher,
509
518
  })
510
- : await dispatchUnit(request, dispatcher);
519
+ : await dispatchUnit(request, dispatcher, resolvedSecrets);
511
520
  // Credential and passthrough values are intentionally sampled only AFTER
512
- // the default dispatcher has authorized/lowered the frozen request and
521
+ // the default dispatcher has lowered the frozen request and
513
522
  // materialized credentials at its terminal dispatch boundary. Custom test
514
523
  // dispatchers receive the same post-dispatch journal scrub. Secret-shaped
515
524
  // run params join the set: they must reach the prompt in clear (the unit
516
- // needs them), but nothing about them needs to reach the journal.
525
+ // needs them), but nothing about them needs to reach the journal. So do the
526
+ // secrets the dispatcher resolved itself (an exec unit's argv/cwd tokens).
517
527
  const sensitiveValues = collectWorkflowDispatchSensitiveValues({
518
528
  ...(request.frozenTarget.kind === "command" ? { runner: request.frozenTarget.runner } : {}),
519
- sensitiveValues: [...(request.sensitiveValues ?? []), ...secretShapedParamValues(ctx.params)],
520
- }, request.env);
529
+ sensitiveValues: [...(request.sensitiveValues ?? []), ...resolvedSecrets, ...secretShapedParamValues(ctx.params)],
530
+ });
521
531
  const outcome = redactUnitOutcome(dispatched, sensitiveValues);
522
532
  const finishedAt = new Date().toISOString();
523
533
  // A dispatched unit's outcome is NEVER silently discarded: the attempt is
@@ -566,7 +576,7 @@ async function dispatchJournaledAttempt(input) {
566
576
  * and hunts for a JSON island inside prose, which is the right forgiving
567
577
  * behavior for an LLM and the wrong one for a command, where it would silently
568
578
  * promote a JSON fragment found in unrelated log noise as the typed artifact.
569
- * Returning `undefined` makes `runStructured` report `parse_error` (a real
579
+ * Returning `undefined` makes the structured loop report `parse_error` (a real
570
580
  * member of the retry taxonomy), so `retry.on: [parse_error]` still works.
571
581
  */
572
582
  function parseExecJson(raw) {
@@ -580,16 +590,9 @@ function parseExecJson(raw) {
580
590
  return undefined;
581
591
  }
582
592
  }
583
- /** Transport failures surface as this sentinel so runStructured doesn't retry them. */
584
- class UnitTransportError extends Error {
585
- result;
586
- constructor(result) {
587
- super(result.error ?? "unit dispatch failed");
588
- this.result = result;
589
- this.name = "UnitTransportError";
590
- }
591
- }
592
- async function dispatchUnit(request, dispatcher) {
593
+ async function dispatchUnit(request, dispatcher,
594
+ /** Receives the secret values the dispatcher resolved, for the caller's journal scrub. */
595
+ resolvedSecrets) {
593
596
  let tokens = 0;
594
597
  let sawUsage = false;
595
598
  let loweringNotices;
@@ -600,20 +603,36 @@ async function dispatchUnit(request, dispatcher) {
600
603
  let sessionId;
601
604
  const dispatchOnce = async (feedback) => {
602
605
  const result = await dispatcher(request, feedback);
606
+ for (const value of result.sensitiveValues ?? [])
607
+ resolvedSecrets.add(value);
603
608
  if (result.usage) {
604
609
  sawUsage = true;
605
610
  tokens +=
606
611
  (result.usage.inputTokens ?? 0) + (result.usage.outputTokens ?? 0) + (result.usage.reasoningTokens ?? 0);
607
612
  }
608
- loweringNotices = mergeLoweringNotices(loweringNotices, result.notices);
613
+ loweringNotices = mergeNotices(loweringNotices, result.notices);
609
614
  // Capture before the ok-check: a failed attempt can still have configured
610
615
  // a session (e.g. codex `session_configured` then a tool crash).
611
616
  if (result.sessionId !== undefined)
612
617
  sessionId = result.sessionId;
613
- if (!result.ok)
614
- throw new UnitTransportError(result);
615
- return result.text;
618
+ if (!result.ok) {
619
+ return {
620
+ ok: false,
621
+ failureReason: result.failureReason ?? "dispatch_error",
622
+ error: result.error ?? "unit dispatch failed",
623
+ text: result.text,
624
+ };
625
+ }
626
+ return { ok: true, raw: result.text };
616
627
  };
628
+ const transportFailed = (failure) => ({
629
+ unitId: request.unitId,
630
+ ok: false,
631
+ failureReason: failure.failureReason,
632
+ error: failure.error,
633
+ text: failure.text,
634
+ ...captured(),
635
+ });
617
636
  const captured = () => ({
618
637
  ...(sawUsage ? { tokens } : {}),
619
638
  ...(sessionId !== undefined ? { sessionId } : {}),
@@ -622,28 +641,42 @@ async function dispatchUnit(request, dispatcher) {
622
641
  try {
623
642
  if (request.schema) {
624
643
  const schema = request.schema;
625
- const structured = await runStructured({
626
- dispatch: dispatchOnce,
644
+ const validate = (candidate) => {
645
+ const errors = validateJsonSchemaSubset(candidate, schema);
646
+ return errors.length === 0
647
+ ? { ok: true, value: candidate }
648
+ : { ok: false, errors, reason: "validation_error" };
649
+ };
650
+ const structured = await structuredLoop({
651
+ dispatch: (correction) => dispatchOnce(correction?.text),
627
652
  // A command is not re-promptable. Its stdout must be EXACTLY one JSON
628
653
  // value: the default embedded-JSON scan (fences, think-blocks, "find the
629
654
  // JSON inside the prose") is right for an LLM and wrong for a command,
630
655
  // where it would pluck a JSON fragment out of unrelated log noise and
631
- // promote it as the typed artifact. And it gets exactly ONE attempt —
632
- // `runStructured`'s corrective retry re-dispatches with feedback, which
656
+ // promote it as the typed artifact. And it gets exactly ONE attempt:
657
+ // the loop's corrective retry re-dispatches with feedback, which
633
658
  // for a command means running a SIDE-EFFECTING process a second time
634
659
  // with byte-identical argv: it cannot produce different output, and it
635
660
  // can produce a second deployment. Declared `retry:` still applies (the
636
661
  // executor's own loop), because that is a policy the author opted into
637
662
  // per failure reason.
638
- ...(request.frozenTarget.kind !== "command" ? { parse: parseExecJson, maxAttempts: 1 } : {}),
639
- validate: (candidate) => {
640
- const errors = validateJsonSchemaSubset(candidate, schema);
641
- return errors.length === 0 ? { ok: true, value: candidate } : { ok: false, errors };
642
- },
663
+ ...(request.frozenTarget.kind !== "command"
664
+ ? {
665
+ attempts: 1,
666
+ parse: (raw) => {
667
+ const candidate = parseExecJson(raw);
668
+ return candidate === undefined
669
+ ? { ok: false, errors: ["no JSON structure found in response"], reason: "parse_error" }
670
+ : validate(candidate);
671
+ },
672
+ }
673
+ : { parse: jsonParser(validate) }),
643
674
  });
644
675
  if (structured.ok) {
645
676
  return { unitId: request.unitId, ok: true, result: structured.value, ...captured() };
646
677
  }
678
+ if (!isRefused(structured))
679
+ return transportFailed(structured);
647
680
  return {
648
681
  unitId: request.unitId,
649
682
  ok: false,
@@ -661,7 +694,10 @@ async function dispatchUnit(request, dispatcher) {
661
694
  ...captured(),
662
695
  };
663
696
  }
664
- const text = await dispatchOnce();
697
+ const dispatched = await dispatchOnce();
698
+ if (!dispatched.ok)
699
+ return transportFailed(dispatched);
700
+ const text = dispatched.raw;
665
701
  // Normalize an EMPTY successful output to "no text". `finishUnitAttempt` journals
666
702
  // result_json = NULL for a falsy text, so durable-reuse rehydrates NO text
667
703
  // from the row (unitOutcomeFromRow). Preserving `text: ""` only in this live
@@ -672,16 +708,6 @@ async function dispatchUnit(request, dispatcher) {
672
708
  return { unitId: request.unitId, ok: true, ...(text ? { text } : {}), ...captured() };
673
709
  }
674
710
  catch (err) {
675
- if (err instanceof UnitTransportError) {
676
- return {
677
- unitId: request.unitId,
678
- ok: false,
679
- failureReason: err.result.failureReason ?? "dispatch_error",
680
- error: err.result.error ?? "unit dispatch failed",
681
- text: err.result.text,
682
- ...captured(),
683
- };
684
- }
685
711
  return {
686
712
  unitId: request.unitId,
687
713
  ok: false,
@@ -693,19 +719,21 @@ async function dispatchUnit(request, dispatcher) {
693
719
  }
694
720
  // ── Default dispatcher (production substrate) ───────────────────────────────
695
721
  /**
696
- * Dispatch a frozen engine through the common prepare → lower → dispatch seam.
722
+ * Dispatch a frozen connection or harness through the common prepare → lower → dispatch seam.
697
723
  * No live profile/default/model map is consulted, and credentials remain
698
724
  * symbolic until the final dispatch boundary.
699
725
  */
700
726
  export const defaultUnitDispatcher = async (request, feedback) => {
701
727
  const frozenTarget = request.frozenTarget;
702
728
  if (frozenTarget.kind === "shell") {
703
- if (frozenTarget.cwdIdentity)
704
- assertFrozenDirectoryContained(frozenTarget.cwdIdentity);
705
- return runExecUnit({
729
+ if (request.cwd === undefined) {
730
+ throw new Error(`exec unit "${request.unitId}" was dispatched with no working directory.`);
731
+ }
732
+ const { exec, secretValues } = substituteExecRefs(request.unitId, frozenTarget.exec);
733
+ const outcome = await runExecUnit({
706
734
  unitId: request.unitId,
707
- exec: frozenTarget.exec,
708
- baseDir: request.cwd ?? frozenTarget.cwdIdentity?.realCwd ?? process.cwd(),
735
+ exec,
736
+ baseDir: request.cwd,
709
737
  ...(request.env ? { env: request.env } : {}),
710
738
  ...(request.execContext ? { context: request.execContext } : {}),
711
739
  ...(request.schema ? { hasOutputSchema: true } : {}),
@@ -713,9 +741,36 @@ export const defaultUnitDispatcher = async (request, feedback) => {
713
741
  ...(request.signal ? { signal: request.signal } : {}),
714
742
  ...(request.eventSource !== undefined ? { eventSource: request.eventSource } : {}),
715
743
  });
744
+ // A secret substituted into argv joins the redaction set, like one bound through an env asset: the
745
+ // executor scrubs after the structured parse, so a quoted or numeric secret is not missed or corrupted.
746
+ return { ...outcome, sensitiveValues: secretValues };
716
747
  }
717
748
  return dispatchWorkflowExecution(request, feedback);
718
749
  };
750
+ /**
751
+ * Replace the `${ref}` tokens in an exec unit's argv and `cwd` (prompts are not substituted): a
752
+ * `secrets/` ref with the secret's value, any other asset ref with its absolute path. A ref no
753
+ * bundle owns fails the unit before anything is spawned.
754
+ */
755
+ function substituteExecRefs(unitId, exec) {
756
+ const slots = Object.fromEntries(exec.command.entries());
757
+ if (exec.cwd !== undefined)
758
+ slots.cwd = exec.cwd;
759
+ const { values, missing, secretValues } = substituteRefTokens(slots, resolveRefToken, isInstalledBundle);
760
+ if (missing.length > 0) {
761
+ throw new NotFoundError(`exec unit "${unitId}" references asset(s) that no bundle owns: ${missing.join(", ")}. Nothing was run.`, "FILE_NOT_FOUND",
762
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: literal `${ref}` token syntax documented for users, not interpolation
763
+ "Write each `${ref}` as a full akm ref that exists, e.g. `${team//scripts/run.sh}`.");
764
+ }
765
+ return {
766
+ exec: {
767
+ ...exec,
768
+ command: exec.command.map((_, index) => values[index]),
769
+ ...(exec.cwd !== undefined ? { cwd: values.cwd } : {}),
770
+ },
771
+ secretValues,
772
+ };
773
+ }
719
774
  // ── Small helpers ────────────────────────────────────────────────────────────
720
775
  /**
721
776
  * Rehydrate a journaled completed unit row into a UnitOutcome (durable-row
@@ -6,25 +6,22 @@
6
6
  * execute path. akm walks the frozen plan (read from `plan_json`, never live
7
7
  * source) and dispatches every unit itself; every step advances through
8
8
  * `completeWorkflowStep`; one O_EXCL lock file per run keeps a second driver
9
- * off (a dead holder's lock is reclaimed); gate loops are bounded; and the
10
- * SDK dispatch registry is drained on every exit so the process can exit.
11
- * See docs/architecture/decisions/0011-engine-run-loop-invariants.md.
9
+ * off (a dead holder's lock is reclaimed); and gate loops are bounded.
12
10
  */
13
11
  import { createHash } from "node:crypto";
14
12
  import fs from "node:fs";
15
13
  import path from "node:path";
16
14
  import { TransientError, UsageError } from "../../core/errors.js";
17
- import { releaseLock } from "../../core/file-lock.js";
15
+ import { probeLock, releaseLock } from "../../core/file-lock.js";
18
16
  import { formatLockHolderPid, tryAcquireRunLock } from "../../core/run-lock.js";
19
- import { disposeDispatchResources } from "../../integrations/agent/runner-dispatch.js";
17
+ import { mergeNotices } from "../../execution/notices.js";
20
18
  import { resolveStorageLocations } from "../../storage/locations.js";
21
19
  import { withWorkflowRunsConnection, withWorkflowRunsRepo } from "../../storage/repositories/workflow-runs-repository.js";
22
20
  import { computePlanHash } from "../ir/plan-hash.js";
23
21
  import { decodeWorkflowPlan, readRunPlan } from "../runtime/run-plan.js";
24
- import { abandonWorkflowRun, getNextWorkflowStep, resumeWorkflowRun } from "../runtime/runs.js";
22
+ import { abandonWorkflowRun, getNextWorkflowStep, listWorkflowRuns, resolveWorkflowRunTarget, resumeWorkflowRun, } from "../runtime/runs.js";
25
23
  import { loadWorkflowAsset } from "../runtime/workflow-asset-loader.js";
26
- import { frozenSummaryJudge } from "./frozen-judge.js";
27
- import { mergeLoweringNotices } from "./lowering-notices.js";
24
+ import { frozenSummaryJudge, resolveJudgeCwd } from "./frozen-judge.js";
28
25
  import { defaultUnitDispatcher, executeStepPlan, } from "./native-executor.js";
29
26
  // Shared step semantics — gate-evaluation journaling, and the whole step-completion path
30
27
  // (`finalizeExecutedStep`) live in step-work.ts as ONE implementation, so the
@@ -34,10 +31,6 @@ export async function runWorkflowSteps(options) {
34
31
  let target = options.target;
35
32
  let params = options.params;
36
33
  let parameterFlags = options.parameterFlags;
37
- // `--new` only applies to the FIRST resolution of `target` (a ref); every
38
- // retry re-targets the run id `startWorkflowRun` already created, so it is
39
- // cleared alongside `params`/`parameterFlags` below (#919).
40
- let newRun = options.newRun;
41
34
  let remainingRetries = options.maxRetries ?? 0;
42
35
  let remainingSteps = options.maxSteps;
43
36
  const executed = [];
@@ -53,12 +46,11 @@ export async function runWorkflowSteps(options) {
53
46
  target,
54
47
  ...(params !== undefined ? { params } : { params: undefined }),
55
48
  ...(parameterFlags !== undefined ? { parameterFlags } : { parameterFlags: undefined }),
56
- newRun,
57
49
  ...(remainingSteps !== undefined ? { maxSteps: remainingSteps } : { maxSteps: undefined }),
58
50
  }, liveEvidence);
59
51
  executed.push(...result.executed);
60
52
  stepsProcessed += result.stepsProcessed;
61
- const notices = mergeLoweringNotices(...executed.map((step) => step.notices));
53
+ const notices = mergeNotices(...executed.map((step) => step.notices));
62
54
  const aggregate = { ...result, executed, stepsProcessed, ...(notices ? { notices } : {}) };
63
55
  // An attempt that executed nothing (an abandoned, undecodable plan) has no
64
56
  // failed step for a retry to re-open.
@@ -81,14 +73,12 @@ export async function runWorkflowSteps(options) {
81
73
  target = result.run.id;
82
74
  params = undefined;
83
75
  parameterFlags = undefined;
84
- newRun = undefined;
85
76
  remainingRetries -= 1;
86
77
  }
87
78
  }
88
79
  async function runWorkflowAttempt(options, liveEvidence) {
89
80
  const next = await getNextWorkflowStep(options.target, options.params, {
90
81
  parameterFlags: options.parameterFlags,
91
- newRun: options.newRun,
92
82
  });
93
83
  // Refuse non-active runs BEFORE any dispatch — completeWorkflowStep would
94
84
  // reject the completion anyway, but only after the units already ran (and
@@ -125,7 +115,6 @@ async function runWorkflowAttempt(options, liveEvidence) {
125
115
  executed: [],
126
116
  stepsProcessed: 0,
127
117
  warnings: [...warnings, message],
128
- ...(next.resumed ? { resumed: true } : {}),
129
118
  };
130
119
  }
131
120
  plan = read.plan;
@@ -141,37 +130,43 @@ async function runWorkflowAttempt(options, liveEvidence) {
141
130
  // Creation/resume-time notices reach the caller only here: the run row
142
131
  // has no warnings column, and a later invocation of the same run must
143
132
  // stay silent about a decision it did not make. `driveRun` never sets
144
- // `warnings` or `resumed` — both are properties of THIS resolution of
145
- // `target`, not of the run row (#919).
133
+ // `warnings` — it is a property of THIS resolution of `target`, not of
134
+ // the run row.
146
135
  return {
147
136
  ...result,
148
- ...(next.resumed ? { resumed: true } : {}),
149
137
  ...(warnings.length > 0 ? { warnings } : {}),
150
138
  };
151
139
  }
152
140
  finally {
153
- try {
154
- if (lock)
155
- releaseLock(lock);
156
- }
157
- finally {
158
- // Process-lifecycle drain (owner finding 4): release any cached SDK server
159
- // child processes so a one-shot CLI invocation exits cleanly instead of
160
- // hanging on the leaked handle. Runs even if the lock release itself
161
- // fails; a teardown-time error must not skip dispatch cleanup.
162
- try {
163
- await (options.disposeDispatchResources ?? disposeDispatchResources)();
164
- }
165
- catch {
166
- /* disposal is best-effort; never let cleanup mask the run outcome */
167
- }
168
- }
141
+ if (lock)
142
+ releaseLock(lock);
169
143
  }
170
144
  }
171
145
  /** The per-run lock file: `<data dir>/workflow-run-locks/<run id>.lock`, next to `state.db`. */
172
146
  export function workflowRunLockPath(runId) {
173
147
  return path.join(path.dirname(resolveStorageLocations().stateDb), "workflow-run-locks", `${runId}.lock`);
174
148
  }
149
+ /**
150
+ * `--skip-if-locked` for a workflow REF (#1239): an active run of `ref` whose
151
+ * lock a live process holds, or `undefined`. A run id (which drives that one
152
+ * run, and fails with `RUN_LEASE_HELD` if it is held) is never a ref. Read-only:
153
+ * `probeLock` reports a dead holder as stale without reclaiming it.
154
+ */
155
+ export async function findLiveLockedRunOfRef(target) {
156
+ if ((await resolveWorkflowRunTarget(target)) !== undefined)
157
+ return undefined;
158
+ const { runs } = await listWorkflowRuns({ workflowRef: target, activeOnly: true });
159
+ for (const run of runs) {
160
+ const probe = probeLock(workflowRunLockPath(run.id));
161
+ if (probe.state === "held") {
162
+ return {
163
+ runId: run.id,
164
+ holder: formatLockHolderPid({ pid: probe.holderPid, launcherPid: probe.launcherPid ?? null }),
165
+ };
166
+ }
167
+ }
168
+ return undefined;
169
+ }
175
170
  /**
176
171
  * Take the run's O_EXCL lock file, or refuse with `RUN_LEASE_HELD` (exit 75)
177
172
  * naming the live holder. A lock whose holder pid is dead is reclaimed by
@@ -215,7 +210,7 @@ async function workflowSourceDriftWarning(runId, workflowRef, plan) {
215
210
  if (current === plan.sourceHash)
216
211
  return undefined;
217
212
  return (`Workflow run ${runId}: ${workflowRef} (${sourcePath}) has changed since this run was frozen; ` +
218
- `continuing with the frozen plan. Start a new run with 'akm workflow run ${workflowRef} --new' to pick up the edit.`);
213
+ `continuing with the frozen plan. Start a new run with 'akm workflow run ${workflowRef}' to pick up the edit.`);
219
214
  }
220
215
  /**
221
216
  * A terminal run is a pure no-op: do not load or integrity-check its frozen
@@ -230,11 +225,11 @@ async function completedRunResult(runId) {
230
225
  ...(doneState.run.status === "completed" ? { done: true } : {}),
231
226
  };
232
227
  }
233
- function workflowSummaryJudge(options, stepPlan, signal, owner) {
228
+ function workflowSummaryJudge(options, stepPlan, signal, owner, workflowRef) {
234
229
  if (options.summaryJudge !== undefined)
235
230
  return options.summaryJudge;
236
231
  // The judge dispatches under the real run/step identity and the same event source as units.
237
- return frozenSummaryJudge(stepPlan.gate.frozenJudge, signal, options.dispatcher ?? defaultUnitDispatcher, owner, options.eventSource);
232
+ return frozenSummaryJudge(stepPlan.gate.frozenJudge, signal, options.dispatcher ?? defaultUnitDispatcher, owner, options.eventSource, options.bundleRootOverride ?? resolveJudgeCwd(stepPlan.gate.frozenJudge, workflowRef));
238
233
  }
239
234
  /**
240
235
  * Seed the run's budget from the append-only attempt journal so a resumed run
@@ -307,6 +302,7 @@ async function executeStepSubgraph(ctx, loop) {
307
302
  ...(options.eventSource !== undefined ? { eventSource: options.eventSource } : {}),
308
303
  ...(options.signal ? { signal: options.signal } : {}),
309
304
  ...(options.dispatcher ? { dispatcher: options.dispatcher } : {}),
305
+ ...(options.bundleRootOverride !== undefined ? { bundleRootOverride: options.bundleRootOverride } : {}),
310
306
  maxConcurrency: Math.min(options.maxConcurrency ?? Number.POSITIVE_INFINITY, plan.execution?.maxConcurrency ?? 1),
311
307
  });
312
308
  }
@@ -484,7 +480,7 @@ liveEvidence) {
484
480
  break;
485
481
  }
486
482
  // Judge-outage contract: resolve the step's frozen completion judge BEFORE
487
- // any dispatch. An unresolvable judge (missing frozen engine, no dispatcher
483
+ // any dispatch. An unresolvable judge (missing frozen connection or harness, no dispatcher
488
484
  // for an agent judge) is verifier INFRASTRUCTURE failure — block the step
489
485
  // for `akm workflow resume` instead of spending on units the gate can never
490
486
  // verify. No gate loop is consumed and nothing is dispatched.
@@ -493,7 +489,7 @@ liveEvidence) {
493
489
  summaryJudge = workflowSummaryJudge(options, stepPlan, options.signal, {
494
490
  runId: next.run.id,
495
491
  stepId: step.id,
496
- });
492
+ }, next.run.workflowRef);
497
493
  }
498
494
  catch (error) {
499
495
  const detail = error instanceof Error && error.message ? ` (${error.message})` : "";
@@ -541,7 +537,7 @@ liveEvidence) {
541
537
  }
542
538
  // Re-read for the freshest run state (the loop may have exited on maxSteps).
543
539
  const finalState = await getNextWorkflowStep(next.run.id);
544
- const notices = mergeLoweringNotices(...executed.map((step) => step.notices));
540
+ const notices = mergeNotices(...executed.map((step) => step.notices));
545
541
  return {
546
542
  run: finalState.run,
547
543
  executed,