akm-cli 0.9.31 → 0.10.26101002-alpha

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 (236) hide show
  1. package/CHANGELOG.md +265 -0
  2. package/STABILITY.md +79 -53
  3. package/dist/api-node.mjs +20 -0
  4. package/dist/api.d.ts +23 -0
  5. package/dist/api.js +45 -0
  6. package/dist/assets/hints/cli-hints-full.md +13 -27
  7. package/dist/assets/hints/cli-hints-short.md +1 -1
  8. package/dist/assets/improve-strategies/default.json +3 -3
  9. package/dist/assets/prompts/consolidate-pair.md +9 -7
  10. package/dist/cli/shared.js +31 -48
  11. package/dist/cli/unknown-flags.js +6 -43
  12. package/dist/cli.js +8 -34
  13. package/dist/commands/agent/contribute-cli.js +1 -1
  14. package/dist/commands/completions.js +1 -2
  15. package/dist/commands/config-cli.js +5 -28
  16. package/dist/commands/env/env-cli.js +5 -5
  17. package/dist/commands/env/secret-cli.js +2 -2
  18. package/dist/commands/health/checks.js +41 -16
  19. package/dist/commands/health/plugin-staleness.js +52 -22
  20. package/dist/commands/improve/autonomy-gate.js +5 -3
  21. package/dist/commands/improve/consolidate/pair-pass.js +7 -1
  22. package/dist/commands/improve/consolidate.js +6 -35
  23. package/dist/commands/improve/distill/lesson-update.js +91 -0
  24. package/dist/commands/improve/distill-guards.js +1 -43
  25. package/dist/commands/improve/distill.js +140 -20
  26. package/dist/commands/improve/eligibility.js +14 -1
  27. package/dist/commands/improve/extract-cli.js +1 -1
  28. package/dist/commands/improve/improve-cli.js +87 -102
  29. package/dist/commands/improve/improve-strategies.js +8 -12
  30. package/dist/commands/improve/improve.js +2 -2
  31. package/dist/commands/improve/loop-stages.js +0 -1
  32. package/dist/commands/improve/planner.js +0 -1
  33. package/dist/commands/improve/preparation.js +40 -99
  34. package/dist/commands/improve/proactive-maintenance.js +2 -2
  35. package/dist/commands/improve/reflect-noise.js +3 -55
  36. package/dist/commands/improve/reflect.js +3 -8
  37. package/dist/commands/improve/retrieval-scope.js +2 -2
  38. package/dist/commands/improve/salience.js +2 -9
  39. package/dist/commands/improve/stage.js +14 -9
  40. package/dist/commands/lint/index.js +5 -20
  41. package/dist/commands/observability-cli.js +3 -9
  42. package/dist/commands/proposal/drain.js +39 -6
  43. package/dist/commands/proposal/proposal-cli.js +11 -31
  44. package/dist/commands/proposal/repository.js +3 -3
  45. package/dist/commands/read/knowledge.js +3 -3
  46. package/dist/commands/read/remember-cli.js +0 -13
  47. package/dist/commands/read/search-cli.js +29 -97
  48. package/dist/commands/read/search.js +0 -11
  49. package/dist/commands/read/show.js +0 -19
  50. package/dist/commands/sources/plugin-upgrade.js +164 -101
  51. package/dist/commands/sources/sources-cli.js +1 -15
  52. package/dist/commands/sources/stash-cli.js +4 -12
  53. package/dist/commands/tasks/tasks-cli.js +4 -115
  54. package/dist/commands/workflow/plan.js +11 -33
  55. package/dist/commands/workflow-cli.js +2 -7
  56. package/dist/core/adapter/adapter-ids.js +1 -2
  57. package/dist/core/adapter/adapters/agent-skills-adapter.js +0 -4
  58. package/dist/core/adapter/adapters/akm-adapter.js +9 -48
  59. package/dist/core/adapter/adapters/akm-lint.js +10 -26
  60. package/dist/core/adapter/adapters/akm-metadata.js +2 -72
  61. package/dist/core/adapter/adapters/akm-task-adapter.js +0 -5
  62. package/dist/core/adapter/adapters/akm-workflow-adapter.js +9 -28
  63. package/dist/core/adapter/adapters/dotenv-adapter.js +1 -20
  64. package/dist/core/adapter/adapters/generic-files-adapter.js +0 -10
  65. package/dist/core/adapter/adapters/llm-wiki-adapter.js +0 -4
  66. package/dist/core/adapter/adapters/tool-dir-shared.js +0 -24
  67. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -4
  68. package/dist/core/adapter/recognize-match.js +3 -4
  69. package/dist/core/common.js +18 -2
  70. package/dist/core/config/config-schema.js +12 -15
  71. package/dist/core/config/config-types.js +6 -15
  72. package/dist/core/config/config-walker.js +6 -23
  73. package/dist/core/config/config.js +17 -80
  74. package/dist/core/config/engine-semantics.js +7 -3
  75. package/dist/core/config/schema/engines.js +7 -7
  76. package/dist/core/config/schema/improve-processes.js +8 -61
  77. package/dist/core/config/schema/improve.js +2 -21
  78. package/dist/core/config/schema/index-config.js +6 -39
  79. package/dist/core/env-secret-ref.js +2 -45
  80. package/dist/core/errors.js +1 -2
  81. package/dist/core/extra-params.js +2 -86
  82. package/dist/core/improve-result.js +11 -1
  83. package/dist/core/mutation-target.js +2 -2
  84. package/dist/core/recognition-util.js +4 -5
  85. package/dist/core/warn.js +21 -4
  86. package/dist/core/write-source.js +3 -3
  87. package/dist/execution/target-ref.js +1 -2
  88. package/dist/indexer/search/db-search.js +4 -19
  89. package/dist/indexer/search/fts-query.js +0 -19
  90. package/dist/integrations/agent/engine-resolution.js +5 -2
  91. package/dist/integrations/agent/index.js +1 -1
  92. package/dist/integrations/agent/profiles.js +41 -98
  93. package/dist/integrations/agent/request-lowering.js +3 -3
  94. package/dist/integrations/harnesses/aider/index.js +5 -0
  95. package/dist/integrations/harnesses/amazonq/index.js +1 -0
  96. package/dist/integrations/harnesses/claude/config-import.js +2 -3
  97. package/dist/integrations/harnesses/claude/index.js +5 -0
  98. package/dist/integrations/harnesses/codex/index.js +1 -0
  99. package/dist/integrations/harnesses/copilot/index.js +1 -0
  100. package/dist/integrations/harnesses/gemini/index.js +1 -0
  101. package/dist/integrations/harnesses/index.js +18 -39
  102. package/dist/integrations/harnesses/opencode/agent-builder.js +60 -35
  103. package/dist/integrations/harnesses/opencode/config-import.js +121 -52
  104. package/dist/integrations/harnesses/opencode/index.js +22 -0
  105. package/dist/integrations/harnesses/opencode/plugin-layout.js +68 -0
  106. package/dist/integrations/harnesses/opencode/session-log-types.js +12 -0
  107. package/dist/integrations/harnesses/opencode/session-log-v1.js +72 -0
  108. package/dist/integrations/harnesses/opencode/session-log-v2.js +140 -0
  109. package/dist/integrations/harnesses/opencode/session-log.js +104 -115
  110. package/dist/integrations/harnesses/opencode/version.js +98 -0
  111. package/dist/integrations/harnesses/opencode-sdk/{harness.js → index.js} +5 -17
  112. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +105 -206
  113. package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +199 -0
  114. package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +228 -0
  115. package/dist/integrations/harnesses/opencode-sdk/wire.js +66 -0
  116. package/dist/integrations/harnesses/openhands/index.js +1 -0
  117. package/dist/integrations/harnesses/pi/index.js +1 -0
  118. package/dist/integrations/harnesses/shared.js +2 -0
  119. package/dist/integrations/harnesses/types.js +2 -0
  120. package/dist/llm/client.js +41 -11
  121. package/dist/output/cli-hints.js +1 -1
  122. package/dist/output/context.js +10 -19
  123. package/dist/output/format-exempt.js +5 -8
  124. package/dist/output/shapes/helpers.js +1 -22
  125. package/dist/output/shapes/passthrough.js +0 -1
  126. package/dist/output/shapes.js +3 -31
  127. package/dist/output/stdout.js +5 -1
  128. package/dist/output/text/command-format.js +6 -1
  129. package/dist/output/text/workflow-format.js +4 -22
  130. package/dist/scripts/akm-migrate-node.js +13049 -14013
  131. package/dist/scripts/akm-migrate.js +16316 -17276
  132. package/dist/setup/detect.js +10 -4
  133. package/dist/setup/harness-config-import.js +5 -14
  134. package/dist/setup/setup.js +1 -1
  135. package/dist/setup/steps/tasks.js +12 -13
  136. package/dist/storage/repositories/task-history-repository.js +0 -5
  137. package/dist/storage/repositories/workflow-runs-repository.js +5 -15
  138. package/dist/tasks/embedded.js +2 -1
  139. package/dist/tasks/run/task-history.js +0 -2
  140. package/dist/tasks/schedule-gates.js +39 -0
  141. package/dist/tasks/scheduler-binding.js +0 -16
  142. package/dist/tasks/scheduler-sync.js +3 -97
  143. package/dist/tasks/source/bounded-document.js +1 -1
  144. package/dist/tasks/source/task-source-v4.js +2 -12
  145. package/dist/tasks/task-run-reserved-flags.js +2 -31
  146. package/dist/workflows/authoring/authoring.js +6 -6
  147. package/dist/workflows/compile.js +8 -65
  148. package/dist/workflows/exec/child-workflow.js +22 -3
  149. package/dist/workflows/exec/native-executor.js +12 -147
  150. package/dist/workflows/exec/run-workflow.js +31 -103
  151. package/dist/workflows/exec/step-work.js +9 -178
  152. package/dist/workflows/exec/unit-dispatch.js +0 -10
  153. package/dist/workflows/freeze/environment.js +3 -44
  154. package/dist/workflows/freeze/freeze.js +8 -41
  155. package/dist/workflows/freeze/targets/child-workflow.js +27 -63
  156. package/dist/workflows/freeze/targets/command.js +2 -16
  157. package/dist/workflows/freeze/targets/shell.js +0 -2
  158. package/dist/workflows/freeze/task-bindings.js +2 -28
  159. package/dist/workflows/ir/params.js +12 -2
  160. package/dist/workflows/parser.js +82 -232
  161. package/dist/workflows/plan.js +1 -1
  162. package/dist/workflows/renderer.js +10 -19
  163. package/dist/workflows/runtime/run-plan.js +11 -53
  164. package/dist/workflows/runtime/runs.js +4 -27
  165. package/dist/workflows/source-files.js +12 -16
  166. package/dist/workflows/source-semantics.js +1 -93
  167. package/docs/README.md +1 -1
  168. package/docs/agents/README.md +3 -3
  169. package/docs/agents/agent-install.md +1 -1
  170. package/docs/architecture/adapters.md +17 -31
  171. package/docs/architecture/architecture.md +4 -5
  172. package/docs/architecture/improvement.md +52 -21
  173. package/docs/architecture/internals/improve-workflow.md +15 -8
  174. package/docs/architecture/internals/indexing.md +1 -1
  175. package/docs/architecture/internals/search.md +1 -2
  176. package/docs/architecture/internals/storage-locations.md +5 -5
  177. package/docs/architecture/persisted-data-compat.md +13 -4
  178. package/docs/architecture/specs/0.9.0-decisions.md +6 -2
  179. package/docs/architecture/specs/improve-collapse-churn-detector-design.md +2 -2
  180. package/docs/architecture/specs/workflow-format-unification.md +1 -6
  181. package/docs/architecture/testing/manual-testing-checklist.md +20 -29
  182. package/docs/architecture/testing/task-workflow-manual-tests.md +106 -203
  183. package/docs/architecture/testing/testing-workflow.md +1 -1
  184. package/docs/architecture/workflow-engine.md +5 -56
  185. package/docs/guides/author-workflows.md +39 -69
  186. package/docs/guides/capture-knowledge.md +1 -1
  187. package/docs/guides/claude-code-vs-akm-workflows.md +1 -2
  188. package/docs/guides/discover-and-load.md +4 -4
  189. package/docs/guides/getting-started.md +1 -1
  190. package/docs/guides/improve-the-library.md +7 -7
  191. package/docs/guides/recipes/headless-install.md +2 -2
  192. package/docs/guides/run-workflows.md +1 -1
  193. package/docs/guides/use-with-any-agent.md +49 -4
  194. package/docs/integration/bundling-akm.md +7 -6
  195. package/docs/maintainers/curate-workmap.md +1 -2
  196. package/docs/maintainers/release-checklist.md +30 -1
  197. package/docs/posts/akm-command-tour.md +3 -3
  198. package/docs/product-surface.md +1 -1
  199. package/docs/reference/README.md +1 -0
  200. package/docs/reference/api.md +65 -0
  201. package/docs/reference/asset-types.md +3 -5
  202. package/docs/reference/bundle-types.md +2 -4
  203. package/docs/reference/cli.md +129 -171
  204. package/docs/reference/configuration.md +84 -19
  205. package/docs/reference/data-and-telemetry.md +1 -1
  206. package/docs/reference/env-and-secrets.md +2 -2
  207. package/docs/reference/supported-formats.md +3 -4
  208. package/docs/reference/tasks.md +12 -19
  209. package/docs/reference/website-sources.md +1 -1
  210. package/docs/reference/workflow-schema.md +89 -317
  211. package/docs/reference/workflows.md +20 -48
  212. package/package.json +12 -2
  213. package/schemas/akm-config.json +2 -243
  214. package/schemas/akm-task.json +2 -3
  215. package/schemas/akm-workflow.json +47 -84
  216. package/dist/assets/improve-strategies/catchup.json +0 -41
  217. package/dist/assets/improve-strategies/proactive-maintenance.json +0 -24
  218. package/dist/assets/improve-strategies/quick.json +0 -17
  219. package/dist/assets/improve-strategies/reflect-distill.json +0 -29
  220. package/dist/assets/improve-strategies/thorough.json +0 -49
  221. package/dist/assets/tasks/improve/akm-improve-catchup.yml +0 -6
  222. package/dist/assets/tasks/improve/akm-improve-frequent.yml +0 -4
  223. package/dist/assets/tasks/improve/akm-improve-nightly.yml +0 -4
  224. package/dist/cli/retired-commands.js +0 -118
  225. package/dist/commands/tasks/validate.js +0 -176
  226. package/dist/core/config/legacy-source-shape-shim.js +0 -117
  227. package/dist/integrations/harnesses/ids.js +0 -28
  228. package/dist/tasks/source/task-source-v3-frozen.js +0 -424
  229. package/dist/tasks/source/task-to-v4.js +0 -863
  230. package/dist/workflows/exec/worktree.js +0 -372
  231. package/dist/workflows/freeze/child-output-references.js +0 -83
  232. package/dist/workflows/freeze/identity.js +0 -22
  233. package/dist/workflows/freeze/targets/script.js +0 -50
  234. package/dist/workflows/freeze/targets/task.js +0 -124
  235. package/dist/workflows/github-yaml.js +0 -506
  236. package/dist/workflows/runtime/run-outputs.js +0 -80
