akm-cli 0.9.17-alpha.2 → 0.9.17-alpha.4

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 (343) hide show
  1. package/CHANGELOG.md +756 -0
  2. package/dist/akm +94 -196
  3. package/dist/cli/shared.js +6 -2
  4. package/dist/cli.js +22 -9
  5. package/dist/commands/agent/agent-dispatch.js +1 -1
  6. package/dist/commands/command/command-execution.js +24 -62
  7. package/dist/commands/feedback-cli.js +0 -1
  8. package/dist/commands/health/accept-rate.js +2 -2
  9. package/dist/commands/health/checks.js +30 -75
  10. package/dist/commands/health/config-skew.js +38 -0
  11. package/dist/commands/health/egress.js +54 -0
  12. package/dist/commands/health/html-report.js +0 -38
  13. package/dist/commands/health/improve-metrics.js +123 -562
  14. package/dist/commands/health/plugin-staleness.js +53 -3
  15. package/dist/commands/health/renderers.js +12 -4
  16. package/dist/commands/health/report-view-model.js +11 -106
  17. package/dist/commands/health/types-improve.js +4 -19
  18. package/dist/commands/health/windows.js +64 -73
  19. package/dist/commands/health.js +122 -143
  20. package/dist/commands/improve/consolidate/chunking.js +25 -100
  21. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  22. package/dist/commands/improve/consolidate.js +538 -1075
  23. package/dist/commands/improve/content-hash.js +16 -24
  24. package/dist/commands/improve/distill/content-repair.js +18 -100
  25. package/dist/commands/improve/distill-guards.js +20 -81
  26. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  27. package/dist/commands/improve/distill.js +608 -1075
  28. package/dist/commands/improve/eligibility.js +126 -400
  29. package/dist/commands/improve/execution.js +3 -5
  30. package/dist/commands/improve/extract.js +487 -1046
  31. package/dist/commands/improve/feedback-valence.js +0 -25
  32. package/dist/commands/improve/improve-cli.js +29 -166
  33. package/dist/commands/improve/improve-result-file.js +10 -66
  34. package/dist/commands/improve/improve-strategies.js +12 -7
  35. package/dist/commands/improve/improve-usage-report.js +18 -64
  36. package/dist/commands/improve/improve.js +443 -1063
  37. package/dist/commands/improve/ledger.js +114 -0
  38. package/dist/commands/improve/locks.js +2 -8
  39. package/dist/commands/improve/loop-stages.js +459 -1172
  40. package/dist/commands/improve/memory/derived-ref.js +12 -77
  41. package/dist/commands/improve/memory/memory-belief.js +14 -118
  42. package/dist/commands/improve/memory/memory-improve.js +4 -3
  43. package/dist/commands/improve/outcome-loop.js +28 -156
  44. package/dist/commands/improve/planner.js +5 -10
  45. package/dist/commands/improve/preparation.js +851 -2339
  46. package/dist/commands/improve/proactive-maintenance.js +34 -101
  47. package/dist/commands/improve/reflect-noise.js +104 -280
  48. package/dist/commands/improve/reflect.js +621 -1367
  49. package/dist/commands/improve/salience.js +46 -232
  50. package/dist/commands/improve/session-asset.js +19 -100
  51. package/dist/commands/improve/stage.js +323 -0
  52. package/dist/commands/proposal/drain.js +251 -644
  53. package/dist/commands/proposal/proposal-cli.js +3 -18
  54. package/dist/commands/proposal/proposal-types.js +20 -41
  55. package/dist/commands/proposal/proposal.js +1 -2
  56. package/dist/commands/proposal/propose.js +134 -160
  57. package/dist/commands/proposal/repository.js +502 -1487
  58. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  59. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  60. package/dist/commands/proposal/validators/proposals.js +13 -89
  61. package/dist/commands/read/curate.js +63 -413
  62. package/dist/commands/read/search-cli.js +16 -33
  63. package/dist/commands/read/search.js +17 -23
  64. package/dist/commands/read/show.js +2 -13
  65. package/dist/commands/sources/bundle-cli.js +25 -2
  66. package/dist/commands/sources/bundle-config-ops.js +7 -0
  67. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  68. package/dist/commands/sources/info.js +2 -11
  69. package/dist/commands/sources/installed-stashes.js +197 -746
  70. package/dist/commands/sources/schema-repair.js +98 -129
  71. package/dist/commands/sources/source-add.js +62 -12
  72. package/dist/commands/sources/stash-cli.js +1 -1
  73. package/dist/commands/tasks/explain.js +10 -13
  74. package/dist/commands/tasks/tasks-cli.js +9 -8
  75. package/dist/commands/tasks/tasks.js +326 -930
  76. package/dist/commands/tasks/validate.js +42 -21
  77. package/dist/commands/workflow/plan.js +22 -29
  78. package/dist/commands/workflow-cli.js +4 -4
  79. package/dist/core/adapter/adapters/akm-adapter.js +0 -1
  80. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  81. package/dist/core/adapter/adapters/akm-metadata.js +11 -12
  82. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  83. package/dist/core/adapter/execution-source.js +17 -29
  84. package/dist/core/asset/resolve-ref.js +1 -1
  85. package/dist/core/bundle-id.js +42 -5
  86. package/dist/core/bundle-rename.js +291 -0
  87. package/dist/core/config/config-io.js +1 -2
  88. package/dist/core/config/config-schema.js +1 -33
  89. package/dist/core/config/config-walker.js +1 -1
  90. package/dist/core/config/config.js +163 -68
  91. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  92. package/dist/core/config/schema/embedding.js +20 -5
  93. package/dist/core/config/schema/engines.js +5 -0
  94. package/dist/core/config/schema/execution.js +1 -1
  95. package/dist/core/config/schema/experimental.js +1 -1
  96. package/dist/core/config/schema/improve-processes.js +21 -95
  97. package/dist/core/config/schema/improve.js +4 -42
  98. package/dist/core/config/schema/scheduler.js +12 -12
  99. package/dist/core/config/schema/search.js +6 -22
  100. package/dist/core/env-secret-ref.js +0 -1
  101. package/dist/core/errors.js +8 -9
  102. package/dist/core/file-lock.js +76 -173
  103. package/dist/core/logs-db.js +2 -2
  104. package/dist/core/paths.js +0 -27
  105. package/dist/core/redaction.js +109 -2
  106. package/dist/core/run-lock.js +2 -5
  107. package/dist/core/spawn-env.js +1 -1
  108. package/dist/core/state/migrations.js +108 -61
  109. package/dist/core/state-db-scope.js +2 -4
  110. package/dist/core/state-db.js +126 -692
  111. package/dist/core/type-presentation.js +1 -9
  112. package/dist/core/write-source.js +293 -1012
  113. package/dist/execution/input-contract.js +1 -1
  114. package/dist/execution/resolved-request.js +135 -689
  115. package/dist/execution/source.js +63 -257
  116. package/dist/execution/target-ref.js +1 -1
  117. package/dist/indexer/bundle-identity-guard.js +2 -2
  118. package/dist/indexer/db/graph-db.js +106 -46
  119. package/dist/indexer/ensure-index.js +44 -85
  120. package/dist/indexer/graph/graph-extraction.js +340 -562
  121. package/dist/indexer/graph/graph-related.js +130 -0
  122. package/dist/indexer/index-rebuild-lock.js +3 -11
  123. package/dist/indexer/index-writer-lock.js +8 -17
  124. package/dist/indexer/index-written-assets.js +139 -151
  125. package/dist/indexer/indexer.js +524 -846
  126. package/dist/indexer/materialize-embeddings.js +60 -397
  127. package/dist/indexer/passes/memory-inference.js +81 -90
  128. package/dist/indexer/passes/metadata.js +132 -200
  129. package/dist/indexer/read-preflight.js +0 -7
  130. package/dist/indexer/scan/doc-to-entry.js +1 -3
  131. package/dist/indexer/scan/drain-dir.js +1 -1
  132. package/dist/indexer/search/db-search.js +181 -590
  133. package/dist/indexer/search/fts-query.js +30 -41
  134. package/dist/indexer/search/ranking.js +28 -154
  135. package/dist/indexer/search/search-attribution.js +12 -32
  136. package/dist/indexer/search/search-fields.js +11 -15
  137. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  138. package/dist/indexer/search/search-source.js +1 -4
  139. package/dist/indexer/usage/usage-events.js +2 -7
  140. package/dist/integrations/agent/engine-fallback.js +23 -40
  141. package/dist/integrations/agent/engine-resolution.js +93 -183
  142. package/dist/integrations/agent/execution.js +507 -0
  143. package/dist/integrations/agent/model-map.js +28 -156
  144. package/dist/integrations/agent/request-lowering.js +66 -141
  145. package/dist/integrations/agent/runner-dispatch.js +143 -321
  146. package/dist/integrations/agent/runner.js +54 -14
  147. package/dist/integrations/lockfile.js +53 -101
  148. package/dist/llm/embedders/deterministic.js +2 -3
  149. package/dist/llm/embedders/profile.js +71 -0
  150. package/dist/llm/embedders/remote.js +10 -15
  151. package/dist/llm/graph-extract.js +3 -12
  152. package/dist/llm/index-passes.js +3 -5
  153. package/dist/llm/memory-infer.js +1 -2
  154. package/dist/llm/metadata-enhance.js +1 -2
  155. package/dist/llm/structured-call.js +5 -24
  156. package/dist/output/generic-render.js +23 -11
  157. package/dist/output/html-render.js +13 -10
  158. package/dist/output/render-registry.js +3 -32
  159. package/dist/output/shapes/helpers.js +2 -34
  160. package/dist/output/shapes/passthrough.js +1 -9
  161. package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
  162. package/dist/output/text/command-format.js +60 -23
  163. package/dist/output/text/helpers.js +1 -1
  164. package/dist/output/text/migrate.js +5 -14
  165. package/dist/output/text/proposal-format.js +1 -2
  166. package/dist/output/text/workflow-format.js +0 -32
  167. package/dist/output/text.js +2 -0
  168. package/dist/registry/factory.js +4 -19
  169. package/dist/registry/network.js +66 -220
  170. package/dist/registry/providers/index.js +0 -2
  171. package/dist/registry/providers/skills-sh.js +3 -14
  172. package/dist/registry/providers/static-index.js +24 -26
  173. package/dist/registry/resolve.js +55 -131
  174. package/dist/scripts/akm-migrate-node.js +43937 -93313
  175. package/dist/scripts/akm-migrate.js +43697 -93071
  176. package/dist/setup/registry-stash-loader.js +4 -13
  177. package/dist/setup/semantic-assets.js +3 -44
  178. package/dist/setup/setup.js +1 -1
  179. package/dist/setup/steps/tasks.js +25 -15
  180. package/dist/sources/provider-factory.js +17 -18
  181. package/dist/sources/providers/filesystem.js +2 -3
  182. package/dist/sources/providers/git-install.js +7 -1
  183. package/dist/sources/providers/git-provider.js +0 -3
  184. package/dist/sources/providers/git-stash.js +0 -17
  185. package/dist/sources/providers/npm.js +2 -4
  186. package/dist/sources/providers/provider-utils.js +5 -10
  187. package/dist/sources/providers/website.js +0 -2
  188. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  189. package/dist/sources/website-url.js +2 -2
  190. package/dist/storage/database.js +9 -35
  191. package/dist/storage/repositories/improve-ledger-repository.js +168 -0
  192. package/dist/storage/repositories/index-connection.js +34 -70
  193. package/dist/storage/repositories/index-entries-repository.js +69 -111
  194. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  195. package/dist/storage/repositories/index-entry-schema.js +83 -269
  196. package/dist/storage/repositories/index-fts-repository.js +86 -256
  197. package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
  198. package/dist/storage/repositories/index-meta-repository.js +6 -4
  199. package/dist/storage/repositories/index-schema.js +192 -220
  200. package/dist/storage/repositories/index-utility-repository.js +8 -29
  201. package/dist/storage/repositories/index-vec-repository.js +133 -414
  202. package/dist/storage/repositories/outcome-repository.js +2 -1
  203. package/dist/storage/repositories/proposals-repository.js +35 -0
  204. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  205. package/dist/storage/repositories/task-history-repository.js +26 -4
  206. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  207. package/dist/storage/sqlite-migrations.js +136 -0
  208. package/dist/storage/sqlite-pragmas.js +11 -9
  209. package/dist/storage/sqlite-transaction.js +170 -0
  210. package/dist/storage/state-db-integrity.js +34 -27
  211. package/dist/tasks/activation-config.js +134 -62
  212. package/dist/tasks/backends/cron.js +129 -277
  213. package/dist/tasks/backends/exec-utils.js +2 -5
  214. package/dist/tasks/backends/launchd.js +125 -745
  215. package/dist/tasks/backends/schtasks.js +101 -620
  216. package/dist/tasks/prepare/prepare-support.js +5 -15
  217. package/dist/tasks/prepare/prepare.js +0 -2
  218. package/dist/tasks/resolve-akm-bin.js +20 -79
  219. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  220. package/dist/tasks/scheduler-binding.js +18 -238
  221. package/dist/tasks/scheduler-invocation.js +52 -52
  222. package/dist/tasks/scheduler-lock.js +53 -0
  223. package/dist/tasks/scheduler-sync.js +363 -679
  224. package/dist/tasks/source/parse-task-source.js +160 -10
  225. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  226. package/dist/tasks/source/task-to-v4.js +2 -2
  227. package/dist/workflows/authoring/authoring.js +3 -12
  228. package/dist/workflows/compile.js +211 -0
  229. package/dist/workflows/concurrency-policy.js +13 -74
  230. package/dist/workflows/exec/child-invocation.js +3 -17
  231. package/dist/workflows/exec/child-workflow.js +32 -141
  232. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  233. package/dist/workflows/exec/environment.js +98 -0
  234. package/dist/workflows/exec/exec-unit.js +33 -140
  235. package/dist/workflows/exec/frozen-judge.js +7 -59
  236. package/dist/workflows/exec/native-executor.js +82 -341
  237. package/dist/workflows/exec/param-secrets.js +29 -47
  238. package/dist/workflows/exec/run-workflow.js +154 -387
  239. package/dist/workflows/exec/scheduler.js +9 -36
  240. package/dist/workflows/exec/step-work.js +127 -430
  241. package/dist/workflows/exec/unit-dispatch.js +11 -63
  242. package/dist/workflows/exec/unit-writer.js +8 -52
  243. package/dist/workflows/exec/worktree.js +39 -273
  244. package/dist/workflows/freeze/child-output-references.js +4 -15
  245. package/dist/workflows/freeze/environment.js +99 -92
  246. package/dist/workflows/freeze/freeze.js +172 -0
  247. package/dist/workflows/freeze/step-values.js +19 -21
  248. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  249. package/dist/workflows/freeze/targets/command.js +10 -33
  250. package/dist/workflows/freeze/targets/script.js +5 -12
  251. package/dist/workflows/freeze/targets/shell.js +3 -6
  252. package/dist/workflows/freeze/targets/task.js +25 -80
  253. package/dist/workflows/freeze/task-bindings.js +20 -67
  254. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  255. package/dist/workflows/ir/params.js +6 -51
  256. package/dist/workflows/ir/plan-hash.js +2 -34
  257. package/dist/workflows/parser.js +140 -43
  258. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  259. package/dist/workflows/renderer.js +36 -69
  260. package/dist/workflows/resource-limits.js +12 -120
  261. package/dist/workflows/runtime/agent-identity.js +8 -40
  262. package/dist/workflows/runtime/run-outputs.js +3 -6
  263. package/dist/workflows/runtime/run-plan.js +316 -0
  264. package/dist/workflows/runtime/runs.js +48 -200
  265. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  266. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  267. package/dist/workflows/validate-summary.js +2 -7
  268. package/docs/integration/bundling-akm.md +49 -42
  269. package/docs/migration/README.md +1 -0
  270. package/docs/migration/release-notes/0.9.17.md +41 -0
  271. package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
  272. package/docs/reference/cli.md +182 -125
  273. package/docs/reference/configuration.md +49 -56
  274. package/docs/reference/data-and-telemetry.md +19 -20
  275. package/docs/reference/tasks.md +86 -38
  276. package/docs/reference/workflow-schema.md +14 -18
  277. package/docs/reference/workflows.md +6 -9
  278. package/package.json +1 -1
  279. package/schemas/akm-config.json +87 -406
  280. package/dist/commands/health/advisories.js +0 -150
  281. package/dist/commands/health/metrics.js +0 -329
  282. package/dist/commands/health/surfaces.js +0 -102
  283. package/dist/commands/improve/anti-collapse.js +0 -83
  284. package/dist/commands/improve/collapse-detector.js +0 -432
  285. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  286. package/dist/commands/improve/consolidate/merge.js +0 -146
  287. package/dist/commands/improve/distill/promote-memory.js +0 -329
  288. package/dist/commands/improve/distill/quality-gate.js +0 -500
  289. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  290. package/dist/commands/improve/proposal-envelope.js +0 -31
  291. package/dist/commands/improve/run-context.js +0 -123
  292. package/dist/commands/improve/shared.js +0 -21
  293. package/dist/commands/improve/source-identity.js +0 -28
  294. package/dist/commands/improve/triage.js +0 -96
  295. package/dist/commands/proposal/drain-policies.js +0 -151
  296. package/dist/commands/sources/update-transaction.js +0 -220
  297. package/dist/core/action-contributors.js +0 -28
  298. package/dist/core/config/config-version-shim.js +0 -101
  299. package/dist/core/config/retired-experimental-keys-shim.js +0 -62
  300. package/dist/core/fs-txn.js +0 -405
  301. package/dist/core/lexical-score.js +0 -25
  302. package/dist/core/maintenance-barrier.js +0 -167
  303. package/dist/execution/executable-identity.js +0 -105
  304. package/dist/execution/guarded-source.js +0 -427
  305. package/dist/indexer/graph/graph-boost.js +0 -427
  306. package/dist/indexer/graph/graph-dedup.js +0 -95
  307. package/dist/indexer/search/name-match.js +0 -35
  308. package/dist/indexer/search/ranking-contributors.js +0 -515
  309. package/dist/indexer/walk/project-context.js +0 -192
  310. package/dist/integrations/agent/execution-cascade.js +0 -566
  311. package/dist/integrations/agent/execution-definitions.js +0 -202
  312. package/dist/integrations/agent/execution-lowering.js +0 -841
  313. package/dist/integrations/agent/execution-preparation.js +0 -98
  314. package/dist/integrations/agent/inline-execution.js +0 -74
  315. package/dist/registry/create-provider-registry.js +0 -29
  316. package/dist/registry/pinned-request-helper.js +0 -247
  317. package/dist/registry/pinned-transport.js +0 -717
  318. package/dist/sources/providers/index.js +0 -14
  319. package/dist/storage/engines/sqlite-migrations.js +0 -271
  320. package/dist/storage/repositories/canaries-repository.js +0 -107
  321. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  322. package/dist/storage/repositories/registry-cache.js +0 -113
  323. package/dist/tasks/scheduler-sync-preview.js +0 -52
  324. package/dist/workflows/freeze/resolve-steps.js +0 -86
  325. package/dist/workflows/freeze/source-freeze.js +0 -64
  326. package/dist/workflows/ir/compile.js +0 -321
  327. package/dist/workflows/ir/environment-v4.js +0 -330
  328. package/dist/workflows/ir/freeze-v4.js +0 -153
  329. package/dist/workflows/ir/schema-v4.js +0 -745
  330. package/dist/workflows/ir/schema.js +0 -354
  331. package/dist/workflows/program/schema.js +0 -78
  332. package/dist/workflows/runtime/checkin.js +0 -57
  333. package/dist/workflows/runtime/plan-classifier.js +0 -196
  334. package/dist/workflows/runtime/unit-checkin.js +0 -45
  335. package/dist/workflows/runtime/unit-phases.js +0 -20
  336. package/dist/workflows/schema.js +0 -4
  337. package/dist/workflows/source-ir/compile.js +0 -200
  338. package/dist/workflows/source-ir/program.js +0 -50
  339. package/dist/workflows/source-ir/result.js +0 -26
  340. package/dist/workflows/source-ir/schema.js +0 -786
  341. package/dist/workflows/source-ir/triggers.js +0 -79
  342. package/dist/workflows/source-ir/uses.js +0 -40
  343. package/dist/workflows/validator.js +0 -60
