akm-cli 0.9.1 → 0.9.2-alpha.2

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 (350) hide show
  1. package/CHANGELOG.md +103 -28
  2. package/README.md +3 -1
  3. package/SECURITY.md +1 -1
  4. package/STABILITY.md +1 -1
  5. package/dist/akm +2 -2
  6. package/dist/akm-migrate +2 -2
  7. package/dist/assets/hints/cli-hints-full.md +14 -9
  8. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
  9. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  10. package/dist/assets/models.json +35 -0
  11. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +3 -4
  12. package/dist/assets/stash-skeleton/facts/conventions/organization.md +1 -3
  13. package/dist/assets/tasks/core/extract.yml +6 -5
  14. package/dist/assets/tasks/core/improve.yml +6 -5
  15. package/dist/assets/tasks/core/index-refresh.yml +6 -5
  16. package/dist/assets/tasks/core/sync.yml +6 -5
  17. package/dist/assets/tasks/core/version-check.yml +6 -5
  18. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
  19. package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
  20. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
  21. package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
  22. package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
  23. package/dist/cli/confirm.js +2 -2
  24. package/dist/cli/parse-args.js +3 -24
  25. package/dist/cli/retired-commands.js +1 -1
  26. package/dist/cli/shared.js +2 -2
  27. package/dist/cli.js +11 -9
  28. package/dist/commands/agent/agent-dispatch.js +55 -89
  29. package/dist/commands/agent/contribute-cli.js +12 -45
  30. package/dist/commands/command/builtin-action.js +32 -0
  31. package/dist/commands/command/command-cli.js +99 -0
  32. package/dist/commands/command/command-execution.js +308 -0
  33. package/dist/commands/command/execution-source-loader.js +176 -0
  34. package/dist/commands/command/portable-template.js +60 -0
  35. package/dist/commands/config-cli.js +10 -4
  36. package/dist/commands/env/env.js +4 -2
  37. package/dist/commands/feedback-cli.js +1 -1
  38. package/dist/commands/health/checks.js +241 -29
  39. package/dist/commands/health/html-report.js +0 -14
  40. package/dist/commands/health/report-view-model.js +0 -1
  41. package/dist/commands/health/surfaces.js +6 -7
  42. package/dist/commands/health/types.js +0 -2
  43. package/dist/commands/health.js +63 -18
  44. package/dist/commands/improve/collapse-detector.js +5 -6
  45. package/dist/commands/improve/consolidate.js +251 -214
  46. package/dist/commands/improve/distill/promote-memory.js +71 -34
  47. package/dist/commands/improve/distill/quality-gate.js +17 -5
  48. package/dist/commands/improve/distill.js +232 -155
  49. package/dist/commands/improve/eligibility.js +112 -79
  50. package/dist/commands/improve/execution.js +57 -0
  51. package/dist/commands/improve/extract-cli.js +5 -5
  52. package/dist/commands/improve/extract-prompt.js +64 -22
  53. package/dist/commands/improve/extract.js +608 -360
  54. package/dist/commands/improve/improve-strategies.js +43 -14
  55. package/dist/commands/improve/improve.js +249 -29
  56. package/dist/commands/improve/loop-stages.js +11 -17
  57. package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
  58. package/dist/commands/improve/outcome-loop.js +22 -38
  59. package/dist/commands/improve/planner.js +134 -0
  60. package/dist/commands/improve/preparation.js +730 -409
  61. package/dist/commands/improve/reflect.js +386 -223
  62. package/dist/commands/improve/run-context.js +3 -4
  63. package/dist/commands/improve/salience.js +6 -58
  64. package/dist/commands/improve/session-asset.js +12 -12
  65. package/dist/commands/lint/index.js +101 -29
  66. package/dist/commands/migrate-cli.js +11 -69
  67. package/dist/commands/migration-tool.js +6 -9
  68. package/dist/commands/models-cli.js +27 -0
  69. package/dist/commands/proposal/drain.js +258 -186
  70. package/dist/commands/proposal/proposal-cli.js +32 -10
  71. package/dist/commands/proposal/proposal.js +2 -5
  72. package/dist/commands/proposal/propose.js +192 -172
  73. package/dist/commands/proposal/repository.js +54 -91
  74. package/dist/commands/proposal/validators/proposal-validators.js +9 -7
  75. package/dist/commands/read/curate.js +53 -22
  76. package/dist/commands/read/registry-search.js +25 -9
  77. package/dist/commands/read/remember-cli.js +14 -2
  78. package/dist/commands/read/search.js +10 -4
  79. package/dist/commands/read/show.js +139 -153
  80. package/dist/commands/registry-cli.js +16 -7
  81. package/dist/commands/remember.js +33 -18
  82. package/dist/commands/sources/add-cli.js +19 -178
  83. package/dist/commands/sources/bundle-cli.js +15 -3
  84. package/dist/commands/sources/dangerous-env-audit.js +135 -0
  85. package/dist/commands/sources/info.js +2 -1
  86. package/dist/commands/sources/installed-stashes.js +901 -177
  87. package/dist/commands/sources/schema-repair.js +174 -95
  88. package/dist/commands/sources/self-update.js +30 -74
  89. package/dist/commands/sources/source-add.js +3 -5
  90. package/dist/commands/sources/sources-cli.js +2 -15
  91. package/dist/commands/sources/update-transaction.js +220 -0
  92. package/dist/commands/tasks/tasks-cli.js +3 -3
  93. package/dist/commands/tasks/tasks.js +736 -317
  94. package/dist/commands/workflow-cli.js +2 -2
  95. package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
  96. package/dist/core/adapter/adapters/akm-adapter.js +85 -35
  97. package/dist/core/adapter/adapters/akm-lint.js +54 -39
  98. package/dist/core/adapter/adapters/akm-metadata.js +45 -45
  99. package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
  100. package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
  101. package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
  102. package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
  103. package/dist/core/adapter/adapters/index.js +0 -9
  104. package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
  105. package/dist/core/adapter/adapters/okf-adapter.js +4 -0
  106. package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
  107. package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
  108. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
  109. package/dist/core/adapter/execution-source.js +308 -0
  110. package/dist/core/adapter/recognize-match.js +36 -13
  111. package/dist/core/adapter/registry.js +0 -9
  112. package/dist/core/asset/stash-meta.js +94 -4
  113. package/dist/core/common.js +6 -11
  114. package/dist/core/config/config-io.js +3 -3
  115. package/dist/core/config/config-schema.js +18 -40
  116. package/dist/core/config/config-sources.js +11 -21
  117. package/dist/core/config/config-walker.js +31 -13
  118. package/dist/core/config/config.js +23 -26
  119. package/dist/core/config/schema/engines.js +8 -7
  120. package/dist/core/config/schema/improve-processes.js +29 -5
  121. package/dist/core/config/schema/index-config.js +0 -27
  122. package/dist/core/config/schema/primitives.js +1 -23
  123. package/dist/core/config/schema/sources-bundles.js +13 -16
  124. package/dist/core/errors.js +2 -0
  125. package/dist/core/events.js +68 -32
  126. package/dist/core/extra-params.js +1 -0
  127. package/dist/core/improve-result.js +315 -0
  128. package/dist/core/lesson-lint.js +0 -6
  129. package/dist/core/maintenance-barrier.js +4 -4
  130. package/dist/core/network-policy.js +152 -0
  131. package/dist/core/paths.js +1 -1
  132. package/dist/core/recognition-util.js +4 -4
  133. package/dist/core/registry-url.js +456 -0
  134. package/dist/core/state/migrations.js +161 -47
  135. package/dist/core/state-db.js +453 -80
  136. package/dist/core/system-error.js +32 -0
  137. package/dist/core/time.js +2 -12
  138. package/dist/core/write-source.js +0 -18
  139. package/dist/execution/directory-identity.js +52 -0
  140. package/dist/execution/executable-identity.js +107 -0
  141. package/dist/execution/guarded-source.js +398 -0
  142. package/dist/execution/json.js +95 -0
  143. package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
  144. package/dist/execution/record.js +55 -0
  145. package/dist/execution/resolved-request.js +730 -0
  146. package/dist/execution/source.js +320 -0
  147. package/dist/indexer/bundle-identity-guard.js +5 -4
  148. package/dist/indexer/db/graph-db.js +33 -0
  149. package/dist/indexer/graph/graph-boost.js +3 -4
  150. package/dist/indexer/graph/graph-extraction.js +562 -373
  151. package/dist/indexer/index-written-assets.js +78 -39
  152. package/dist/indexer/indexer.js +471 -432
  153. package/dist/indexer/installations.js +6 -0
  154. package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
  155. package/dist/indexer/materialize-embeddings.js +155 -0
  156. package/dist/indexer/passes/memory-inference.js +227 -174
  157. package/dist/indexer/passes/metadata.js +263 -118
  158. package/dist/indexer/scan/doc-to-entry.js +7 -10
  159. package/dist/indexer/scan/drain-dir.js +51 -23
  160. package/dist/indexer/search/db-search.js +156 -50
  161. package/dist/indexer/search/fts-query.js +40 -40
  162. package/dist/indexer/search/ranking.js +36 -1
  163. package/dist/indexer/search/search-attribution.js +3 -1
  164. package/dist/indexer/search/search-fields.js +23 -14
  165. package/dist/indexer/search/search-hit-enrichers.js +1 -1
  166. package/dist/indexer/search/search-source.js +7 -16
  167. package/dist/indexer/search/semantic-status.js +10 -1
  168. package/dist/indexer/usage/show-usage.js +105 -0
  169. package/dist/indexer/usage/usage-events.js +7 -2
  170. package/dist/indexer/walk/matchers.js +40 -10
  171. package/dist/indexer/walk/path-resolver.js +5 -2
  172. package/dist/indexer/walk/walker.js +20 -2
  173. package/dist/integrations/agent/builder-shared.js +3 -6
  174. package/dist/integrations/agent/conversation-fallback.js +16 -0
  175. package/dist/integrations/agent/engine-resolution.js +87 -87
  176. package/dist/integrations/agent/execution-cascade.js +566 -0
  177. package/dist/integrations/agent/execution-definitions.js +211 -0
  178. package/dist/integrations/agent/execution-lowering.js +811 -0
  179. package/dist/integrations/agent/execution-preparation.js +67 -0
  180. package/dist/integrations/agent/index.js +0 -2
  181. package/dist/integrations/agent/inline-execution.js +74 -0
  182. package/dist/integrations/agent/model-map.js +515 -0
  183. package/dist/integrations/agent/persona-fallback.js +30 -0
  184. package/dist/integrations/agent/request-lowering.js +186 -0
  185. package/dist/integrations/agent/runner-dispatch.js +230 -37
  186. package/dist/integrations/agent/runner.js +12 -83
  187. package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
  188. package/dist/integrations/harnesses/aider/index.js +0 -1
  189. package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
  190. package/dist/integrations/harnesses/amazonq/index.js +0 -1
  191. package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
  192. package/dist/integrations/harnesses/claude/index.js +1 -5
  193. package/dist/integrations/harnesses/claude/session-log.js +3 -33
  194. package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
  195. package/dist/integrations/harnesses/codex/index.js +0 -1
  196. package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
  197. package/dist/integrations/harnesses/copilot/index.js +0 -1
  198. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
  199. package/dist/integrations/harnesses/gemini/index.js +0 -1
  200. package/dist/integrations/harnesses/index.js +4 -44
  201. package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
  202. package/dist/integrations/harnesses/opencode/index.js +0 -2
  203. package/dist/integrations/harnesses/opencode/session-log.js +14 -204
  204. package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
  205. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
  206. package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
  207. package/dist/integrations/harnesses/openhands/index.js +0 -1
  208. package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
  209. package/dist/integrations/harnesses/pi/index.js +0 -1
  210. package/dist/integrations/harnesses/shared.js +0 -1
  211. package/dist/integrations/harnesses/types.js +1 -3
  212. package/dist/integrations/lockfile.js +82 -79
  213. package/dist/integrations/session-logs/index.js +6 -17
  214. package/dist/integrations/session-logs/provider-base.js +1 -29
  215. package/dist/llm/client.js +10 -5
  216. package/dist/llm/embedder.js +6 -7
  217. package/dist/llm/embedders/local.js +37 -88
  218. package/dist/llm/embedders/types.js +1 -1
  219. package/dist/llm/graph-extract.js +75 -50
  220. package/dist/llm/index-passes.js +43 -5
  221. package/dist/llm/memory-infer.js +8 -6
  222. package/dist/llm/metadata-enhance.js +5 -3
  223. package/dist/llm/structured-call.js +122 -25
  224. package/dist/output/format-exempt.js +1 -1
  225. package/dist/output/render-registry.js +0 -16
  226. package/dist/output/renderers.js +12 -7
  227. package/dist/output/shapes/curate.js +1 -0
  228. package/dist/output/shapes/helpers.js +10 -2
  229. package/dist/output/shapes/passthrough.js +2 -0
  230. package/dist/output/text/command-format.js +31 -33
  231. package/dist/output/text/health-format.js +1 -29
  232. package/dist/output/text/migrate.js +6 -56
  233. package/dist/output/text/proposal-format.js +16 -1
  234. package/dist/output/text/workflow-format.js +16 -0
  235. package/dist/registry/network.js +279 -0
  236. package/dist/registry/pinned-request-helper.js +247 -0
  237. package/dist/registry/pinned-transport.js +717 -0
  238. package/dist/registry/providers/skills-sh.js +18 -6
  239. package/dist/registry/providers/static-index.js +20 -7
  240. package/dist/registry/resolve.js +53 -28
  241. package/dist/scripts/akm-migrate-node.js +19334 -52269
  242. package/dist/scripts/akm-migrate.js +19270 -51612
  243. package/dist/setup/registry-stash-loader.js +64 -20
  244. package/dist/setup/semantic-assets.js +9 -34
  245. package/dist/setup/setup.js +12 -30
  246. package/dist/setup/source-identity.js +17 -0
  247. package/dist/setup/steps/sources.js +36 -15
  248. package/dist/setup/steps/tasks.js +39 -11
  249. package/dist/sources/providers/git-provider.js +3 -3
  250. package/dist/sources/providers/npm.js +2 -2
  251. package/dist/sources/providers/provider-utils.js +4 -3
  252. package/dist/sources/providers/website.js +11 -7
  253. package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
  254. package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
  255. package/dist/sources/website-url.js +73 -0
  256. package/dist/storage/engines/sqlite-migrations.js +81 -26
  257. package/dist/storage/managed-db.js +27 -24
  258. package/dist/storage/repositories/events-repository.js +3 -0
  259. package/dist/storage/repositories/index-connection.js +42 -10
  260. package/dist/storage/repositories/index-entries-repository.js +203 -229
  261. package/dist/storage/repositories/index-entry-mapper.js +8 -12
  262. package/dist/storage/repositories/index-entry-schema.js +255 -0
  263. package/dist/storage/repositories/index-fts-repository.js +64 -71
  264. package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
  265. package/dist/storage/repositories/index-meta-repository.js +0 -11
  266. package/dist/storage/repositories/index-schema.js +74 -350
  267. package/dist/storage/repositories/index-utility-repository.js +12 -17
  268. package/dist/storage/repositories/index-vec-repository.js +56 -7
  269. package/dist/storage/repositories/proposals-repository.js +4 -127
  270. package/dist/storage/repositories/registry-cache.js +2 -1
  271. package/dist/storage/repositories/task-history-repository.js +20 -40
  272. package/dist/storage/repositories/workflow-runs-repository.js +228 -129
  273. package/dist/storage/sqlite-read-snapshot.js +148 -0
  274. package/dist/tasks/backends/cron.js +170 -42
  275. package/dist/tasks/backends/index.js +1 -1
  276. package/dist/tasks/backends/launchd.js +787 -202
  277. package/dist/tasks/backends/schtasks.js +282 -83
  278. package/dist/tasks/embedded.js +7 -7
  279. package/dist/tasks/frozen-script.js +50 -0
  280. package/dist/tasks/resolve-akm-bin.js +5 -1
  281. package/dist/tasks/runner.js +239 -251
  282. package/dist/tasks/runtime-v3.js +281 -0
  283. package/dist/tasks/scheduler-binding.js +272 -0
  284. package/dist/tasks/scheduler-invocation.js +57 -43
  285. package/dist/tasks/scheduler-sync.js +654 -0
  286. package/dist/tasks/source-v3.js +752 -0
  287. package/dist/tasks/standalone-script-entry.js +5 -0
  288. package/dist/tasks/task-id.js +29 -0
  289. package/dist/workflows/authoring/authoring.js +15 -32
  290. package/dist/workflows/exec/dispatch-redaction.js +14 -8
  291. package/dist/workflows/exec/exec-unit.js +7 -28
  292. package/dist/workflows/exec/frozen-judge.js +57 -89
  293. package/dist/workflows/exec/lowering-notices.js +23 -0
  294. package/dist/workflows/exec/native-executor.js +301 -458
  295. package/dist/workflows/exec/param-secrets.js +4 -3
  296. package/dist/workflows/exec/run-workflow.js +26 -32
  297. package/dist/workflows/exec/step-work.js +105 -109
  298. package/dist/workflows/exec/unit-dispatch.js +103 -27
  299. package/dist/workflows/exec/unit-writer.js +3 -3
  300. package/dist/workflows/exec/worktree.js +2 -2
  301. package/dist/workflows/ir/compile.js +86 -72
  302. package/dist/workflows/ir/environment-v4.js +328 -0
  303. package/dist/workflows/ir/freeze-v4.js +122 -0
  304. package/dist/workflows/ir/plan-hash.js +13 -7
  305. package/dist/workflows/ir/schema-v4.js +525 -0
  306. package/dist/workflows/ir/schema.js +25 -284
  307. package/dist/workflows/ir/source-freeze-v4.js +506 -0
  308. package/dist/workflows/parser.js +27 -24
  309. package/dist/workflows/program/schema.js +1 -2
  310. package/dist/workflows/renderer.js +42 -29
  311. package/dist/workflows/resource-limits.js +4 -5
  312. package/dist/workflows/runtime/agent-identity.js +11 -13
  313. package/dist/workflows/runtime/plan-classifier.js +8 -8
  314. package/dist/workflows/runtime/runs.js +27 -43
  315. package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
  316. package/dist/workflows/source-files.js +373 -0
  317. package/dist/workflows/source-ir/compile.js +196 -0
  318. package/dist/workflows/source-ir/github-yaml.js +577 -0
  319. package/dist/workflows/source-ir/ordering.js +38 -0
  320. package/dist/workflows/source-ir/program.js +50 -0
  321. package/dist/workflows/source-ir/result.js +26 -0
  322. package/dist/workflows/source-ir/schema.js +772 -0
  323. package/dist/workflows/source-ir/semantics.js +242 -0
  324. package/dist/workflows/source-ir/uses.js +14 -0
  325. package/docs/README.md +2 -0
  326. package/docs/migration/README.md +3 -1
  327. package/docs/migration/release-notes/0.9.2.md +55 -0
  328. package/docs/migration/release-notes/README.md +5 -0
  329. package/docs/migration/v0.8-to-v0.9.md +76 -1077
  330. package/docs/migration/v0.9.0-troubleshooting.md +104 -516
  331. package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
  332. package/docs/reference/README.md +1 -0
  333. package/docs/reference/cli.md +230 -98
  334. package/docs/reference/configuration.md +159 -36
  335. package/docs/reference/data-and-telemetry.md +19 -1
  336. package/docs/reference/supported-formats.md +23 -3
  337. package/docs/reference/tasks.md +182 -0
  338. package/docs/reference/workflow-schema.md +91 -40
  339. package/docs/reference/workflows.md +33 -6
  340. package/package.json +10 -6
  341. package/schemas/akm-config.json +372 -224
  342. package/schemas/akm-task.json +324 -80
  343. package/schemas/akm-workflow.json +6 -9
  344. package/dist/core/migration-operation.js +0 -75
  345. package/dist/integrations/agent/model-aliases.js +0 -74
  346. package/dist/tasks/parser.js +0 -380
  347. package/dist/tasks/schema.js +0 -123
  348. package/dist/tasks/validator.js +0 -80
  349. package/dist/workflows/ir/freeze.js +0 -320
  350. package/dist/workflows/runtime/document-cache.js +0 -13