@@ -17,15 +17,10 @@ import { checkWorkflowPlan } from "../compile.js";
17
17
  import { defaultMapConcurrency, workflowMaxConcurrency } from "../concurrency-policy.js";
18
18
  import { canonicalJson } from "../ir/plan-hash.js";
19
19
  import { WORKFLOW_PLAN_VERSION, } from "../plan.js";
20
- import { classifyWorkflowStepUses } from "../source-semantics.js";
21
- import { assertChildOutputReferences } from "./child-output-references.js";
22
- import { qualifyRef } from "./environment.js";
23
20
  import { baseUnitOf } from "./step-values.js";
24
21
  import { childWorkflowDispatch } from "./targets/child-workflow.js";
25
22
  import { commandDispatch, commandResult } from "./targets/command.js";
26
- import { directScript } from "./targets/script.js";
27
23
  import { directShell } from "./targets/shell.js";
28
- import { taskDispatch } from "./targets/task.js";
29
24
  /** Resolve and freeze one workflow (and, recursively, every child it composes). */
30
25
  export async function freezeWorkflow(asset, config, refPath = [asset.ref]) {
31
26
  const compiled = asset.plan;
@@ -45,12 +40,9 @@ export async function freezeWorkflow(asset, config, refPath = [asset.ref]) {
45
40
  for (const step of compiled.steps) {
46
41
  const { spec, ...frozenStep } = step;
47
42
  const source = { ...(spec ?? { source: { path: asset.path, start: 1, end: 1 } }), id: step.stepId };
48
- let root;
49
- if (!step.route) {
50
- const resolved = await resolveStep(source, context);
51
- engineAnnouncement ??= resolved.engineAnnouncement;
52
- root = frozenRoot(step.stepId, source, resolved, compiled, config);
53
- }
43
+ const resolved = await resolveStep(source, context);
44
+ engineAnnouncement ??= resolved.engineAnnouncement;
45
+ const root = frozenRoot(step.stepId, source, resolved, compiled, config);
54
46
  let frozenJudge = null;
55
47
  if (step.gate.criteria.length > 0) {
56
48
  const judge = resolveJudge(source, step.gate.criteria[0] ?? "", context);
@@ -64,16 +56,14 @@ export async function freezeWorkflow(asset, config, refPath = [asset.ref]) {
64
56
  "for `akm workflow resume` once it is reached.");
65
57
  }
66
58
  }
67
- steps.push({ ...frozenStep, ...(root ? { root } : {}), gate: { ...step.gate, frozenJudge } });
59
+ steps.push({ ...frozenStep, root, gate: { ...step.gate, frozenJudge } });
68
60
  }
69
- assertChildOutputReferences(steps);
70
61
  const plan = {
71
62
  irVersion: WORKFLOW_PLAN_VERSION,
72
63
  title: asset.title,
73
64
  ...(compiled.params ? { params: compiled.params } : {}),
74
65
  ...(compiled.paramSchemas ? { paramSchemas: compiled.paramSchemas } : {}),
75
66
  ...(compiled.budget ? { budget: compiled.budget } : {}),
76
- ...(compiled.outputs ? { outputs: compiled.outputs } : {}),
77
67
  execution: { maxConcurrency: workflowMaxConcurrency(config.workflow?.maxConcurrency) },
78
68
  sourceHash: asset.sourceHash,
79
69
  steps,
@@ -84,33 +74,11 @@ async function resolveStep(source, context) {
84
74
  const baseUnit = baseUnitOf(source);
85
75
  if (source.exec)
86
76
  return directShell(source, baseUnit, context);
87
- if (!source.uses)
88
- throw new Error(`workflow step ${source.id} has neither exec nor uses`);
89
- const target = classifyWorkflowStepUses(source.uses);
90
- if (target.kind === "task")
91
- return taskDispatch(source, baseUnit, target.ref, context);
92
- if (target.kind === "workflow") {
93
- return childWorkflowDispatch({
94
- source,
95
- baseUnit,
96
- childRefInput: target.ref,
97
- context,
98
- via: "direct",
99
- authoredInputs: { kind: "with", value: source.with },
100
- });
101
- }
102
- // `commands/<ref>` and `scripts/<ref>` are not binding surfaces; `akm/command`'s
103
- // `with:` is its own argument bag.
104
- if (target.kind !== "builtin-command" && source.with !== undefined) {
105
- const family = target.kind === "command" ? "commands" : "scripts";
106
- throw new UsageError(`Workflow step ${source.id} cannot pass with: to ${family} target ${target.ref}; a ${target.kind} ref is not a binding surface.`, "COMPOSITION_INVALID");
77
+ if (source.workflow) {
78
+ return childWorkflowDispatch({ source, baseUnit, childRefInput: source.workflow, context });
107
79
  }
108
- if (target.kind === "script")
109
- return directScript(source, baseUnit, target.ref, context);
110
- const action = target.kind === "builtin-command"
111
- ? source.with
112
- : { ref: qualifyRef(target.ref, "commands", context.asset, context.config) };
113
- return commandDispatch(source, baseUnit, action, context);
80
+ // A prose step: its body is the `akm/command` literal content (`parser.ts` `stepSpec`).
81
+ return commandDispatch(source, baseUnit, source.with, context);
114
82
  }
115
83
  /** The gate judge's frozen command target, or undefined when no engine is available and none is configured. */
116
84
  function resolveJudge(source, rubric, context) {
@@ -153,7 +121,6 @@ function frozenRoot(stepId, source, resolved, plan, config) {
153
121
  ...(unit.retry ? { retry: { max: unit.retry.max, on: [...unit.retry.on] } } : {}),
154
122
  onError: unit.onError ?? plan.defaults?.onError ?? "fail",
155
123
  ...(unit.env ? { env: [...unit.env] } : {}),
156
- isolation: unit.isolation ?? "none",
157
124
  source: { ...source.source },
158
125
  frozenTarget: target,
159
126
  environment: [...resolved.environment],
@@ -1,48 +1,31 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
1
  /**
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.
2
+ * The one child-workflow resolver (`unit: { workflow: <ref> }`, Experimental).
3
+ * It resolves the child, refuses a composition cycle, freezes the child
4
+ * completely through the injected `ResolutionContext.freezeChild`, binds the
5
+ * step's `with:` against the child's `params:`, and embeds the frozen child
6
+ * plan in the target.
11
7
  */
12
8
  import { createHash } from "node:crypto";
13
9
  import { parseBundleRef } from "../../../core/asset/asset-ref.js";
14
10
  import { UsageError } from "../../../core/errors.js";
15
- import { warn } from "../../../core/warn.js";
16
11
  import { workflowParamContract } from "../../ir/params.js";
17
12
  import { canonicalJson, canonicalPlanJson } from "../../ir/plan-hash.js";
18
13
  import { loadWorkflowAsset } from "../../runtime/workflow-asset-loader.js";
19
14
  import { resolveOwnedAsset } from "../environment.js";
20
15
  import { declaredParamNames, earlierStepIds, } from "../step-values.js";
21
- import { freezeTaskInputBindings, rebindTaskInputBindings } from "../task-bindings.js";
22
- /** The child target's own content identity: its ref, embedded plan hash, route, and bindings. */
16
+ import { freezeTaskInputBindings } from "../task-bindings.js";
17
+ /** The child target's own content identity: its ref, embedded plan hash, and bindings. */
23
18
  function childWorkflowContentHash(fields) {
24
19
  return createHash("sha256")
25
- .update("akm.workflow.child-workflow\0v1\0")
20
+ .update("akm.workflow.child-workflow\0v2\0")
26
21
  .update(canonicalJson({
27
22
  ref: fields.ref,
28
23
  planHash: fields.planHash,
29
- via: fields.via,
30
- taskRef: fields.taskRef ?? null,
31
24
  inputBindings: fields.inputBindings.length > 0 ? fields.inputBindings : null,
32
25
  }))
33
26
  .digest("hex");
34
27
  }
35
- /** A composing step's own `env:` (literal or `unit.env`) cannot reach the child run, so say so. */
36
- function warnIfStepEnvironment(stepId, childRef, source) {
37
- const hasLiteralEnv = Object.keys(source.env ?? {}).length > 0;
38
- const hasEnvRefs = (source.unit?.env ?? []).length > 0;
39
- if (!hasLiteralEnv && !hasEnvRefs)
40
- return;
41
- warn(`Workflow step ${stepId} declares env: while composing ${childRef}: a child run carries its own frozen ` +
42
- `environment inside its own plan, so this composing step's env: (or unit: env:) is not delivered into it ` +
43
- `and has no effect. Set those variables inside ${childRef}'s own source instead.`);
44
- }
45
- /** A workflow entry of a composition `refPath` — the only entries a cycle can close through. */
28
+ /** A workflow entry of a composition `refPath`. */
46
29
  function isWorkflowRef(ref) {
47
30
  try {
48
31
  return parseBundleRef(ref).conceptId.startsWith("workflows/");
@@ -62,62 +45,43 @@ function assertNoCompositionCycle(stepId, childRef, refPath) {
62
45
  "composing itself, directly or through intermediates.");
63
46
  }
64
47
  export async function childWorkflowDispatch(input) {
65
- const { source, baseUnit, childRefInput, context, via, taskRef, authoredInputs } = input;
66
- // resolve + qualify. Resolution failures propagate unchanged,
67
- // in code and shape — the same authority every other
68
- // composition target (command/script/task) already resolves through.
48
+ const { source, baseUnit, childRefInput, context } = input;
49
+ // Resolution failures propagate unchanged, in code and shape — the same
50
+ // authority every other asset reference resolves through.
69
51
  const owned = await resolveOwnedAsset(childRefInput, "workflow", context);
70
52
  const childAsset = await loadWorkflowAsset(owned.ref);
71
53
  const childRef = childAsset.ref;
72
- // Issue 10: an authored env: on the composing step has no path to reach
73
- // the child run — warn rather than vanish silently (see
74
- // warnIfStepEnvironment's doc comment).
75
- warnIfStepEnvironment(source.id, childRef, source);
76
- // the composition cycle check, before any child compilation.
54
+ // The composition cycle check, before any child compilation.
77
55
  assertNoCompositionCycle(source.id, childRef, context.refPath);
78
56
  // 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);
57
+ const child = await context.freezeChild(childAsset, [...context.refPath, childRef]);
81
58
  // Embed the child plan as plain canonical JSON, exactly as `plan_json` stores it.
82
59
  const embeddedPlanJson = canonicalPlanJson(child.plan);
83
60
  const frozenPlan = JSON.parse(embeddedPlanJson);
84
- // Bind the step's effective inputs against the child's declared params.
85
- const inputBindings = authoredInputs.kind === "bindings"
86
- ? rebindTaskInputBindings({
87
- stepId: source.id,
88
- targetRef: childRef,
89
- bindings: authoredInputs.value,
90
- contract: workflowParamContract(frozenPlan),
91
- })
92
- : freezeTaskInputBindings({
93
- stepId: source.id,
94
- targetRef: childRef,
95
- with: authoredInputs.value,
96
- contract: workflowParamContract(frozenPlan),
97
- earlierStepIds: earlierStepIds(context.plan, source.id),
98
- declaredParamNames: declaredParamNames(context.plan),
99
- });
100
- // build the frozen target.
61
+ // Bind the step's `with:` against the child's declared params.
62
+ const inputBindings = freezeTaskInputBindings({
63
+ stepId: source.id,
64
+ targetRef: childRef,
65
+ with: source.with,
66
+ contract: workflowParamContract(frozenPlan),
67
+ earlierStepIds: earlierStepIds(context.plan, source.id),
68
+ declaredParamNames: declaredParamNames(context.plan),
69
+ });
101
70
  const planHash = createHash("sha256").update(embeddedPlanJson).digest("hex");
102
- const contentHash = childWorkflowContentHash({ ref: childRef, planHash, via, taskRef, inputBindings });
103
71
  const target = Object.freeze({
104
72
  kind: "child-workflow",
105
73
  ref: childRef,
106
74
  planHash,
107
75
  frozenPlan,
108
- contentHash,
109
- via,
110
- ...(taskRef !== undefined ? { taskRef } : {}),
76
+ contentHash: childWorkflowContentHash({ ref: childRef, planHash, inputBindings }),
111
77
  ...(inputBindings.length > 0 ? { inputBindings } : {}),
112
78
  });
113
79
  return {
114
80
  target,
115
- // A child run carries its own frozen environment inside its own plan.
116
- // A composing step's own env: cannot reach it, so assertNoStepEnvironment
117
- // above rejects one instead of it silently vanishing here.
81
+ // A child run carries its own frozen environment inside its own plan; the
82
+ // parser rejects an `env` beside `workflow`, so there is nothing to deliver.
118
83
  environment: [],
119
84
  unit: baseUnit,
120
- instructions: source.instructions ??
121
- (via === "task" && taskRef !== undefined ? `Run task ${taskRef}.` : `Run workflow ${childRef}.`),
85
+ instructions: source.instructions ?? `Run workflow ${childRef}.`,
122
86
  };
123
87
  }
@@ -2,34 +2,21 @@
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 { createHash } from "node:crypto";
5
- import { parseBuiltinCommandAction } from "../../../commands/command/builtin-action.js";
6
5
  import { prepareCommandInvocation } from "../../../commands/command/command-execution.js";
7
- import { PORTABLE_ARGUMENTS_PLACEHOLDER } from "../../../commands/command/portable-template.js";
8
6
  import { captureFrozenDirectoryIdentity } from "../../../execution/directory-identity.js";
9
7
  import { canonicalResolvedExecutionRequest, } from "../../../execution/resolved-request.js";
10
8
  import { fallbackAnnouncement } from "../../../integrations/agent/engine-fallback.js";
11
9
  import { buildExecution } from "../../../integrations/agent/execution.js";
12
10
  import { freezeEnvironment, workflowExecutionSource } from "../environment.js";
13
- import { gitIdentity } from "../identity.js";
14
11
  import { durableRequest, executionUnitValues, targetConcurrency, } from "../step-values.js";
15
- function inlineWorkflowCommandAction(action, commandMode) {
16
- if (commandMode !== "portable-template")
17
- return action;
18
- const parsed = parseBuiltinCommandAction(action);
19
- if (parsed.kind !== "inline")
20
- return action;
21
- return { content: parsed.content.split(PORTABLE_ARGUMENTS_PLACEHOLDER).join(parsed.arguments ?? "") };
22
- }
23
12
  export async function commandDispatch(source, baseUnit, action, context) {
24
13
  const prepared = await prepareCommandInvocation({
25
- action: inlineWorkflowCommandAction(action, source.commandMode),
14
+ action,
26
15
  config: context.config,
27
16
  ...(context.plan.defaults
28
17
  ? { invocationDefaults: executionUnitValues(context.plan.defaults, context.asset.sourcePath) }
29
18
  : {}),
30
- ...(source.commandMode === "literal" || source.commandMode === "portable-template"
31
- ? { inlineContentMode: "literal" }
32
- : {}),
19
+ inlineContentMode: "literal",
33
20
  current: executionUnitValues(source.unit, context.asset.sourcePath),
34
21
  sourceLoader: (ref, kind) => workflowExecutionSource(ref, kind, context),
35
22
  });
@@ -57,7 +44,6 @@ export function commandResult(source, baseUnit, prepared, context, literals = []
57
44
  runner,
58
45
  ...(targetConcurrency(runner, context.config) ? { concurrency: targetConcurrency(runner, context.config) } : {}),
59
46
  cwdIdentity,
60
- ...gitIdentity(baseUnit, cwdIdentity.realRoot),
61
47
  });
62
48
  const engineAnnouncement = fallbackAnnouncement(prepared.fallbackEngineName, request.engine.name);
63
49
  return {
@@ -3,7 +3,6 @@
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  import { captureFrozenDirectoryIdentity } from "../../../execution/directory-identity.js";
5
5
  import { freezeEnvironment } from "../environment.js";
6
- import { gitIdentity } from "../identity.js";
7
6
  import { freezeExecSpec, } from "../step-values.js";
8
7
  export function directShell(source, baseUnit, context) {
9
8
  const authoredExec = baseUnit.exec;
@@ -17,7 +16,6 @@ export function directShell(source, baseUnit, context) {
17
16
  contentHash: "",
18
17
  exec,
19
18
  cwdIdentity,
20
- ...gitIdentity(baseUnit, cwdIdentity.realRoot),
21
19
  });
22
20
  return {
23
21
  target,
@@ -4,10 +4,8 @@
4
4
  /**
5
5
  * Pure freeze-time binding of a composing step's inputs.
6
6
  * {@link freezeTaskInputBindings} classifies an authored `with:` against a
7
- * contract; {@link rebindTaskInputBindings} re-binds already-classified
8
- * bindings by name against another contract (a task's effective inputs
9
- * against a child workflow's `params:`) without re-deriving their kind. A
10
- * reference's resolved value is validated before each attempt (`exec/step-work.ts`).
7
+ * child workflow's `params:` contract. A reference's resolved value is
8
+ * validated before each attempt (`exec/step-work.ts`).
11
9
  * See docs/architecture/decisions/0008-task-binding-normalization.md.
12
10
  */
13
11
  import { isRecord } from "../../core/common.js";
@@ -41,30 +39,6 @@ export function freezeTaskInputBindings(input) {
41
39
  }
42
40
  return finalizeBindings(stepId, targetRef, contract, byName);
43
41
  }
44
- /**
45
- * Re-bind already-normalized bindings by name against a different contract,
46
- * keeping each entry's kind (a literal shaped like `{from}` stays a literal).
47
- * A literal is validated against the new contract; a reference keeps its
48
- * `from` and takes the new contract's schema; undeclared names are
49
- * `INPUT_BINDING_INVALID`; missing keys are defaulted or required as usual.
50
- */
51
- export function rebindTaskInputBindings(input) {
52
- const { stepId, targetRef, contract } = input;
53
- const declaredNames = Object.keys(contract).sort();
54
- const byName = new Map();
55
- for (const binding of input.bindings ?? []) {
56
- if (!Object.hasOwn(contract, binding.name)) {
57
- throw unknownBindingNameError(stepId, targetRef, binding.name, declaredNames);
58
- }
59
- const declaration = contract[binding.name];
60
- if (!declaration)
61
- throw inputBindingInvalid(`Workflow step ${stepId} targets ${targetRef} with.${binding.name} is invalid.`);
62
- byName.set(binding.name, binding.kind === "literal"
63
- ? binding
64
- : Object.freeze({ kind: "reference", name: binding.name, from: binding.from, schema: declaration.schema }));
65
- }
66
- return finalizeBindings(stepId, targetRef, contract, byName);
67
- }
68
42
  /** Shared tail: apply defaults (or require), schema-validate every literal, and sort by name. */
69
43
  function finalizeBindings(stepId, targetRef, contract, byName) {
70
44
  for (const [name, declaration] of Object.entries(contract)) {
@@ -7,13 +7,16 @@
7
7
  * every declared param is optional, and the messages are the workflow ones.
8
8
  */
9
9
  import { UsageError } from "../../core/errors.js";
10
- import { materializeInputFlags, validateInputs, } from "../../execution/input-contract.js";
10
+ import { applyInputDefaults, materializeInputFlags, validateInputs, } from "../../execution/input-contract.js";
11
11
  /** Every declared workflow param as an `InputDeclaration`, `required: false` — workflow params declare nothing required. */
12
12
  function contractFromPlan(plan) {
13
13
  const names = plan.params ?? Object.keys(plan.paramSchemas ?? {});
14
14
  const contract = {};
15
15
  for (const name of names) {
16
- contract[name] = { schema: plan.paramSchemas?.[name] ?? {}, required: false };
16
+ const schema = plan.paramSchemas?.[name] ?? {};
17
+ contract[name] = Object.hasOwn(schema, "default")
18
+ ? { schema, default: schema.default, required: false }
19
+ : { schema, required: false };
17
20
  }
18
21
  return contract;
19
22
  }
@@ -45,6 +48,13 @@ export function materializeWorkflowParameterFlags(plan, flags) {
45
48
  return {};
46
49
  return materializeInputFlags(contractFromPlan(plan), flags, WORKFLOW_PARAMETER_DIAGNOSTICS);
47
50
  }
51
+ /**
52
+ * Fill each declared param the run did not supply with its `default:`. An
53
+ * explicit value always wins; params without a default stay absent.
54
+ */
55
+ export function applyWorkflowParamDefaults(plan, params) {
56
+ return applyInputDefaults(contractFromPlan(plan), params);
57
+ }
48
58
  /**
49
59
  * Validate a run's supplied params against the plan's frozen param schemas.
50
60
  * Returns a flat list of human-readable, path-prefixed error strings (empty =