akm-cli 0.9.1 → 0.9.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +103 -28
- package/README.md +3 -1
- package/SECURITY.md +1 -1
- package/STABILITY.md +1 -1
- package/dist/akm +2 -2
- package/dist/akm-migrate +2 -2
- package/dist/assets/hints/cli-hints-full.md +14 -9
- package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/models.json +35 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +3 -4
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +1 -3
- package/dist/assets/tasks/core/extract.yml +6 -5
- package/dist/assets/tasks/core/improve.yml +6 -5
- package/dist/assets/tasks/core/index-refresh.yml +6 -5
- package/dist/assets/tasks/core/sync.yml +6 -5
- package/dist/assets/tasks/core/version-check.yml +6 -5
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
- package/dist/cli/confirm.js +2 -2
- package/dist/cli/parse-args.js +3 -24
- package/dist/cli/retired-commands.js +1 -1
- package/dist/cli/shared.js +2 -2
- package/dist/cli.js +11 -9
- package/dist/commands/agent/agent-dispatch.js +55 -89
- package/dist/commands/agent/contribute-cli.js +12 -45
- package/dist/commands/command/builtin-action.js +32 -0
- package/dist/commands/command/command-cli.js +99 -0
- package/dist/commands/command/command-execution.js +308 -0
- package/dist/commands/command/execution-source-loader.js +176 -0
- package/dist/commands/command/portable-template.js +60 -0
- package/dist/commands/config-cli.js +10 -4
- package/dist/commands/env/env.js +4 -2
- package/dist/commands/feedback-cli.js +1 -1
- package/dist/commands/health/checks.js +241 -29
- package/dist/commands/health/html-report.js +0 -14
- package/dist/commands/health/report-view-model.js +0 -1
- package/dist/commands/health/surfaces.js +6 -7
- package/dist/commands/health/types.js +0 -2
- package/dist/commands/health.js +63 -18
- package/dist/commands/improve/collapse-detector.js +5 -6
- package/dist/commands/improve/consolidate.js +251 -214
- package/dist/commands/improve/distill/promote-memory.js +71 -34
- package/dist/commands/improve/distill/quality-gate.js +17 -5
- package/dist/commands/improve/distill.js +232 -155
- package/dist/commands/improve/eligibility.js +112 -79
- package/dist/commands/improve/execution.js +57 -0
- package/dist/commands/improve/extract-cli.js +5 -5
- package/dist/commands/improve/extract-prompt.js +64 -22
- package/dist/commands/improve/extract.js +608 -360
- package/dist/commands/improve/improve-strategies.js +43 -14
- package/dist/commands/improve/improve.js +249 -29
- package/dist/commands/improve/loop-stages.js +11 -17
- package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
- package/dist/commands/improve/outcome-loop.js +22 -38
- package/dist/commands/improve/planner.js +134 -0
- package/dist/commands/improve/preparation.js +730 -409
- package/dist/commands/improve/reflect.js +386 -223
- package/dist/commands/improve/run-context.js +3 -4
- package/dist/commands/improve/salience.js +6 -58
- package/dist/commands/improve/session-asset.js +12 -12
- package/dist/commands/lint/index.js +101 -29
- package/dist/commands/migrate-cli.js +11 -69
- package/dist/commands/migration-tool.js +6 -9
- package/dist/commands/models-cli.js +27 -0
- package/dist/commands/proposal/drain.js +258 -186
- package/dist/commands/proposal/proposal-cli.js +32 -10
- package/dist/commands/proposal/proposal.js +2 -5
- package/dist/commands/proposal/propose.js +192 -172
- package/dist/commands/proposal/repository.js +54 -91
- package/dist/commands/proposal/validators/proposal-validators.js +9 -7
- package/dist/commands/read/curate.js +53 -22
- package/dist/commands/read/registry-search.js +25 -9
- package/dist/commands/read/remember-cli.js +14 -2
- package/dist/commands/read/search.js +10 -4
- package/dist/commands/read/show.js +139 -153
- package/dist/commands/registry-cli.js +16 -7
- package/dist/commands/remember.js +33 -18
- package/dist/commands/sources/add-cli.js +19 -178
- package/dist/commands/sources/bundle-cli.js +15 -3
- package/dist/commands/sources/dangerous-env-audit.js +135 -0
- package/dist/commands/sources/info.js +2 -1
- package/dist/commands/sources/installed-stashes.js +901 -177
- package/dist/commands/sources/schema-repair.js +174 -95
- package/dist/commands/sources/self-update.js +30 -74
- package/dist/commands/sources/source-add.js +3 -5
- package/dist/commands/sources/sources-cli.js +2 -15
- package/dist/commands/sources/update-transaction.js +220 -0
- package/dist/commands/tasks/tasks-cli.js +3 -3
- package/dist/commands/tasks/tasks.js +736 -317
- package/dist/commands/workflow-cli.js +2 -2
- package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
- package/dist/core/adapter/adapters/akm-adapter.js +85 -35
- package/dist/core/adapter/adapters/akm-lint.js +54 -39
- package/dist/core/adapter/adapters/akm-metadata.js +45 -45
- package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
- package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
- package/dist/core/adapter/adapters/index.js +0 -9
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
- package/dist/core/adapter/adapters/okf-adapter.js +4 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
- package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
- package/dist/core/adapter/execution-source.js +308 -0
- package/dist/core/adapter/recognize-match.js +36 -13
- package/dist/core/adapter/registry.js +0 -9
- package/dist/core/asset/stash-meta.js +94 -4
- package/dist/core/common.js +6 -11
- package/dist/core/config/config-io.js +3 -3
- package/dist/core/config/config-schema.js +18 -40
- package/dist/core/config/config-sources.js +11 -21
- package/dist/core/config/config-walker.js +31 -13
- package/dist/core/config/config.js +23 -26
- package/dist/core/config/schema/engines.js +8 -7
- package/dist/core/config/schema/improve-processes.js +29 -5
- package/dist/core/config/schema/index-config.js +0 -27
- package/dist/core/config/schema/primitives.js +1 -23
- package/dist/core/config/schema/sources-bundles.js +13 -16
- package/dist/core/errors.js +2 -0
- package/dist/core/events.js +68 -32
- package/dist/core/extra-params.js +1 -0
- package/dist/core/improve-result.js +315 -0
- package/dist/core/lesson-lint.js +0 -6
- package/dist/core/maintenance-barrier.js +4 -4
- package/dist/core/network-policy.js +152 -0
- package/dist/core/paths.js +1 -1
- package/dist/core/recognition-util.js +4 -4
- package/dist/core/registry-url.js +456 -0
- package/dist/core/state/migrations.js +161 -47
- package/dist/core/state-db.js +453 -80
- package/dist/core/system-error.js +32 -0
- package/dist/core/time.js +2 -12
- package/dist/core/write-source.js +0 -18
- package/dist/execution/directory-identity.js +52 -0
- package/dist/execution/executable-identity.js +107 -0
- package/dist/execution/guarded-source.js +398 -0
- package/dist/execution/json.js +95 -0
- package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
- package/dist/execution/record.js +55 -0
- package/dist/execution/resolved-request.js +730 -0
- package/dist/execution/source.js +320 -0
- package/dist/indexer/bundle-identity-guard.js +5 -4
- package/dist/indexer/db/graph-db.js +33 -0
- package/dist/indexer/graph/graph-boost.js +3 -4
- package/dist/indexer/graph/graph-extraction.js +562 -373
- package/dist/indexer/index-written-assets.js +78 -39
- package/dist/indexer/indexer.js +471 -432
- package/dist/indexer/installations.js +6 -0
- package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
- package/dist/indexer/materialize-embeddings.js +155 -0
- package/dist/indexer/passes/memory-inference.js +227 -174
- package/dist/indexer/passes/metadata.js +263 -118
- package/dist/indexer/scan/doc-to-entry.js +7 -10
- package/dist/indexer/scan/drain-dir.js +51 -23
- package/dist/indexer/search/db-search.js +156 -50
- package/dist/indexer/search/fts-query.js +40 -40
- package/dist/indexer/search/ranking.js +36 -1
- package/dist/indexer/search/search-attribution.js +3 -1
- package/dist/indexer/search/search-fields.js +23 -14
- package/dist/indexer/search/search-hit-enrichers.js +1 -1
- package/dist/indexer/search/search-source.js +7 -16
- package/dist/indexer/search/semantic-status.js +10 -1
- package/dist/indexer/usage/show-usage.js +105 -0
- package/dist/indexer/usage/usage-events.js +7 -2
- package/dist/indexer/walk/matchers.js +40 -10
- package/dist/indexer/walk/path-resolver.js +5 -2
- package/dist/indexer/walk/walker.js +20 -2
- package/dist/integrations/agent/builder-shared.js +3 -6
- package/dist/integrations/agent/conversation-fallback.js +16 -0
- package/dist/integrations/agent/engine-resolution.js +87 -87
- package/dist/integrations/agent/execution-cascade.js +566 -0
- package/dist/integrations/agent/execution-definitions.js +211 -0
- package/dist/integrations/agent/execution-lowering.js +811 -0
- package/dist/integrations/agent/execution-preparation.js +67 -0
- package/dist/integrations/agent/index.js +0 -2
- package/dist/integrations/agent/inline-execution.js +74 -0
- package/dist/integrations/agent/model-map.js +515 -0
- package/dist/integrations/agent/persona-fallback.js +30 -0
- package/dist/integrations/agent/request-lowering.js +186 -0
- package/dist/integrations/agent/runner-dispatch.js +230 -37
- package/dist/integrations/agent/runner.js +12 -83
- package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
- package/dist/integrations/harnesses/aider/index.js +0 -1
- package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
- package/dist/integrations/harnesses/amazonq/index.js +0 -1
- package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
- package/dist/integrations/harnesses/claude/index.js +1 -5
- package/dist/integrations/harnesses/claude/session-log.js +3 -33
- package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
- package/dist/integrations/harnesses/codex/index.js +0 -1
- package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
- package/dist/integrations/harnesses/copilot/index.js +0 -1
- package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
- package/dist/integrations/harnesses/gemini/index.js +0 -1
- package/dist/integrations/harnesses/index.js +4 -44
- package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
- package/dist/integrations/harnesses/opencode/index.js +0 -2
- package/dist/integrations/harnesses/opencode/session-log.js +14 -204
- package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
- package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
- package/dist/integrations/harnesses/openhands/index.js +0 -1
- package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
- package/dist/integrations/harnesses/pi/index.js +0 -1
- package/dist/integrations/harnesses/shared.js +0 -1
- package/dist/integrations/harnesses/types.js +1 -3
- package/dist/integrations/lockfile.js +82 -79
- package/dist/integrations/session-logs/index.js +6 -17
- package/dist/integrations/session-logs/provider-base.js +1 -29
- package/dist/llm/client.js +10 -5
- package/dist/llm/embedder.js +6 -7
- package/dist/llm/embedders/local.js +37 -88
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/graph-extract.js +75 -50
- package/dist/llm/index-passes.js +43 -5
- package/dist/llm/memory-infer.js +8 -6
- package/dist/llm/metadata-enhance.js +5 -3
- package/dist/llm/structured-call.js +122 -25
- package/dist/output/format-exempt.js +1 -1
- package/dist/output/render-registry.js +0 -16
- package/dist/output/renderers.js +12 -7
- package/dist/output/shapes/curate.js +1 -0
- package/dist/output/shapes/helpers.js +10 -2
- package/dist/output/shapes/passthrough.js +2 -0
- package/dist/output/text/command-format.js +31 -33
- package/dist/output/text/health-format.js +1 -29
- package/dist/output/text/migrate.js +6 -56
- package/dist/output/text/proposal-format.js +16 -1
- package/dist/output/text/workflow-format.js +16 -0
- package/dist/registry/network.js +279 -0
- package/dist/registry/pinned-request-helper.js +247 -0
- package/dist/registry/pinned-transport.js +717 -0
- package/dist/registry/providers/skills-sh.js +18 -6
- package/dist/registry/providers/static-index.js +20 -7
- package/dist/registry/resolve.js +53 -28
- package/dist/scripts/akm-migrate-node.js +19334 -52269
- package/dist/scripts/akm-migrate.js +19270 -51612
- package/dist/setup/registry-stash-loader.js +64 -20
- package/dist/setup/semantic-assets.js +9 -34
- package/dist/setup/setup.js +12 -30
- package/dist/setup/source-identity.js +17 -0
- package/dist/setup/steps/sources.js +36 -15
- package/dist/setup/steps/tasks.js +39 -11
- package/dist/sources/providers/git-provider.js +3 -3
- package/dist/sources/providers/npm.js +2 -2
- package/dist/sources/providers/provider-utils.js +4 -3
- package/dist/sources/providers/website.js +11 -7
- package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
- package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
- package/dist/sources/website-url.js +73 -0
- package/dist/storage/engines/sqlite-migrations.js +81 -26
- package/dist/storage/managed-db.js +27 -24
- package/dist/storage/repositories/events-repository.js +3 -0
- package/dist/storage/repositories/index-connection.js +42 -10
- package/dist/storage/repositories/index-entries-repository.js +203 -229
- package/dist/storage/repositories/index-entry-mapper.js +8 -12
- package/dist/storage/repositories/index-entry-schema.js +255 -0
- package/dist/storage/repositories/index-fts-repository.js +64 -71
- package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
- package/dist/storage/repositories/index-meta-repository.js +0 -11
- package/dist/storage/repositories/index-schema.js +74 -350
- package/dist/storage/repositories/index-utility-repository.js +12 -17
- package/dist/storage/repositories/index-vec-repository.js +56 -7
- package/dist/storage/repositories/proposals-repository.js +4 -127
- package/dist/storage/repositories/registry-cache.js +2 -1
- package/dist/storage/repositories/task-history-repository.js +20 -40
- package/dist/storage/repositories/workflow-runs-repository.js +228 -129
- package/dist/storage/sqlite-read-snapshot.js +148 -0
- package/dist/tasks/backends/cron.js +170 -42
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +787 -202
- package/dist/tasks/backends/schtasks.js +282 -83
- package/dist/tasks/embedded.js +7 -7
- package/dist/tasks/frozen-script.js +50 -0
- package/dist/tasks/resolve-akm-bin.js +5 -1
- package/dist/tasks/runner.js +239 -251
- package/dist/tasks/runtime-v3.js +281 -0
- package/dist/tasks/scheduler-binding.js +272 -0
- package/dist/tasks/scheduler-invocation.js +57 -43
- package/dist/tasks/scheduler-sync.js +654 -0
- package/dist/tasks/source-v3.js +752 -0
- package/dist/tasks/standalone-script-entry.js +5 -0
- package/dist/tasks/task-id.js +29 -0
- package/dist/workflows/authoring/authoring.js +15 -32
- package/dist/workflows/exec/dispatch-redaction.js +14 -8
- package/dist/workflows/exec/exec-unit.js +7 -28
- package/dist/workflows/exec/frozen-judge.js +57 -89
- package/dist/workflows/exec/lowering-notices.js +23 -0
- package/dist/workflows/exec/native-executor.js +301 -458
- package/dist/workflows/exec/param-secrets.js +4 -3
- package/dist/workflows/exec/run-workflow.js +26 -32
- package/dist/workflows/exec/step-work.js +105 -109
- package/dist/workflows/exec/unit-dispatch.js +103 -27
- package/dist/workflows/exec/unit-writer.js +3 -3
- package/dist/workflows/exec/worktree.js +2 -2
- package/dist/workflows/ir/compile.js +86 -72
- package/dist/workflows/ir/environment-v4.js +328 -0
- package/dist/workflows/ir/freeze-v4.js +122 -0
- package/dist/workflows/ir/plan-hash.js +13 -7
- package/dist/workflows/ir/schema-v4.js +525 -0
- package/dist/workflows/ir/schema.js +25 -284
- package/dist/workflows/ir/source-freeze-v4.js +506 -0
- package/dist/workflows/parser.js +27 -24
- package/dist/workflows/program/schema.js +1 -2
- package/dist/workflows/renderer.js +42 -29
- package/dist/workflows/resource-limits.js +4 -5
- package/dist/workflows/runtime/agent-identity.js +11 -13
- package/dist/workflows/runtime/plan-classifier.js +8 -8
- package/dist/workflows/runtime/runs.js +27 -43
- package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
- package/dist/workflows/source-files.js +373 -0
- package/dist/workflows/source-ir/compile.js +196 -0
- package/dist/workflows/source-ir/github-yaml.js +577 -0
- package/dist/workflows/source-ir/ordering.js +38 -0
- package/dist/workflows/source-ir/program.js +50 -0
- package/dist/workflows/source-ir/result.js +26 -0
- package/dist/workflows/source-ir/schema.js +772 -0
- package/dist/workflows/source-ir/semantics.js +242 -0
- package/dist/workflows/source-ir/uses.js +14 -0
- package/docs/README.md +2 -0
- package/docs/migration/README.md +3 -1
- package/docs/migration/release-notes/0.9.2.md +55 -0
- package/docs/migration/release-notes/README.md +5 -0
- package/docs/migration/v0.8-to-v0.9.md +76 -1077
- package/docs/migration/v0.9.0-troubleshooting.md +104 -516
- package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
- package/docs/reference/README.md +1 -0
- package/docs/reference/cli.md +230 -98
- package/docs/reference/configuration.md +159 -36
- package/docs/reference/data-and-telemetry.md +19 -1
- package/docs/reference/supported-formats.md +23 -3
- package/docs/reference/tasks.md +182 -0
- package/docs/reference/workflow-schema.md +91 -40
- package/docs/reference/workflows.md +33 -6
- package/package.json +10 -6
- package/schemas/akm-config.json +372 -224
- package/schemas/akm-task.json +324 -80
- package/schemas/akm-workflow.json +6 -9
- package/dist/core/migration-operation.js +0 -75
- package/dist/integrations/agent/model-aliases.js +0 -74
- package/dist/tasks/parser.js +0 -380
- package/dist/tasks/schema.js +0 -123
- package/dist/tasks/validator.js +0 -80
- package/dist/workflows/ir/freeze.js +0 -320
- package/dist/workflows/runtime/document-cache.js +0 -13
|
@@ -2,17 +2,17 @@
|
|
|
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
|
-
* Show + indexing renderer for
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* public `ShowResponse` shape and into search hints for the indexer,
|
|
5
|
+
* Show + indexing renderer for peer workflow sources. `.md` and `.yml` both
|
|
6
|
+
* compile through `compileWorkflowSource` into source IR v1, which is projected
|
|
7
|
+
* down to the public `ShowResponse` shape and into search hints for the indexer,
|
|
9
8
|
* including a compact per-step orchestration summary (engine/model or an exec
|
|
10
9
|
* unit's argv, `map.over` reference, route table) when the step declares one.
|
|
11
10
|
*/
|
|
12
11
|
import { displayRef } from "../core/asset/resolve-ref.js";
|
|
13
12
|
import { UsageError } from "../core/errors.js";
|
|
14
|
-
import { parseWorkflow } from "./parser.js";
|
|
15
13
|
import { projectExecCore } from "./program/schema.js";
|
|
14
|
+
import { compileWorkflowSource } from "./source-ir/compile.js";
|
|
15
|
+
import { sourceStepInstructions, workflowShellCommand } from "./source-ir/program.js";
|
|
16
16
|
function shellQuote(value) {
|
|
17
17
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
18
18
|
}
|
|
@@ -26,11 +26,11 @@ function deriveName(ctx) {
|
|
|
26
26
|
const ext = ctx.relPath.lastIndexOf(".");
|
|
27
27
|
return ext > 0 ? ctx.relPath.slice(0, ext) : ctx.relPath;
|
|
28
28
|
}
|
|
29
|
-
function
|
|
30
|
-
const result =
|
|
29
|
+
function loadSourceIr(ctx) {
|
|
30
|
+
const result = compileWorkflowSource(ctx.content(), { path: ctx.relPath, workspaceRoot: ctx.stashRoot });
|
|
31
31
|
if (result.ok)
|
|
32
|
-
return result.
|
|
33
|
-
const summary = result.errors.map((e) => `${
|
|
32
|
+
return result.ir;
|
|
33
|
+
const summary = result.errors.map((e) => `${e.path}:${e.line} — ${e.message}`).join("\n");
|
|
34
34
|
throw new UsageError(`Workflow has errors:\n${summary}`);
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
@@ -40,8 +40,9 @@ function loadDocument(ctx) {
|
|
|
40
40
|
* a non-empty instructions string).
|
|
41
41
|
*/
|
|
42
42
|
function stepInstructions(step) {
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
const instructions = sourceStepInstructions(step);
|
|
44
|
+
if (instructions)
|
|
45
|
+
return instructions;
|
|
45
46
|
if (step.route) {
|
|
46
47
|
const branches = step.route.branches.map((b) => `"${b.match}" -> ${b.stepId}`);
|
|
47
48
|
if (step.route.defaultStepId !== undefined)
|
|
@@ -51,10 +52,10 @@ function stepInstructions(step) {
|
|
|
51
52
|
return "";
|
|
52
53
|
}
|
|
53
54
|
/** Project the `params` block into the flat `WorkflowParameter` list. */
|
|
54
|
-
function projectParameters(
|
|
55
|
-
if (!
|
|
55
|
+
function projectParameters(sourceIr) {
|
|
56
|
+
if (!sourceIr.params)
|
|
56
57
|
return undefined;
|
|
57
|
-
const parameters = Object.entries(
|
|
58
|
+
const parameters = Object.entries(sourceIr.params).map(([name, schema]) => {
|
|
58
59
|
const description = schema.description;
|
|
59
60
|
return { name, ...(typeof description === "string" && description !== "" ? { description } : {}) };
|
|
60
61
|
});
|
|
@@ -91,8 +92,15 @@ function projectParameters(document) {
|
|
|
91
92
|
* `instructions` this same projection already carries whole.
|
|
92
93
|
*/
|
|
93
94
|
function summarizeStepOrchestration(step, defaults) {
|
|
94
|
-
const unit = step.unit
|
|
95
|
-
const exec =
|
|
95
|
+
const unit = step.unit;
|
|
96
|
+
const exec = step.exec
|
|
97
|
+
? step.exec
|
|
98
|
+
: step.run !== undefined
|
|
99
|
+
? {
|
|
100
|
+
command: workflowShellCommand(step.shell ?? "sh", step.run),
|
|
101
|
+
...(step.workingDirectory ? { cwd: step.workingDirectory } : {}),
|
|
102
|
+
}
|
|
103
|
+
: undefined;
|
|
96
104
|
const engine = exec ? undefined : (unit?.engine ?? defaults?.engine);
|
|
97
105
|
const model = exec ? undefined : (unit?.model ?? defaults?.model);
|
|
98
106
|
const timeoutMs = unit?.timeoutMs !== undefined ? unit.timeoutMs : defaults?.timeoutMs;
|
|
@@ -126,16 +134,21 @@ function summarizeStepOrchestration(step, defaults) {
|
|
|
126
134
|
};
|
|
127
135
|
return Object.keys(summary).length > 0 ? summary : undefined;
|
|
128
136
|
}
|
|
129
|
-
function projectStepDefinitions(
|
|
130
|
-
|
|
131
|
-
|
|
137
|
+
function projectStepDefinitions(sourceIr) {
|
|
138
|
+
const flattened = sourceIr.jobs.flatMap((job) => job.steps.map((step) => ({ jobId: job.id, step })));
|
|
139
|
+
const counts = new Map();
|
|
140
|
+
for (const { step } of flattened)
|
|
141
|
+
counts.set(step.id, (counts.get(step.id) ?? 0) + 1);
|
|
142
|
+
return flattened.map(({ jobId, step }, sequenceIndex) => {
|
|
143
|
+
const id = (counts.get(step.id) ?? 0) > 1 ? `${jobId}-${step.id}` : step.id;
|
|
144
|
+
const orchestration = summarizeStepOrchestration(step, sourceIr.defaults);
|
|
132
145
|
return {
|
|
133
|
-
id
|
|
134
|
-
// No titles
|
|
146
|
+
id,
|
|
147
|
+
// No titles in the shared source IR — a step IS its id.
|
|
135
148
|
title: step.id,
|
|
136
149
|
instructions: stepInstructions(step),
|
|
137
|
-
...(step.
|
|
138
|
-
sequenceIndex
|
|
150
|
+
...(step.gate?.rubric?.trim() ? { completionCriteria: [step.gate.rubric] } : {}),
|
|
151
|
+
sequenceIndex,
|
|
139
152
|
...(orchestration ? { orchestration } : {}),
|
|
140
153
|
};
|
|
141
154
|
});
|
|
@@ -144,26 +157,26 @@ export const workflowMdRenderer = {
|
|
|
144
157
|
name: "workflow-md",
|
|
145
158
|
buildShowResponse(ctx) {
|
|
146
159
|
const name = deriveName(ctx);
|
|
147
|
-
const
|
|
160
|
+
const sourceIr = loadSourceIr(ctx);
|
|
148
161
|
// WI-8.5b (display flip): the `akm workflow run <ref>` action is DISPLAY
|
|
149
162
|
// output — its spelling follows the D-R5 display rule (`displayRef`). A
|
|
150
163
|
// primary/default-bundle workflow renders the SHORT conceptId
|
|
151
164
|
// (`workflows/<name>`); a named source qualifies it as
|
|
152
165
|
// (`<bundle>//workflows/<name>`).
|
|
153
166
|
const ref = displayRef({ type: "workflow", name, bundleId: ctx.origin }, ctx.defaultBundle);
|
|
154
|
-
const parameters = projectParameters(
|
|
167
|
+
const parameters = projectParameters(sourceIr);
|
|
155
168
|
return {
|
|
156
169
|
type: "workflow",
|
|
157
170
|
name,
|
|
158
171
|
path: ctx.absPath,
|
|
159
172
|
action: buildWorkflowAction(ref),
|
|
160
|
-
...(
|
|
161
|
-
description:
|
|
162
|
-
// No authored title in the
|
|
173
|
+
...(sourceIr.preamble ? { content: sourceIr.preamble } : {}),
|
|
174
|
+
description: sourceIr.description,
|
|
175
|
+
// No authored title in the shared source IR — the asset's human name is
|
|
163
176
|
// its `description`/H1 like any other asset; this is its canonical name.
|
|
164
177
|
workflowTitle: name,
|
|
165
178
|
...(parameters ? { parameters: parameters.map((p) => p.name), workflowParameters: parameters } : {}),
|
|
166
|
-
steps: projectStepDefinitions(
|
|
179
|
+
steps: projectStepDefinitions(sourceIr),
|
|
167
180
|
};
|
|
168
181
|
},
|
|
169
182
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
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 { EXECUTION_MAX_TIMEOUT_MS } from "../execution/limits.js";
|
|
4
5
|
export const WORKFLOW_MAX_PLAN_BYTES = 2 * 1024 * 1024;
|
|
5
6
|
export const WORKFLOW_MAX_SOURCE_BYTES = 1024 * 1024;
|
|
6
7
|
export const WORKFLOW_MAX_STEPS = 256;
|
|
@@ -33,7 +34,7 @@ export const WORKFLOW_MAX_GATE_LOOPS = 100;
|
|
|
33
34
|
/** Max retry attempts per unit. */
|
|
34
35
|
export const WORKFLOW_MAX_RETRIES = 100;
|
|
35
36
|
/** Max timeout in milliseconds (setTimeout's 32-bit signed ceiling: 2^31-1, ~24.8 days). */
|
|
36
|
-
export const WORKFLOW_MAX_TIMEOUT_MS =
|
|
37
|
+
export const WORKFLOW_MAX_TIMEOUT_MS = EXECUTION_MAX_TIMEOUT_MS;
|
|
37
38
|
/** Engine names: lowercase dash-separated runs of letters/digits, starting with a letter. */
|
|
38
39
|
export const WORKFLOW_ENGINE_NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
39
40
|
export const WORKFLOW_MAX_ENGINE_NAME_LENGTH = 63;
|
|
@@ -51,10 +52,8 @@ export const WORKFLOW_MAX_EXEC_CWD_LENGTH = 1024;
|
|
|
51
52
|
/**
|
|
52
53
|
* Max entries in an exec unit's `pass_env:` list.
|
|
53
54
|
*
|
|
54
|
-
* `pass_env` is
|
|
55
|
-
*
|
|
56
|
-
* many names wants full inheritance and should say so where a reviewer can see
|
|
57
|
-
* it.
|
|
55
|
+
* `pass_env` is bounded; use explicit named `env:` bindings for a larger set.
|
|
56
|
+
* New v4 starts do not offer whole-process inheritance.
|
|
58
57
|
*/
|
|
59
58
|
export const WORKFLOW_MAX_EXEC_PASS_ENV = 32;
|
|
60
59
|
/**
|
|
@@ -2,13 +2,13 @@
|
|
|
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
|
-
* Resolve the
|
|
5
|
+
* Resolve the invoking harness/session identity for the current process.
|
|
6
6
|
*
|
|
7
|
-
* This is the first concrete slice of #501 / #506: capturing
|
|
8
|
-
*
|
|
9
|
-
* with session activity. It deliberately does NOT start any
|
|
10
|
-
* timer, or daemon — it only reads identity that the
|
|
11
|
-
* already exposes via the environment.
|
|
7
|
+
* This is the first concrete slice of #501 / #506: capturing the invoking
|
|
8
|
+
* harness/session identity so a future (separately-approved) monitor can
|
|
9
|
+
* correlate runs with session activity. It deliberately does NOT start any
|
|
10
|
+
* background thread, timer, or daemon — it only reads identity that the
|
|
11
|
+
* surrounding agent harness already exposes via the environment.
|
|
12
12
|
*
|
|
13
13
|
* Resolution is best-effort and environment-driven:
|
|
14
14
|
* - harness: AKM_AGENT_HARNESS, else inferred from a harness session-id
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
*
|
|
31
31
|
* @module workflows/agent-identity
|
|
32
32
|
*/
|
|
33
|
-
import {
|
|
33
|
+
import { HARNESS_REGISTRY } from "../../integrations/harnesses/index.js";
|
|
34
34
|
/**
|
|
35
35
|
* Derive a marker table from one registry env-var field, ordered by canonical
|
|
36
36
|
* id. The sort keeps the pre-derivation precedence byte-identical ('claude'
|
|
@@ -67,15 +67,13 @@ export function resolveAgentIdentity(env = process.env) {
|
|
|
67
67
|
if (!harness) {
|
|
68
68
|
// Infer the harness from a harness-specific *session* env var first
|
|
69
69
|
// (registry `identityEnv` markers). A concrete session id is the
|
|
70
|
-
// strongest evidence of the
|
|
70
|
+
// strongest evidence of the invoking harness/session context, so it
|
|
71
|
+
// outranks any
|
|
71
72
|
// presence flag — e.g. opencode launched inside a codex sandbox
|
|
72
73
|
// (OPENCODE_SESSION_ID + CODEX_SANDBOX) attributes to opencode.
|
|
73
74
|
for (const marker of SESSION_MARKERS) {
|
|
74
75
|
if (firstNonEmpty(env, marker.envKeys)) {
|
|
75
|
-
|
|
76
|
-
// 'claude-code') via the registry's #562 bridge so the persisted
|
|
77
|
-
// runtime string can't drift.
|
|
78
|
-
harness = denormalizeRuntimeIdentity(marker.harnessId);
|
|
76
|
+
harness = marker.harnessId;
|
|
79
77
|
break;
|
|
80
78
|
}
|
|
81
79
|
}
|
|
@@ -87,7 +85,7 @@ export function resolveAgentIdentity(env = process.env) {
|
|
|
87
85
|
// but they carry no session id, so sessionId stays null below.
|
|
88
86
|
for (const marker of PRESENCE_MARKERS) {
|
|
89
87
|
if (firstNonEmpty(env, marker.envKeys)) {
|
|
90
|
-
harness =
|
|
88
|
+
harness = marker.harnessId;
|
|
91
89
|
break;
|
|
92
90
|
}
|
|
93
91
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { UsageError } from "../../core/errors.js";
|
|
5
5
|
import { decodeCanonicalPlan } from "../ir/plan-hash.js";
|
|
6
|
-
import {
|
|
6
|
+
import { WORKFLOW_IR_V4_VERSION } from "../ir/schema-v4.js";
|
|
7
7
|
/** Validate that a live run carries exactly the current frozen-plan format. */
|
|
8
8
|
export function classifyWorkflowRunPlan(row) {
|
|
9
9
|
const runId = row.id ?? "(unknown)";
|
|
@@ -16,31 +16,31 @@ export function classifyWorkflowRunPlan(row) {
|
|
|
16
16
|
}
|
|
17
17
|
if (row.plan_ir_version !== null &&
|
|
18
18
|
row.plan_ir_version !== undefined &&
|
|
19
|
-
row.plan_ir_version !==
|
|
19
|
+
row.plan_ir_version !== WORKFLOW_IR_V4_VERSION) {
|
|
20
20
|
return {
|
|
21
21
|
support: "unsupported-version",
|
|
22
22
|
irVersion: row.plan_ir_version,
|
|
23
|
-
error: `Workflow run ${runId} uses unsupported workflow IR version ${row.plan_ir_version}; this runtime
|
|
23
|
+
error: `Workflow run ${runId} uses unsupported workflow IR version ${row.plan_ir_version}; this runtime supports only workflow IR version 4. Start a new run from the authored workflow.`,
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
-
if (row.plan_ir_version !==
|
|
26
|
+
if (row.plan_ir_version !== WORKFLOW_IR_V4_VERSION) {
|
|
27
27
|
return {
|
|
28
28
|
support: "corrupt-plan",
|
|
29
29
|
irVersion: null,
|
|
30
|
-
error: `Workflow run ${runId} does not declare workflow IR version
|
|
30
|
+
error: `Workflow run ${runId} does not declare a supported workflow IR version.`,
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
try {
|
|
34
34
|
return {
|
|
35
35
|
support: "supported",
|
|
36
|
-
irVersion:
|
|
37
|
-
plan: decodeCanonicalPlan(runId, row.plan_json, row.plan_hash),
|
|
36
|
+
irVersion: row.plan_ir_version,
|
|
37
|
+
plan: decodeCanonicalPlan(runId, row.plan_json, row.plan_hash, row.plan_ir_version),
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
catch (cause) {
|
|
41
41
|
return {
|
|
42
42
|
support: "corrupt-plan",
|
|
43
|
-
irVersion:
|
|
43
|
+
irVersion: row.plan_ir_version,
|
|
44
44
|
error: cause instanceof Error ? cause.message : String(cause),
|
|
45
45
|
};
|
|
46
46
|
}
|
|
@@ -13,10 +13,9 @@ import { getCurrentWorkflowScopeKey } from "../authoring/scope-key.js";
|
|
|
13
13
|
import { frozenSummaryJudge } from "../exec/frozen-judge.js";
|
|
14
14
|
import { detectSecretShapedParams } from "../exec/param-secrets.js";
|
|
15
15
|
import { collectWorkflowWarnings } from "../ir/compile.js";
|
|
16
|
-
import {
|
|
16
|
+
import { compileResolveFreezeWorkflowV4 } from "../ir/freeze-v4.js";
|
|
17
17
|
import { materializeWorkflowParameterFlags, validateWorkflowParams } from "../ir/params.js";
|
|
18
18
|
import { canonicalPlanJson, computePlanHash } from "../ir/plan-hash.js";
|
|
19
|
-
import { decodeWorkflowPlanV3, WORKFLOW_IR_VERSION } from "../ir/schema.js";
|
|
20
19
|
import { clip, utf8Bytes, WORKFLOW_EVIDENCE_TRUNCATION_PREVIEW_CHARS, WORKFLOW_MAX_EVIDENCE_JSON_BYTES, WORKFLOW_UNIT_DIAGNOSTIC_CLIP, } from "../resource-limits.js";
|
|
21
20
|
import { validateStepSummary } from "../validate-summary.js";
|
|
22
21
|
import { resolveAgentIdentity } from "./agent-identity.js";
|
|
@@ -33,7 +32,7 @@ const IR_RUNTIME_KINDS = { llm: true, agent: true, sdk: true, exec: true };
|
|
|
33
32
|
function runtimeKindOf(runner) {
|
|
34
33
|
return runner !== null && Object.hasOwn(IR_RUNTIME_KINDS, runner) ? runner : null;
|
|
35
34
|
}
|
|
36
|
-
function toUnitDiagnostic(row, stale
|
|
35
|
+
function toUnitDiagnostic(row, stale) {
|
|
37
36
|
let diagnostic = null;
|
|
38
37
|
if (row.result_json !== null) {
|
|
39
38
|
// `result_json` is a JSON-encoded value: a bare JSON string for a free-text
|
|
@@ -69,7 +68,7 @@ function toUnitDiagnostic(row, stale, plannedEngine) {
|
|
|
69
68
|
claimExpiresAt: row.claim_expires_at,
|
|
70
69
|
engine: row.engine ?? null,
|
|
71
70
|
runtimeKind: runtimeKindOf(row.runner),
|
|
72
|
-
platform:
|
|
71
|
+
platform: null,
|
|
73
72
|
};
|
|
74
73
|
}
|
|
75
74
|
export async function startWorkflowRun(ref, params = {}, options) {
|
|
@@ -78,8 +77,8 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
78
77
|
// persist it on the run row in the same transaction as the insert. Every
|
|
79
78
|
// later invocation executes this snapshot — the asset file is never re-read
|
|
80
79
|
// for an in-flight run; re-planning is an explicit new run.
|
|
81
|
-
const frozen =
|
|
82
|
-
const plan =
|
|
80
|
+
const frozen = await compileResolveFreezeWorkflowV4(asset, loadConfig());
|
|
81
|
+
const plan = frozen.plan;
|
|
83
82
|
if (options?.parameterFlags?.length && Object.keys(params).length > 0) {
|
|
84
83
|
throw new UsageError("Workflow parameters must use either an object or per-parameter flags, not both.");
|
|
85
84
|
}
|
|
@@ -89,7 +88,7 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
89
88
|
// Non-fatal WARNINGS: untyped-step and undeclared-param advisories surface
|
|
90
89
|
// as `warn()` lines at start (stderr, consistent with the repo's other
|
|
91
90
|
// author-facing warnings) without blocking the run.
|
|
92
|
-
for (const w of collectWorkflowWarnings(asset.
|
|
91
|
+
for (const w of collectWorkflowWarnings(asset.sourceIr)) {
|
|
93
92
|
warn(`workflow run: ${asset.path}:${w.line} — ${w.message}`);
|
|
94
93
|
}
|
|
95
94
|
// Reviewer #12: validate supplied parameters against the frozen param
|
|
@@ -111,7 +110,7 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
111
110
|
const scopeKey = getCurrentWorkflowScopeKey();
|
|
112
111
|
const currentStepId = plan.steps[0]?.stepId ?? null;
|
|
113
112
|
const workflowEntryId = resolveWorkflowEntryId(asset.sourcePath, asset.ref, asset.adapterId);
|
|
114
|
-
// Capture the
|
|
113
|
+
// Capture the invoking harness/session identity for this run. Explicit options
|
|
115
114
|
// win; otherwise fall back to best-effort environment detection. This is
|
|
116
115
|
// identity-only — no background thread or timer is started here.
|
|
117
116
|
const detected = resolveAgentIdentity();
|
|
@@ -127,15 +126,10 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
127
126
|
// per the workflow-agent check-in ADR) so a stalled run can be
|
|
128
127
|
// re-targeted with a `continue` directive. The agent harness + session id
|
|
129
128
|
// are already resolved above (agentHarness/agentSessionId, from #501).
|
|
130
|
-
repo.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
throw new UsageError(`Workflow ${asset.ref} already has an active run in this scope (id=${existing.id}, step=${existing.current_step_id ?? "—"}). ` +
|
|
135
|
-
`Use 'akm workflow run ${asset.ref}' to resume it or 'akm workflow abandon ${existing.id}' to give up on it.`, "RESOURCE_ALREADY_EXISTS");
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
repo.insertRun({
|
|
129
|
+
repo.publishWorkflowRunV4({
|
|
130
|
+
workflowRefs,
|
|
131
|
+
...(options?.force ? { force: true } : {}),
|
|
132
|
+
run: {
|
|
139
133
|
id: runId,
|
|
140
134
|
workflowRef: asset.ref,
|
|
141
135
|
scopeKey,
|
|
@@ -148,17 +142,18 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
148
142
|
agentHarness,
|
|
149
143
|
agentSessionId,
|
|
150
144
|
checkinArmedAt: now,
|
|
151
|
-
}
|
|
152
|
-
|
|
145
|
+
},
|
|
146
|
+
steps: frozenStepRows(plan).map((step) => ({
|
|
153
147
|
runId,
|
|
154
148
|
stepId: step.stepId,
|
|
155
149
|
stepTitle: step.stepTitle,
|
|
156
150
|
instructions: step.instructions,
|
|
157
151
|
completionJson: step.completionJson,
|
|
158
152
|
sequenceIndex: step.sequenceIndex,
|
|
159
|
-
}))
|
|
160
|
-
|
|
161
|
-
|
|
153
|
+
})),
|
|
154
|
+
planJson,
|
|
155
|
+
planHash,
|
|
156
|
+
revalidateSources: () => frozen.sourceCollector.revalidate(),
|
|
162
157
|
});
|
|
163
158
|
const result = await getWorkflowStatus(runId);
|
|
164
159
|
// #13: params are declared non-secret (they are copied verbatim into every
|
|
@@ -174,16 +169,6 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
174
169
|
// re-announces a decision it did not make.
|
|
175
170
|
if (frozen.engineAnnouncement)
|
|
176
171
|
result.warnings = [...(result.warnings ?? []), frozen.engineAnnouncement];
|
|
177
|
-
// 07 P1-B: emit only the run id + status — NOT the raw workflowTitle (which
|
|
178
|
-
// comes verbatim from the workflow asset's frontmatter and is therefore
|
|
179
|
-
// attacker-influenceable). Keeping raw titles out of the events stream
|
|
180
|
-
// shrinks the injectable footprint for any consumer that re-surfaces events
|
|
181
|
-
// into agent context.
|
|
182
|
-
appendEvent({
|
|
183
|
-
eventType: "workflow_started",
|
|
184
|
-
ref: asset.ref,
|
|
185
|
-
metadata: { runId: result.run.id, status: result.run.status },
|
|
186
|
-
});
|
|
187
172
|
return result;
|
|
188
173
|
});
|
|
189
174
|
}
|
|
@@ -201,9 +186,7 @@ export async function getWorkflowStatus(runId, opts) {
|
|
|
201
186
|
// injected for deterministic tests) so a unit left `running` by a process
|
|
202
187
|
// that died surfaces as stale here, not just as raw `running`.
|
|
203
188
|
const staleById = new Map(evaluateStaleUnits(rows, opts.now ?? Date.now()).map((u) => [u.unitId, u]));
|
|
204
|
-
|
|
205
|
-
const engines = classified.support === "supported" ? classified.plan.execution?.engines : undefined;
|
|
206
|
-
detail.units = rows.map((row) => toUnitDiagnostic(row, staleById.get(row.unit_id), row.engine ? engines?.[row.engine] : undefined));
|
|
189
|
+
detail.units = rows.map((row) => toUnitDiagnostic(row, staleById.get(row.unit_id)));
|
|
207
190
|
}
|
|
208
191
|
return detail;
|
|
209
192
|
});
|
|
@@ -296,9 +279,9 @@ function projectNextResult(run, steps) {
|
|
|
296
279
|
export async function resumeWorkflowRun(runId) {
|
|
297
280
|
return withWorkflowRunsRepo((repo) => {
|
|
298
281
|
const run = readWorkflowRun(repo, runId);
|
|
299
|
-
const
|
|
282
|
+
const storedPlan = requireExecutableWorkflowPlan(run);
|
|
300
283
|
const steps = readWorkflowRunSteps(repo, run.id);
|
|
301
|
-
assertWorkflowSpineMatchesPlan(
|
|
284
|
+
assertWorkflowSpineMatchesPlan(storedPlan, run, steps);
|
|
302
285
|
if (run.status === "completed") {
|
|
303
286
|
throw new UsageError(`Workflow run ${run.id} is already completed and cannot be resumed.`);
|
|
304
287
|
}
|
|
@@ -473,9 +456,9 @@ export async function completeWorkflowStep(input) {
|
|
|
473
456
|
// the write transaction — a slow/hung LLM must never hold a db write lock.
|
|
474
457
|
const preflight = await withWorkflowRunsRepo((repo) => {
|
|
475
458
|
const run = readWorkflowRun(repo, input.runId);
|
|
476
|
-
const
|
|
459
|
+
const storedPlan = requireExecutableWorkflowPlan(run);
|
|
477
460
|
const steps = readWorkflowRunSteps(repo, run.id);
|
|
478
|
-
assertWorkflowSpineMatchesPlan(
|
|
461
|
+
assertWorkflowSpineMatchesPlan(storedPlan, run, steps);
|
|
479
462
|
if (run.status !== "active") {
|
|
480
463
|
throw new UsageError(`Workflow run ${run.id} is ${run.status} and cannot be updated.`);
|
|
481
464
|
}
|
|
@@ -490,10 +473,10 @@ export async function completeWorkflowStep(input) {
|
|
|
490
473
|
if (run.current_step_id !== existing.step_id) {
|
|
491
474
|
throw new UsageError(`Step "${input.stepId}" is not the current step for workflow run ${run.id}. Complete "${run.current_step_id}" first.`);
|
|
492
475
|
}
|
|
493
|
-
const stepPlan =
|
|
476
|
+
const stepPlan = storedPlan.steps.find((step) => step.stepId === input.stepId);
|
|
494
477
|
if (!stepPlan)
|
|
495
478
|
throw new NotFoundError(`Step "${input.stepId}" was not found in workflow run ${run.id}.`);
|
|
496
|
-
return { existing, plan, stepPlan };
|
|
479
|
+
return { existing, plan: storedPlan, stepPlan };
|
|
497
480
|
});
|
|
498
481
|
const summary = input.summary?.trim();
|
|
499
482
|
// #506: completing a step requires a summary of the work done.
|
|
@@ -510,7 +493,7 @@ export async function completeWorkflowStep(input) {
|
|
|
510
493
|
? // Manual completion journals no gate row, so there is no `<stepId>.gate:l<loop>`
|
|
511
494
|
// identity to agree with — but the dispatch still names the REAL run and
|
|
512
495
|
// step (frozen-judge falls back to the gate node id for the unit id).
|
|
513
|
-
frozenSummaryJudge(preflight.
|
|
496
|
+
frozenSummaryJudge(preflight.stepPlan.gate.frozenJudge, input.signal, undefined, {
|
|
514
497
|
runId: input.runId,
|
|
515
498
|
stepId: input.stepId,
|
|
516
499
|
})
|
|
@@ -750,7 +733,8 @@ function toWorkflowRunSummary(run) {
|
|
|
750
733
|
planIrVersion: plan.irVersion,
|
|
751
734
|
executionSupport: plan.support,
|
|
752
735
|
// Surface the engine lease (holder id + expiry — never workflow-authored
|
|
753
|
-
// content) so `workflow run`/`status` show
|
|
736
|
+
// content) so `workflow run`/`status` show which native execution
|
|
737
|
+
// invocation currently holds the run lease.
|
|
754
738
|
...(run.engine_lease_holder && run.engine_lease_until
|
|
755
739
|
? { engineLease: { holder: run.engine_lease_holder, until: run.engine_lease_until } }
|
|
756
740
|
: {}),
|