@@ -1,34 +1,110 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { deepMergeConfig } from "../../core/config/deep-merge.js";
5
- import { resolveCredentialFromEnv } from "../../integrations/agent/engine-resolution.js";
4
+ import { ConfigError } from "../../core/errors.js";
5
+ import { assertFrozenDirectoryIdentity } from "../../execution/directory-identity.js";
6
+ import { assertFrozenExecutableIdentity } from "../../execution/executable-identity.js";
7
+ import { canonicalResolvedExecutionRequest, decodeResolvedExecutionRequest, } from "../../execution/resolved-request.js";
8
+ import { dispatchLoweredExecutionRequest, lowerResolvedExecutionRequestWithRunner, } from "../../integrations/agent/execution-lowering.js";
9
+ import { getHarness } from "../../integrations/harnesses/index.js";
10
+ /** Lower a persisted v4 common request through its persisted runner only. */
11
+ export function prepareWorkflowExecution(request, prompt = request.prompt) {
12
+ const target = request.frozenTarget;
13
+ if (target.cwdIdentity)
14
+ assertFrozenDirectoryIdentity(target.cwdIdentity);
15
+ if (target.executable)
16
+ assertFrozenExecutableIdentity(target.executable, `unit ${request.unitId} executable`);
17
+ const wire = JSON.parse(canonicalResolvedExecutionRequest(target.request));
18
+ const command = { ...wire.command, content: prompt };
19
+ const runtime = {
20
+ ...wire.runtime,
21
+ ...(request.cwd !== undefined
22
+ ? { workspace: request.cwd }
23
+ : target.cwdIdentity
24
+ ? { workspace: target.cwdIdentity.realCwd }
25
+ : {}),
26
+ ...(request.env !== undefined ? { environment: request.env } : {}),
27
+ };
28
+ wire.command = command;
29
+ wire.runtime = runtime;
30
+ if (request.systemPrompt !== undefined) {
31
+ wire.conversation = [{ role: "system", content: request.systemPrompt }];
32
+ }
33
+ return lowerResolvedExecutionRequestWithRunner(decodeResolvedExecutionRequest(wire), target.runner);
34
+ }
35
+ function message(err) {
36
+ return err instanceof Error ? err.message : String(err);
37
+ }
6
38
  /**
7
- * Materialize a frozen llm engine snapshot into a live connection: resolve the
8
- * credential out of `process.env`, then apply the invocation's model/llm
9
- * overrides. The ONE definition — the default dispatcher's llm runner and the
10
- * frozen gate judge both dispatch through it, so credential resolution and
11
- * connection-field mapping cannot drift between the two llm dispatch paths.
12
- *
13
- * The credential read itself is {@link resolveCredentialFromEnv}, shared with
14
- * the live-config dispatch boundary (`materializeLlmConnection`): a frozen
15
- * snapshot's `credential` and a resolved engine's `CredentialDescriptor` are the
16
- * same descriptor, so lookup order and the "required … is not set" failure are
17
- * one implementation, not two that happen to agree.
39
+ * Dispatch one frozen workflow engine call through the common prepared/lowered
40
+ * seam. Credential materialization happens inside the final dispatch only.
18
41
  */
