akm-cli 0.9.0-rc.1 → 0.9.0-rc.13
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 +1190 -52
- package/README.md +62 -37
- package/SECURITY.md +46 -31
- package/dist/akm +162 -38
- package/dist/akm-migrate +44 -0
- package/dist/assets/backends/schtasks-template.xml +2 -1
- package/dist/assets/hints/cli-hints-full.md +268 -118
- package/dist/assets/hints/cli-hints-short.md +87 -24
- package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
- package/dist/assets/improve-strategies/frequent.json +15 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
- package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
- package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
- package/dist/assets/improve-strategies/reflect-distill.json +30 -0
- package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +5 -5
- package/dist/assets/prompts/extract-session.md +2 -6
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
- package/dist/assets/prompts/reflect-output-repair.md +3 -0
- package/dist/assets/stash-skeleton/README.md +38 -10
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
- package/dist/assets/tasks/core/extract.yml +3 -2
- package/dist/assets/tasks/core/improve.yml +2 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +2 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +5 -4
- package/dist/assets/workflows/workflow-template.md +31 -15
- package/dist/cli/invocation.js +279 -0
- package/dist/cli/parse-args.js +5 -90
- package/dist/cli/retired-commands.js +78 -0
- package/dist/cli/shared.js +158 -48
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +747 -293
- package/dist/commands/agent/agent-dispatch.js +19 -18
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +43 -97
- package/dist/commands/completions.js +80 -23
- package/dist/commands/config-cli.js +44 -281
- package/dist/commands/env/env-binding.js +13 -9
- package/dist/commands/env/env-cli.js +76 -159
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +45 -61
- package/dist/commands/env/secret.js +32 -62
- package/dist/commands/feedback-cli.js +179 -85
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +7 -8
- package/dist/commands/health/checks.js +279 -94
- package/dist/commands/health/html-report.js +197 -578
- package/dist/commands/health/improve-metrics.js +277 -246
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +16 -7
- package/dist/commands/health/metrics.js +67 -32
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +508 -0
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +16 -56
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
- package/dist/commands/health/types-improve.js +29 -0
- package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
- package/dist/commands/health/types-result.js +7 -0
- package/dist/commands/health/types-runs.js +4 -0
- package/dist/commands/health/types-session-log.js +4 -0
- package/dist/commands/health/types-windows.js +4 -0
- package/dist/commands/health/types.js +26 -21
- package/dist/commands/health/windows.js +2 -3
- package/dist/commands/health.js +296 -167
- package/dist/commands/improve/anti-collapse.js +5 -5
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +65 -52
- package/dist/commands/improve/consolidate/chunking.js +9 -7
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +454 -1354
- package/dist/commands/improve/content-hash.js +39 -0
- package/dist/commands/improve/distill/content-repair.js +4 -10
- package/dist/commands/improve/distill/promote-memory.js +89 -64
- package/dist/commands/improve/distill/quality-gate.js +118 -42
- package/dist/commands/improve/distill-guards.js +1 -1
- package/dist/commands/improve/distill-promotion-policy.js +33 -888
- package/dist/commands/improve/distill.js +607 -363
- package/dist/commands/improve/eligibility.js +165 -79
- package/dist/commands/improve/extract-cli.js +35 -126
- package/dist/commands/improve/extract-prompt.js +6 -35
- package/dist/commands/improve/extract.js +640 -391
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +134 -135
- package/dist/commands/improve/improve-result-file.js +30 -50
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +135 -0
- package/dist/commands/improve/improve.js +904 -701
- package/dist/commands/improve/locks.js +64 -111
- package/dist/commands/improve/loop-stages.js +1110 -923
- package/dist/commands/improve/memory/derived-ref.js +124 -0
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
- package/dist/commands/improve/memory/memory-improve.js +25 -37
- package/dist/commands/improve/outcome-loop.js +25 -88
- package/dist/commands/improve/preparation.js +1034 -813
- package/dist/commands/improve/proactive-maintenance.js +34 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +983 -794
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +24 -127
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -34
- package/dist/commands/improve/source-identity.js +28 -0
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +340 -313
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +185 -30
- package/dist/commands/{events.js → log.js} +28 -38
- package/dist/commands/migrate-cli.js +54 -0
- package/dist/commands/migration-tool.js +55 -0
- package/dist/commands/observability-cli.js +70 -208
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +91 -40
- package/dist/commands/proposal/proposal-cli.js +134 -132
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +83 -65
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +105 -88
- package/dist/commands/proposal/repository.js +1303 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
- package/dist/commands/proposal/validators/proposal-validators.js +61 -12
- package/dist/commands/proposal/validators/proposals.js +6 -8
- package/dist/commands/read/curate.js +78 -73
- package/dist/commands/read/knowledge.js +510 -13
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +84 -15
- package/dist/commands/read/search-cli.js +203 -96
- package/dist/commands/read/search.js +126 -94
- package/dist/commands/read/show.js +226 -250
- package/dist/commands/registry-cli.js +34 -60
- package/dist/commands/remember.js +18 -57
- package/dist/commands/sources/add-cli.js +104 -49
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +63 -0
- package/dist/commands/sources/info.js +27 -15
- package/dist/commands/sources/init.js +30 -40
- package/dist/commands/sources/installed-stashes.js +469 -172
- package/dist/commands/sources/schema-repair.js +10 -9
- package/dist/commands/sources/self-update.js +182 -121
- package/dist/commands/sources/source-add.js +169 -178
- package/dist/commands/sources/source-clone.js +144 -41
- package/dist/commands/sources/source-manage.js +94 -59
- package/dist/commands/sources/sources-cli.js +64 -205
- package/dist/commands/sources/stash-cli.js +91 -54
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +106 -104
- package/dist/commands/tasks/tasks.js +445 -262
- package/dist/commands/workflow-cli.js +75 -228
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/activation-policy.js +49 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
- package/dist/core/adapter/adapters/akm-adapter.js +528 -0
- package/dist/core/adapter/adapters/akm-lint.js +392 -0
- package/dist/core/adapter/adapters/akm-metadata.js +387 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
- package/dist/core/adapter/adapters/claude-adapter.js +61 -0
- package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
- package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
- package/dist/core/adapter/adapters/okf-adapter.js +391 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
- package/dist/core/adapter/adapters/shared.js +286 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +44 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/akm-markdown.js +30 -0
- package/dist/core/asset/asset-placement.js +243 -0
- package/dist/core/asset/asset-ref.js +110 -79
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +28 -12
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +274 -0
- package/dist/core/asset/stash-meta.js +2 -2
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +281 -86
- package/dist/core/config/config-io.js +42 -128
- package/dist/core/config/config-schema.js +233 -855
- package/dist/core/config/config-sources.js +162 -39
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +126 -37
- package/dist/core/config/config.js +154 -331
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +28 -0
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/experimental.js +47 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +389 -0
- package/dist/core/config/schema/improve.js +94 -0
- package/dist/core/config/schema/index-config.js +176 -0
- package/dist/core/config/schema/output.js +18 -0
- package/dist/core/config/schema/primitives.js +94 -0
- package/dist/core/config/schema/search.js +30 -0
- package/dist/core/config/schema/setup.js +18 -0
- package/dist/core/config/schema/sources-bundles.js +169 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +155 -20
- package/dist/core/errors.js +17 -15
- package/dist/core/events-types.js +4 -0
- package/dist/core/events.js +46 -128
- package/dist/core/extra-params.js +62 -0
- package/dist/core/file-change.js +17 -0
- package/dist/core/file-lock.js +202 -57
- package/dist/core/fs-txn.js +392 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +167 -0
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +135 -0
- package/dist/core/migration-operation.js +44 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/paths.js +22 -25
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +128 -0
- package/dist/core/redaction.js +392 -0
- package/dist/core/standards/resolve-standards-context.js +36 -65
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +5 -5
- package/dist/core/state/migrations.js +242 -11
- package/dist/core/state-db.js +98 -10
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +303 -0
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +834 -118
- package/dist/indexer/bundle-identity-guard.js +92 -0
- package/dist/indexer/db/graph-db.js +1 -25
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +30 -9
- package/dist/indexer/graph/graph-boost.js +9 -30
- package/dist/indexer/graph/graph-extraction.js +41 -27
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-writer-lock.js +93 -49
- package/dist/indexer/index-written-assets.js +100 -53
- package/dist/indexer/indexer.js +746 -329
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +142 -0
- package/dist/indexer/passes/dir-staleness.js +18 -10
- package/dist/indexer/passes/memory-inference.js +25 -15
- package/dist/indexer/passes/metadata.js +412 -243
- package/dist/indexer/scan/doc-to-entry.js +160 -0
- package/dist/indexer/scan/drain-dir.js +134 -0
- package/dist/indexer/search/db-search.js +292 -108
- package/dist/indexer/search/fts-query.js +64 -0
- package/dist/indexer/search/ranking-contributors.js +145 -25
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +28 -71
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-fields.js +18 -3
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +157 -111
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/usage-events.js +10 -30
- package/dist/indexer/walk/file-context.js +3 -45
- package/dist/indexer/walk/matchers.js +42 -73
- package/dist/indexer/walk/path-resolver.js +11 -5
- package/dist/indexer/walk/walker.js +42 -14
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -58
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +231 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +8 -3
- package/dist/integrations/agent/profiles.js +6 -99
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +78 -13
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +48 -279
- package/dist/integrations/harnesses/aider/agent-builder.js +9 -8
- package/dist/integrations/harnesses/aider/index.js +2 -12
- package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -16
- package/dist/integrations/harnesses/amazonq/index.js +3 -17
- package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +1 -14
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +8 -7
- package/dist/integrations/harnesses/codex/index.js +2 -13
- package/dist/integrations/harnesses/copilot/agent-builder.js +9 -9
- package/dist/integrations/harnesses/copilot/index.js +1 -13
- package/dist/integrations/harnesses/gemini/agent-builder.js +8 -9
- package/dist/integrations/harnesses/gemini/index.js +1 -13
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +31 -33
- package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +1 -18
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +3 -17
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +274 -191
- package/dist/integrations/harnesses/openhands/agent-builder.js +12 -10
- package/dist/integrations/harnesses/openhands/index.js +2 -12
- package/dist/integrations/harnesses/pi/agent-builder.js +11 -18
- package/dist/integrations/harnesses/pi/index.js +3 -16
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +38 -34
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +24 -40
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +182 -110
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +21 -9
- package/dist/llm/feature-gate.js +17 -57
- package/dist/llm/graph-extract.js +12 -13
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +45 -30
- package/dist/llm/structured-call.js +16 -8
- package/dist/llm/usage-persist.js +30 -5
- package/dist/llm/usage-telemetry.js +59 -6
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/command-registry.js +27 -0
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +251 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +15 -281
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +58 -84
- package/dist/output/shapes/passthrough.js +8 -40
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/shapes.js +0 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +562 -0
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/helpers.js +15 -1375
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +202 -0
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +117 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +332 -0
- package/dist/output/text/workflow.js +1 -2
- package/dist/output/text.js +10 -19
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +15 -25
- package/dist/registry/resolve.js +43 -94
- package/dist/registry/semver.js +43 -0
- package/dist/runtime.js +81 -12
- package/dist/scripts/akm-migrate.js +35529 -0
- package/dist/setup/detect.js +5 -7
- package/dist/setup/detected-engines.js +136 -0
- package/dist/setup/engine-config.js +100 -0
- package/dist/setup/registry-stash-loader.js +3 -3
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +444 -208
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +108 -305
- package/dist/setup/steps/platforms.js +13 -12
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +21 -15
- package/dist/setup/steps/stashdir.js +6 -4
- package/dist/setup/steps/tasks.js +236 -119
- package/dist/setup/steps.js +3 -2
- package/dist/sources/freshness.js +39 -0
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +54 -56
- package/dist/sources/providers/git-stash.js +420 -91
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +47 -22
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +11 -10
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
- package/dist/storage/database.js +60 -4
- package/dist/storage/engines/sqlite-migrations.js +156 -5
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +51 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -32
- package/dist/storage/repositories/index-connection.js +79 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +863 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +167 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
- package/dist/storage/repositories/index-meta-repository.js +49 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +356 -0
- package/dist/storage/repositories/index-vec-repository.js +250 -0
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +317 -75
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +110 -3
- package/dist/storage/repositories/workflow-runs-repository.js +68 -35
- package/dist/tasks/backends/cron.js +169 -46
- package/dist/tasks/backends/exec-utils.js +76 -3
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +292 -55
- package/dist/tasks/backends/schtasks.js +557 -70
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/command-executable.js +93 -0
- package/dist/tasks/embedded.js +56 -38
- package/dist/tasks/parser.js +156 -64
- package/dist/tasks/resolve-akm-bin.js +144 -51
- package/dist/tasks/runner.js +377 -209
- package/dist/tasks/schedule.js +108 -19
- package/dist/tasks/scheduler-invocation.js +296 -0
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/task-id.js +35 -0
- package/dist/tasks/validator.js +30 -16
- package/dist/workflows/authoring/authoring.js +96 -148
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -20
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +25 -59
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +157 -94
- package/dist/workflows/exec/report.js +365 -200
- package/dist/workflows/exec/run-workflow.js +46 -40
- package/dist/workflows/exec/scheduler.js +12 -41
- package/dist/workflows/exec/step-work.js +239 -205
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/ir/compile.js +141 -283
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/plan-hash.js +40 -5
- package/dist/workflows/ir/schema.js +537 -1
- package/dist/workflows/parser.js +878 -306
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +7 -10
- package/dist/workflows/renderer.js +99 -121
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +200 -113
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +235 -97
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +4 -26
- package/dist/workflows/validator.js +52 -30
- package/docs/README.md +42 -78
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +9 -8
- package/docs/migration/release-notes/0.9.0.md +158 -14
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +844 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/data-and-telemetry.md +333 -0
- package/package.json +21 -17
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +4636 -0
- package/schemas/akm-task.json +87 -0
- package/{dist/schemas → schemas}/akm-workflow.json +127 -82
- package/dist/akm-migrate-storage +0 -38
- package/dist/assets/help/help-accept.md +0 -12
- package/dist/assets/help/help-improve.md +0 -84
- package/dist/assets/help/help-proposals.md +0 -17
- package/dist/assets/help/help-propose.md +0 -17
- package/dist/assets/help/help-reject.md +0 -11
- package/dist/assets/profiles/frequent.json +0 -13
- package/dist/assets/profiles/recombine-only.json +0 -21
- package/dist/assets/profiles/reflect-distill.json +0 -30
- package/dist/assets/profiles/synthesize.json +0 -15
- package/dist/assets/prompts/procedural-system.md +0 -44
- package/dist/assets/prompts/recombine-system.md +0 -40
- package/dist/assets/prompts/staleness-detect-system.md +0 -6
- package/dist/assets/tasks/core/backup.yml +0 -4
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/assets/templates/html/default.html +0 -78
- package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
- package/dist/assets/wiki/index-template.md +0 -12
- package/dist/assets/wiki/ingest-workflow-template.md +0 -83
- package/dist/assets/wiki/log-template.md +0 -8
- package/dist/assets/wiki/schema-template.md +0 -61
- package/dist/cli/config-migrate.js +0 -150
- package/dist/cli/config-validate.js +0 -39
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -487
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -276
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/commands/improve/procedural.js +0 -398
- package/dist/commands/improve/recombine.js +0 -818
- package/dist/commands/improve/schema-similarity-gate.js +0 -168
- package/dist/commands/lint/agent-linter.js +0 -44
- package/dist/commands/lint/command-linter.js +0 -44
- package/dist/commands/lint/default-linter.js +0 -16
- package/dist/commands/lint/fact-linter.js +0 -39
- package/dist/commands/lint/knowledge-linter.js +0 -16
- package/dist/commands/lint/memory-linter.js +0 -61
- package/dist/commands/lint/registry.js +0 -41
- package/dist/commands/lint/skill-linter.js +0 -45
- package/dist/commands/lint/task-linter.js +0 -50
- package/dist/commands/lint/workflow-linter.js +0 -81
- package/dist/commands/proposal/legacy-import.js +0 -115
- package/dist/commands/sources/history.js +0 -196
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/commands/wiki-cli.js +0 -292
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -316
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/core/eval/rank-metrics.js +0 -113
- package/dist/core/ripgrep/install.js +0 -163
- package/dist/core/ripgrep/resolve.js +0 -81
- package/dist/indexer/db/db.js +0 -1414
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
- package/dist/llm/call-ai.js +0 -62
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/output/text/wiki.js +0 -16
- package/dist/registry/build-index.js +0 -386
- package/dist/schemas/akm-config.json +0 -14225
- package/dist/scripts/migrate-storage.js +0 -13169
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -10169
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/setup/legacy-config.js +0 -106
- package/dist/storage/repositories/consolidation-repository.js +0 -38
- package/dist/storage/repositories/recombine-repository.js +0 -213
- package/dist/wiki/wiki-templates.js +0 -15
- package/dist/wiki/wiki.js +0 -1012
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/db.js +0 -350
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -760
- package/dist/workflows/program/project.js +0 -105
- package/docs/data-and-telemetry.md +0 -227
- package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
|
@@ -0,0 +1,131 @@
|
|
|
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
|
+
import { UsageError } from "../../core/errors.js";
|
|
5
|
+
import { decodeCanonicalPlan } from "../ir/plan-hash.js";
|
|
6
|
+
import { WORKFLOW_IR_VERSION } from "../ir/schema.js";
|
|
7
|
+
/** Validate that a live run carries exactly the current frozen-plan format. */
|
|
8
|
+
export function classifyWorkflowRunPlan(row) {
|
|
9
|
+
const runId = row.id ?? "(unknown)";
|
|
10
|
+
if (!row.plan_json) {
|
|
11
|
+
return {
|
|
12
|
+
support: "missing-plan",
|
|
13
|
+
irVersion: row.plan_ir_version ?? null,
|
|
14
|
+
error: `Workflow run ${runId} has no frozen workflow plan.`,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
if (row.plan_ir_version !== null &&
|
|
18
|
+
row.plan_ir_version !== undefined &&
|
|
19
|
+
row.plan_ir_version !== WORKFLOW_IR_VERSION) {
|
|
20
|
+
return {
|
|
21
|
+
support: "unsupported-version",
|
|
22
|
+
irVersion: row.plan_ir_version,
|
|
23
|
+
error: `Workflow run ${runId} uses unsupported workflow IR version ${row.plan_ir_version}; this runtime requires version ${WORKFLOW_IR_VERSION}.`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (row.plan_ir_version !== WORKFLOW_IR_VERSION) {
|
|
27
|
+
return {
|
|
28
|
+
support: "corrupt-plan",
|
|
29
|
+
irVersion: null,
|
|
30
|
+
error: `Workflow run ${runId} does not declare workflow IR version ${WORKFLOW_IR_VERSION}.`,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
return {
|
|
35
|
+
support: "supported",
|
|
36
|
+
irVersion: WORKFLOW_IR_VERSION,
|
|
37
|
+
plan: decodeCanonicalPlan(runId, row.plan_json, row.plan_hash),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (cause) {
|
|
41
|
+
return {
|
|
42
|
+
support: "corrupt-plan",
|
|
43
|
+
irVersion: WORKFLOW_IR_VERSION,
|
|
44
|
+
error: cause instanceof Error ? cause.message : String(cause),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Reject any operation that requires a valid current frozen plan. */
|
|
49
|
+
export function requireExecutableWorkflowPlan(row) {
|
|
50
|
+
const classified = classifyWorkflowRunPlan(row);
|
|
51
|
+
if (classified.support === "supported")
|
|
52
|
+
return classified.plan;
|
|
53
|
+
throw new UsageError(classified.error, "INVALID_JSON_ARGUMENT");
|
|
54
|
+
}
|
|
55
|
+
/** Project persisted spine rows from the decoded plan, never from the mutable source asset. */
|
|
56
|
+
export function frozenStepRows(plan) {
|
|
57
|
+
return plan.steps.map((step) => ({
|
|
58
|
+
stepId: step.stepId,
|
|
59
|
+
stepTitle: step.title,
|
|
60
|
+
instructions: step.root
|
|
61
|
+
? step.root.kind === "map"
|
|
62
|
+
? step.root.template.instructions
|
|
63
|
+
: step.root.instructions
|
|
64
|
+
: routeInstructions(step.route),
|
|
65
|
+
completionJson: step.gate.criteria.length > 0 ? JSON.stringify(step.gate.criteria) : null,
|
|
66
|
+
sequenceIndex: step.sequenceIndex,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
/** Verify the durable spine still agrees with the decoded/hash-verified plan before any mutation. */
|
|
70
|
+
export function assertWorkflowSpineMatchesPlan(plan, run, rows) {
|
|
71
|
+
const expected = frozenStepRows(plan);
|
|
72
|
+
if (rows.length !== expected.length)
|
|
73
|
+
corruptSpine(run.id, "step count differs from the frozen plan");
|
|
74
|
+
for (let index = 0; index < expected.length; index++) {
|
|
75
|
+
const actual = rows[index];
|
|
76
|
+
const planned = expected[index];
|
|
77
|
+
// The length check above (corruptSpine returns `never`) guarantees both are
|
|
78
|
+
// present; the guard narrows them and preserves the "missing row" message.
|
|
79
|
+
if (!actual || !planned) {
|
|
80
|
+
corruptSpine(run.id, `step row ${index} differs from the frozen plan (missing row)`);
|
|
81
|
+
}
|
|
82
|
+
if (actual.step_id !== planned.stepId ||
|
|
83
|
+
actual.step_title !== planned.stepTitle ||
|
|
84
|
+
actual.instructions !== planned.instructions ||
|
|
85
|
+
actual.completion_json !== planned.completionJson ||
|
|
86
|
+
actual.sequence_index !== planned.sequenceIndex) {
|
|
87
|
+
const fields = [
|
|
88
|
+
actual.step_id !== planned.stepId ? "step_id" : "",
|
|
89
|
+
actual.step_title !== planned.stepTitle ? "step_title" : "",
|
|
90
|
+
actual.instructions !== planned.instructions ? "instructions" : "",
|
|
91
|
+
actual.completion_json !== planned.completionJson ? "completion_json" : "",
|
|
92
|
+
actual.sequence_index !== planned.sequenceIndex ? "sequence_index" : "",
|
|
93
|
+
].filter(Boolean);
|
|
94
|
+
corruptSpine(run.id, `step row ${index} differs from the frozen plan (${fields.join(", ")})`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (run.current_step_id !== null && !expected.some((step) => step.stepId === run.current_step_id))
|
|
98
|
+
corruptSpine(run.id, `current step ${run.current_step_id} is not in the frozen plan`);
|
|
99
|
+
const current = run.current_step_id ? rows.find((row) => row.step_id === run.current_step_id) : undefined;
|
|
100
|
+
if (run.status === "active") {
|
|
101
|
+
const firstPending = rows.find((row) => row.status === "pending");
|
|
102
|
+
if (!current || current.status !== "pending" || firstPending?.step_id !== current.step_id)
|
|
103
|
+
corruptSpine(run.id, "active status/current step does not match the first pending plan step");
|
|
104
|
+
}
|
|
105
|
+
else if (run.status === "blocked") {
|
|
106
|
+
if (!current || current.status !== "blocked")
|
|
107
|
+
corruptSpine(run.id, `${run.status} status does not match the current plan step`);
|
|
108
|
+
}
|
|
109
|
+
else if (run.status === "failed") {
|
|
110
|
+
// `workflow abandon` marks the run failed while intentionally leaving its
|
|
111
|
+
// current step pending so `resume` can reopen the same work.
|
|
112
|
+
if (!current || (current.status !== "failed" && current.status !== "pending"))
|
|
113
|
+
corruptSpine(run.id, `${run.status} status does not match the current plan step`);
|
|
114
|
+
}
|
|
115
|
+
else if (run.status === "completed") {
|
|
116
|
+
if (run.current_step_id !== null ||
|
|
117
|
+
rows.some((row) => row.status === "pending" || row.status === "blocked" || row.status === "failed"))
|
|
118
|
+
corruptSpine(run.id, "completed status disagrees with the plan spine");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function routeInstructions(route) {
|
|
122
|
+
const branches = Object.entries(route.when)
|
|
123
|
+
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
124
|
+
.map(([match, stepId]) => `"${match}" -> ${stepId}`);
|
|
125
|
+
if (route.defaultStepId !== undefined)
|
|
126
|
+
branches.push(`default -> ${route.defaultStepId}`);
|
|
127
|
+
return `Route on ${route.input}: ${branches.join(", ")}.`;
|
|
128
|
+
}
|
|
129
|
+
function corruptSpine(runId, detail) {
|
|
130
|
+
throw new UsageError(`Workflow run ${runId} has a corrupt durable step spine: ${detail}. Refusing to mutate state that disagrees with its frozen plan.`, "INVALID_JSON_ARGUMENT");
|
|
131
|
+
}
|
|
@@ -2,26 +2,30 @@
|
|
|
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 { randomUUID } from "node:crypto";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { getDefaultLlmConfig, loadConfig } from "../../core/config/config.js";
|
|
5
|
+
import { parseBundleRef } from "../../core/asset/asset-ref.js";
|
|
6
|
+
import { loadConfig } from "../../core/config/config.js";
|
|
8
7
|
import { NotFoundError, UsageError } from "../../core/errors.js";
|
|
9
8
|
import { appendEvent } from "../../core/events.js";
|
|
10
9
|
import { warn } from "../../core/warn.js";
|
|
10
|
+
import { insertEventOnce } from "../../storage/repositories/events-repository.js";
|
|
11
11
|
import { withWorkflowRunsRepo, } from "../../storage/repositories/workflow-runs-repository.js";
|
|
12
12
|
import { getCurrentWorkflowScopeKey } from "../authoring/scope-key.js";
|
|
13
|
+
import { frozenSummaryJudge } from "../exec/frozen-judge.js";
|
|
13
14
|
import { detectSecretShapedParams } from "../exec/param-secrets.js";
|
|
14
|
-
import {
|
|
15
|
+
import { collectWorkflowWarnings } from "../ir/compile.js";
|
|
16
|
+
import { compileResolveFreezeWorkflow } from "../ir/freeze.js";
|
|
15
17
|
import { validateWorkflowParams } from "../ir/params.js";
|
|
16
18
|
import { canonicalPlanJson, computePlanHash } from "../ir/plan-hash.js";
|
|
19
|
+
import { decodeWorkflowPlanV3, WORKFLOW_IR_VERSION } from "../ir/schema.js";
|
|
17
20
|
import { validateStepSummary } from "../validate-summary.js";
|
|
18
21
|
import { resolveAgentIdentity } from "./agent-identity.js";
|
|
19
22
|
import { evaluateCheckin } from "./checkin.js";
|
|
23
|
+
import { assertWorkflowSpineMatchesPlan, classifyWorkflowRunPlan, frozenStepRows, requireExecutableWorkflowPlan, } from "./plan-classifier.js";
|
|
20
24
|
import { evaluateStaleUnits } from "./unit-checkin.js";
|
|
21
|
-
import {
|
|
25
|
+
import { canonicalizeWorkflowRefInput, loadWorkflowAsset, resolveWorkflowEntryId } from "./workflow-asset-loader.js";
|
|
22
26
|
/** Clip bound for a unit's `result_json` on the `--units` diagnostic surface. */
|
|
23
27
|
const UNIT_DIAGNOSTIC_CLIP = 2000;
|
|
24
|
-
function toUnitDiagnostic(row, stale) {
|
|
28
|
+
function toUnitDiagnostic(row, stale, plannedEngine) {
|
|
25
29
|
let diagnostic = null;
|
|
26
30
|
if (row.result_json !== null) {
|
|
27
31
|
// `result_json` is a JSON-encoded value: a bare JSON string for a free-text
|
|
@@ -55,6 +59,9 @@ function toUnitDiagnostic(row, stale) {
|
|
|
55
59
|
staleIdleMs: stale ? (Number.isFinite(stale.idleMs) ? stale.idleMs : null) : null,
|
|
56
60
|
claimHolder: row.claim_holder,
|
|
57
61
|
claimExpiresAt: row.claim_expires_at,
|
|
62
|
+
engine: row.engine ?? null,
|
|
63
|
+
runtimeKind: row.engine && (row.runner === "llm" || row.runner === "agent" || row.runner === "sdk") ? row.runner : null,
|
|
64
|
+
platform: plannedEngine?.kind === "agent" ? plannedEngine.platform : null,
|
|
58
65
|
};
|
|
59
66
|
}
|
|
60
67
|
export async function startWorkflowRun(ref, params = {}, options) {
|
|
@@ -63,15 +70,12 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
63
70
|
// persist it on the run row in the same transaction as the insert. Every
|
|
64
71
|
// later invocation executes this snapshot — the asset file is never re-read
|
|
65
72
|
// for an in-flight run; re-planning is an explicit new run.
|
|
66
|
-
const plan =
|
|
67
|
-
// Non-fatal WARNINGS
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
for (const w of collectProgramWarnings(asset.program)) {
|
|
73
|
-
warn(`workflow start: ${asset.path}:${w.line} — ${w.message}`);
|
|
74
|
-
}
|
|
73
|
+
const plan = decodeWorkflowPlanV3(compileResolveFreezeWorkflow(asset, loadConfig()).plan);
|
|
74
|
+
// Non-fatal WARNINGS: untyped-step and undeclared-param advisories surface
|
|
75
|
+
// as `warn()` lines at start (stderr, consistent with the repo's other
|
|
76
|
+
// author-facing warnings) without blocking the run.
|
|
77
|
+
for (const w of collectWorkflowWarnings(asset.document)) {
|
|
78
|
+
warn(`workflow start: ${asset.path}:${w.line} — ${w.message}`);
|
|
75
79
|
}
|
|
76
80
|
// Reviewer #12: validate supplied `--params` against the frozen param
|
|
77
81
|
// schemas BEFORE creating the run, so a type-mismatched param (e.g. a string
|
|
@@ -85,12 +89,13 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
85
89
|
}
|
|
86
90
|
const planJson = canonicalPlanJson(plan);
|
|
87
91
|
const planHash = computePlanHash(plan);
|
|
92
|
+
const workflowRefs = await workflowRunRefSet(asset.ref, ref);
|
|
88
93
|
return withWorkflowRunsRepo(async (repo) => {
|
|
89
94
|
const now = new Date().toISOString();
|
|
90
95
|
const runId = randomUUID();
|
|
91
96
|
const scopeKey = getCurrentWorkflowScopeKey();
|
|
92
|
-
const currentStepId =
|
|
93
|
-
const workflowEntryId = resolveWorkflowEntryId(asset.sourcePath, asset.ref);
|
|
97
|
+
const currentStepId = plan.steps[0]?.stepId ?? null;
|
|
98
|
+
const workflowEntryId = resolveWorkflowEntryId(asset.sourcePath, asset.ref, asset.adapterId);
|
|
94
99
|
// Capture the agent harness + session driving this run. Explicit options
|
|
95
100
|
// win; otherwise fall back to best-effort environment detection. This is
|
|
96
101
|
// identity-only — no background thread or timer is started here.
|
|
@@ -101,19 +106,20 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
101
106
|
// (workflow_ref, scope_key) pair, refuse to create a parallel run unless
|
|
102
107
|
// `force: true` is set. Previously every call inserted unconditionally,
|
|
103
108
|
// so two terminals running `akm workflow start <ref>` left two runs
|
|
104
|
-
// racing; `akm workflow next` then non-deterministically picked one.
|
|
105
|
-
|
|
106
|
-
const existing = repo.findActiveRunForScope(asset.ref, scopeKey);
|
|
107
|
-
if (existing) {
|
|
108
|
-
throw new UsageError(`Workflow ${asset.ref} already has an active run in this scope (id=${existing.id}, step=${existing.current_step_id ?? "—"}). ` +
|
|
109
|
-
`Use 'akm workflow next ${asset.ref}' to resume it, 'akm workflow abandon ${existing.id}' to give up on it, or pass --force to start a parallel run.`, "RESOURCE_ALREADY_EXISTS");
|
|
110
|
-
}
|
|
111
|
-
}
|
|
109
|
+
// racing; `akm workflow next` then non-deterministically picked one. The
|
|
110
|
+
// active-alias query and all inserts now share this immediate transaction.
|
|
112
111
|
// #506: arm a file-signal check-in (a timestamp, NOT a background thread —
|
|
113
|
-
//
|
|
112
|
+
// per the workflow-agent check-in ADR) so a stalled run can be
|
|
114
113
|
// re-targeted with a `continue` directive. The agent harness + session id
|
|
115
114
|
// are already resolved above (agentHarness/agentSessionId, from #501).
|
|
116
|
-
repo.
|
|
115
|
+
repo.immediateTransaction(() => {
|
|
116
|
+
if (!options?.force) {
|
|
117
|
+
const existing = repo.findActiveRunForScope(workflowRefs, scopeKey);
|
|
118
|
+
if (existing) {
|
|
119
|
+
throw new UsageError(`Workflow ${asset.ref} already has an active run in this scope (id=${existing.id}, step=${existing.current_step_id ?? "—"}). ` +
|
|
120
|
+
`Use 'akm workflow next ${asset.ref}' to resume it, 'akm workflow abandon ${existing.id}' to give up on it, or pass --force to start a parallel run.`, "RESOURCE_ALREADY_EXISTS");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
117
123
|
repo.insertRun({
|
|
118
124
|
id: runId,
|
|
119
125
|
workflowRef: asset.ref,
|
|
@@ -128,17 +134,16 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
128
134
|
agentSessionId,
|
|
129
135
|
checkinArmedAt: now,
|
|
130
136
|
});
|
|
131
|
-
repo.insertSteps(
|
|
137
|
+
repo.insertSteps(frozenStepRows(plan).map((step) => ({
|
|
132
138
|
runId,
|
|
133
|
-
stepId: step.
|
|
134
|
-
stepTitle: step.
|
|
139
|
+
stepId: step.stepId,
|
|
140
|
+
stepTitle: step.stepTitle,
|
|
135
141
|
instructions: step.instructions,
|
|
136
|
-
completionJson: step.
|
|
137
|
-
sequenceIndex: step.sequenceIndex
|
|
142
|
+
completionJson: step.completionJson,
|
|
143
|
+
sequenceIndex: step.sequenceIndex,
|
|
138
144
|
})));
|
|
139
|
-
// Same transaction as the insert: a run row never exists without its
|
|
140
|
-
|
|
141
|
-
repo.setRunPlan(runId, planJson, planHash);
|
|
145
|
+
// Same transaction as the insert: a run row never exists without its frozen plan.
|
|
146
|
+
repo.setRunPlan(runId, planJson, planHash, WORKFLOW_IR_VERSION);
|
|
142
147
|
});
|
|
143
148
|
const result = await getWorkflowStatus(runId);
|
|
144
149
|
// #13: params are declared non-secret (they are copied verbatim into every
|
|
@@ -156,7 +161,7 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
156
161
|
// into agent context.
|
|
157
162
|
appendEvent({
|
|
158
163
|
eventType: "workflow_started",
|
|
159
|
-
ref: ref,
|
|
164
|
+
ref: asset.ref,
|
|
160
165
|
metadata: { runId: result.run.id, status: result.run.status },
|
|
161
166
|
});
|
|
162
167
|
return result;
|
|
@@ -176,7 +181,9 @@ export async function getWorkflowStatus(runId, opts) {
|
|
|
176
181
|
// uses (`now` injected for deterministic tests) so a dead driver's claimed
|
|
177
182
|
// `running` unit surfaces as stale here too, not just as raw `running`.
|
|
178
183
|
const staleById = new Map(evaluateStaleUnits(rows, opts.now ?? Date.now()).map((u) => [u.unitId, u]));
|
|
179
|
-
|
|
184
|
+
const classified = classifyWorkflowRunPlan(run);
|
|
185
|
+
const engines = classified.support === "supported" ? classified.plan.execution?.engines : undefined;
|
|
186
|
+
detail.units = rows.map((row) => toUnitDiagnostic(row, staleById.get(row.unit_id), row.engine ? engines?.[row.engine] : undefined));
|
|
180
187
|
}
|
|
181
188
|
return detail;
|
|
182
189
|
});
|
|
@@ -185,28 +192,50 @@ export async function hasWorkflowRun(runId) {
|
|
|
185
192
|
return withWorkflowRunsRepo((repo) => repo.hasRun(runId));
|
|
186
193
|
}
|
|
187
194
|
export async function listWorkflowRuns(input) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
const scopeKey = getCurrentWorkflowScopeKey();
|
|
196
|
+
const activeOnly = input?.activeOnly === true;
|
|
197
|
+
if (input?.workflowRef === undefined) {
|
|
198
|
+
return withWorkflowRunsRepo((repo) => ({
|
|
199
|
+
runs: repo.listRuns({ scopeKey, ...(activeOnly ? { activeOnly: true } : {}) }).map(toWorkflowRunSummary),
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
const exactRef = input.workflowRef.trim();
|
|
203
|
+
if (!exactRef) {
|
|
204
|
+
throw new UsageError("Workflow ref filter cannot be empty.", "INVALID_FLAG_VALUE");
|
|
205
|
+
}
|
|
206
|
+
const parsedExactRef = parseBundleRef(exactRef);
|
|
207
|
+
if (parsedExactRef.fragment !== undefined) {
|
|
208
|
+
throw new UsageError("Workflow ref filters do not accept fragments.", "INVALID_FLAG_VALUE");
|
|
209
|
+
}
|
|
210
|
+
let workflowRefs = [exactRef];
|
|
211
|
+
try {
|
|
212
|
+
const canonicalRef = await canonicalizeWorkflowSpecifier(exactRef);
|
|
213
|
+
workflowRefs = await workflowRunRefSet(canonicalRef, exactRef);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
if (parsedExactRef.bundle !== undefined) {
|
|
217
|
+
const exactRows = await withWorkflowRunsRepo((repo) => repo.listRuns({ scopeKey, workflowRef: exactRef }));
|
|
218
|
+
if (exactRows.length === 0)
|
|
219
|
+
throw error;
|
|
220
|
+
return {
|
|
221
|
+
runs: exactRows.filter((row) => !activeOnly || row.status === "active").map(toWorkflowRunSummary),
|
|
222
|
+
};
|
|
197
223
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
224
|
+
if (!(error instanceof NotFoundError))
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
return withWorkflowRunsRepo((repo) => ({
|
|
228
|
+
runs: repo
|
|
229
|
+
.listRuns({ scopeKey, workflowRefs, ...(activeOnly ? { activeOnly: true } : {}) })
|
|
230
|
+
.map(toWorkflowRunSummary),
|
|
231
|
+
}));
|
|
205
232
|
}
|
|
206
233
|
export async function getNextWorkflowStep(specifier, params) {
|
|
207
234
|
return withWorkflowRunsRepo(async (repo) => {
|
|
208
235
|
const { run, autoStarted } = await resolveRunSpecifier(repo, specifier, params);
|
|
209
236
|
const steps = readWorkflowRunSteps(repo, run.id);
|
|
237
|
+
const plan = requireExecutableWorkflowPlan(run);
|
|
238
|
+
assertWorkflowSpineMatchesPlan(plan, run, steps);
|
|
210
239
|
return { ...projectNextResult(run, steps), ...(autoStarted ? { autoStarted: true } : {}) };
|
|
211
240
|
});
|
|
212
241
|
}
|
|
@@ -255,6 +284,8 @@ export async function snapshotRunForDriver(runId) {
|
|
|
255
284
|
return withWorkflowRunsRepo((repo) => repo.transaction(() => {
|
|
256
285
|
const run = readWorkflowRun(repo, runId);
|
|
257
286
|
const steps = readWorkflowRunSteps(repo, run.id);
|
|
287
|
+
const plan = requireExecutableWorkflowPlan(run);
|
|
288
|
+
assertWorkflowSpineMatchesPlan(plan, run, steps);
|
|
258
289
|
const units = repo.getUnitsForRun(run.id);
|
|
259
290
|
return { next: projectNextResult(run, steps), run, units };
|
|
260
291
|
}));
|
|
@@ -262,11 +293,13 @@ export async function snapshotRunForDriver(runId) {
|
|
|
262
293
|
export async function resumeWorkflowRun(runId) {
|
|
263
294
|
return withWorkflowRunsRepo((repo) => {
|
|
264
295
|
const run = readWorkflowRun(repo, runId);
|
|
296
|
+
const plan = requireExecutableWorkflowPlan(run);
|
|
297
|
+
const steps = readWorkflowRunSteps(repo, run.id);
|
|
298
|
+
assertWorkflowSpineMatchesPlan(plan, run, steps);
|
|
265
299
|
if (run.status === "completed") {
|
|
266
300
|
throw new UsageError(`Workflow run ${run.id} is already completed and cannot be resumed.`);
|
|
267
301
|
}
|
|
268
302
|
if (run.status === "active") {
|
|
269
|
-
const steps = readWorkflowRunSteps(repo, run.id);
|
|
270
303
|
return buildWorkflowRunDetail(run, steps);
|
|
271
304
|
}
|
|
272
305
|
// blocked or failed → flip back to active and re-open the current step so
|
|
@@ -279,8 +312,8 @@ export async function resumeWorkflowRun(runId) {
|
|
|
279
312
|
repo.markRunActive(run.id, now);
|
|
280
313
|
});
|
|
281
314
|
const updated = { ...run, status: "active", updated_at: now };
|
|
282
|
-
const
|
|
283
|
-
return buildWorkflowRunDetail(updated,
|
|
315
|
+
const refreshedSteps = readWorkflowRunSteps(repo, run.id);
|
|
316
|
+
return buildWorkflowRunDetail(updated, refreshedSteps);
|
|
284
317
|
});
|
|
285
318
|
}
|
|
286
319
|
/**
|
|
@@ -291,18 +324,24 @@ export async function resumeWorkflowRun(runId) {
|
|
|
291
324
|
*/
|
|
292
325
|
export async function abandonWorkflowRun(runId) {
|
|
293
326
|
return withWorkflowRunsRepo((repo) => {
|
|
294
|
-
const run = readWorkflowRun(repo, runId);
|
|
295
|
-
if (run.status === "completed" || run.status === "failed") {
|
|
296
|
-
throw new UsageError(`Workflow run ${run.id} is already ${run.status}.`);
|
|
297
|
-
}
|
|
298
327
|
const now = new Date().toISOString();
|
|
299
|
-
repo.
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
328
|
+
const run = repo.immediateTransaction((db) => {
|
|
329
|
+
const current = readWorkflowRun(repo, runId);
|
|
330
|
+
if (current.status === "completed" || current.status === "failed") {
|
|
331
|
+
throw new UsageError(`Workflow run ${current.id} is already ${current.status}.`);
|
|
332
|
+
}
|
|
333
|
+
if (!repo.markRunAbandoned(current.id, now)) {
|
|
334
|
+
throw new UsageError(`Workflow run ${current.id} is ${current.status} and cannot be abandoned.`);
|
|
335
|
+
}
|
|
336
|
+
insertEventOnce(db, {
|
|
337
|
+
eventType: "workflow_abandoned",
|
|
338
|
+
ts: now,
|
|
339
|
+
ref: current.workflow_ref,
|
|
340
|
+
metadata: { runId: current.id },
|
|
341
|
+
idempotencyKey: current.id,
|
|
342
|
+
idempotencyMetadataKey: "runId",
|
|
343
|
+
});
|
|
344
|
+
return current;
|
|
306
345
|
});
|
|
307
346
|
const updated = {
|
|
308
347
|
...run,
|
|
@@ -313,9 +352,6 @@ export async function abandonWorkflowRun(runId) {
|
|
|
313
352
|
};
|
|
314
353
|
const steps = readWorkflowRunSteps(repo, run.id);
|
|
315
354
|
const detail = buildWorkflowRunDetail(updated, steps);
|
|
316
|
-
// Same injectable-footprint rule as workflow_started (07 P1-B): ids and
|
|
317
|
-
// status only, never the frontmatter-derived title.
|
|
318
|
-
appendEvent({ eventType: "workflow_abandoned", ref: run.workflow_ref, metadata: { runId: run.id } });
|
|
319
355
|
return detail;
|
|
320
356
|
});
|
|
321
357
|
}
|
|
@@ -324,6 +360,9 @@ export async function completeWorkflowStep(input) {
|
|
|
324
360
|
// the write transaction — a slow/hung LLM must never hold a db write lock.
|
|
325
361
|
const preflight = await withWorkflowRunsRepo((repo) => {
|
|
326
362
|
const run = readWorkflowRun(repo, input.runId);
|
|
363
|
+
const plan = requireExecutableWorkflowPlan(run);
|
|
364
|
+
const steps = readWorkflowRunSteps(repo, run.id);
|
|
365
|
+
assertWorkflowSpineMatchesPlan(plan, run, steps);
|
|
327
366
|
if (run.status !== "active") {
|
|
328
367
|
throw new UsageError(`Workflow run ${run.id} is ${run.status} and cannot be updated.`);
|
|
329
368
|
}
|
|
@@ -338,7 +377,10 @@ export async function completeWorkflowStep(input) {
|
|
|
338
377
|
if (run.current_step_id !== existing.step_id) {
|
|
339
378
|
throw new UsageError(`Step "${input.stepId}" is not the current step for workflow run ${run.id}. Complete "${run.current_step_id}" first.`);
|
|
340
379
|
}
|
|
341
|
-
|
|
380
|
+
const stepPlan = plan.steps.find((step) => step.stepId === input.stepId);
|
|
381
|
+
if (!stepPlan)
|
|
382
|
+
throw new NotFoundError(`Step "${input.stepId}" was not found in workflow run ${run.id}.`);
|
|
383
|
+
return { existing, plan, stepPlan };
|
|
342
384
|
});
|
|
343
385
|
const summary = input.summary?.trim();
|
|
344
386
|
// #506: completing a step requires a summary of the work done.
|
|
@@ -349,9 +391,11 @@ export async function completeWorkflowStep(input) {
|
|
|
349
391
|
// completionCriteria via the configured LLM. Fail-open when no criteria or no
|
|
350
392
|
// judge. Only a well-formed `complete: false` blocks completion.
|
|
351
393
|
if (input.status === "completed" && summary) {
|
|
352
|
-
const criteria =
|
|
353
|
-
const judge = input.summaryJudge === undefined
|
|
354
|
-
|
|
394
|
+
const criteria = preflight.stepPlan.gate.criteria;
|
|
395
|
+
const judge = input.summaryJudge === undefined
|
|
396
|
+
? frozenSummaryJudge(preflight.plan, preflight.stepPlan.gate.judge)
|
|
397
|
+
: input.summaryJudge;
|
|
398
|
+
const verdict = await validateStepSummary({ stepTitle: preflight.stepPlan.title, completionCriteria: criteria, summary }, judge ?? undefined);
|
|
355
399
|
if (!verdict.complete) {
|
|
356
400
|
// Re-arm the check-in so a subsequent stall is still nudged, but leave the
|
|
357
401
|
// step pending and return corrective feedback instead of completing.
|
|
@@ -364,9 +408,6 @@ export async function completeWorkflowStep(input) {
|
|
|
364
408
|
stepId: input.stepId,
|
|
365
409
|
missing: verdict.missing,
|
|
366
410
|
feedback: verdict.feedback ?? "The summary does not satisfy the step's completion criteria.",
|
|
367
|
-
// A REQUIRED gate that could not be judged (finding A): the caller BLOCKS
|
|
368
|
-
// rather than treating this as a normal, retryable gate rejection.
|
|
369
|
-
...(verdict.errored ? { errored: true } : {}),
|
|
370
411
|
};
|
|
371
412
|
}
|
|
372
413
|
}
|
|
@@ -375,6 +416,9 @@ export async function completeWorkflowStep(input) {
|
|
|
375
416
|
let refreshedSteps = [];
|
|
376
417
|
repo.transaction(() => {
|
|
377
418
|
const run = readWorkflowRun(repo, input.runId);
|
|
419
|
+
const plan = requireExecutableWorkflowPlan(run);
|
|
420
|
+
const spine = readWorkflowRunSteps(repo, run.id);
|
|
421
|
+
assertWorkflowSpineMatchesPlan(plan, run, spine);
|
|
378
422
|
if (run.status !== "active") {
|
|
379
423
|
throw new UsageError(`Workflow run ${run.id} is ${run.status} and cannot be updated.`);
|
|
380
424
|
}
|
|
@@ -449,16 +493,28 @@ async function resolveRunSpecifier(repo, specifier, params) {
|
|
|
449
493
|
}
|
|
450
494
|
return { run: explicitRun, autoStarted: false };
|
|
451
495
|
}
|
|
452
|
-
|
|
453
|
-
|
|
496
|
+
const scopeKey = getCurrentWorkflowScopeKey();
|
|
497
|
+
const exactRef = specifier.trim();
|
|
498
|
+
const parsedExact = parseBundleRef(exactRef);
|
|
499
|
+
const qualifiedExact = parsedExact.bundle !== undefined && parsedExact.fragment === undefined;
|
|
500
|
+
const detached = qualifiedExact ? repo.getActiveRunRowForScope(exactRef, scopeKey) : undefined;
|
|
501
|
+
let ref;
|
|
502
|
+
try {
|
|
503
|
+
ref = await canonicalizeWorkflowSpecifier(specifier);
|
|
454
504
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
505
|
+
catch (error) {
|
|
506
|
+
if (detached) {
|
|
507
|
+
if (params && Object.keys(params).length > 0) {
|
|
508
|
+
throw new UsageError(`--params can only be set on a new run; ${specifier} already has an active run`);
|
|
509
|
+
}
|
|
510
|
+
return { run: detached, autoStarted: false };
|
|
511
|
+
}
|
|
512
|
+
if (error instanceof NotFoundError && !specifier.includes(":") && !specifier.includes("/")) {
|
|
513
|
+
throw new NotFoundError(`Workflow run or workflow "${specifier}" not found.`, "WORKFLOW_NOT_FOUND");
|
|
514
|
+
}
|
|
515
|
+
throw error;
|
|
458
516
|
}
|
|
459
|
-
const
|
|
460
|
-
const scopeKey = getCurrentWorkflowScopeKey();
|
|
461
|
-
const active = repo.getActiveRunRowForScope(ref, scopeKey);
|
|
517
|
+
const active = repo.getActiveRunRowForScope(await workflowRunRefSet(ref, exactRef), scopeKey);
|
|
462
518
|
if (active) {
|
|
463
519
|
if (params && Object.keys(params).length > 0) {
|
|
464
520
|
throw new UsageError(`--params can only be set on a new run; ${ref} already has an active run`);
|
|
@@ -468,6 +524,62 @@ async function resolveRunSpecifier(repo, specifier, params) {
|
|
|
468
524
|
const started = await startWorkflowRun(ref, params ?? {});
|
|
469
525
|
return { run: readWorkflowRun(repo, started.run.id), autoStarted: true };
|
|
470
526
|
}
|
|
527
|
+
async function canonicalizeWorkflowSpecifier(specifier) {
|
|
528
|
+
return canonicalizeWorkflowRefInput(specifier);
|
|
529
|
+
}
|
|
530
|
+
async function workflowRunRefSet(canonicalRef, exactRef) {
|
|
531
|
+
const parsed = parseBundleRef(canonicalRef);
|
|
532
|
+
const refs = new Set([canonicalRef, exactRef.trim()]);
|
|
533
|
+
const exact = parseBundleRef(exactRef.trim());
|
|
534
|
+
if (exact.bundle === undefined) {
|
|
535
|
+
refs.add(parsed.conceptId);
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
try {
|
|
539
|
+
if ((await canonicalizeWorkflowSpecifier(parsed.conceptId)) === canonicalRef)
|
|
540
|
+
refs.add(parsed.conceptId);
|
|
541
|
+
}
|
|
542
|
+
catch (error) {
|
|
543
|
+
if (!(error instanceof NotFoundError))
|
|
544
|
+
throw error;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
return [...refs];
|
|
548
|
+
}
|
|
549
|
+
/** Resolve an existing active run without auto-starting or rebinding a detached short ref. */
|
|
550
|
+
export async function resolveExistingWorkflowRunId(target) {
|
|
551
|
+
return withWorkflowRunsRepo(async (repo) => {
|
|
552
|
+
const byId = repo.getRunById(target);
|
|
553
|
+
if (byId)
|
|
554
|
+
return byId.id;
|
|
555
|
+
const scopeKey = getCurrentWorkflowScopeKey();
|
|
556
|
+
const exactRef = target.trim();
|
|
557
|
+
if (!exactRef.includes(":") && !exactRef.includes("/")) {
|
|
558
|
+
throw new NotFoundError(`Workflow run or workflow "${target}" not found.`, "WORKFLOW_NOT_FOUND");
|
|
559
|
+
}
|
|
560
|
+
const parsedExact = parseBundleRef(exactRef);
|
|
561
|
+
const detached = parsedExact.bundle && parsedExact.fragment === undefined
|
|
562
|
+
? repo.getActiveRunRowForScope(exactRef, scopeKey)
|
|
563
|
+
: undefined;
|
|
564
|
+
let canonicalRef;
|
|
565
|
+
try {
|
|
566
|
+
canonicalRef = await canonicalizeWorkflowSpecifier(exactRef);
|
|
567
|
+
}
|
|
568
|
+
catch (error) {
|
|
569
|
+
if (detached)
|
|
570
|
+
return detached.id;
|
|
571
|
+
if (error instanceof NotFoundError) {
|
|
572
|
+
throw new NotFoundError(`Workflow run or workflow "${target}" not found.`, "WORKFLOW_NOT_FOUND");
|
|
573
|
+
}
|
|
574
|
+
throw error;
|
|
575
|
+
}
|
|
576
|
+
const active = repo.getActiveRunRowForScope(await workflowRunRefSet(canonicalRef, exactRef), scopeKey);
|
|
577
|
+
if (!active) {
|
|
578
|
+
throw new NotFoundError(`No active workflow run for ${canonicalRef} in this scope.`, "WORKFLOW_NOT_FOUND");
|
|
579
|
+
}
|
|
580
|
+
return active.id;
|
|
581
|
+
});
|
|
582
|
+
}
|
|
471
583
|
function readWorkflowRun(repo, runId) {
|
|
472
584
|
const run = repo.getRunById(runId);
|
|
473
585
|
if (!run) {
|
|
@@ -500,6 +612,7 @@ function buildWorkflowRunDetail(run, steps) {
|
|
|
500
612
|
};
|
|
501
613
|
}
|
|
502
614
|
function toWorkflowRunSummary(run) {
|
|
615
|
+
const plan = classifyWorkflowRunPlan(run);
|
|
503
616
|
return {
|
|
504
617
|
id: run.id,
|
|
505
618
|
workflowRef: run.workflow_ref,
|
|
@@ -514,6 +627,8 @@ function toWorkflowRunSummary(run) {
|
|
|
514
627
|
params: parseJsonObject(run.params_json),
|
|
515
628
|
agentHarness: run.agent_harness ?? null,
|
|
516
629
|
agentSessionId: run.agent_session_id ?? null,
|
|
630
|
+
planIrVersion: plan.irVersion,
|
|
631
|
+
executionSupport: plan.support,
|
|
517
632
|
// Surface the engine lease (holder id + expiry — never workflow-authored
|
|
518
633
|
// content) so `workflow next`/`status` show who is driving the run.
|
|
519
634
|
...(run.engine_lease_holder && run.engine_lease_until
|
|
@@ -579,34 +694,6 @@ function deriveRunState(steps) {
|
|
|
579
694
|
.at(-1);
|
|
580
695
|
return { status: "completed", currentStepId: null, completedAt: completedAt ?? null };
|
|
581
696
|
}
|
|
582
|
-
/**
|
|
583
|
-
* Build the default summary-validation judge from the configured LLM, or return
|
|
584
|
-
* `null` when no LLM is configured (gate is then skipped — fail-open). Lazily
|
|
585
|
-
* imports the client/config so the workflow engine has no hard LLM dependency.
|
|
586
|
-
*
|
|
587
|
-
* Exported for the engine loop (`exec/run-workflow.ts`), which wraps the judge
|
|
588
|
-
* to journal engine-driven gate evaluations as unit rows (addendum R2).
|
|
589
|
-
*/
|
|
590
|
-
export function buildDefaultSummaryJudge() {
|
|
591
|
-
let llm;
|
|
592
|
-
try {
|
|
593
|
-
const config = loadConfig();
|
|
594
|
-
llm = getDefaultLlmConfig(config);
|
|
595
|
-
}
|
|
596
|
-
catch {
|
|
597
|
-
return null;
|
|
598
|
-
}
|
|
599
|
-
if (!llm)
|
|
600
|
-
return null;
|
|
601
|
-
const resolved = llm;
|
|
602
|
-
return async ({ system, user }) => {
|
|
603
|
-
const { chatCompletion } = await import("../../llm/client.js");
|
|
604
|
-
return chatCompletion(resolved, [
|
|
605
|
-
{ role: "system", content: system },
|
|
606
|
-
{ role: "user", content: user },
|
|
607
|
-
]);
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
697
|
function parseJsonObject(value) {
|
|
611
698
|
if (!value)
|
|
612
699
|
return undefined;
|
|
@@ -1,7 +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 { GATE_EVALUATION_PHASE } from "
|
|
4
|
+
import { GATE_EVALUATION_PHASE } from "./unit-phases.js";
|
|
5
5
|
/**
|
|
6
6
|
* Default staleness window. A unit claimed `running` whose last heartbeat (or,
|
|
7
7
|
* absent any heartbeat, its first claim) is older than this is surfaced as
|