@@ -2,42 +2,24 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * The ONE recursive child-workflow resolver (spec docs/plans/specs/
6
- * p3a-plan-v5-child-freeze.md §4). BOTH composition forms lower here:
7
- *
8
- * - a direct step `uses: workflows/<ref>` (`resolve-steps.ts`'s
9
- * `resolveStep`, `via: "direct"`);
10
- * - a task-wrapped workflow target — a `uses: tasks/<ref>` step whose task's
11
- * OWN target is a workflow (`targets/task.ts`'s `taskDispatch`,
12
- * `via: "task"`).
13
- *
14
- * `childWorkflowDispatch` resolves and qualifies the child ref, enforces the
15
- * three composition bounds (depth, cycle, aggregate embedded bytes — all
16
- * FREEZE-time, before publication, `COMPOSITION_INVALID`), recursively
17
- * freezes the child COMPLETELY through the injected `ResolutionContext.freezeChild`
18
- * (never a direct import of `compileResolveFreezeWorkflowV4` —
19
- * `freeze/step-values.ts`'s `ChildCompositionContext` doc explains why: this
20
- * module is downstream of `ir/freeze-v4.ts`, so importing back from it would
21
- * close a static cycle), absorbs the child's own fresh source collector into
22
- * the parent's (A-N7), binds the composing step's effective inputs against
23
- * the child's declared `params:` (A-N8 — see `AuthoredChildInputs` below for
24
- * the two ways that mapping arrives), and returns the standard
25
- * `ResolvedDispatch` envelope carrying a `FrozenChildWorkflowTarget`
26
- * (`ir/schema-v4.ts`).
5
+ * The one child-workflow resolver. Both composition forms lower here: a direct
6
+ * `uses: workflows/<ref>` step (`via: "direct"`) and a `uses: tasks/<ref>`
7
+ * step whose task targets a workflow (`via: "task"`). It resolves the child,
8
+ * refuses a composition cycle, freezes the child completely through the
9
+ * injected `ResolutionContext.freezeChild`, binds the step's inputs against
10
+ * the child's `params:`, and embeds the frozen child plan in the target.
27
11
  */