19
- export function materializeFrozenLlm(snapshot, invocation) {
20
- const apiKey = resolveCredentialFromEnv(snapshot.credential);
21
- const base = {
22
- provider: snapshot.provider,
23
- endpoint: snapshot.endpoint,
24
- model: invocation?.model ?? snapshot.model,
25
- ...(snapshot.temperature !== undefined ? { temperature: snapshot.temperature } : {}),
26
- ...(snapshot.maxTokens !== undefined ? { maxTokens: snapshot.maxTokens } : {}),
27
- ...(snapshot.supportsJsonSchema !== undefined ? { supportsJsonSchema: snapshot.supportsJsonSchema } : {}),
28
- ...(snapshot.extraParams ? { extraParams: snapshot.extraParams } : {}),
29
- ...(snapshot.contextLength !== undefined ? { contextLength: snapshot.contextLength } : {}),
30
- ...(snapshot.enableThinking !== undefined ? { enableThinking: snapshot.enableThinking } : {}),
31
- ...(apiKey ? { apiKey } : {}),
42
+ export async function dispatchWorkflowExecution(request, feedback) {
43
+ const prompt = feedback ? `${request.prompt}\n\n${feedback}` : request.prompt;
44
+ if (request.frozenTarget.kind !== "command") {
45
+ throw new ConfigError(`unit ${JSON.stringify(request.unitId)} is not a command target.`, "INVALID_CONFIG_FILE");
46
+ }
47
+ const lowered = prepareWorkflowExecution(request, prompt);
48
+ const notices = lowered.notices.length > 0 ? lowered.notices : undefined;
49
+ if (request.env && Object.keys(request.env).length > 0 && lowered.runner.kind === "llm") {
50
+ return {
51
+ ok: false,
52
+ text: "",
53
+ failureReason: "env_unsupported",
54
+ error: `unit ${JSON.stringify(request.unitId)} declares env bindings, which require a child process ` +
55
+ `(agent or sdk runner) — the "llm" runner cannot inject a per-unit child environment.`,
56
+ ...(notices ? { notices } : {}),
57
+ };
58
+ }
59
+ if (request.cwd && lowered.runner.kind === "llm") {
60
+ return {
61
+ ok: false,
62
+ text: "",
63
+ failureReason: "isolation_unsupported",
64
+ error: `unit ${JSON.stringify(request.unitId)} declares isolation: worktree but resolved to the "llm" runner, ` +
65
+ `which has no working directory to isolate. Use the agent or sdk runner for isolated units.`,
66
+ ...(notices ? { notices } : {}),
67
+ };
68
+ }
69
+ let result;
70
+ try {
71
+ result = await dispatchLoweredExecutionRequest(lowered, {
72
+ runOptions: {
73
+ stdio: "captured",
74
+ parseOutput: "text",
75
+ ...(request.signal ? { signal: request.signal } : {}),
76
+ },
77
+ });
78
+ }
79
+ catch (err) {
80
+ if (err instanceof ConfigError)
81
+ throw err;
82
+ return {
83
+ ok: false,
84
+ text: "",
85
+ failureReason: "dispatch_error",
86
+ error: message(err),
87
+ ...(notices ? { notices } : {}),
88
+ };
89
+ }
90
+ let text = result.stdout;
91
+ let sessionId = result.sessionId;
92
+ if (lowered.runner.kind === "agent" && result.ok) {
93
+ const harness = getHarness(lowered.runner.profile.platform ?? lowered.runner.profile.name);
94
+ if (harness?.resultExtractor) {
95
+ const extraction = harness.resultExtractor(result);
96
+ text = extraction.text;
97
+ if (extraction.sessionId !== undefined)
98
+ sessionId = extraction.sessionId;
99
+ }
100
+ }
101
+ return {
102
+ ok: result.ok,
103
+ text,
104
+ ...(sessionId !== undefined ? { sessionId } : {}),
105
+ ...(result.reason ? { failureReason: result.reason } : {}),
106
+ ...(result.error ? { error: result.error } : {}),
107
+ ...(result.usage ? { usage: result.usage } : {}),
108
+ ...(notices ? { notices } : {}),
32
109
  };
33
- return invocation?.llm ? deepMergeConfig(base, invocation.llm) : base;
34
110
  }
@@ -16,11 +16,11 @@
16
16
  * admission control: every unit write executes strictly in enqueue order.
17
17
  *
18
18
  * That is the ONLY invariant the chain owns. In particular it does NOT own
19
- * per-unit insert→finish ordering: `dispatchJournaledAttempt` awaits its insert
19
+ * per-unit reserve→finish ordering: `dispatchJournaledAttempt` awaits its reservation
20
20
  * before it dispatches and only finishes after the dispatch resolves, so a
21
21
  * unit's own writes are ordered by program order, not by queue position. The
22
- * queue could be reordered arbitrarily between units without breaking
23
- * `finishUnitFromDispatch`'s row-conditional logic.
22
+ * queue could be reordered arbitrarily between units without breaking the
23
+ * attempt claim/dispatch CAS.
24
24
  *
25
25
  * ## Scope of the serialization (issue B)
26
26
  *
@@ -225,7 +225,7 @@ async function pathExists(p) {
225
225
  * GC sweep — in this process or another one — never collects the tree while the
226
226
  * unit is still running in it.
227
227
  */
228
- export async function createUnitWorktree(baseDir, runId, attemptId) {
228
+ export async function createUnitWorktree(baseDir, runId, attemptId, commitOid) {
229
229
  // Opportunistic, at most once per process, never awaited — GC must never sit
230
230
  // on the dispatch path.
231
231
  sweepStaleWorktreesOnce();
@@ -273,7 +273,7 @@ export async function createUnitWorktree(baseDir, runId, attemptId) {
273
273
  prunedRuns.set(runId, new Set([repoKey]));
274
274
  await git(baseDir, ["worktree", "prune"]);
275
275
  }
276
- const added = await git(baseDir, ["worktree", "add", "--detach", dest]);
276
+ const added = await git(baseDir, ["worktree", "add", "--detach", dest, ...(commitOid ? [commitOid] : [])]);
277
277
  if (!added.ok) {
278
278
  return {
279
279
  ok: false,
@@ -4,10 +4,9 @@
4
4
  /**
5
5
  * Frontend -> unresolved workflow plan compiler (workflow-format-unification).
6
6
  *
7
- * ONE frontend now: {@link compileWorkflowPlan} lowers a parsed unified
8
- * `WorkflowDocument` (`../parser.ts`) into the same `WorkflowPlanDraft` shape
9
- * IR v3 has always consumed the pre-unification split between a linear
10
- * markdown compiler and a YAML-program compiler is gone. This pass owns the
7
+ * ONE frontend now: {@link compileWorkflowPlan} lowers adapter-neutral source
8
+ * IR into the current unresolved plan draft. Markdown and YAML never reach a
9
+ * format-specific runtime compiler. This pass owns the
11
10
  * semantic rules the parser deliberately does not check:
12
11
  *
13
12
  * - every reference string (`map.over` / `route.input` / `inputs[]`) parses
@@ -28,18 +27,33 @@
28
27
  */
29
28
  import { formatReference, parseReference } from "../program/expressions.js";
30
29
  import { projectExecCore } from "../program/schema.js";
30
+ import { sourceStepInstructions, sourceStepProgramUnit, sourceStepRef } from "../source-ir/program.js";
31
+ import { decodeWorkflowSourceIrV1, } from "../source-ir/schema.js";
31
32
  /**
32
- * Compile a parsed unified workflow document into a frozen-plan-ready graph.
33
+ * Compile source IR into a frozen-plan-ready graph.
33
34
  * `title` is the run-level display title (the asset's canonical name — the
34
35
  * format carries no authored title). Assumes the document came out of
35
36
  * `parseWorkflow` ok (structure already valid).
36
37
  */
37
- export function compileWorkflowPlan(document, title) {
38
+ export function compileWorkflowPlan(input, title, resolvedUnits = new Map()) {
39
+ const sourceIr = decodeWorkflowSourceIrV1(input);
38
40
  const errors = [];
39
- const allStepIds = new Set(document.steps.map((s) => s.id));
41
+ if (sourceIr.jobs.length !== 1) {
42
+ return {
43
+ ok: false,
44
+ errors: [
45
+ {
46
+ line: sourceIr.jobs[1]?.source.start ?? sourceIr.source.start,
47
+ message: "Current workflow execution requires exactly one source-IR job.",
48
+ },
49
+ ],
50
+ };
51
+ }
52
+ const sourceSteps = sourceIr.jobs[0]?.steps ?? [];
53
+ const allStepIds = new Set(sourceSteps.map((step) => step.id));
40
54
  const earlierStepIds = new Set();
41
55
  const steps = [];
42
- document.steps.forEach((step) => {
56
+ sourceSteps.forEach((step, sequenceIndex) => {
43
57
  const check = { allStepIds, earlierStepIds, errors };
44
58
  if (step.map) {
45
59
  checkReferenceField(step.map.over, { ...check, line: step.source.start, label: `Step "${step.id}" map.over` });
@@ -58,24 +72,26 @@ export function compileWorkflowPlan(document, title) {
58
72
  label: `Step "${step.id}" inputs`,
59
73
  });
60
74
  }
61
- steps.push(compileStep(step, defaultsOf(document)));
75
+ steps.push(compileStep(step, sequenceIndex, sourceIr.defaults, resolvedUnits.get(step.id)));
62
76
  earlierStepIds.add(step.id);
63
77
  });
64
78
  if (errors.length > 0)
65
79
  return { ok: false, errors };
66
- const paramNames = document.params ? Object.keys(document.params) : [];
80
+ const paramNames = sourceIr.params ? Object.keys(sourceIr.params) : [];
67
81
  return {
68
82
  ok: true,
69
- warnings: collectWorkflowWarnings(document),
83
+ warnings: collectWorkflowWarnings(sourceIr),
70
84
  plan: {
71
85
  title,
72
86
  ...(paramNames.length > 0 ? { params: paramNames } : {}),
73
- ...(document.params && paramNames.length > 0 ? { paramSchemas: document.params } : {}),
74
- ...(document.budget
87
+ ...(sourceIr.params && paramNames.length > 0
88
+ ? { paramSchemas: sourceIr.params }
89
+ : {}),
90
+ ...(sourceIr.budget
75
91
  ? {
76
92
  budget: {
77
- ...(document.budget.maxTokens !== undefined ? { maxTokens: document.budget.maxTokens } : {}),
78
- ...(document.budget.maxUnits !== undefined ? { maxUnits: document.budget.maxUnits } : {}),
93
+ ...(sourceIr.budget.maxTokens !== undefined ? { maxTokens: sourceIr.budget.maxTokens } : {}),
94
+ ...(sourceIr.budget.maxUnits !== undefined ? { maxUnits: sourceIr.budget.maxUnits } : {}),
79
95
  },
80
96
  }
81
97
  : {}),
@@ -83,10 +99,7 @@ export function compileWorkflowPlan(document, title) {
83
99
  },
84
100
  };
85
101
  }
86
- function defaultsOf(document) {
87
- return document.defaults;
88
- }
89
- function compileStep(step, defaults) {
102
+ function compileStep(step, sequenceIndex, defaults, resolved) {
90
103
  const gate = {
91
104
  kind: "gate",
92
105
  id: `${step.id}.gate`,
@@ -94,31 +107,32 @@ function compileStep(step, defaults) {
94
107
  // The body `### gate` rubric is carried through as the ONE criterion string
95
108
  // — the judge receives the whole section byte-exact (spec §2.4). A step
96
109
  // with no rubric needs no verification (criteria: []).
97
- criteria: step.gateRubric?.text.trim() ? [step.gateRubric.text] : [],
110
+ criteria: step.gate?.rubric?.trim() ? [step.gate.rubric] : [],
98
111
  ...(step.gate?.maxLoops !== undefined ? { maxLoops: step.gate.maxLoops } : {}),
99
112
  };
100
113
  let root;
101
114
  if (step.route === undefined) {
102
- const instructionsText = step.instructions?.text ?? "";
115
+ const unit = resolved?.unit ?? sourceStepProgramUnit(step);
116
+ const instructionsText = resolved?.instructions ?? sourceStepInstructions(step);
103
117
  if (step.map) {
104
118
  root = {
105
119
  kind: "map",
106
120
  id: `${step.id}.map`,
107
121
  over: step.map.over,
108
- template: compileUnit(step.map.unit, `${step.id}.unit`, instructionsText, defaults, step.inputs, step.source),
122
+ template: compileUnit(unit, `${step.id}.unit`, instructionsText, defaults, step.inputs, sourceStepRef(step)),
109
123
  ...(step.map.concurrency !== undefined ? { concurrency: step.map.concurrency } : {}),
110
124
  reducer: step.map.reducer ?? "collect",
111
125
  source: step.source,
112
126
  };
113
127
  }
114
128
  else {
115
- root = compileUnit(step.unit, step.id, instructionsText, defaults, step.inputs, step.instructions?.source);
129
+ root = compileUnit(unit, step.id, instructionsText, defaults, step.inputs, sourceStepRef(step));
116
130
  }
117
131
  }
118
132
  return {
119
133
  stepId: step.id,
120
134
  title: step.id,
121
- sequenceIndex: step.sequenceIndex,
135
+ sequenceIndex,
122
136
  ...(root ? { root } : {}),
123
137
  ...(step.route
124
138
  ? {
@@ -144,18 +158,15 @@ function compileUnit(unit, id, instructions, defaults, inputs, source) {
144
158
  kind: "unit",
145
159
  id,
146
160
  instructions,
147
- templating: "verbatim",
148
161
  ...(inputs && inputs.length > 0 ? { inputs: [...inputs] } : {}),
149
- // Shared projection: both env-scope keys are carried CONDITIONALLY (and
150
- // `inheritEnv` only when true), so an exec unit that says nothing about its
151
- // environment freezes and therefore hashes — byte-identically to one
152
- // authored before these keys existed.
153
- ...(unit?.exec ? { exec: projectExecCore(unit.exec) } : {}),
154
- ...(unit?.output !== undefined ? { schema: unit.output } : {}),
155
- ...(unit?.retry ? { retry: { max: unit.retry.max, on: [...unit.retry.on] } } : {}),
156
- onError: unit?.onError ?? defaults?.onError ?? "fail",
157
- ...(unit?.env ? { env: [...unit.env] } : {}),
158
- ...(unit?.isolation !== undefined ? { isolation: unit.isolation } : {}),
162
+ // Shared projection: named pass-through scope is carried conditionally;
163
+ // whole-process environment inheritance is not an authoring surface.
164
+ ...(unit.exec ? { exec: projectExecCore(unit.exec) } : {}),
165
+ ...(unit.output !== undefined ? { schema: unit.output } : {}),
166
+ ...(unit.retry ? { retry: { max: unit.retry.max, on: [...unit.retry.on] } } : {}),
167
+ onError: unit.onError ?? defaults?.onError ?? "fail",
168
+ ...(unit.env ? { env: [...unit.env] } : {}),
169
+ ...(unit.isolation !== undefined ? { isolation: unit.isolation } : {}),
159
170
  ...(source ? { source } : {}),
160
171
  };
161
172
  }
@@ -223,47 +234,50 @@ function checkInputReference(text, index, check) {
223
234
  * only re-run the identical command — and its side effects. The declared
224
235
  * budget is not silently different from what runs; say so.
225
236
  */
226
- export function collectWorkflowWarnings(document) {
237
+ export function collectWorkflowWarnings(input) {
238
+ const sourceIr = decodeWorkflowSourceIrV1(input);
227
239
  const warnings = [];
228
- const declaredParams = document.params ? new Set(Object.keys(document.params)) : undefined;
229
- for (const step of document.steps) {
230
- const maxLoops = step.gate?.maxLoops ?? 1;
231
- const execUnit = step.map ? step.map.unit?.exec : step.unit?.exec;
232
- if (maxLoops > 1 && execUnit && step.gateRubric?.text.trim()) {
233
- warnings.push({
234
- line: step.source.start,
235
- message: `Step "${step.id}" declares \`gate.max_loops: ${maxLoops}\` on an \`exec\` step — it runs its command ` +
236
- `ONCE. A gate loop re-executes the step so it can address the judge's feedback, and a frozen argv cannot ` +
237
- `read that feedback; looping would only repeat the command's side effects. The gate still evaluates and ` +
238
- `can still fail the step.`,
239
- });
240
- }
241
- if ((step.map || step.route === undefined) && step.output === undefined) {
242
- warnings.push({
243
- line: step.source.start,
244
- message: `Step "${step.id}" declares no \`output:\` schema — its unit results are carried as an untyped ` +
245
- `artifact (permitted). Add an \`output:\` JSON Schema to type and validate the step artifact.`,
246
- });
247
- }
248
- if (declaredParams) {
249
- const declaredList = [...declaredParams].join(", ");
250
- const scan = (text, label) => {
251
- if (!text)
252
- return;
253
- const parsed = parseReference(text);
254
- if (!parsed.ok || parsed.expr.kind !== "param" || declaredParams.has(parsed.expr.name))
255
- return;
240
+ const declaredParams = sourceIr.params ? new Set(Object.keys(sourceIr.params)) : undefined;
241
+ for (const job of sourceIr.jobs) {
242
+ for (const step of job.steps) {
243
+ const maxLoops = step.gate?.maxLoops ?? 1;
244
+ const execUnit = step.exec ?? step.run;
245
+ if (maxLoops > 1 && execUnit && step.gate?.rubric?.trim()) {
256
246
  warnings.push({
257
247
  line: step.source.start,
258
- message: `${label}: "${formatReference(parsed.expr)}" references a param not declared in \`params:\` ` +
259
- `(declared: ${declaredList || "none"}) likely a typo. An undeclared param supplied at start still ` +
260
- `resolves at run time.`,
248
+ message: `Step "${step.id}" declares \`gate.max_loops: ${maxLoops}\` on an \`exec\` step — it runs its command ` +
249
+ `ONCE. A gate loop re-executes the step so it can address the judge's feedback, and a frozen argv cannot ` +
250
+ `read that feedback; looping would only repeat the command's side effects. The gate still evaluates and ` +
251
+ `can still fail the step.`,
261
252
  });
262
- };
263
- if (step.map)
264
- scan(step.map.over, `Step "${step.id}" map.over`);
265
- if (step.route)
266
- scan(step.route.input, `Step "${step.id}" route.input`);
253
+ }
254
+ if ((step.map || step.route === undefined) && step.output === undefined) {
255
+ warnings.push({
256
+ line: step.source.start,
257
+ message: `Step "${step.id}" declares no \`output:\` schema — its unit results are carried as an untyped ` +
258
+ `artifact (permitted). Add an \`output:\` JSON Schema to type and validate the step artifact.`,
259
+ });
260
+ }
261
+ if (declaredParams) {
262
+ const declaredList = [...declaredParams].join(", ");
263
+ const scan = (text, label) => {
264
+ if (!text)
265
+ return;
266
+ const parsed = parseReference(text);
267
+ if (!parsed.ok || parsed.expr.kind !== "param" || declaredParams.has(parsed.expr.name))
268
+ return;
269
+ warnings.push({
270
+ line: step.source.start,
271
+ message: `${label}: "${formatReference(parsed.expr)}" references a param not declared in \`params:\` ` +
272
+ `(declared: ${declaredList || "none"}) — likely a typo. An undeclared param supplied at start still ` +
273
+ `resolves at run time.`,
274
+ });
275
+ };
276
+ if (step.map)
277
+ scan(step.map.over, `Step "${step.id}" map.over`);
278
+ if (step.route)
279
+ scan(step.route.input, `Step "${step.id}" route.input`);
280
+ }
267
281
  }
268
282
  }
269
283
  return warnings;