akm-cli 0.9.0-rc.8 → 0.9.0
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 +1063 -44
- package/README.md +51 -25
- package/SECURITY.md +14 -1
- package/STABILITY.md +497 -0
- package/dist/akm +148 -35
- package/dist/{akm-migrate-storage → akm-migrate} +6 -9
- package/dist/assets/hints/cli-hints-full.md +223 -95
- package/dist/assets/hints/cli-hints-short.md +85 -22
- package/dist/assets/improve-strategies/default.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/stash-skeleton/README.md +6 -5
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
- package/dist/assets/tasks/core/extract.yml +1 -1
- package/dist/assets/tasks/core/version-check.yml +1 -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 +1 -3
- package/dist/assets/workflows/workflow-template.md +32 -15
- package/dist/cli/invocation.js +40 -15
- package/dist/cli/parse-args.js +0 -22
- package/dist/cli/retired-commands.js +121 -0
- package/dist/cli/shared.js +154 -22
- package/dist/cli/unknown-flags.js +236 -0
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +696 -258
- package/dist/commands/agent/agent-dispatch.js +14 -3
- package/dist/commands/agent/contribute-cli.js +73 -88
- package/dist/commands/completions.js +79 -22
- package/dist/commands/config-cli.js +17 -150
- package/dist/commands/env/env-cli.js +59 -143
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +36 -66
- package/dist/commands/env/secret.js +24 -57
- package/dist/commands/feedback-cli.js +141 -87
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +3 -4
- package/dist/commands/health/checks.js +85 -23
- package/dist/commands/health/html-report.js +7 -10
- package/dist/commands/health/improve-metrics.js +25 -83
- package/dist/commands/health/md-report.js +5 -9
- package/dist/commands/health/metrics.js +62 -20
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +4 -5
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +3 -48
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/commands/health/types-improve.js +7 -0
- package/dist/commands/health.js +99 -28
- package/dist/commands/improve/anti-collapse.js +2 -2
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +41 -40
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +140 -1000
- package/dist/commands/improve/distill/promote-memory.js +12 -12
- package/dist/commands/improve/distill/quality-gate.js +6 -6
- package/dist/commands/improve/distill.js +58 -69
- package/dist/commands/improve/eligibility.js +105 -57
- package/dist/commands/improve/extract-cli.js +14 -133
- package/dist/commands/improve/improve-cli.js +98 -114
- package/dist/commands/improve/improve-result-file.js +1 -28
- package/dist/commands/improve/improve-strategies.js +8 -5
- package/dist/commands/improve/improve.js +128 -91
- package/dist/commands/improve/loop-stages.js +182 -20
- package/dist/commands/improve/memory/derived-ref.js +45 -43
- package/dist/commands/improve/memory/memory-belief.js +1 -1
- package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
- package/dist/commands/improve/memory/memory-improve.js +6 -5
- package/dist/commands/improve/outcome-loop.js +22 -65
- package/dist/commands/improve/preparation.js +114 -123
- package/dist/commands/improve/proactive-maintenance.js +2 -5
- package/dist/commands/improve/reflect.js +56 -160
- package/dist/commands/improve/salience.js +11 -122
- package/dist/commands/improve/source-identity.js +10 -38
- package/dist/commands/lint/base-linter.js +20 -124
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +249 -43
- package/dist/commands/{events.js → log.js} +33 -38
- package/dist/commands/migrate-cli.js +92 -12
- package/dist/commands/migration-tool.js +46 -0
- package/dist/commands/observability-cli.js +70 -209
- package/dist/commands/proposal/drain.js +101 -29
- package/dist/commands/proposal/proposal-cli.js +76 -48
- package/dist/commands/proposal/proposal.js +54 -18
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +23 -15
- package/dist/commands/proposal/repository.js +701 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
- package/dist/commands/proposal/validators/proposal-validators.js +55 -7
- package/dist/commands/proposal/validators/proposals.js +4 -7
- package/dist/commands/read/curate.js +34 -53
- package/dist/commands/read/knowledge.js +150 -95
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +42 -15
- package/dist/commands/read/search-cli.js +180 -78
- package/dist/commands/read/search.js +58 -43
- package/dist/commands/read/show.js +197 -141
- package/dist/commands/registry-cli.js +12 -51
- package/dist/commands/remember.js +14 -57
- package/dist/commands/sources/add-cli.js +100 -31
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +7 -2
- package/dist/commands/sources/info.js +18 -5
- package/dist/commands/sources/init.js +12 -12
- package/dist/commands/sources/installed-stashes.js +382 -98
- package/dist/commands/sources/schema-repair.js +3 -2
- package/dist/commands/sources/self-update.js +131 -38
- package/dist/commands/sources/source-add.js +72 -17
- package/dist/commands/sources/source-clone.js +129 -45
- package/dist/commands/sources/source-manage.js +43 -23
- package/dist/commands/sources/sources-cli.js +57 -208
- package/dist/commands/sources/stash-cli.js +46 -53
- package/dist/commands/tasks/tasks-cli.js +91 -97
- package/dist/commands/tasks/tasks.js +276 -421
- package/dist/commands/workflow-cli.js +175 -450
- package/dist/core/adapter/adapters/akm-adapter.js +47 -28
- package/dist/core/adapter/adapters/akm-lint.js +42 -27
- package/dist/core/adapter/adapters/akm-metadata.js +15 -44
- package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
- package/dist/core/adapter/adapters/index.js +6 -6
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
- package/dist/core/adapter/adapters/okf-adapter.js +187 -19
- package/dist/core/adapter/adapters/shared.js +3 -19
- package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +6 -4
- package/dist/core/adapter/validate-context.js +214 -0
- package/dist/core/asset/akm-markdown.js +63 -0
- package/dist/core/asset/asset-placement.js +20 -6
- package/dist/core/asset/asset-ref.js +11 -9
- package/dist/core/asset/frontmatter-lint.js +30 -0
- package/dist/core/asset/frontmatter.js +37 -9
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +89 -18
- package/dist/core/asset/stash-meta.js +1 -1
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +152 -38
- package/dist/core/config/config-io.js +12 -1
- package/dist/core/config/config-schema.js +35 -8
- package/dist/core/config/config-sources.js +55 -11
- package/dist/core/config/config-walker.js +25 -9
- package/dist/core/config/config.js +9 -48
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +5 -1
- package/dist/core/config/schema/experimental.js +30 -0
- package/dist/core/config/schema/improve-processes.js +0 -6
- package/dist/core/config/schema/improve.js +21 -3
- package/dist/core/config/schema/index-config.js +8 -15
- package/dist/core/config/schema/output.js +4 -1
- package/dist/core/config/schema/setup.js +9 -18
- package/dist/core/config/schema/sources-bundles.js +49 -33
- package/dist/core/config/schema/workflow.js +3 -3
- package/dist/core/env-secret-ref.js +76 -46
- package/dist/core/errors.js +18 -12
- package/dist/core/events.js +46 -128
- package/dist/core/file-change.js +6 -5
- package/dist/core/fs-txn.js +83 -7
- package/dist/core/git-message.js +2 -2
- package/dist/core/improve-result.js +1 -100
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +2 -1
- package/dist/core/migration-operation.js +16 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/parse.js +4 -1
- package/dist/core/paths.js +17 -20
- package/dist/core/recognition-util.js +12 -14
- package/dist/core/redaction.js +34 -0
- package/dist/core/standards/resolve-standards-context.js +2 -14
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +2 -2
- package/dist/core/state/migrations.js +41 -18
- package/dist/core/state-db.js +5 -14
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +6 -4
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/type-presentation.js +3 -3
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +771 -95
- package/dist/indexer/bundle-identity-guard.js +3 -2
- package/dist/indexer/db/graph-db.js +0 -24
- package/dist/indexer/ensure-index.js +1 -0
- package/dist/indexer/graph/graph-boost.js +9 -34
- package/dist/indexer/graph/graph-extraction.js +8 -5
- package/dist/indexer/index-writer-lock.js +53 -17
- package/dist/indexer/index-written-assets.js +16 -22
- package/dist/indexer/indexer.js +497 -239
- package/dist/indexer/installations.js +14 -96
- package/dist/indexer/passes/dir-staleness.js +16 -9
- package/dist/indexer/passes/memory-inference.js +11 -9
- package/dist/indexer/passes/metadata.js +113 -47
- package/dist/indexer/scan/doc-to-entry.js +38 -1
- package/dist/indexer/scan/drain-dir.js +13 -23
- package/dist/indexer/search/db-search.js +99 -54
- package/dist/indexer/search/fts-query.js +47 -24
- package/dist/indexer/search/ranking-contributors.js +42 -20
- package/dist/indexer/search/ranking.js +18 -99
- package/dist/indexer/search/search-fields.js +7 -2
- package/dist/indexer/search/search-source.js +82 -93
- package/dist/indexer/usage/usage-events.js +0 -89
- package/dist/indexer/walk/file-context.js +2 -1
- package/dist/indexer/walk/matchers.js +30 -43
- package/dist/indexer/walk/path-resolver.js +7 -2
- package/dist/indexer/walk/walker.js +38 -12
- package/dist/integrations/agent/builders.js +0 -6
- package/dist/integrations/agent/config.js +2 -2
- package/dist/integrations/agent/detect.js +49 -19
- package/dist/integrations/agent/engine-fallback.js +76 -0
- package/dist/integrations/agent/profiles.js +14 -0
- package/dist/integrations/agent/prompts.js +12 -8
- package/dist/integrations/agent/runner-dispatch.js +4 -2
- package/dist/integrations/agent/runner.js +0 -1
- package/dist/integrations/agent/spawn.js +5 -6
- package/dist/integrations/github.js +1 -1
- package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
- package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
- package/dist/integrations/harnesses/claude/session-log.js +0 -10
- package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
- package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
- package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
- package/dist/integrations/harnesses/index.js +3 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
- package/dist/integrations/harnesses/opencode/session-log.js +0 -15
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
- package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
- package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
- package/dist/integrations/lockfile.js +101 -6
- package/dist/integrations/session-logs/index.js +3 -28
- package/dist/llm/client.js +136 -100
- package/dist/llm/embedders/remote.js +13 -5
- package/dist/llm/feature-gate.js +4 -12
- package/dist/llm/graph-extract.js +5 -11
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +5 -7
- package/dist/llm/structured-call.js +1 -1
- package/dist/llm/usage-persist.js +26 -5
- package/dist/llm/usage-telemetry.js +25 -2
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +259 -0
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -36
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +56 -83
- package/dist/output/shapes/migrate.js +8 -0
- package/dist/output/shapes/passthrough.js +7 -41
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes.js +2 -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 +164 -96
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/health-format.js +103 -0
- package/dist/output/text/health.js +7 -0
- package/dist/output/text/helpers.js +10 -8
- package/dist/output/text/lint-format.js +43 -0
- package/dist/output/text/{save.js → lint.js} +2 -2
- package/dist/output/text/migrate.js +88 -0
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +44 -72
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +15 -7
- package/dist/output/text/status-list.js +32 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +24 -203
- package/dist/output/text/workflow.js +1 -7
- package/dist/output/text.js +16 -17
- 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 +13 -23
- package/dist/registry/resolve.js +42 -7
- package/dist/registry/semver.js +34 -84
- package/dist/runtime.js +2 -23
- package/dist/scripts/akm-migrate-node.js +60290 -0
- package/dist/scripts/akm-migrate.js +59628 -0
- package/dist/setup/detect.js +42 -15
- package/dist/setup/registry-stash-loader.js +2 -2
- package/dist/setup/setup.js +236 -136
- package/dist/setup/steps/connection.js +7 -9
- package/dist/setup/steps/platforms.js +9 -9
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +12 -13
- package/dist/setup/steps/stashdir.js +2 -3
- package/dist/setup/steps/tasks.js +237 -120
- package/dist/sources/freshness.js +1 -1
- 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 +25 -23
- package/dist/sources/providers/git-stash.js +395 -106
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +7 -4
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +6 -1
- package/dist/sources/resolve.js +6 -5
- package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
- package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
- package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
- package/dist/sources/snapshot-fetchers/github.js +100 -0
- package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
- package/dist/sources/snapshot-fetchers/registry.js +17 -1
- package/dist/sources/snapshot-fetchers/robots.js +348 -0
- package/dist/sources/snapshot-fetchers/rss.js +282 -0
- package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
- package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
- package/dist/sources/snapshot-fetchers/x.js +910 -0
- package/dist/storage/database.js +7 -0
- package/dist/storage/engines/sqlite-migrations.js +23 -111
- package/dist/storage/managed-db.js +2 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +27 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -12
- package/dist/storage/repositories/index-connection.js +17 -6
- package/dist/storage/repositories/index-entries-repository.js +151 -240
- package/dist/storage/repositories/index-entry-mapper.js +15 -11
- package/dist/storage/repositories/index-fts-repository.js +5 -2
- package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
- package/dist/storage/repositories/index-meta-repository.js +2 -3
- package/dist/storage/repositories/index-schema.js +10 -25
- package/dist/storage/repositories/index-utility-repository.js +15 -28
- package/dist/storage/repositories/index-vec-repository.js +6 -1
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +296 -59
- package/dist/storage/repositories/registry-cache.js +19 -0
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +15 -13
- package/dist/storage/repositories/workflow-runs-repository.js +52 -40
- package/dist/tasks/backends/cron.js +105 -15
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +85 -38
- package/dist/tasks/backends/schtasks.js +135 -15
- package/dist/tasks/embedded.js +56 -40
- package/dist/tasks/parser.js +7 -157
- package/dist/tasks/resolve-akm-bin.js +137 -59
- package/dist/tasks/runner.js +79 -42
- package/dist/tasks/scheduler-invocation.js +220 -10
- package/dist/tasks/schema.js +24 -1
- package/dist/tasks/task-id.js +1 -3
- package/dist/tasks/validator.js +20 -6
- package/dist/workflows/authoring/authoring.js +94 -143
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/exec/frozen-judge.js +28 -2
- package/dist/workflows/exec/native-executor.js +77 -57
- package/dist/workflows/exec/param-secrets.js +9 -9
- package/dist/workflows/exec/run-workflow.js +133 -79
- package/dist/workflows/exec/step-work.js +219 -346
- package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
- package/dist/workflows/ir/compile.js +141 -270
- package/dist/workflows/ir/freeze.js +40 -30
- package/dist/workflows/ir/params.js +135 -11
- package/dist/workflows/ir/plan-hash.js +1 -1
- package/dist/workflows/ir/schema.js +25 -26
- package/dist/workflows/parser.js +872 -307
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +7 -10
- package/dist/workflows/renderer.js +95 -68
- package/dist/workflows/resource-limits.js +2 -0
- package/dist/workflows/runtime/checkin.js +3 -3
- package/dist/workflows/runtime/plan-classifier.js +16 -75
- package/dist/workflows/runtime/runs.js +186 -127
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +2 -2
- package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +30 -36
- package/dist/workflows/validator.js +21 -62
- package/docs/README.md +68 -0
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.7.0.md +11 -11
- package/docs/migration/release-notes/0.9.0.md +208 -27
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +564 -208
- package/docs/migration/v0.9.0-troubleshooting.md +561 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/cli.md +2253 -0
- package/docs/reference/configuration.md +358 -0
- package/docs/reference/data-and-telemetry.md +105 -42
- package/docs/reference/workflows.md +647 -0
- package/package.json +22 -11
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +81 -128
- package/schemas/akm-workflow.json +74 -73
- package/dist/assets/tasks/core/backup.yml +0 -5
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/cli/config-migrate.js +0 -1806
- package/dist/cli/config-validate.js +0 -41
- package/dist/commands/backup-cli.js +0 -56
- package/dist/commands/bundle/bundle-cli.js +0 -68
- package/dist/commands/bundle/bundle.js +0 -219
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -489
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/mv-cli.js +0 -1221
- package/dist/commands/sources/history.js +0 -201
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/core/migration-backup.js +0 -1234
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/migrate/legacy/config-source-migration.js +0 -223
- package/dist/migrate/legacy/content-migration.js +0 -305
- package/dist/migrate/legacy/legacy-layout.js +0 -779
- package/dist/migrate/legacy/legacy-paths.js +0 -25
- package/dist/migrate/legacy/legacy-stash-json.js +0 -72
- package/dist/migrate/legacy/proposal-fs-import.js +0 -168
- package/dist/migrate/legacy/task-target-ref-migration.js +0 -272
- package/dist/migrate/legacy/three-db-cutover.js +0 -841
- package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
- package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
- package/dist/migrate/legacy-ref-grammar.js +0 -214
- 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/registry/build-index.js +0 -382
- package/dist/schemas/akm-config.json +0 -4704
- package/dist/schemas/akm-task.json +0 -87
- package/dist/schemas/akm-workflow.json +0 -372
- package/dist/scripts/migrate-storage.js +0 -3816
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/cli.js +0 -53
- package/dist/workflows/exec/brief.js +0 -481
- package/dist/workflows/exec/report.js +0 -1460
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -813
- package/dist/workflows/program/project.js +0 -104
|
@@ -4,84 +4,30 @@
|
|
|
4
4
|
import { UsageError } from "../../core/errors.js";
|
|
5
5
|
import { decodeCanonicalPlan } from "../ir/plan-hash.js";
|
|
6
6
|
import { WORKFLOW_IR_VERSION } from "../ir/schema.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)";
|
|
10
10
|
if (!row.plan_json) {
|
|
11
|
-
if (row.plan_ir_version === WORKFLOW_IR_VERSION) {
|
|
12
|
-
return {
|
|
13
|
-
support: "corrupt-plan",
|
|
14
|
-
irVersion: row.plan_ir_version,
|
|
15
|
-
error: `Workflow run ${runId} declares workflow IR version ${row.plan_ir_version} but has no frozen plan.`,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
support: row.plan_ir_version === null || row.plan_ir_version === undefined ? "missing-plan" : "unsupported-version",
|
|
20
|
-
irVersion: row.plan_ir_version ?? null,
|
|
21
|
-
error: row.plan_ir_version === null || row.plan_ir_version === undefined
|
|
22
|
-
? `Workflow run ${runId} has no executable workflow IR plan.`
|
|
23
|
-
: `Workflow run ${runId} uses unsupported workflow IR version ${String(row.plan_ir_version)} and has no frozen plan.`,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
let raw;
|
|
27
|
-
try {
|
|
28
|
-
raw = JSON.parse(row.plan_json);
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
if (row.plan_ir_version !== WORKFLOW_IR_VERSION) {
|
|
32
|
-
return {
|
|
33
|
-
support: row.plan_ir_version === null || row.plan_ir_version === undefined ? "missing-plan" : "unsupported-version",
|
|
34
|
-
irVersion: row.plan_ir_version ?? null,
|
|
35
|
-
error: `Workflow run ${runId} has malformed historical frozen plan JSON that cannot be executed.`,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
return {
|
|
39
|
-
support: "corrupt-plan",
|
|
40
|
-
irVersion: row.plan_ir_version ?? null,
|
|
41
|
-
error: `Workflow run ${runId} has corrupt frozen plan JSON.`,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
const decodedVersion = typeof raw === "object" && raw !== null ? raw.irVersion : null;
|
|
45
|
-
if (!Number.isSafeInteger(decodedVersion) || decodedVersion < 1) {
|
|
46
|
-
if (row.plan_ir_version !== WORKFLOW_IR_VERSION) {
|
|
47
|
-
return {
|
|
48
|
-
support: row.plan_ir_version === null || row.plan_ir_version === undefined ? "missing-plan" : "unsupported-version",
|
|
49
|
-
irVersion: row.plan_ir_version ?? null,
|
|
50
|
-
error: `Workflow run ${runId} has historical frozen plan data with no supported IR version.`,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
11
|
return {
|
|
54
|
-
support: "
|
|
12
|
+
support: "missing-plan",
|
|
55
13
|
irVersion: row.plan_ir_version ?? null,
|
|
56
|
-
error: `Workflow run ${runId} has
|
|
14
|
+
error: `Workflow run ${runId} has no frozen workflow plan.`,
|
|
57
15
|
};
|
|
58
16
|
}
|
|
59
|
-
if (row.plan_ir_version !== null &&
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
support: "unsupported-version",
|
|
63
|
-
irVersion: decodedVersion,
|
|
64
|
-
error: `Workflow run ${runId} uses unsupported workflow IR version ${String(decodedVersion)} with mismatched historical metadata.`,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
return {
|
|
68
|
-
support: "corrupt-plan",
|
|
69
|
-
irVersion: decodedVersion,
|
|
70
|
-
error: `Workflow run ${runId} has mismatched stored plan IR version (${String(row.plan_ir_version)} != ${String(decodedVersion)}).`,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
if (decodedVersion !== WORKFLOW_IR_VERSION) {
|
|
17
|
+
if (row.plan_ir_version !== null &&
|
|
18
|
+
row.plan_ir_version !== undefined &&
|
|
19
|
+
row.plan_ir_version !== WORKFLOW_IR_VERSION) {
|
|
74
20
|
return {
|
|
75
21
|
support: "unsupported-version",
|
|
76
|
-
irVersion:
|
|
77
|
-
error: `Workflow run ${runId} uses unsupported workflow IR 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}.`,
|
|
78
24
|
};
|
|
79
25
|
}
|
|
80
26
|
if (row.plan_ir_version !== WORKFLOW_IR_VERSION) {
|
|
81
27
|
return {
|
|
82
28
|
support: "corrupt-plan",
|
|
83
|
-
irVersion:
|
|
84
|
-
error: `Workflow run ${runId}
|
|
29
|
+
irVersion: null,
|
|
30
|
+
error: `Workflow run ${runId} does not declare workflow IR version ${WORKFLOW_IR_VERSION}.`,
|
|
85
31
|
};
|
|
86
32
|
}
|
|
87
33
|
try {
|
|
@@ -92,25 +38,20 @@ export function classifyWorkflowRunPlan(row) {
|
|
|
92
38
|
};
|
|
93
39
|
}
|
|
94
40
|
catch (cause) {
|
|
95
|
-
return {
|
|
41
|
+
return {
|
|
42
|
+
support: "corrupt-plan",
|
|
43
|
+
irVersion: WORKFLOW_IR_VERSION,
|
|
44
|
+
error: cause instanceof Error ? cause.message : String(cause),
|
|
45
|
+
};
|
|
96
46
|
}
|
|
97
47
|
}
|
|
98
|
-
/** Reject
|
|
48
|
+
/** Reject any operation that requires a valid current frozen plan. */
|
|
99
49
|
export function requireExecutableWorkflowPlan(row) {
|
|
100
50
|
const classified = classifyWorkflowRunPlan(row);
|
|
101
51
|
if (classified.support === "supported")
|
|
102
52
|
return classified.plan;
|
|
103
|
-
if (classified.support === "missing-plan" || classified.support === "unsupported-version") {
|
|
104
|
-
throw new UsageError(`${classified.error} This historical run is inspection-only; abandon it with \`akm workflow abandon ${row.id ?? "<run>"}\` and start a new run.`, "WORKFLOW_IR_VERSION_UNSUPPORTED");
|
|
105
|
-
}
|
|
106
53
|
throw new UsageError(classified.error, "INVALID_JSON_ARGUMENT");
|
|
107
54
|
}
|
|
108
|
-
/** Abandon is the sole mutation allowed for a historical run; corrupt v3 data is never mutated. */
|
|
109
|
-
export function requireAbandonableWorkflowPlan(row) {
|
|
110
|
-
const classified = classifyWorkflowRunPlan(row);
|
|
111
|
-
if (classified.support === "corrupt-plan")
|
|
112
|
-
throw new UsageError(classified.error, "INVALID_JSON_ARGUMENT");
|
|
113
|
-
}
|
|
114
55
|
/** Project persisted spine rows from the decoded plan, never from the mutable source asset. */
|
|
115
56
|
export function frozenStepRows(plan) {
|
|
116
57
|
return plan.steps.map((step) => ({
|
|
@@ -2,26 +2,27 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { parseBundleRef } from "../../core/asset/asset-ref.js";
|
|
5
6
|
import { loadConfig } from "../../core/config/config.js";
|
|
6
|
-
import { NotFoundError, UsageError } from "../../core/errors.js";
|
|
7
|
+
import { ConfigError, NotFoundError, UsageError } from "../../core/errors.js";
|
|
7
8
|
import { appendEvent } from "../../core/events.js";
|
|
8
|
-
import { canonicalizeWorkflowName } from "../../core/recognition-util.js";
|
|
9
9
|
import { warn } from "../../core/warn.js";
|
|
10
|
+
import { insertEventOnce } from "../../storage/repositories/events-repository.js";
|
|
10
11
|
import { withWorkflowRunsRepo, } from "../../storage/repositories/workflow-runs-repository.js";
|
|
11
12
|
import { getCurrentWorkflowScopeKey } from "../authoring/scope-key.js";
|
|
12
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";
|
|
15
16
|
import { compileResolveFreezeWorkflow } from "../ir/freeze.js";
|
|
16
|
-
import { validateWorkflowParams } from "../ir/params.js";
|
|
17
|
+
import { materializeWorkflowParameterFlags, validateWorkflowParams } from "../ir/params.js";
|
|
17
18
|
import { canonicalPlanJson, computePlanHash } from "../ir/plan-hash.js";
|
|
18
19
|
import { decodeWorkflowPlanV3, WORKFLOW_IR_VERSION } from "../ir/schema.js";
|
|
19
20
|
import { validateStepSummary } from "../validate-summary.js";
|
|
20
21
|
import { resolveAgentIdentity } from "./agent-identity.js";
|
|
21
22
|
import { evaluateCheckin } from "./checkin.js";
|
|
22
|
-
import { assertWorkflowSpineMatchesPlan, classifyWorkflowRunPlan, frozenStepRows,
|
|
23
|
+
import { assertWorkflowSpineMatchesPlan, classifyWorkflowRunPlan, frozenStepRows, requireExecutableWorkflowPlan, } from "./plan-classifier.js";
|
|
23
24
|
import { evaluateStaleUnits } from "./unit-checkin.js";
|
|
24
|
-
import {
|
|
25
|
+
import { canonicalizeWorkflowRefInput, loadWorkflowAsset, resolveWorkflowEntryId } from "./workflow-asset-loader.js";
|
|
25
26
|
/** Clip bound for a unit's `result_json` on the `--units` diagnostic surface. */
|
|
26
27
|
const UNIT_DIAGNOSTIC_CLIP = 2000;
|
|
27
28
|
function toUnitDiagnostic(row, stale, plannedEngine) {
|
|
@@ -61,7 +62,6 @@ function toUnitDiagnostic(row, stale, plannedEngine) {
|
|
|
61
62
|
engine: row.engine ?? null,
|
|
62
63
|
runtimeKind: row.engine && (row.runner === "llm" || row.runner === "agent" || row.runner === "sdk") ? row.runner : null,
|
|
63
64
|
platform: plannedEngine?.kind === "agent" ? plannedEngine.platform : null,
|
|
64
|
-
...(!row.engine && row.runner ? { legacyRunnerSelector: row.runner } : {}),
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
export async function startWorkflowRun(ref, params = {}, options) {
|
|
@@ -70,34 +70,39 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
70
70
|
// persist it on the run row in the same transaction as the insert. Every
|
|
71
71
|
// later invocation executes this snapshot — the asset file is never re-read
|
|
72
72
|
// for an in-flight run; re-planning is an explicit new run.
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
const frozen = compileResolveFreezeWorkflow(asset, loadConfig());
|
|
74
|
+
const plan = decodeWorkflowPlanV3(frozen.plan);
|
|
75
|
+
if (options?.parameterFlags?.length && Object.keys(params).length > 0) {
|
|
76
|
+
throw new UsageError("Workflow parameters must use either an object or per-parameter flags, not both.");
|
|
77
|
+
}
|
|
78
|
+
const effectiveParams = options?.parameterFlags?.length
|
|
79
|
+
? materializeWorkflowParameterFlags(plan, options.parameterFlags)
|
|
80
|
+
: params;
|
|
81
|
+
// Non-fatal WARNINGS: untyped-step and undeclared-param advisories surface
|
|
82
|
+
// as `warn()` lines at start (stderr, consistent with the repo's other
|
|
83
|
+
// author-facing warnings) without blocking the run.
|
|
84
|
+
for (const w of collectWorkflowWarnings(asset.document)) {
|
|
85
|
+
warn(`workflow run: ${asset.path}:${w.line} — ${w.message}`);
|
|
82
86
|
}
|
|
83
|
-
// Reviewer #12: validate supplied
|
|
87
|
+
// Reviewer #12: validate supplied parameters against the frozen param
|
|
84
88
|
// schemas BEFORE creating the run, so a type-mismatched param (e.g. a string
|
|
85
89
|
// for a `{ type: array }` param) is rejected with actionable errors instead
|
|
86
90
|
// of flowing silently into a unit prompt. Programs without declared param
|
|
87
91
|
// schemas (and every Markdown workflow) validate trivially.
|
|
88
|
-
const paramErrors = validateWorkflowParams(plan,
|
|
92
|
+
const paramErrors = validateWorkflowParams(plan, effectiveParams);
|
|
89
93
|
if (paramErrors.length > 0) {
|
|
90
|
-
throw new UsageError(`Cannot start ${asset.ref}: the supplied
|
|
94
|
+
throw new UsageError(`Cannot start ${asset.ref}: the supplied parameters do not satisfy the workflow's declared schemas:\n` +
|
|
91
95
|
paramErrors.map((e) => ` - ${e}`).join("\n"), "INVALID_JSON_ARGUMENT");
|
|
92
96
|
}
|
|
93
97
|
const planJson = canonicalPlanJson(plan);
|
|
94
98
|
const planHash = computePlanHash(plan);
|
|
99
|
+
const workflowRefs = await workflowRunRefSet(asset.ref, ref);
|
|
95
100
|
return withWorkflowRunsRepo(async (repo) => {
|
|
96
101
|
const now = new Date().toISOString();
|
|
97
102
|
const runId = randomUUID();
|
|
98
103
|
const scopeKey = getCurrentWorkflowScopeKey();
|
|
99
104
|
const currentStepId = plan.steps[0]?.stepId ?? null;
|
|
100
|
-
const workflowEntryId = resolveWorkflowEntryId(asset.sourcePath, asset.ref);
|
|
105
|
+
const workflowEntryId = resolveWorkflowEntryId(asset.sourcePath, asset.ref, asset.adapterId);
|
|
101
106
|
// Capture the agent harness + session driving this run. Explicit options
|
|
102
107
|
// win; otherwise fall back to best-effort environment detection. This is
|
|
103
108
|
// identity-only — no background thread or timer is started here.
|
|
@@ -107,27 +112,28 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
107
112
|
// Concurrency guard (#485): if an active run already exists in this
|
|
108
113
|
// (workflow_ref, scope_key) pair, refuse to create a parallel run unless
|
|
109
114
|
// `force: true` is set. Previously every call inserted unconditionally,
|
|
110
|
-
// so two terminals
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
const existing = repo.findActiveRunForScope(asset.ref, scopeKey);
|
|
114
|
-
if (existing) {
|
|
115
|
-
throw new UsageError(`Workflow ${asset.ref} already has an active run in this scope (id=${existing.id}, step=${existing.current_step_id ?? "—"}). ` +
|
|
116
|
-
`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");
|
|
117
|
-
}
|
|
118
|
-
}
|
|
115
|
+
// so two terminals starting the same workflow could leave two runs racing.
|
|
116
|
+
// The
|
|
117
|
+
// active-alias query and all inserts now share this immediate transaction.
|
|
119
118
|
// #506: arm a file-signal check-in (a timestamp, NOT a background thread —
|
|
120
119
|
// per the workflow-agent check-in ADR) so a stalled run can be
|
|
121
120
|
// re-targeted with a `continue` directive. The agent harness + session id
|
|
122
121
|
// are already resolved above (agentHarness/agentSessionId, from #501).
|
|
123
|
-
repo.
|
|
122
|
+
repo.immediateTransaction(() => {
|
|
123
|
+
if (!options?.force) {
|
|
124
|
+
const existing = repo.findActiveRunForScope(workflowRefs, scopeKey);
|
|
125
|
+
if (existing) {
|
|
126
|
+
throw new UsageError(`Workflow ${asset.ref} already has an active run in this scope (id=${existing.id}, step=${existing.current_step_id ?? "—"}). ` +
|
|
127
|
+
`Use 'akm workflow run ${asset.ref}' to resume it or 'akm workflow abandon ${existing.id}' to give up on it.`, "RESOURCE_ALREADY_EXISTS");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
124
130
|
repo.insertRun({
|
|
125
131
|
id: runId,
|
|
126
132
|
workflowRef: asset.ref,
|
|
127
133
|
scopeKey,
|
|
128
134
|
workflowEntryId,
|
|
129
135
|
workflowTitle: asset.title,
|
|
130
|
-
paramsJson: JSON.stringify(
|
|
136
|
+
paramsJson: JSON.stringify(effectiveParams),
|
|
131
137
|
currentStepId,
|
|
132
138
|
createdAt: now,
|
|
133
139
|
updatedAt: now,
|
|
@@ -143,19 +149,23 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
143
149
|
completionJson: step.completionJson,
|
|
144
150
|
sequenceIndex: step.sequenceIndex,
|
|
145
151
|
})));
|
|
146
|
-
// Same transaction as the insert: a run row never exists without its
|
|
147
|
-
// frozen plan (rows with NULL plan_json are pre-006 legacy runs).
|
|
152
|
+
// Same transaction as the insert: a run row never exists without its frozen plan.
|
|
148
153
|
repo.setRunPlan(runId, planJson, planHash, WORKFLOW_IR_VERSION);
|
|
149
154
|
});
|
|
150
155
|
const result = await getWorkflowStatus(runId);
|
|
151
156
|
// #13: params are declared non-secret (they are copied verbatim into every
|
|
152
157
|
// unit prompt and hashed into the unit identity, so they cannot be redacted
|
|
153
|
-
// without breaking
|
|
158
|
+
// without breaking replay determinism). Surface a loud, best-effort warning
|
|
154
159
|
// when a param LOOKS like a credential so the author moves it to an env
|
|
155
160
|
// binding. Advisory only — never blocks the start.
|
|
156
|
-
const secretWarnings = detectSecretShapedParams(
|
|
161
|
+
const secretWarnings = detectSecretShapedParams(effectiveParams);
|
|
157
162
|
if (secretWarnings.length > 0)
|
|
158
163
|
result.warnings = [...(result.warnings ?? []), ...secretWarnings];
|
|
164
|
+
// The implicit engine fallback is announced ONCE, here at run creation —
|
|
165
|
+
// the frozen plan records the engine actually used, so a resume never
|
|
166
|
+
// re-announces a decision it did not make.
|
|
167
|
+
if (frozen.engineAnnouncement)
|
|
168
|
+
result.warnings = [...(result.warnings ?? []), frozen.engineAnnouncement];
|
|
159
169
|
// 07 P1-B: emit only the run id + status — NOT the raw workflowTitle (which
|
|
160
170
|
// comes verbatim from the workflow asset's frontmatter and is therefore
|
|
161
171
|
// attacker-influenceable). Keeping raw titles out of the events stream
|
|
@@ -163,7 +173,7 @@ export async function startWorkflowRun(ref, params = {}, options) {
|
|
|
163
173
|
// into agent context.
|
|
164
174
|
appendEvent({
|
|
165
175
|
eventType: "workflow_started",
|
|
166
|
-
ref: ref,
|
|
176
|
+
ref: asset.ref,
|
|
167
177
|
metadata: { runId: result.run.id, status: result.run.status },
|
|
168
178
|
});
|
|
169
179
|
return result;
|
|
@@ -179,9 +189,9 @@ export async function getWorkflowStatus(runId, opts) {
|
|
|
179
189
|
// project each row, INCLUDING failures whose diagnostic text the
|
|
180
190
|
// deterministic evidence graph drops. Read-only; never mutates the run.
|
|
181
191
|
const rows = repo.getUnitsForRun(run.id);
|
|
182
|
-
// Codex round-3 finding B: run the
|
|
183
|
-
//
|
|
184
|
-
//
|
|
192
|
+
// Codex round-3 finding B: run the pure stale-claim evaluator (`now`
|
|
193
|
+
// injected for deterministic tests) so a unit left `running` by a process
|
|
194
|
+
// that died surfaces as stale here, not just as raw `running`.
|
|
185
195
|
const staleById = new Map(evaluateStaleUnits(rows, opts.now ?? Date.now()).map((u) => [u.unitId, u]));
|
|
186
196
|
const classified = classifyWorkflowRunPlan(run);
|
|
187
197
|
const engines = classified.support === "supported" ? classified.plan.execution?.engines : undefined;
|
|
@@ -194,36 +204,60 @@ export async function hasWorkflowRun(runId) {
|
|
|
194
204
|
return withWorkflowRunsRepo((repo) => repo.hasRun(runId));
|
|
195
205
|
}
|
|
196
206
|
export async function listWorkflowRuns(input) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
207
|
+
const scopeKey = getCurrentWorkflowScopeKey();
|
|
208
|
+
const activeOnly = input?.activeOnly === true;
|
|
209
|
+
if (input?.workflowRef === undefined) {
|
|
210
|
+
return withWorkflowRunsRepo((repo) => ({
|
|
211
|
+
runs: repo.listRuns({ scopeKey, ...(activeOnly ? { activeOnly: true } : {}) }).map(toWorkflowRunSummary),
|
|
212
|
+
}));
|
|
213
|
+
}
|
|
214
|
+
const exactRef = input.workflowRef.trim();
|
|
215
|
+
if (!exactRef) {
|
|
216
|
+
throw new UsageError("Workflow ref filter cannot be empty.", "INVALID_FLAG_VALUE");
|
|
217
|
+
}
|
|
218
|
+
const parsedExactRef = parseBundleRef(exactRef);
|
|
219
|
+
if (parsedExactRef.fragment !== undefined) {
|
|
220
|
+
throw new UsageError("Workflow ref filters do not accept fragments.", "INVALID_FLAG_VALUE");
|
|
221
|
+
}
|
|
222
|
+
let workflowRefs = [exactRef];
|
|
223
|
+
try {
|
|
224
|
+
const canonicalRef = await canonicalizeWorkflowSpecifier(exactRef);
|
|
225
|
+
workflowRefs = await workflowRunRefSet(canonicalRef, exactRef);
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
if (parsedExactRef.bundle !== undefined) {
|
|
229
|
+
const exactRows = await withWorkflowRunsRepo((repo) => repo.listRuns({ scopeKey, workflowRef: exactRef }));
|
|
230
|
+
if (exactRows.length === 0)
|
|
231
|
+
throw error;
|
|
232
|
+
return {
|
|
233
|
+
runs: exactRows.filter((row) => !activeOnly || row.status === "active").map(toWorkflowRunSummary),
|
|
234
|
+
};
|
|
206
235
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
236
|
+
if (!(error instanceof NotFoundError))
|
|
237
|
+
throw error;
|
|
238
|
+
}
|
|
239
|
+
return withWorkflowRunsRepo((repo) => ({
|
|
240
|
+
runs: repo
|
|
241
|
+
.listRuns({ scopeKey, workflowRefs, ...(activeOnly ? { activeOnly: true } : {}) })
|
|
242
|
+
.map(toWorkflowRunSummary),
|
|
243
|
+
}));
|
|
214
244
|
}
|
|
215
|
-
export async function getNextWorkflowStep(specifier, params) {
|
|
245
|
+
export async function getNextWorkflowStep(specifier, params, options) {
|
|
216
246
|
return withWorkflowRunsRepo(async (repo) => {
|
|
217
|
-
const { run, autoStarted } = await resolveRunSpecifier(repo, specifier, params);
|
|
247
|
+
const { run, autoStarted, startWarnings } = await resolveRunSpecifier(repo, specifier, params, options?.parameterFlags);
|
|
218
248
|
const steps = readWorkflowRunSteps(repo, run.id);
|
|
219
249
|
const plan = requireExecutableWorkflowPlan(run);
|
|
220
250
|
assertWorkflowSpineMatchesPlan(plan, run, steps);
|
|
221
|
-
return {
|
|
251
|
+
return {
|
|
252
|
+
...projectNextResult(run, steps),
|
|
253
|
+
...(autoStarted ? { autoStarted: true } : {}),
|
|
254
|
+
...(startWarnings?.length ? { startWarnings } : {}),
|
|
255
|
+
};
|
|
222
256
|
});
|
|
223
257
|
}
|
|
224
258
|
/**
|
|
225
259
|
* Project a run row + its step rows into a {@link WorkflowNextResult}. The pure
|
|
226
|
-
* read-shaping half of {@link getNextWorkflowStep}, extracted so the
|
|
260
|
+
* read-shaping half of {@link getNextWorkflowStep}, extracted so the run
|
|
227
261
|
* snapshot below reproduces the exact same projection without re-running the
|
|
228
262
|
* auto-start-capable {@link resolveRunSpecifier}.
|
|
229
263
|
*/
|
|
@@ -251,27 +285,6 @@ function projectNextResult(run, steps) {
|
|
|
251
285
|
...(checkin ? { checkin } : {}),
|
|
252
286
|
};
|
|
253
287
|
}
|
|
254
|
-
/**
|
|
255
|
-
* A consistent point-in-time snapshot of a run for the harness-neutral driver
|
|
256
|
-
* protocol (PR #714 review round 2, #14). `brief`/`report` previously read the
|
|
257
|
-
* spine (`getNextWorkflowStep`) and then, in a SEPARATE connection, the run row
|
|
258
|
-
* + unit journal — so a concurrent `report`/`run`/manual completion could change
|
|
259
|
-
* the active step BETWEEN the two reads, leaving the described work-list
|
|
260
|
-
* inconsistent with the run row it was stamped against. This reads the run row,
|
|
261
|
-
* its steps, AND its unit rows inside ONE transaction (one connection, one
|
|
262
|
-
* snapshot) so all three agree. It never auto-starts — `runId` must already
|
|
263
|
-
* resolve to a concrete run — because the driver protocol never mutates on read.
|
|
264
|
-
*/
|
|
265
|
-
export async function snapshotRunForDriver(runId) {
|
|
266
|
-
return withWorkflowRunsRepo((repo) => repo.transaction(() => {
|
|
267
|
-
const run = readWorkflowRun(repo, runId);
|
|
268
|
-
const steps = readWorkflowRunSteps(repo, run.id);
|
|
269
|
-
const plan = requireExecutableWorkflowPlan(run);
|
|
270
|
-
assertWorkflowSpineMatchesPlan(plan, run, steps);
|
|
271
|
-
const units = repo.getUnitsForRun(run.id);
|
|
272
|
-
return { next: projectNextResult(run, steps), run, units };
|
|
273
|
-
}));
|
|
274
|
-
}
|
|
275
288
|
export async function resumeWorkflowRun(runId) {
|
|
276
289
|
return withWorkflowRunsRepo((repo) => {
|
|
277
290
|
const run = readWorkflowRun(repo, runId);
|
|
@@ -306,23 +319,24 @@ export async function resumeWorkflowRun(runId) {
|
|
|
306
319
|
*/
|
|
307
320
|
export async function abandonWorkflowRun(runId) {
|
|
308
321
|
return withWorkflowRunsRepo((repo) => {
|
|
309
|
-
const run = readWorkflowRun(repo, runId);
|
|
310
|
-
requireAbandonableWorkflowPlan(run);
|
|
311
|
-
const classified = classifyWorkflowRunPlan(run);
|
|
312
|
-
const existingSteps = readWorkflowRunSteps(repo, run.id);
|
|
313
|
-
if (classified.support === "supported")
|
|
314
|
-
assertWorkflowSpineMatchesPlan(classified.plan, run, existingSteps);
|
|
315
|
-
if (run.status === "completed" || run.status === "failed") {
|
|
316
|
-
throw new UsageError(`Workflow run ${run.id} is already ${run.status}.`);
|
|
317
|
-
}
|
|
318
322
|
const now = new Date().toISOString();
|
|
319
|
-
repo.
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
323
|
+
const run = repo.immediateTransaction((db) => {
|
|
324
|
+
const current = readWorkflowRun(repo, runId);
|
|
325
|
+
if (current.status === "completed" || current.status === "failed") {
|
|
326
|
+
throw new UsageError(`Workflow run ${current.id} is already ${current.status}.`);
|
|
327
|
+
}
|
|
328
|
+
if (!repo.markRunAbandoned(current.id, now)) {
|
|
329
|
+
throw new UsageError(`Workflow run ${current.id} is ${current.status} and cannot be abandoned.`);
|
|
330
|
+
}
|
|
331
|
+
insertEventOnce(db, {
|
|
332
|
+
eventType: "workflow_abandoned",
|
|
333
|
+
ts: now,
|
|
334
|
+
ref: current.workflow_ref,
|
|
335
|
+
metadata: { runId: current.id },
|
|
336
|
+
idempotencyKey: current.id,
|
|
337
|
+
idempotencyMetadataKey: "runId",
|
|
338
|
+
});
|
|
339
|
+
return current;
|
|
326
340
|
});
|
|
327
341
|
const updated = {
|
|
328
342
|
...run,
|
|
@@ -333,9 +347,6 @@ export async function abandonWorkflowRun(runId) {
|
|
|
333
347
|
};
|
|
334
348
|
const steps = readWorkflowRunSteps(repo, run.id);
|
|
335
349
|
const detail = buildWorkflowRunDetail(updated, steps);
|
|
336
|
-
// Same injectable-footprint rule as workflow_started (07 P1-B): ids and
|
|
337
|
-
// status only, never the frontmatter-derived title.
|
|
338
|
-
appendEvent({ eventType: "workflow_abandoned", ref: run.workflow_ref, metadata: { runId: run.id } });
|
|
339
350
|
return detail;
|
|
340
351
|
});
|
|
341
352
|
}
|
|
@@ -371,15 +382,20 @@ export async function completeWorkflowStep(input) {
|
|
|
371
382
|
if (input.status === "completed" && !summary) {
|
|
372
383
|
throw new UsageError(`Completing step "${input.stepId}" requires a --summary describing the work done.`, "MISSING_REQUIRED_ARGUMENT");
|
|
373
384
|
}
|
|
374
|
-
// #506: validation gate —
|
|
375
|
-
//
|
|
376
|
-
// judge. Only a well-formed `complete: false` blocks completion.
|
|
385
|
+
// #506: validation gate — a criteria-bearing step must have a frozen judge
|
|
386
|
+
// and receive an affirmative verdict before it can advance.
|
|
377
387
|
if (input.status === "completed" && summary) {
|
|
378
388
|
const criteria = preflight.stepPlan.gate.criteria;
|
|
389
|
+
if (input.signal?.aborted)
|
|
390
|
+
throw interruptionReason(input.signal);
|
|
379
391
|
const judge = input.summaryJudge === undefined
|
|
380
|
-
? frozenSummaryJudge(preflight.plan, preflight.stepPlan.gate.judge)
|
|
392
|
+
? frozenSummaryJudge(preflight.plan, preflight.stepPlan.gate.judge, input.signal)
|
|
381
393
|
: input.summaryJudge;
|
|
382
|
-
|
|
394
|
+
if (criteria.length > 0 && !judge) {
|
|
395
|
+
throw new ConfigError(`Workflow run ${input.runId} has completion criteria for step "${input.stepId}" but its frozen plan has no judge. ` +
|
|
396
|
+
"Set workflow.judgeEngine, abandon this run, and create a new one with `akm workflow run <ref>`.", "INVALID_CONFIG_FILE");
|
|
397
|
+
}
|
|
398
|
+
const verdict = await validateStepSummary({ stepTitle: preflight.stepPlan.title, completionCriteria: criteria, summary }, judge ?? undefined, input.signal);
|
|
383
399
|
if (!verdict.complete) {
|
|
384
400
|
// Re-arm the check-in so a subsequent stall is still nudged, but leave the
|
|
385
401
|
// step pending and return corrective feedback instead of completing.
|
|
@@ -392,12 +408,11 @@ export async function completeWorkflowStep(input) {
|
|
|
392
408
|
stepId: input.stepId,
|
|
393
409
|
missing: verdict.missing,
|
|
394
410
|
feedback: verdict.feedback ?? "The summary does not satisfy the step's completion criteria.",
|
|
395
|
-
// A REQUIRED gate that could not be judged (finding A): the caller BLOCKS
|
|
396
|
-
// rather than treating this as a normal, retryable gate rejection.
|
|
397
|
-
...(verdict.errored ? { errored: true } : {}),
|
|
398
411
|
};
|
|
399
412
|
}
|
|
400
413
|
}
|
|
414
|
+
if (input.signal?.aborted)
|
|
415
|
+
throw interruptionReason(input.signal);
|
|
401
416
|
return withWorkflowRunsRepo((repo) => {
|
|
402
417
|
let updatedRun;
|
|
403
418
|
let refreshedSteps = [];
|
|
@@ -423,6 +438,8 @@ export async function completeWorkflowStep(input) {
|
|
|
423
438
|
if (run.current_step_id !== existing.step_id) {
|
|
424
439
|
throw new UsageError(`Step "${input.stepId}" is not the current step for workflow run ${run.id}. Complete "${run.current_step_id}" first.`);
|
|
425
440
|
}
|
|
441
|
+
if (input.signal?.aborted)
|
|
442
|
+
throw interruptionReason(input.signal);
|
|
426
443
|
const completedAt = new Date().toISOString();
|
|
427
444
|
repo.updateStepCompletion({
|
|
428
445
|
status: input.status,
|
|
@@ -472,34 +489,76 @@ export async function completeWorkflowStep(input) {
|
|
|
472
489
|
return detail;
|
|
473
490
|
});
|
|
474
491
|
}
|
|
475
|
-
async function resolveRunSpecifier(repo, specifier, params) {
|
|
492
|
+
async function resolveRunSpecifier(repo, specifier, params, parameterFlags) {
|
|
493
|
+
const hasParameters = (params && Object.keys(params).length > 0) || (parameterFlags?.length ?? 0) > 0;
|
|
476
494
|
const explicitRun = repo.getRunById(specifier);
|
|
477
495
|
if (explicitRun) {
|
|
478
|
-
if (
|
|
479
|
-
throw new UsageError(
|
|
496
|
+
if (hasParameters) {
|
|
497
|
+
throw new UsageError(`Workflow parameter flags can only be used when starting a new run, not with existing run id "${specifier}".`);
|
|
480
498
|
}
|
|
481
499
|
return { run: explicitRun, autoStarted: false };
|
|
482
500
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
501
|
+
const scopeKey = getCurrentWorkflowScopeKey();
|
|
502
|
+
const exactRef = specifier.trim();
|
|
503
|
+
const parsedExact = parseBundleRef(exactRef);
|
|
504
|
+
const qualifiedExact = parsedExact.bundle !== undefined && parsedExact.fragment === undefined;
|
|
505
|
+
const detached = qualifiedExact ? repo.getActiveRunRowForScope(exactRef, scopeKey) : undefined;
|
|
506
|
+
let ref;
|
|
507
|
+
try {
|
|
508
|
+
ref = await canonicalizeWorkflowSpecifier(specifier);
|
|
487
509
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
510
|
+
catch (error) {
|
|
511
|
+
if (detached) {
|
|
512
|
+
if (hasParameters) {
|
|
513
|
+
throw new UsageError(`Workflow parameter flags can only be set on a new run; ${specifier} is already active.`);
|
|
514
|
+
}
|
|
515
|
+
return { run: detached, autoStarted: false };
|
|
516
|
+
}
|
|
517
|
+
if (error instanceof NotFoundError && !specifier.includes(":") && !specifier.includes("/")) {
|
|
518
|
+
throw new NotFoundError(`Workflow run or workflow "${specifier}" not found.`, "WORKFLOW_NOT_FOUND");
|
|
519
|
+
}
|
|
520
|
+
throw error;
|
|
491
521
|
}
|
|
492
|
-
const
|
|
493
|
-
const scopeKey = getCurrentWorkflowScopeKey();
|
|
494
|
-
const active = repo.getActiveRunRowForScope(ref, scopeKey);
|
|
522
|
+
const active = repo.getActiveRunRowForScope(await workflowRunRefSet(ref, exactRef), scopeKey);
|
|
495
523
|
if (active) {
|
|
496
|
-
if (
|
|
497
|
-
throw new UsageError(
|
|
524
|
+
if (hasParameters) {
|
|
525
|
+
throw new UsageError(`Workflow parameter flags can only be set on a new run; ${ref} is already active.`);
|
|
498
526
|
}
|
|
499
527
|
return { run: active, autoStarted: false };
|
|
500
528
|
}
|
|
501
|
-
const started = await startWorkflowRun(ref, params ?? {}
|
|
502
|
-
|
|
529
|
+
const started = await startWorkflowRun(ref, params ?? {}, {
|
|
530
|
+
...(parameterFlags !== undefined ? { parameterFlags } : {}),
|
|
531
|
+
});
|
|
532
|
+
return {
|
|
533
|
+
run: readWorkflowRun(repo, started.run.id),
|
|
534
|
+
autoStarted: true,
|
|
535
|
+
...(started.warnings?.length ? { startWarnings: started.warnings } : {}),
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
function interruptionReason(signal) {
|
|
539
|
+
return signal.reason instanceof Error ? signal.reason : new Error("Workflow run interrupted.");
|
|
540
|
+
}
|
|
541
|
+
async function canonicalizeWorkflowSpecifier(specifier) {
|
|
542
|
+
return canonicalizeWorkflowRefInput(specifier);
|
|
543
|
+
}
|
|
544
|
+
async function workflowRunRefSet(canonicalRef, exactRef) {
|
|
545
|
+
const parsed = parseBundleRef(canonicalRef);
|
|
546
|
+
const refs = new Set([canonicalRef, exactRef.trim()]);
|
|
547
|
+
const exact = parseBundleRef(exactRef.trim());
|
|
548
|
+
if (exact.bundle === undefined) {
|
|
549
|
+
refs.add(parsed.conceptId);
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
try {
|
|
553
|
+
if ((await canonicalizeWorkflowSpecifier(parsed.conceptId)) === canonicalRef)
|
|
554
|
+
refs.add(parsed.conceptId);
|
|
555
|
+
}
|
|
556
|
+
catch (error) {
|
|
557
|
+
if (!(error instanceof NotFoundError))
|
|
558
|
+
throw error;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return [...refs];
|
|
503
562
|
}
|
|
504
563
|
function readWorkflowRun(repo, runId) {
|
|
505
564
|
const run = repo.getRunById(runId);
|
|
@@ -513,7 +572,7 @@ function readWorkflowRunSteps(repo, runId) {
|
|
|
513
572
|
}
|
|
514
573
|
function buildWorkflowRunDetail(run, steps) {
|
|
515
574
|
// Review M1: `workflow status` (and every other detail-shaped response) now
|
|
516
|
-
// evaluates the check-in, not just `workflow
|
|
575
|
+
// evaluates the check-in, not just `workflow run`. Pure timestamp check —
|
|
517
576
|
// no background thread (see checkin.ts).
|
|
518
577
|
const checkin = evaluateCheckin({
|
|
519
578
|
status: run.status,
|
|
@@ -551,7 +610,7 @@ function toWorkflowRunSummary(run) {
|
|
|
551
610
|
planIrVersion: plan.irVersion,
|
|
552
611
|
executionSupport: plan.support,
|
|
553
612
|
// Surface the engine lease (holder id + expiry — never workflow-authored
|
|
554
|
-
// content) so `workflow
|
|
613
|
+
// content) so `workflow run`/`status` show who is driving the run.
|
|
555
614
|
...(run.engine_lease_holder && run.engine_lease_until
|
|
556
615
|
? { engineLease: { holder: run.engine_lease_holder, until: run.engine_lease_until } }
|
|
557
616
|
: {}),
|
|
@@ -560,7 +619,7 @@ function toWorkflowRunSummary(run) {
|
|
|
560
619
|
/**
|
|
561
620
|
* Single-driver enforcement (R2 run lease): while a LIVE (unexpired) engine
|
|
562
621
|
* lease is held, only the holding engine may advance the gate spine. Manual
|
|
563
|
-
*
|
|
622
|
+
* A call with no `leaseHolder` — or a stale engine invocation
|
|
564
623
|
* whose lease was claimed by another — is refused with the holder + expiry.
|
|
565
624
|
* An EXPIRED lease never blocks: the engine that held it is presumed dead.
|
|
566
625
|
*/
|