28
12
  import { createHash } from "node:crypto";
29
13
  import { parseBundleRef } from "../../../core/asset/asset-ref.js";
30
14
  import { UsageError } from "../../../core/errors.js";
31
15
  import { warn } from "../../../core/warn.js";
32
- import { GuardedExecutionSourceCollector } from "../../../execution/guarded-source.js";
33
16
  import { workflowParamContract } from "../../ir/params.js";
34
17
  import { canonicalJson, canonicalPlanJson } from "../../ir/plan-hash.js";
35
- import { utf8Bytes } from "../../resource-limits.js";
36
18
  import { loadWorkflowAsset } from "../../runtime/workflow-asset-loader.js";
37
19
  import { resolveOwnedAsset } from "../environment.js";
38
- import { declaredParamNames, earlierStepIds } from "../step-values.js";
20
+ import { declaredParamNames, earlierStepIds, } from "../step-values.js";
39
21
  import { freezeTaskInputBindings, rebindTaskInputBindings } from "../task-bindings.js";
40
- /** §3.5's exact `contentHash` formula — mirrors `ir/schema-v4.ts`'s private decode-side `childWorkflowContentHash` byte-for-byte (the decoder re-verifies what this produces); duplicated rather than imported so this freeze-side module needs no edit to Lane A's already-landed decoder file. */
22
+ /** The child target's own content identity: its ref, embedded plan hash, route, and bindings. */
41
23
  function childWorkflowContentHash(fields) {
42
24
  return createHash("sha256")
43
25
  .update("akm.workflow.child-workflow\0v1\0")
@@ -50,19 +32,7 @@ function childWorkflowContentHash(fields) {
50
32
  }))
