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.
- package/CHANGELOG.md +265 -0
- package/STABILITY.md +79 -53
- package/dist/api-node.mjs +20 -0
- package/dist/api.d.ts +23 -0
- package/dist/api.js +45 -0
- package/dist/assets/hints/cli-hints-full.md +13 -27
- package/dist/assets/hints/cli-hints-short.md +1 -1
- package/dist/assets/improve-strategies/default.json +3 -3
- package/dist/assets/prompts/consolidate-pair.md +9 -7
- package/dist/cli/shared.js +31 -48
- package/dist/cli/unknown-flags.js +6 -43
- package/dist/cli.js +8 -34
- package/dist/commands/agent/contribute-cli.js +1 -1
- package/dist/commands/completions.js +1 -2
- package/dist/commands/config-cli.js +5 -28
- package/dist/commands/env/env-cli.js +5 -5
- package/dist/commands/env/secret-cli.js +2 -2
- package/dist/commands/health/checks.js +41 -16
- package/dist/commands/health/plugin-staleness.js +52 -22
- package/dist/commands/improve/autonomy-gate.js +5 -3
- package/dist/commands/improve/consolidate/pair-pass.js +7 -1
- package/dist/commands/improve/consolidate.js +6 -35
- package/dist/commands/improve/distill/lesson-update.js +91 -0
- package/dist/commands/improve/distill-guards.js +1 -43
- package/dist/commands/improve/distill.js +140 -20
- package/dist/commands/improve/eligibility.js +14 -1
- package/dist/commands/improve/extract-cli.js +1 -1
- package/dist/commands/improve/improve-cli.js +87 -102
- package/dist/commands/improve/improve-strategies.js +8 -12
- package/dist/commands/improve/improve.js +2 -2
- package/dist/commands/improve/loop-stages.js +0 -1
- package/dist/commands/improve/planner.js +0 -1
- package/dist/commands/improve/preparation.js +40 -99
- package/dist/commands/improve/proactive-maintenance.js +2 -2
- package/dist/commands/improve/reflect-noise.js +3 -55
- package/dist/commands/improve/reflect.js +3 -8
- package/dist/commands/improve/retrieval-scope.js +2 -2
- package/dist/commands/improve/salience.js +2 -9
- package/dist/commands/improve/stage.js +14 -9
- package/dist/commands/lint/index.js +5 -20
- package/dist/commands/observability-cli.js +3 -9
- package/dist/commands/proposal/drain.js +39 -6
- package/dist/commands/proposal/proposal-cli.js +11 -31
- package/dist/commands/proposal/repository.js +3 -3
- package/dist/commands/read/knowledge.js +3 -3
- package/dist/commands/read/remember-cli.js +0 -13
- package/dist/commands/read/search-cli.js +29 -97
- package/dist/commands/read/search.js +0 -11
- package/dist/commands/read/show.js +0 -19
- package/dist/commands/sources/plugin-upgrade.js +164 -101
- package/dist/commands/sources/sources-cli.js +1 -15
- package/dist/commands/sources/stash-cli.js +4 -12
- package/dist/commands/tasks/tasks-cli.js +4 -115
- package/dist/commands/workflow/plan.js +11 -33
- package/dist/commands/workflow-cli.js +2 -7
- package/dist/core/adapter/adapter-ids.js +1 -2
- package/dist/core/adapter/adapters/agent-skills-adapter.js +0 -4
- package/dist/core/adapter/adapters/akm-adapter.js +9 -48
- package/dist/core/adapter/adapters/akm-lint.js +10 -26
- package/dist/core/adapter/adapters/akm-metadata.js +2 -72
- package/dist/core/adapter/adapters/akm-task-adapter.js +0 -5
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +9 -28
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -20
- package/dist/core/adapter/adapters/generic-files-adapter.js +0 -10
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +0 -4
- package/dist/core/adapter/adapters/tool-dir-shared.js +0 -24
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -4
- package/dist/core/adapter/recognize-match.js +3 -4
- package/dist/core/common.js +18 -2
- package/dist/core/config/config-schema.js +12 -15
- package/dist/core/config/config-types.js +6 -15
- package/dist/core/config/config-walker.js +6 -23
- package/dist/core/config/config.js +17 -80
- package/dist/core/config/engine-semantics.js +7 -3
- package/dist/core/config/schema/engines.js +7 -7
- package/dist/core/config/schema/improve-processes.js +8 -61
- package/dist/core/config/schema/improve.js +2 -21
- package/dist/core/config/schema/index-config.js +6 -39
- package/dist/core/env-secret-ref.js +2 -45
- package/dist/core/errors.js +1 -2
- package/dist/core/extra-params.js +2 -86
- package/dist/core/improve-result.js +11 -1
- package/dist/core/mutation-target.js +2 -2
- package/dist/core/recognition-util.js +4 -5
- package/dist/core/warn.js +21 -4
- package/dist/core/write-source.js +3 -3
- package/dist/execution/target-ref.js +1 -2
- package/dist/indexer/search/db-search.js +4 -19
- package/dist/indexer/search/fts-query.js +0 -19
- package/dist/integrations/agent/engine-resolution.js +5 -2
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +41 -98
- package/dist/integrations/agent/request-lowering.js +3 -3
- package/dist/integrations/harnesses/aider/index.js +5 -0
- package/dist/integrations/harnesses/amazonq/index.js +1 -0
- package/dist/integrations/harnesses/claude/config-import.js +2 -3
- package/dist/integrations/harnesses/claude/index.js +5 -0
- package/dist/integrations/harnesses/codex/index.js +1 -0
- package/dist/integrations/harnesses/copilot/index.js +1 -0
- package/dist/integrations/harnesses/gemini/index.js +1 -0
- package/dist/integrations/harnesses/index.js +18 -39
- package/dist/integrations/harnesses/opencode/agent-builder.js +60 -35
- package/dist/integrations/harnesses/opencode/config-import.js +121 -52
- package/dist/integrations/harnesses/opencode/index.js +22 -0
- package/dist/integrations/harnesses/opencode/plugin-layout.js +68 -0
- package/dist/integrations/harnesses/opencode/session-log-types.js +12 -0
- package/dist/integrations/harnesses/opencode/session-log-v1.js +72 -0
- package/dist/integrations/harnesses/opencode/session-log-v2.js +140 -0
- package/dist/integrations/harnesses/opencode/session-log.js +104 -115
- package/dist/integrations/harnesses/opencode/version.js +98 -0
- package/dist/integrations/harnesses/opencode-sdk/{harness.js → index.js} +5 -17
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +105 -206
- package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +199 -0
- package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +228 -0
- package/dist/integrations/harnesses/opencode-sdk/wire.js +66 -0
- package/dist/integrations/harnesses/openhands/index.js +1 -0
- package/dist/integrations/harnesses/pi/index.js +1 -0
- package/dist/integrations/harnesses/shared.js +2 -0
- package/dist/integrations/harnesses/types.js +2 -0
- package/dist/llm/client.js +41 -11
- package/dist/output/cli-hints.js +1 -1
- package/dist/output/context.js +10 -19
- package/dist/output/format-exempt.js +5 -8
- package/dist/output/shapes/helpers.js +1 -22
- package/dist/output/shapes/passthrough.js +0 -1
- package/dist/output/shapes.js +3 -31
- package/dist/output/stdout.js +5 -1
- package/dist/output/text/command-format.js +6 -1
- package/dist/output/text/workflow-format.js +4 -22
- package/dist/scripts/akm-migrate-node.js +13049 -14013
- package/dist/scripts/akm-migrate.js +16316 -17276
- package/dist/setup/detect.js +10 -4
- package/dist/setup/harness-config-import.js +5 -14
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/tasks.js +12 -13
- package/dist/storage/repositories/task-history-repository.js +0 -5
- package/dist/storage/repositories/workflow-runs-repository.js +5 -15
- package/dist/tasks/embedded.js +2 -1
- package/dist/tasks/run/task-history.js +0 -2
- package/dist/tasks/schedule-gates.js +39 -0
- package/dist/tasks/scheduler-binding.js +0 -16
- package/dist/tasks/scheduler-sync.js +3 -97
- package/dist/tasks/source/bounded-document.js +1 -1
- package/dist/tasks/source/task-source-v4.js +2 -12
- package/dist/tasks/task-run-reserved-flags.js +2 -31
- package/dist/workflows/authoring/authoring.js +6 -6
- package/dist/workflows/compile.js +8 -65
- package/dist/workflows/exec/child-workflow.js +22 -3
- package/dist/workflows/exec/native-executor.js +12 -147
- package/dist/workflows/exec/run-workflow.js +31 -103
- package/dist/workflows/exec/step-work.js +9 -178
- package/dist/workflows/exec/unit-dispatch.js +0 -10
- package/dist/workflows/freeze/environment.js +3 -44
- package/dist/workflows/freeze/freeze.js +8 -41
- package/dist/workflows/freeze/targets/child-workflow.js +27 -63
- package/dist/workflows/freeze/targets/command.js +2 -16
- package/dist/workflows/freeze/targets/shell.js +0 -2
- package/dist/workflows/freeze/task-bindings.js +2 -28
- package/dist/workflows/ir/params.js +12 -2
- package/dist/workflows/parser.js +82 -232
- package/dist/workflows/plan.js +1 -1
- package/dist/workflows/renderer.js +10 -19
- package/dist/workflows/runtime/run-plan.js +11 -53
- package/dist/workflows/runtime/runs.js +4 -27
- package/dist/workflows/source-files.js +12 -16
- package/dist/workflows/source-semantics.js +1 -93
- package/docs/README.md +1 -1
- package/docs/agents/README.md +3 -3
- package/docs/agents/agent-install.md +1 -1
- package/docs/architecture/adapters.md +17 -31
- package/docs/architecture/architecture.md +4 -5
- package/docs/architecture/improvement.md +52 -21
- package/docs/architecture/internals/improve-workflow.md +15 -8
- package/docs/architecture/internals/indexing.md +1 -1
- package/docs/architecture/internals/search.md +1 -2
- package/docs/architecture/internals/storage-locations.md +5 -5
- package/docs/architecture/persisted-data-compat.md +13 -4
- package/docs/architecture/specs/0.9.0-decisions.md +6 -2
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +2 -2
- package/docs/architecture/specs/workflow-format-unification.md +1 -6
- package/docs/architecture/testing/manual-testing-checklist.md +20 -29
- package/docs/architecture/testing/task-workflow-manual-tests.md +106 -203
- package/docs/architecture/testing/testing-workflow.md +1 -1
- package/docs/architecture/workflow-engine.md +5 -56
- package/docs/guides/author-workflows.md +39 -69
- package/docs/guides/capture-knowledge.md +1 -1
- package/docs/guides/claude-code-vs-akm-workflows.md +1 -2
- package/docs/guides/discover-and-load.md +4 -4
- package/docs/guides/getting-started.md +1 -1
- package/docs/guides/improve-the-library.md +7 -7
- package/docs/guides/recipes/headless-install.md +2 -2
- package/docs/guides/run-workflows.md +1 -1
- package/docs/guides/use-with-any-agent.md +49 -4
- package/docs/integration/bundling-akm.md +7 -6
- package/docs/maintainers/curate-workmap.md +1 -2
- package/docs/maintainers/release-checklist.md +30 -1
- package/docs/posts/akm-command-tour.md +3 -3
- package/docs/product-surface.md +1 -1
- package/docs/reference/README.md +1 -0
- package/docs/reference/api.md +65 -0
- package/docs/reference/asset-types.md +3 -5
- package/docs/reference/bundle-types.md +2 -4
- package/docs/reference/cli.md +129 -171
- package/docs/reference/configuration.md +84 -19
- package/docs/reference/data-and-telemetry.md +1 -1
- package/docs/reference/env-and-secrets.md +2 -2
- package/docs/reference/supported-formats.md +3 -4
- package/docs/reference/tasks.md +12 -19
- package/docs/reference/website-sources.md +1 -1
- package/docs/reference/workflow-schema.md +89 -317
- package/docs/reference/workflows.md +20 -48
- package/package.json +12 -2
- package/schemas/akm-config.json +2 -243
- package/schemas/akm-task.json +2 -3
- package/schemas/akm-workflow.json +47 -84
- package/dist/assets/improve-strategies/catchup.json +0 -41
- package/dist/assets/improve-strategies/proactive-maintenance.json +0 -24
- package/dist/assets/improve-strategies/quick.json +0 -17
- package/dist/assets/improve-strategies/reflect-distill.json +0 -29
- package/dist/assets/improve-strategies/thorough.json +0 -49
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +0 -6
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +0 -4
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +0 -4
- package/dist/cli/retired-commands.js +0 -118
- package/dist/commands/tasks/validate.js +0 -176
- package/dist/core/config/legacy-source-shape-shim.js +0 -117
- package/dist/integrations/harnesses/ids.js +0 -28
- package/dist/tasks/source/task-source-v3-frozen.js +0 -424
- package/dist/tasks/source/task-to-v4.js +0 -863
- package/dist/workflows/exec/worktree.js +0 -372
- package/dist/workflows/freeze/child-output-references.js +0 -83
- package/dist/workflows/freeze/identity.js +0 -22
- package/dist/workflows/freeze/targets/script.js +0 -50
- package/dist/workflows/freeze/targets/task.js +0 -124
- package/dist/workflows/github-yaml.js +0 -506
- 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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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,
|
|
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 (
|
|
88
|
-
|
|
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
|
-
|
|
109
|
-
|
|
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
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
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
|
|
22
|
-
/** The child target's own content identity: its ref, embedded plan hash,
|
|
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\
|
|
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
|
|
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
|
|
66
|
-
//
|
|
67
|
-
//
|
|
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
|
-
//
|
|
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
|
|
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
|
|
85
|
-
const inputBindings =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
//
|
|
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
|
|
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
|
-
|
|
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
|
|
8
|
-
*
|
|
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
|
-
|
|
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 =
|