akm-cli 0.9.0-rc.0 → 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 +1283 -22
- 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/prompts/workflow-unit-preamble.md +26 -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 +99 -0
- package/dist/commands/env/env-cli.js +84 -224
- 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/migration-help.js +7 -4
- 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 +232 -121
- 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 -834
- 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/json-schema.js +142 -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 -34
- 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 -56
- 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 +16 -2
- package/dist/integrations/agent/profiles.js +36 -62
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +93 -4
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +88 -196
- package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
- package/dist/integrations/harnesses/aider/index.js +48 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
- package/dist/integrations/harnesses/amazonq/index.js +45 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +24 -35
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
- package/dist/integrations/harnesses/codex/index.js +52 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
- package/dist/integrations/harnesses/copilot/index.js +48 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
- package/dist/integrations/harnesses/gemini/index.js +48 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +54 -34
- 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 +14 -32
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
- package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
- package/dist/integrations/harnesses/openhands/index.js +48 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
- package/dist/integrations/harnesses/pi/index.js +45 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +43 -32
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +36 -39
- 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 +14 -279
- 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 +11 -39
- 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 -1164
- 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 +3 -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 +240 -19
- 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/text-import-hook.mjs +1 -1
- package/dist/workflows/authoring/authoring.js +104 -43
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -16
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +450 -0
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +1038 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1460 -0
- package/dist/workflows/exec/run-workflow.js +602 -0
- package/dist/workflows/exec/scheduler.js +71 -0
- package/dist/workflows/exec/step-work.js +1190 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +246 -0
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +68 -0
- package/dist/workflows/ir/schema.js +540 -0
- package/dist/workflows/parser.js +878 -304
- package/dist/workflows/program/expressions.js +181 -0
- package/dist/workflows/program/schema.js +51 -0
- package/dist/workflows/renderer.js +100 -45
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +376 -119
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +2 -3
- 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/schemas/akm-workflow.json +373 -0
- 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 -259
- 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 -1413
- 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 -49
- 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/scripts/migrate-storage.js +0 -19108
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
- 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/db.js +0 -215
- package/docs/data-and-telemetry.md +0 -226
- /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,23 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Serialized writer queue for `workflow_run_units` (orchestration plan,
|
|
6
|
+
* *Persistence changes*).
|
|
7
|
+
*
|
|
8
|
+
* `withWorkflowRunsRepo` opens a fresh SQLite connection per call, so N
|
|
9
|
+
* parallel units completing at once would contend on SQLite's single writer
|
|
10
|
+
* and burn the 30 s busy_timeout. Bun is single-threaded, so a promise-chained
|
|
11
|
+
* in-process queue is sufficient: every unit write is appended to one chain
|
|
12
|
+
* and executes strictly in enqueue order. Reads and gate evaluation stay OFF
|
|
13
|
+
* this queue — only writes serialize.
|
|
14
|
+
*
|
|
15
|
+
* A failed write rejects its own caller but never wedges the chain.
|
|
16
|
+
*/
|
|
17
|
+
let tail = Promise.resolve();
|
|
18
|
+
export function enqueueUnitWrite(fn) {
|
|
19
|
+
const run = tail.then(() => fn());
|
|
20
|
+
// Keep the chain alive regardless of individual outcomes.
|
|
21
|
+
tail = run.then(() => undefined, () => undefined);
|
|
22
|
+
return run;
|
|
23
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* The `akm workflow` engine gate (`experimental.workflowEngine`, Q-05).
|
|
6
|
+
*
|
|
7
|
+
* Mirrors the shape of `src/commands/improve/autonomy-gate.ts` (D8) for a
|
|
8
|
+
* different failure mode. `akm improve`'s gated lanes have a safe downgrade —
|
|
9
|
+
* skip the lane, keep the rest of the run going — but a workflow step either
|
|
10
|
+
* executes or it does not: there is no partial-execution fallback to degrade
|
|
11
|
+
* into. So this gate REFUSES outright rather than silently skipping: an
|
|
12
|
+
* ungated call throws a classified `ConfigError` naming the exact config key,
|
|
13
|
+
* which the CLI's JSON error envelope (`emitJsonError`, `src/cli/shared.ts`)
|
|
14
|
+
* always routes to stderr with a non-zero exit — in every `--format`, not
|
|
15
|
+
* just `json` — so the refusal is visible and never a silent no-op. (A
|
|
16
|
+
* second, plain-text `warn()` call alongside the throw was deliberately
|
|
17
|
+
* rejected: it would interleave non-JSON text with the JSON error envelope on
|
|
18
|
+
* the SAME stream, corrupting stderr for any `--json` caller — a real defect,
|
|
19
|
+
* not just a test inconvenience.)
|
|
20
|
+
*
|
|
21
|
+
* Gated surfaces:
|
|
22
|
+
* - `akm workflow run` — the native step-execution engine
|
|
23
|
+
* - `akm workflow brief` — the harness-neutral driver protocol (read half)
|
|
24
|
+
* - `akm workflow report` — the harness-neutral driver protocol (write half)
|
|
25
|
+
*
|
|
26
|
+
* Deliberately NOT gated: authoring/linting the unified markdown format and
|
|
27
|
+
* the manual workflow CLI contract (`start`, `next`, `complete`, `status`,
|
|
28
|
+
* `list`, `create`, `resume`, `abandon`) remain stable per STABILITY.md.
|
|
29
|
+
*/
|
|
30
|
+
import { ConfigError } from "../../core/errors.js";
|
|
31
|
+
/**
|
|
32
|
+
* The config key an operator sets to enable the workflow engine.
|
|
33
|
+
*
|
|
34
|
+
* Named rather than inlined because it is user-facing text: it goes into the
|
|
35
|
+
* thrown error's message and `akm task doctor`, and those must name the same
|
|
36
|
+
* key as the schema.
|
|
37
|
+
*/
|
|
38
|
+
export const WORKFLOW_ENGINE_CONFIG_KEY = "experimental.workflowEngine";
|
|
39
|
+
/**
|
|
40
|
+
* True only when the user has explicitly opted into the workflow engine.
|
|
41
|
+
* Absent, an absent `experimental` section, and an explicit `false` all read
|
|
42
|
+
* as off — the engine is never enabled by inference.
|
|
43
|
+
*/
|
|
44
|
+
export function isWorkflowEngineEnabled(config) {
|
|
45
|
+
return config?.experimental?.workflowEngine === true;
|
|
46
|
+
}
|
|
47
|
+
/** The message shown to the user AND matched by tests naming the config key. */
|
|
48
|
+
export function workflowEngineGateMessage(surface) {
|
|
49
|
+
return (`\`akm workflow ${surface}\` is EXPERIMENTAL and refuses to run until ` +
|
|
50
|
+
`\`${WORKFLOW_ENGINE_CONFIG_KEY}\` is set. Run \`akm config set ${WORKFLOW_ENGINE_CONFIG_KEY} true\` to enable it.`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Refuse a gated workflow-engine surface unless the opt-in is set.
|
|
54
|
+
*
|
|
55
|
+
* `surface` is the human name of the subcommand/action being refused (e.g.
|
|
56
|
+
* `"run"`, `"brief"`, `"create <name>.yaml"`) — it is folded into the thrown
|
|
57
|
+
* error's message so the refusal names both the surface and the exact config
|
|
58
|
+
* key that would enable it. The throw alone is the whole mechanism: every
|
|
59
|
+
* command defined with `defineJsonCommand` routes an uncaught throw through
|
|
60
|
+
* `runWithJsonErrors`/`emitJsonError`, which prints the error to stderr and
|
|
61
|
+
* exits non-zero regardless of `--format` — so this is never a silent no-op.
|
|
62
|
+
*/
|
|
63
|
+
export function requireWorkflowEngineEnabled(config, surface) {
|
|
64
|
+
if (isWorkflowEngineEnabled(config))
|
|
65
|
+
return;
|
|
66
|
+
throw new ConfigError(workflowEngineGateMessage(surface), "WORKFLOW_ENGINE_NOT_ENABLED");
|
|
67
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Git worktree lifecycle for `isolation: worktree` units (redesign addendum,
|
|
6
|
+
* R2). Parallel file-mutating units on the agent/sdk runners each get a
|
|
7
|
+
* fresh DETACHED worktree of the run's base repository under a run-scoped
|
|
8
|
+
* tmp directory, so concurrent units can never trample each other's working
|
|
9
|
+
* tree. Lifecycle (driven by the native executor per journaled attempt):
|
|
10
|
+
*
|
|
11
|
+
* 1. {@link assertGitWorkTree} — preflight, once per step: a non-git base
|
|
12
|
+
* directory fails the step cleanly before anything dispatches.
|
|
13
|
+
* 2. {@link createUnitWorktree} — `git worktree add --detach` into
|
|
14
|
+
* `<tmp>/akm-worktrees/<runId>/<attemptId>`; the path is journaled on
|
|
15
|
+
* the unit row (`workflow_run_units.worktree_path`, migration 004) and
|
|
16
|
+
* passed to dispatch as the unit's cwd.
|
|
17
|
+
* 3. {@link cleanupUnitWorktree} — after the unit finishes:
|
|
18
|
+
* `git status --porcelain` CLEAN → the worktree is removed;
|
|
19
|
+
* DIRTY → it is RETAINED (the caller logs the path) so uncollected work
|
|
20
|
+
* is never destroyed.
|
|
21
|
+
*
|
|
22
|
+
* What "uncollected work" means (the honest contract): the clean probe is
|
|
23
|
+
* `git status --porcelain` WITHOUT `--ignored`, so it counts tracked-file
|
|
24
|
+
* modifications and untracked *unignored* files, but NOT files the base repo's
|
|
25
|
+
* own `.gitignore` matches (build outputs, caches, logs, dependency dirs such
|
|
26
|
+
* as `node_modules`/`dist`). Those ignored files are DISPOSABLE BY DEFINITION
|
|
27
|
+
* — the repository already declares them regenerable — so a worktree whose only
|
|
28
|
+
* residue is ignored files probes clean and IS removed. This is deliberate:
|
|
29
|
+
* adding `--ignored` would retain a worktree after essentially every unit that
|
|
30
|
+
* ran a package install or a build (the ignored `node_modules`/`dist` tree),
|
|
31
|
+
* blowing up disk under the run-scoped tmp root. Work a unit needs preserved
|
|
32
|
+
* must therefore be tracked or untracked-unignored; anything the workflow
|
|
33
|
+
* repo has chosen to `.gitignore` is treated as throwaway.
|
|
34
|
+
*
|
|
35
|
+
* All git invocations are `spawnSync` (the repo-wide pattern for git
|
|
36
|
+
* shell-outs) with explicit timeouts; this module never throws — every
|
|
37
|
+
* operation returns a result object so the executor maps failures onto its
|
|
38
|
+
* own step/unit failure vocabulary.
|
|
39
|
+
*/
|
|
40
|
+
import { spawnSync } from "node:child_process";
|
|
41
|
+
import fs from "node:fs";
|
|
42
|
+
import os from "node:os";
|
|
43
|
+
import path from "node:path";
|
|
44
|
+
const GIT_TIMEOUT_MS = 30_000;
|
|
45
|
+
/** Run one git command; `ok` = exit 0. Never throws (spawn errors → ok: false). */
|
|
46
|
+
function git(cwd, args) {
|
|
47
|
+
const result = spawnSync("git", ["-C", cwd, ...args], { encoding: "utf8", timeout: GIT_TIMEOUT_MS });
|
|
48
|
+
if (result.error) {
|
|
49
|
+
return { ok: false, stdout: "", error: `git ${args[0]} failed to spawn: ${result.error.message}` };
|
|
50
|
+
}
|
|
51
|
+
if (result.status !== 0) {
|
|
52
|
+
const detail = (result.stderr || result.stdout || "").trim();
|
|
53
|
+
return {
|
|
54
|
+
ok: false,
|
|
55
|
+
stdout: result.stdout ?? "",
|
|
56
|
+
error: `git ${args.join(" ")} exited ${result.status}${detail ? `: ${detail}` : ""}`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return { ok: true, stdout: result.stdout ?? "" };
|
|
60
|
+
}
|
|
61
|
+
/** True when a usable `git` binary is on PATH (tests skip gracefully without one). */
|
|
62
|
+
export function isGitAvailable() {
|
|
63
|
+
const result = spawnSync("git", ["--version"], { encoding: "utf8", timeout: 5_000 });
|
|
64
|
+
return !result.error && result.status === 0;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Preflight for worktree isolation: `dir` must be inside a git work tree.
|
|
68
|
+
* Returns an error message (for a clean step failure) or undefined when ok.
|
|
69
|
+
* A missing git binary reports as the same clean failure — a workflow that
|
|
70
|
+
* declares isolation cannot run without git.
|
|
71
|
+
*/
|
|
72
|
+
export function assertGitWorkTree(dir) {
|
|
73
|
+
const result = git(dir, ["rev-parse", "--is-inside-work-tree"]);
|
|
74
|
+
if (!result.ok) {
|
|
75
|
+
return `"${dir}" is not a git repository (isolation: worktree requires one): ${result.error}`;
|
|
76
|
+
}
|
|
77
|
+
if (result.stdout.trim() !== "true") {
|
|
78
|
+
return `"${dir}" is not inside a git work tree (isolation: worktree requires one).`;
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
/** Journal-safe directory name for a unit attempt id (ids carry `:` / `~`). */
|
|
83
|
+
function sanitizeAttemptId(attemptId) {
|
|
84
|
+
return attemptId.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
85
|
+
}
|
|
86
|
+
/** Run-scoped parent directory for all of one run's unit worktrees. */
|
|
87
|
+
export function runWorktreeRoot(runId) {
|
|
88
|
+
return path.join(os.tmpdir(), "akm-worktrees", runId);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Move a leftover attempt directory aside to `<dest>.retained-<ts>[-n]`
|
|
92
|
+
* (never overwriting an earlier retained copy). Throws on fs errors — the
|
|
93
|
+
* caller maps them onto its result object.
|
|
94
|
+
*/
|
|
95
|
+
function moveLeftoverAside(dest) {
|
|
96
|
+
const base = `${dest}.retained-${Date.now()}`;
|
|
97
|
+
let aside = base;
|
|
98
|
+
for (let n = 1; fs.existsSync(aside); n++)
|
|
99
|
+
aside = `${base}-${n}`;
|
|
100
|
+
fs.renameSync(dest, aside);
|
|
101
|
+
return aside;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Create a fresh DETACHED worktree of `baseDir`'s repository at
|
|
105
|
+
* `<tmp>/akm-worktrees/<runId>/<attemptId>` (detached HEAD — no branch is
|
|
106
|
+
* minted, so parallel units cannot collide on branch names).
|
|
107
|
+
*
|
|
108
|
+
* A leftover directory at the attempt path (a RETAINED dirty worktree from a
|
|
109
|
+
* prior invocation, or a crashed attempt's partial state) is handled with the
|
|
110
|
+
* same never-destroy-unverified-work rule as {@link cleanupUnitWorktree}:
|
|
111
|
+
* `git status --porcelain` CLEAN → removed; DIRTY or unverifiable (the probe
|
|
112
|
+
* fails — e.g. a half-created directory that is no longer a valid worktree)
|
|
113
|
+
* → moved aside to `<dest>.retained-<ts>` and reported via
|
|
114
|
+
* `preservedLeftover` so the caller can log where the work went. Either way
|
|
115
|
+
* `git worktree prune` clears the stale registration before re-creating.
|
|
116
|
+
*/
|
|
117
|
+
export function createUnitWorktree(baseDir, runId, attemptId) {
|
|
118
|
+
const dest = path.join(runWorktreeRoot(runId), sanitizeAttemptId(attemptId));
|
|
119
|
+
let preservedLeftover;
|
|
120
|
+
try {
|
|
121
|
+
if (fs.existsSync(dest)) {
|
|
122
|
+
const status = git(dest, ["status", "--porcelain"]);
|
|
123
|
+
if (status.ok && status.stdout.trim() === "") {
|
|
124
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
preservedLeftover = moveLeftoverAside(dest);
|
|
128
|
+
}
|
|
129
|
+
git(baseDir, ["worktree", "prune"]);
|
|
130
|
+
}
|
|
131
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
return { ok: false, error: `could not prepare worktree directory ${dest}: ${message(err)}` };
|
|
135
|
+
}
|
|
136
|
+
const added = git(baseDir, ["worktree", "add", "--detach", dest]);
|
|
137
|
+
if (!added.ok) {
|
|
138
|
+
return { ok: false, error: `could not create isolation worktree at ${dest}: ${added.error}` };
|
|
139
|
+
}
|
|
140
|
+
return { ok: true, path: dest, ...(preservedLeftover !== undefined ? { preservedLeftover } : {}) };
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Post-unit cleanup: remove the worktree when `git status --porcelain` shows
|
|
144
|
+
* it clean; retain it (dirty: true) when the unit left uncommitted work —
|
|
145
|
+
* the caller logs the retained path. Any git failure retains the worktree
|
|
146
|
+
* too (never destroy a tree whose state could not be verified).
|
|
147
|
+
*
|
|
148
|
+
* The probe deliberately omits `--ignored`: a worktree whose only residue is
|
|
149
|
+
* files matched by the base repo's `.gitignore` (build artifacts, caches,
|
|
150
|
+
* logs, `node_modules`) probes clean and IS removed. Those files are disposable
|
|
151
|
+
* by the repo's own declaration; retaining a worktree per build/install would
|
|
152
|
+
* blow up disk. "Uncollected work" the caller preserves is therefore
|
|
153
|
+
* tracked-or-untracked-unignored changes only (module doc).
|
|
154
|
+
*/
|
|
155
|
+
export function cleanupUnitWorktree(baseDir, worktreePath) {
|
|
156
|
+
const status = git(worktreePath, ["status", "--porcelain"]);
|
|
157
|
+
if (!status.ok) {
|
|
158
|
+
return { removed: false, dirty: false, error: status.error };
|
|
159
|
+
}
|
|
160
|
+
if (status.stdout.trim() !== "") {
|
|
161
|
+
return { removed: false, dirty: true };
|
|
162
|
+
}
|
|
163
|
+
const removed = git(baseDir, ["worktree", "remove", worktreePath]);
|
|
164
|
+
if (!removed.ok) {
|
|
165
|
+
return { removed: false, dirty: false, error: removed.error };
|
|
166
|
+
}
|
|
167
|
+
return { removed: true, dirty: false };
|
|
168
|
+
}
|
|
169
|
+
function message(err) {
|
|
170
|
+
return err instanceof Error ? err.message : String(err);
|
|
171
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Frontend -> unresolved workflow plan compiler (workflow-format-unification).
|
|
6
|
+
*
|
|
7
|
+
* ONE frontend now: {@link compileWorkflowPlan} lowers a parsed unified
|
|
8
|
+
* `WorkflowDocument` (`../parser.ts`) into the same `WorkflowPlanDraft` shape
|
|
9
|
+
* IR v3 has always consumed — the pre-unification split between a linear
|
|
10
|
+
* markdown compiler and a YAML-program compiler is gone. This pass owns the
|
|
11
|
+
* semantic rules the parser deliberately does not check:
|
|
12
|
+
*
|
|
13
|
+
* - every reference string (`map.over` / `route.input` / `inputs[]`) parses
|
|
14
|
+
* against the CLOSED two-root grammar (`program/expressions.ts`);
|
|
15
|
+
* - `steps.<id>` references name an EARLIER step (a producer that has
|
|
16
|
+
* already run when the reference resolves);
|
|
17
|
+
* - `inputs:` entries must reference a STEP OUTPUT, never `params.*` — params
|
|
18
|
+
* are already attached to every unit unconditionally, so naming one as a
|
|
19
|
+
* declared input would be redundant.
|
|
20
|
+
*
|
|
21
|
+
* Node-id convention (stable, unique within a plan):
|
|
22
|
+
* step root → `<stepId>` (unit) or `<stepId>.map` (map)
|
|
23
|
+
* map unit → `<stepId>.unit` (template instantiated per item)
|
|
24
|
+
* gate → `<stepId>.gate`
|
|
25
|
+
*
|
|
26
|
+
* Returns accumulated `WorkflowError`s rather than throwing. Pure and
|
|
27
|
+
* deterministic: the same document always compiles to the same plan.
|
|
28
|
+
*/
|
|
29
|
+
import { formatReference, parseReference } from "../program/expressions.js";
|
|
30
|
+
/**
|
|
31
|
+
* Compile a parsed unified workflow document into a frozen-plan-ready graph.
|
|
32
|
+
* `title` is the run-level display title (the asset's canonical name — the
|
|
33
|
+
* format carries no authored title). Assumes the document came out of
|
|
34
|
+
* `parseWorkflow` ok (structure already valid).
|
|
35
|
+
*/
|
|
36
|
+
export function compileWorkflowPlan(document, title) {
|
|
37
|
+
const errors = [];
|
|
38
|
+
const allStepIds = new Set(document.steps.map((s) => s.id));
|
|
39
|
+
const earlierStepIds = new Set();
|
|
40
|
+
const steps = [];
|
|
41
|
+
document.steps.forEach((step) => {
|
|
42
|
+
const check = { allStepIds, earlierStepIds, errors };
|
|
43
|
+
if (step.map) {
|
|
44
|
+
checkReferenceField(step.map.over, { ...check, line: step.source.start, label: `Step "${step.id}" map.over` });
|
|
45
|
+
}
|
|
46
|
+
if (step.route) {
|
|
47
|
+
checkReferenceField(step.route.input, {
|
|
48
|
+
...check,
|
|
49
|
+
line: step.source.start,
|
|
50
|
+
label: `Step "${step.id}" route.input`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
for (const [index, reference] of (step.inputs ?? []).entries()) {
|
|
54
|
+
checkInputReference(reference, index, {
|
|
55
|
+
...check,
|
|
56
|
+
line: step.source.start,
|
|
57
|
+
label: `Step "${step.id}" inputs`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
steps.push(compileStep(step, defaultsOf(document)));
|
|
61
|
+
earlierStepIds.add(step.id);
|
|
62
|
+
});
|
|
63
|
+
if (errors.length > 0)
|
|
64
|
+
return { ok: false, errors };
|
|
65
|
+
const paramNames = document.params ? Object.keys(document.params) : [];
|
|
66
|
+
return {
|
|
67
|
+
ok: true,
|
|
68
|
+
warnings: collectWorkflowWarnings(document),
|
|
69
|
+
plan: {
|
|
70
|
+
title,
|
|
71
|
+
...(paramNames.length > 0 ? { params: paramNames } : {}),
|
|
72
|
+
...(document.params && paramNames.length > 0 ? { paramSchemas: document.params } : {}),
|
|
73
|
+
...(document.budget
|
|
74
|
+
? {
|
|
75
|
+
budget: {
|
|
76
|
+
...(document.budget.maxTokens !== undefined ? { maxTokens: document.budget.maxTokens } : {}),
|
|
77
|
+
...(document.budget.maxUnits !== undefined ? { maxUnits: document.budget.maxUnits } : {}),
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
: {}),
|
|
81
|
+
steps,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function defaultsOf(document) {
|
|
86
|
+
return document.defaults;
|
|
87
|
+
}
|
|
88
|
+
function compileStep(step, defaults) {
|
|
89
|
+
const gate = {
|
|
90
|
+
kind: "gate",
|
|
91
|
+
id: `${step.id}.gate`,
|
|
92
|
+
stepId: step.id,
|
|
93
|
+
// The body `### gate` rubric is carried through as the ONE criterion string
|
|
94
|
+
// — the judge receives the whole section byte-exact (spec §2.4). A step
|
|
95
|
+
// with no rubric has no gate at all (fail-open, criteria: []).
|
|
96
|
+
criteria: step.gateRubric?.text.trim() ? [step.gateRubric.text] : [],
|
|
97
|
+
...(step.gate?.maxLoops !== undefined ? { maxLoops: step.gate.maxLoops } : {}),
|
|
98
|
+
};
|
|
99
|
+
let root;
|
|
100
|
+
if (step.route === undefined) {
|
|
101
|
+
const instructionsText = step.instructions?.text ?? "";
|
|
102
|
+
if (step.map) {
|
|
103
|
+
root = {
|
|
104
|
+
kind: "map",
|
|
105
|
+
id: `${step.id}.map`,
|
|
106
|
+
over: step.map.over,
|
|
107
|
+
template: compileUnit(step.map.unit, `${step.id}.unit`, instructionsText, defaults, step.inputs, step.source),
|
|
108
|
+
...(step.map.concurrency !== undefined ? { concurrency: step.map.concurrency } : {}),
|
|
109
|
+
reducer: step.map.reducer ?? "collect",
|
|
110
|
+
source: step.source,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
root = compileUnit(step.unit, step.id, instructionsText, defaults, step.inputs, step.instructions?.source);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
stepId: step.id,
|
|
119
|
+
title: step.id,
|
|
120
|
+
sequenceIndex: step.sequenceIndex,
|
|
121
|
+
...(root ? { root } : {}),
|
|
122
|
+
...(step.route
|
|
123
|
+
? {
|
|
124
|
+
route: {
|
|
125
|
+
input: step.route.input,
|
|
126
|
+
when: Object.fromEntries(step.route.branches.map((b) => [b.match, b.stepId])),
|
|
127
|
+
...(step.route.defaultStepId !== undefined ? { defaultStepId: step.route.defaultStepId } : {}),
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
: {}),
|
|
131
|
+
...(step.output !== undefined ? { outputSchema: step.output } : {}),
|
|
132
|
+
gate,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Lower one source unit into the unresolved structural plan. Instructions are
|
|
137
|
+
* ALWAYS the step's body prose, byte-exact — never templated, never scanned
|
|
138
|
+
* for reference syntax. Engine/model/timeout settings remain on the parsed
|
|
139
|
+
* override bag until the single freeze boundary.
|
|
140
|
+
*/
|
|
141
|
+
function compileUnit(unit, id, instructions, defaults, inputs, source) {
|
|
142
|
+
return {
|
|
143
|
+
kind: "unit",
|
|
144
|
+
id,
|
|
145
|
+
instructions,
|
|
146
|
+
templating: "verbatim",
|
|
147
|
+
...(inputs && inputs.length > 0 ? { inputs: [...inputs] } : {}),
|
|
148
|
+
...(unit?.output !== undefined ? { schema: unit.output } : {}),
|
|
149
|
+
...(unit?.retry ? { retry: { max: unit.retry.max, on: [...unit.retry.on] } } : {}),
|
|
150
|
+
onError: unit?.onError ?? defaults?.onError ?? "fail",
|
|
151
|
+
...(unit?.env ? { env: [...unit.env] } : {}),
|
|
152
|
+
...(unit?.isolation !== undefined ? { isolation: unit.isolation } : {}),
|
|
153
|
+
...(source ? { source } : {}),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/** Validate a whole-value reference field (`map.over`, `route.input`). */
|
|
157
|
+
function checkReferenceField(text, check) {
|
|
158
|
+
const parsed = parseReference(text);
|
|
159
|
+
if (!parsed.ok) {
|
|
160
|
+
check.errors.push({ line: check.line, message: `${check.label}: ${parsed.message}` });
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (parsed.expr.kind === "stepOutput" && !check.earlierStepIds.has(parsed.expr.stepId)) {
|
|
164
|
+
const why = check.allStepIds.has(parsed.expr.stepId)
|
|
165
|
+
? `step "${parsed.expr.stepId}" does not come before this step — references must name an earlier step (a producer that has already run)`
|
|
166
|
+
: `"${parsed.expr.stepId}" is not a step in this workflow`;
|
|
167
|
+
check.errors.push({
|
|
168
|
+
line: check.line,
|
|
169
|
+
message: `${check.label}: "${formatReference(parsed.expr)}" cannot be resolved — ${why}.`,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/** Validate one `inputs[]` entry: must be a step-output reference to an earlier step. */
|
|
174
|
+
function checkInputReference(text, index, check) {
|
|
175
|
+
const parsed = parseReference(text);
|
|
176
|
+
if (!parsed.ok) {
|
|
177
|
+
check.errors.push({ line: check.line, message: `${check.label}[${index}]: ${parsed.message}` });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (parsed.expr.kind === "param") {
|
|
181
|
+
check.errors.push({
|
|
182
|
+
line: check.line,
|
|
183
|
+
message: `${check.label}[${index}]: "${formatReference(parsed.expr)}" names a param, not a step output — ` +
|
|
184
|
+
`params are already attached to every unit, so declaring one as an input is redundant. "inputs:" only ` +
|
|
185
|
+
`names step outputs (steps.<id>.output...).`,
|
|
186
|
+
});
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (!check.earlierStepIds.has(parsed.expr.stepId)) {
|
|
190
|
+
const why = check.allStepIds.has(parsed.expr.stepId)
|
|
191
|
+
? `step "${parsed.expr.stepId}" does not come before this step — references must name an earlier step (a producer that has already run)`
|
|
192
|
+
: `"${parsed.expr.stepId}" is not a step in this workflow`;
|
|
193
|
+
check.errors.push({
|
|
194
|
+
line: check.line,
|
|
195
|
+
message: `${check.label}[${index}]: "${formatReference(parsed.expr)}" cannot be resolved — ${why}.`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// ── Non-fatal warnings ───────────────────────────────────────────────────────
|
|
200
|
+
/**
|
|
201
|
+
* Collect the document's non-fatal WARNINGS — advisories that never fail
|
|
202
|
+
* compilation, never change the frozen plan or its hash, and are surfaced by
|
|
203
|
+
* `workflow validate` (human + JSON) and as `warn()` lines at `workflow start`.
|
|
204
|
+
*
|
|
205
|
+
* A. A unit/map step with NO step-level `output:` schema carries its units'
|
|
206
|
+
* raw results as an untyped artifact — permitted, but worth flagging.
|
|
207
|
+
* B. A `params.<name>` reference (in `map.over`/`route.input`) to an
|
|
208
|
+
* UNDECLARED param, but ONLY when the document declares a `params:`
|
|
209
|
+
* block — a likely typo. Prose can no longer carry param references at
|
|
210
|
+
* all (it is never scanned), so this warning's surface shrinks to the
|
|
211
|
+
* two whole-value fields that can legally contain one.
|
|
212
|
+
*/
|
|
213
|
+
export function collectWorkflowWarnings(document) {
|
|
214
|
+
const warnings = [];
|
|
215
|
+
const declaredParams = document.params ? new Set(Object.keys(document.params)) : undefined;
|
|
216
|
+
for (const step of document.steps) {
|
|
217
|
+
if ((step.map || step.route === undefined) && step.output === undefined) {
|
|
218
|
+
warnings.push({
|
|
219
|
+
line: step.source.start,
|
|
220
|
+
message: `Step "${step.id}" declares no \`output:\` schema — its unit results are carried as an untyped ` +
|
|
221
|
+
`artifact (permitted). Add an \`output:\` JSON Schema to type and validate the step artifact.`,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
if (declaredParams) {
|
|
225
|
+
const declaredList = [...declaredParams].join(", ");
|
|
226
|
+
const scan = (text, label) => {
|
|
227
|
+
if (!text)
|
|
228
|
+
return;
|
|
229
|
+
const parsed = parseReference(text);
|
|
230
|
+
if (!parsed.ok || parsed.expr.kind !== "param" || declaredParams.has(parsed.expr.name))
|
|
231
|
+
return;
|
|
232
|
+
warnings.push({
|
|
233
|
+
line: step.source.start,
|
|
234
|
+
message: `${label}: "${formatReference(parsed.expr)}" references a param not declared in \`params:\` ` +
|
|
235
|
+
`(declared: ${declaredList || "none"}) — likely a typo. An undeclared param supplied at start still ` +
|
|
236
|
+
`resolves at run time.`,
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
if (step.map)
|
|
240
|
+
scan(step.map.over, `Step "${step.id}" map.over`);
|
|
241
|
+
if (step.route)
|
|
242
|
+
scan(step.route.input, `Step "${step.id}" route.input`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return warnings;
|
|
246
|
+
}
|