51
33
  .digest("hex");
52
34
  }
53
- /**
54
- * Code-review finding (see this file's `environment: []` return field): a
55
- * step composing a child workflow has no path to honor its own authored
56
- * `env:` — the child run carries its own frozen environment inside its own
57
- * plan, so `freezeEnvironment` (the ONE mechanism a step's `env:` reaches a
58
- * frozen unit through, `../environment.ts`) is never called for this
59
- * target. Leaving that silent would repeat exactly the defect A-N5 already
60
- * closed for `with:` on a non-binding surface — an authored construct that
61
- * cannot be honored on this composing target now rejects instead of
62
- * vanishing. Checks BOTH shapes a step's `env:` can take (`../environment.ts`'s
63
- * `freezeEnvironment`): literal `env:` values and `unit: {env: [...]}` refs.
64
- * An absent/empty `env:` is not authored and stays valid.
65
- */
35
+ /** A composing step's own `env:` (literal or `unit.env`) cannot reach the child run, so say so. */
66
36
  function warnIfStepEnvironment(stepId, childRef, source) {
67
37
  const hasLiteralEnv = Object.keys(source.env ?? {}).length > 0;
68
38
  const hasEnvRefs = (source.unit?.env ?? []).length > 0;
@@ -72,7 +42,7 @@ function warnIfStepEnvironment(stepId, childRef, source) {
72
42
  `environment inside its own plan, so this composing step's env: (or unit: env:) is not delivered into it ` +
73
43
  `and has no effect. Set those variables inside ${childRef}'s own source instead.`);
74
44
  }
75
- /** A workflow entry of a composition `refPath` — the only entries a cycle can close through (§4.5: a task target can never itself be a task, so no task->task chain exists to close one). */
45
+ /** A workflow entry of a composition `refPath` — the only entries a cycle can close through. */
76
46
  function isWorkflowRef(ref) {
77
47
  try {
78
48
  return parseBundleRef(ref).conceptId.startsWith("workflows/");
@@ -91,20 +61,10 @@ function assertNoCompositionCycle(stepId, childRef, refPath) {
91
61
  `Path: ${compositionPath(refPath, childRef)}.`, "COMPOSITION_INVALID", "Break the cycle: remove or redirect one of the compositions in the path above so no workflow ends up " +
92
62
  "composing itself, directly or through intermediates.");
93
63
  }
94
- /**
95
- * Add the child's embedded plan bytes to the shared, tree-wide budget
96
- * (A-N6) and fail before publication if the AGGREGATE crosses the cap.
97
- * Mutates `budget` only on success — a rejected step leaves the running
98
- * total exactly as it was, matching every other freeze-time failure's
99
- * no-partial-effect shape.
100
- */
101
- function chargeEmbeddedBudget(_stepId, _childRef, childPlanBytes, budget) {
102
- budget.embeddedBytes += childPlanBytes;
103
- }
104
64
  export async function childWorkflowDispatch(input) {
105
65
  const { source, baseUnit, childRefInput, context, via, taskRef, authoredInputs } = input;
106
- // §4.2 step 1: resolve + qualify. Resolution failures propagate unchanged,
107
- // in code and shape (row B-11) — the same authority every other
66
+ // resolve + qualify. Resolution failures propagate unchanged,
67
+ // in code and shape — the same authority every other
108
68
  // composition target (command/script/task) already resolves through.
109
69
  const owned = await resolveOwnedAsset(childRefInput, "workflow", context);
110
70
  const childAsset = await loadWorkflowAsset(owned.ref);
@@ -113,44 +73,15 @@ export async function childWorkflowDispatch(input) {
113
73
  // the child run — warn rather than vanish silently (see
114
74
  // warnIfStepEnvironment's doc comment).
115
75
  warnIfStepEnvironment(source.id, childRef, source);
116
- // §4.2 step 2: the composition cycle check, before any child compilation.
117
- assertNoCompositionCycle(source.id, childRef, context.composition.refPath);
118
- const childDepth = context.composition.depth + 1;
119
- // §4.2 step 4: freeze the child COMPLETELY (compile -> validate -> freeze),
120
- // with its OWN fresh collector (A-N7) so its plan is a pure function of its
121
- // own source, and the SAME mutable budget object so the aggregate bound
122
- // sees every descendant across the whole tree.
123
- const childRefPath = via === "task" && taskRef !== undefined
124
- ? [...context.composition.refPath, taskRef, childRef]
125
- : [...context.composition.refPath, childRef];
126
- const child = await context.freezeChild({
127
- asset: childAsset,
128
- sourceCollector: new GuardedExecutionSourceCollector(),
129
- composition: { depth: childDepth, refPath: childRefPath, budget: context.composition.budget },
130
- });
131
- // The embedded `frozenPlan` must be a PLAIN, symbol-free JSON structure —
132
- // exactly the shape `decodeWorkflowPlanV4` will (recursively) re-verify it
133
- // as, both right now (the PARENT's own top-level `decodeWorkflowPlanV4`
134
- // call in `ir/freeze-v4.ts` walks straight into this target) and later,
135
- // read back from a stored run's `plan_json`. `child.plan` — the in-memory
136
- // result of the child's OWN already-decoded freeze — carries internal
137
- // resolved-request construction brands (`execution/resolved-request.ts`)
138
- // that `decodeResolvedExecutionRequest` deliberately rejects on ANY
139
- // "fresh rehydrate" input; round-tripping through canonical JSON strips
140
- // them, the same way persisting and re-reading `plan_json` naturally would.
76
+ // the composition cycle check, before any child compilation.
77
+ assertNoCompositionCycle(source.id, childRef, context.refPath);
78
+ // Freeze the child completely; its plan is a pure function of its own source.
79
+ const childRefPath = via === "task" && taskRef !== undefined ? [...context.refPath, taskRef, childRef] : [...context.refPath, childRef];
80
+ const child = await context.freezeChild(childAsset, childRefPath);
81
+ // Embed the child plan as plain canonical JSON, exactly as `plan_json` stores it.
141
82
  const embeddedPlanJson = canonicalPlanJson(child.plan);
142
83
  const frozenPlan = JSON.parse(embeddedPlanJson);
143
- // §4.2 step 5.
144
- chargeEmbeddedBudget(source.id, childRef, utf8Bytes(embeddedPlanJson), context.composition.budget);
145
- // §4.2 step 6 (A-N7): absorb the child's captured sources so the parent's
146
- // final pre-publication CAS (`revalidate()`) covers every child file too.
147
- context.collector.absorb(child.sourceCollector);
148
- // §4.2 step 7 (A-N8): bind the composing step's effective inputs against
149
- // the child's declared params:. A genuinely authored `with:` goes through
150
- // the SAME normalizer every other binding surface uses; an
151
- // already-classified binding set (a v4 task's effective inputs) is
152
- // RE-bound instead, never round-tripped back through the `with:` grammar
153
- // (code-review finding — see AuthoredChildInputs above).
84
+ // Bind the step's effective inputs against the child's declared params.
154
85
  const inputBindings = authoredInputs.kind === "bindings"
155
86
  ? rebindTaskInputBindings({
156
87
  stepId: source.id,
@@ -163,10 +94,10 @@ export async function childWorkflowDispatch(input) {
163
94
  targetRef: childRef,
164
95
  with: authoredInputs.value,
165
96
  contract: workflowParamContract(frozenPlan),
166
- earlierStepIds: earlierStepIds(context.sourceIr, source.id),
167
- declaredParamNames: declaredParamNames(context.sourceIr),
97
+ earlierStepIds: earlierStepIds(context.plan, source.id),
98
+ declaredParamNames: declaredParamNames(context.plan),
168
99
  });
169
- // §4.2 step 8: build the frozen target.
100
+ // build the frozen target.
170
101
  const planHash = createHash("sha256").update(embeddedPlanJson).digest("hex");
171
102
  const contentHash = childWorkflowContentHash({ ref: childRef, planHash, via, taskRef, inputBindings });
172
103
  const target = Object.freeze({
@@ -183,7 +114,7 @@ export async function childWorkflowDispatch(input) {
183
114
  target,
184
115
  // A child run carries its own frozen environment inside its own plan.
185
116
  // A composing step's own env: cannot reach it, so assertNoStepEnvironment
186
- // above rejects one instead of it silently vanishing here (§4.2 step 8).
117
+ // above rejects one instead of it silently vanishing here.
187
118
  environment: [],
188
119
  unit: baseUnit,
189
120
  instructions: source.instructions ??
@@ -6,15 +6,12 @@ import { parseBuiltinCommandAction } from "../../../commands/command/builtin-act
6
6
  import { prepareCommandInvocation } from "../../../commands/command/command-execution.js";
7
7
  import { PORTABLE_ARGUMENTS_PLACEHOLDER } from "../../../commands/command/portable-template.js";
8
8
  import { captureFrozenDirectoryIdentity } from "../../../execution/directory-identity.js";
9
- import { freezeExecutableIdentity } from "../../../execution/executable-identity.js";
10
9
  import { canonicalResolvedExecutionRequest, } from "../../../execution/resolved-request.js";
11
10
  import { fallbackAnnouncement } from "../../../integrations/agent/engine-fallback.js";
12
- import { requireAuthorizedExecutionPlan } from "../../../integrations/agent/execution-cascade.js";
13
- import { lowerResolvedExecutionRequest } from "../../../integrations/agent/execution-lowering.js";
14
- import { prepareInlineExecution } from "../../../integrations/agent/inline-execution.js";
15
- import { freezeEnvironment, guardedExecutionSource } from "../environment.js";
11
+ import { buildExecution } from "../../../integrations/agent/execution.js";
12
+ import { freezeEnvironment, workflowExecutionSource } from "../environment.js";
16
13
  import { gitIdentity } from "../identity.js";
17
- import { durableRequest, executionUnitValues, executionValues, targetConcurrency, } from "../step-values.js";
14
+ import { durableRequest, executionUnitValues, targetConcurrency, } from "../step-values.js";
18
15
  function inlineWorkflowCommandAction(action, commandMode) {
19
16
  if (commandMode !== "portable-template")
20
17
  return action;
@@ -27,41 +24,22 @@ export async function commandDispatch(source, baseUnit, action, context) {
27
24
  const prepared = await prepareCommandInvocation({
28
25
  action: inlineWorkflowCommandAction(action, source.commandMode),
29
26
  config: context.config,
30
- invocationKind: "workflow",
31
- ...(context.sourceIr.defaults
32
- ? { invocationDefaults: executionUnitValues(context.sourceIr.defaults, context.asset.sourcePath) }
27
+ ...(context.plan.defaults
28
+ ? { invocationDefaults: executionUnitValues(context.plan.defaults, context.asset.sourcePath) }
33
29
  : {}),
34
30
  ...(source.commandMode === "literal" || source.commandMode === "portable-template"
35
31
  ? { inlineContentMode: "literal" }
36
32
  : {}),
37
- current: executionValues(source, context.asset.sourcePath),
38
- sourceLoader: (ref, kind) => guardedExecutionSource(ref, kind, context),
39
- });
40
- return commandResult(source, baseUnit, prepared, context);
41
- }
42
- export function inlineDispatch(source, baseUnit, context) {
43
- const content = source.instructions ?? `Execute workflow step ${source.id}.`;
44
- const prepared = prepareInlineExecution({
45
- content,
46
- config: context.config,
47
- invocationKind: "workflow",
48
- ...(context.sourceIr.defaults
49
- ? { invocationDefaults: executionUnitValues(context.sourceIr.defaults, context.asset.sourcePath) }
50
- : {}),
51
- current: executionValues(source, context.asset.sourcePath),
33
+ current: executionUnitValues(source.unit, context.asset.sourcePath),
34
+ sourceLoader: (ref, kind) => workflowExecutionSource(ref, kind, context),
52
35
  });
53
36
  return commandResult(source, baseUnit, prepared, context);
54
37
  }
55
38
  export function commandResult(source, baseUnit, prepared, context, literals = []) {
56
- const request = durableRequest(requireAuthorizedExecutionPlan(prepared.plan));
57
- const lowered = lowerResolvedExecutionRequest(request, prepared.config);
39
+ const request = durableRequest(prepared.request);
40
+ const lowered = buildExecution(request, prepared.runner);
58
41
  const cwdIdentity = captureFrozenDirectoryIdentity(context.asset.sourcePath);
59
- let runner = lowered.runner;
60
- let executable;
61
- if (runner.kind === "agent") {
62
- executable = freezeExecutableIdentity(runner.profile.bin, { cwd: cwdIdentity.realCwd });
63
- runner = Object.freeze({ ...runner, profile: Object.freeze({ ...runner.profile, bin: executable.absolutePath }) });
64
- }
42
+ const runner = lowered.runner;
65
43
  const unit = {
66
44
  ...baseUnit,
67
45
  engine: request.engine.name,
@@ -79,7 +57,6 @@ export function commandResult(source, baseUnit, prepared, context, literals = []
79
57
  runner,
80
58
  ...(targetConcurrency(runner, context.config) ? { concurrency: targetConcurrency(runner, context.config) } : {}),
81
59
  cwdIdentity,
82
- ...(executable ? { executable } : {}),
83
60
  ...gitIdentity(baseUnit, cwdIdentity.realRoot),
84
61
  });
85
62
  const engineAnnouncement = fallbackAnnouncement(prepared.fallbackEngineName, request.engine.name);
@@ -1,22 +1,18 @@
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 { freezeExecutableIdentity } from "../../../execution/executable-identity.js";
4
+ import fs from "node:fs";
5
5
  import { prepareScriptTarget } from "../../../tasks/prepare/prepare-script-target.js";
6
- import { captureOwned, freezeEnvironment, resolveOwnedAsset } from "../environment.js";
6
+ import { freezeEnvironment, resolveOwnedAsset } from "../environment.js";
7
7
  import { gitIdentity, scriptExecutable } from "../identity.js";
8
- import { freezeExecSpec } from "../step-values.js";
8
+ import { freezeExecSpec, } from "../step-values.js";
9
9
  export async function directScript(source, baseUnit, refInput, context) {
10
10
  const owned = await resolveOwnedAsset(refInput, "script", context);
11
- captureOwned(owned, context.collector);
12
- // Typed preparer (P1b spec §4.3) — no synthetic task YAML, no parseTaskV3Yaml
13
- // call, no fabricated schedule/filePath/taskId/taskRef. The script's own
14
- // owned identity (ref/file/bundleRoot) is all prepareScriptTarget needs.
15
11
  const captured = prepareScriptTarget({
16
12
  ref: owned.ref,
17
13
  file: owned.file,
18
14
  bundleRoot: owned.root,
19
- readFile: () => context.collector.readBytes(owned.file, owned.root),
15
+ readFile: () => fs.readFileSync(owned.file),
20
16
  });
21
17
  return scriptResult(source, baseUnit, {
22
18
  sourceRef: captured.ref,
@@ -29,9 +25,7 @@ export async function directScript(source, baseUnit, refInput, context) {
29
25
  }, context, []);
30
26
  }
31
27
  export function scriptResult(source, baseUnit, prepared, context, literals) {
32
- const requestedExecutable = scriptExecutable(prepared.interpreter);
33
- const executable = freezeExecutableIdentity(requestedExecutable, { cwd: prepared.cwdIdentity.realCwd });
34
- const authoredExec = { command: [executable.absolutePath, "<frozen-script>"] };
28
+ const authoredExec = { command: [scriptExecutable(prepared.interpreter), "<frozen-script>"] };
35
29
  const exec = freezeExecSpec(source, authoredExec, context);
36
30
  const environment = Object.freeze([...literals, ...freezeEnvironment(source, authoredExec, context)]);
37
31
  const target = Object.freeze({
@@ -45,7 +39,6 @@ export function scriptResult(source, baseUnit, prepared, context, literals) {
45
39
  byteLength: prepared.byteLength,
46
40
  cwdIdentity: prepared.cwdIdentity,
47
41
  materialization: "ephemeral-0700-delete",
48
- executable,
49
42
  ...gitIdentity(baseUnit, prepared.cwdIdentity.realRoot),
50
43
  });
51
44
  return {
@@ -2,30 +2,27 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { captureFrozenDirectoryIdentity } from "../../../execution/directory-identity.js";
5
- import { freezeExecutableIdentity } from "../../../execution/executable-identity.js";
6
5
  import { freezeEnvironment } from "../environment.js";
7
6
  import { gitIdentity } from "../identity.js";
8
- import { freezeExecSpec } from "../step-values.js";
7
+ import { freezeExecSpec, } from "../step-values.js";
9
8
  export function directShell(source, baseUnit, context) {
10
9
  const authoredExec = baseUnit.exec;
11
10
  if (!authoredExec)
12
- throw new Error(`workflow shell step ${source.id} lost its source-IR execution spec`);
11
+ throw new Error(`workflow shell step ${source.id} has no argv`);
13
12
  const exec = freezeExecSpec(source, authoredExec, context);
14
13
  const cwdIdentity = captureFrozenDirectoryIdentity(context.asset.sourcePath, authoredExec.cwd);
15
- const executable = freezeExecutableIdentity(authoredExec.command[0], { cwd: cwdIdentity.realCwd });
16
14
  const environment = Object.freeze(freezeEnvironment(source, authoredExec, context));
17
15
  const target = Object.freeze({
18
16
  kind: "shell",
19
17
  contentHash: "",
20
18
  exec,
21
19
  cwdIdentity,
22
- executable,
23
20
  ...gitIdentity(baseUnit, cwdIdentity.realRoot),
24
21
  });
25
22
  return {
26
23
  target,
27
24
  environment,
28
25
  unit: { ...baseUnit, exec },
29
- instructions: source.instructions ?? `Run ${source.run ?? authoredExec.command.join(" ")}.`,
26
+ instructions: source.instructions ?? `Run ${authoredExec.command.join(" ")}.`,
30
27
  };
31
28
  }
@@ -1,101 +1,60 @@
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 fs from "node:fs";
4
5
  import path from "node:path";
5
6
  import { parseBundleRef } from "../../../core/asset/asset-ref.js";
6
7
  import { UsageError } from "../../../core/errors.js";
7
- import { freezeExecutableIdentity } from "../../../execution/executable-identity.js";
8
8
  import { prepareTaskV3Execution } from "../../../tasks/prepare/prepare.js";
9
9
  import { parseTaskSource } from "../../../tasks/source/parse-task-source.js";
10
10
  import { projectTaskSourceV4 } from "../../../tasks/source/project-v4.js";
11
- import { workflowShellCommand } from "../../source-ir/program.js";
12
- import { captureOwned, freezeEnvironment, guardedExecutionSource, resolveOwnedAsset } from "../environment.js";
11
+ import { workflowShellCommand } from "../../source-semantics.js";
12
+ import { freezeEnvironment, resolveOwnedAsset, workflowExecutionSource } from "../environment.js";
13
13
  import { gitIdentity } from "../identity.js";
14
14
  import { declaredParamNames, earlierStepIds, freezeExecSpec, } from "../step-values.js";
15
15
  import { freezeTaskInputBindings } from "../task-bindings.js";
16
16
  import { childWorkflowDispatch } from "./child-workflow.js";
17
17
  import { commandResult } from "./command.js";
18
18
  import { scriptResult } from "./script.js";
19
- /** The one message shared by every "cannot prove this is a valid binding surface" rejection (A-N5). */
19
+ /** The rejection for a `with:` on a task that declares no inputs (or does not resolve). */
20
20
  function noDeclaredInputsError(stepId, ref) {
21
21
  return new UsageError(`Workflow step ${stepId} cannot pass with: to task target ${ref}; ${ref} declares no inputs.`, "COMPOSITION_INVALID");
22
22
  }
23
23
  /**
24
- * A-N6 (spec docs/plans/specs/p2b-input-bindings.md §1.7): LC-N1's
25
- * peek-and-throw (p2a §1.5) is GONE — a version: 4 target now composes.
26
- * `parseTaskSource` parses the YAML ONCE and routes on the SAME {root,
27
- * lineAt} the v3 arm always used, so a v3 composition stays byte-identical
28
- * (B-07, B-08). `contract` is undefined for a v3 task (which can never
29
- * declare `inputs:`, P2a §1.2 D2) or a v4 task with no `inputs:` key at all —
30
- * either way, "no declared inputs" (A-N5).
31
- *
32
- * RECORDED TENSION (spec §0, Review log): A-N5's "no declared inputs"
33
- * rejection is reasoned from the target's PARSED `inputs:` contract, which
34
- * needs the target to resolve — yet `tests/workflows/with-rejection.test.ts`
35
- * B-02b pins `COMPOSITION_INVALID` (not an asset-resolution error) for an
36
- * UNRESOLVABLE task ref with an authored `with:`. Reconciled here: an
37
- * authored `with:` whose target cannot even be resolved/parsed "cannot be
38
- * proven a valid binding surface", so it is refused the same
39
- * no-declared-inputs way — a `with:`-free step's resolution failure is
40
- * untouched and propagates as before.
41
- *
42
- * Code-review finding: that reconciliation must stay scoped to ASSET
43
- * resolution (`resolveOwnedAsset`/`captureOwned`) only. Once the target
44
- * resolves to a real file, `parseTaskSource`/`projectTaskSourceV4` reports a
45
- * genuine, path-and-line-anchored defect in the composed task's OWN source
46
- * (e.g. `TASK_SOURCE_INVALID` for an unsupported `inputs.<name>` field) —
47
- * that is never "cannot be proven a valid binding surface" and must not be
48
- * repainted as `noDeclaredInputsError`. Parsing therefore happens OUTSIDE
49
- * the try/catch below, so its errors propagate unchanged regardless of
50
- * whether this step authored a `with:`.
24
+ * Resolve and parse the composed task. An authored `with:` whose target does
25
+ * not even resolve cannot be proven a valid binding surface, so it is refused
26
+ * the same no-declared-inputs way; a genuine defect in the resolved task's own
27
+ * source propagates unchanged.
51
28
  */
52
29
  async function resolveTaskForComposition(source, refInput, context) {
53
- const { owned, retained } = await resolveAndCaptureTaskAsset(source, refInput, context);
54
- const parsed = parseTaskSource({ yaml: retained.content, filePath: owned.file, workspaceRoot: owned.root });
55
- const contract = parsed.v4.inputs;
56
- const task = projectTaskSourceV4(parsed.v4);
57
- return { owned, task, contract };
58
- }
59
- /** The asset-resolution-only half of {@link resolveTaskForComposition} — the sole failure mode an authored `with:` on an unresolvable ref may repaint as `noDeclaredInputsError` (A-N5's `with-rejection.test.ts` B-02b). */
60
- async function resolveAndCaptureTaskAsset(source, refInput, context) {
30
+ let owned;
31
+ let yaml;
61
32
  try {
62
- const owned = await resolveOwnedAsset(refInput, "task", context);
63
- const retained = captureOwned(owned, context.collector);
64
- return { owned, retained };
33
+ owned = await resolveOwnedAsset(refInput, "task", context);
34
+ yaml = fs.readFileSync(owned.file, "utf8");
65
35
  }
66
36
  catch (cause) {
67
37
  if (source.with !== undefined)
68
38
  throw noDeclaredInputsError(source.id, refInput);
69
39
  throw cause;
70
40
  }
41
+ const parsed = parseTaskSource({ yaml, filePath: owned.file, workspaceRoot: owned.root });
42
+ return { owned, task: projectTaskSourceV4(parsed.v4), contract: parsed.v4.inputs };
71
43
  }
72
44
  export async function taskDispatch(source, baseUnit, refInput, context) {
73
45
  const { owned, task, contract } = await resolveTaskForComposition(source, refInput, context);
74
- // A-N5: a with: on a target that declares no inputs: at all is
75
- // COMPOSITION_INVALID. Fires on ANY authored with: shape, including `{}`
76
- // (the check is `!== undefined`, not "non-empty").
46
+ // Any authored `with:` (even `{}`) on a task that declares no inputs is COMPOSITION_INVALID.
77
47
  if (source.with !== undefined && contract === undefined) {
78
48
  throw noDeclaredInputsError(source.id, refInput);
79
49
  }
80
- // P3a (docs/plans/specs/p3a-plan-v5-child-freeze.md §4.2, row B-12): a task
81
- // whose OWN target is `uses: workflows/<ref>` used to fast-fail here,
82
- // before ever calling prepareTaskV3Execution. That rejection is REMOVED —
83
- // flow continues to the bindings computation and the prepare call exactly
84
- // as for any other task target, and `prepared.kind === "workflow"` below
85
- // routes to the ONE child-workflow resolver instead.
86
- // Lane A2 (§3.2-§3.5): normalize THIS step's own with: against THIS task's
87
- // OWN declared inputs — no merge across a composition chain (B-29). A task
88
- // with no inputs: has contract === undefined, so an empty {} contract is
89
- // used; freezeTaskInputBindings then produces no bindings for it (there is
90
- // nothing to bind, and the COMPOSITION_INVALID check above already fired
91
- // for any authored with:).
50
+ // This step's own `with:` against this task's own declared inputs (none → no bindings).
92
51
  const bindings = freezeTaskInputBindings({
93
52
  stepId: source.id,
94
53
  targetRef: refInput,
95
54
  with: source.with,
96
55
  contract: contract ?? {},
97
- earlierStepIds: earlierStepIds(context.sourceIr, source.id),
98
- declaredParamNames: declaredParamNames(context.sourceIr),
56
+ earlierStepIds: earlierStepIds(context.plan, source.id),
57
+ declaredParamNames: declaredParamNames(context.plan),
99
58
  });
100
59
  const prepared = await prepareTaskV3Execution(task, {
101
60
  taskId: parseBundleRef(owned.ref).conceptId.slice("tasks/".length),
@@ -103,30 +62,18 @@ export async function taskDispatch(source, baseUnit, refInput, context) {
103
62
  bundleName: owned.bundle,
104
63
  bundleRoot: owned.root,
105
64
  config: context.config,
106
- commandSourceLoader: (ref, kind) => guardedExecutionSource(ref, kind, context),
65
+ commandSourceLoader: (ref, kind) => workflowExecutionSource(ref, kind, context),
107
66
  resolveAsset: async ({ ref, type }) => {
108
67
  const target = await resolveOwnedAsset(ref, type, context);
109
- captureOwned(target, context.collector);
110
68
  return { file: target.file, bundleRoot: target.root };
111
69
  },
112
- readFile: (file, root = owned.root) => context.collector.readBytes(file, root),
113
70
  });
114
71
  if (prepared.kind === "workflow") {
115
- // P3a (spec §4.2, rows B-12/B-13): routes to the ONE child-workflow
116
- // resolver instead of rejecting. `prepared.ref`/`prepared.taskRef` are
117
- // already qualified (§4.2 step 1 re-resolves and re-canonicalizes them
118
- // regardless). Always hands over the bindings just computed above — this
119
- // task's OWN effective inputs, already classified once against its own
120
- // contract — to be RE-bound against the child's declared `params:`
121
- // (never round-tripped through the `with:` grammar: doing so would let a
122
- // literal value shaped like `{from: ...}` be silently reinterpreted as a
123
- // reference, code-review finding). Task source v4 rejects `with:` on any
124
- // target but `uses: akm/command` (row B-28), so a workflow-target task
125
- // can no longer author `with:` at all — the `{kind:"with"}` arm this
126
- // ternary used to reach for a v3 task, or a v4 task with no `inputs:`,
127
- // is unreachable from here and deleted (P4 §3.2.7, row B-30).
128
- // `AuthoredChildInputs`'s `{kind:"with"}` member itself stays — the
129
- // DIRECT composition path (`resolve-steps.ts`) still produces it.
72
+ // A task whose own target is a workflow composes it as a child. This
73
+ // task's effective inputs, already classified against its own contract,
74
+ // are re-bound against the child's `params:` — never round-tripped through
75
+ // the `with:` grammar, which would reinterpret a literal shaped like
76
+ // `{from: ...}` as a reference.
130
77
  return childWorkflowDispatch({
131
78
  source,
132
79
  baseUnit,
@@ -150,13 +97,11 @@ export async function taskDispatch(source, baseUnit, refInput, context) {
150
97
  };
151
98
  const exec = freezeExecSpec(source, authoredExec, context);
152
99
  const environment = Object.freeze([...taskLiterals, ...freezeEnvironment(source, authoredExec, context)]);
153
- const executable = freezeExecutableIdentity(exec.command[0], { cwd: prepared.cwdIdentity.realCwd });
154
100
  const target = Object.freeze({
155
101
  kind: "shell",
156
102
  contentHash: "",
157
103
  exec,
158
104
  cwdIdentity: prepared.cwdIdentity,
159
- executable,
160
105
  ...gitIdentity(baseUnit, prepared.cwdIdentity.realRoot),
161
106
  });
162
107
  return withInputBindings({
@@ -168,7 +113,7 @@ export async function taskDispatch(source, baseUnit, refInput, context) {
168
113
  }
169
114
  return withInputBindings(scriptResult(source, baseUnit, prepared, context, taskLiterals), bindings);
170
115
  }
171
- /** Attach the frozen inputBindings (A-N7) to whichever target shape taskDispatch produced. Absent, never [], when empty. */
116
+ /** Attach the frozen inputBindings to whichever target shape taskDispatch produced. Absent, never [], when empty. */
172
117
  function withInputBindings(resolved, bindings) {
173
118
  if (bindings.length === 0)
174
119
  return resolved;