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
package/dist/tasks/runner.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
/**
|
|
5
|
-
* `akm
|
|
5
|
+
* `akm task run <id>` — what cron / launchd / schtasks invoke at the
|
|
6
6
|
* scheduled moment.
|
|
7
7
|
*
|
|
8
8
|
* Responsibilities:
|
|
@@ -12,155 +12,187 @@
|
|
|
12
12
|
* `tasks sync` time, not here — at run time we still want to attempt
|
|
13
13
|
* execution and surface the actual failure rather than re-fail on a
|
|
14
14
|
* validation error that the user already knows about.)
|
|
15
|
-
* 3.
|
|
15
|
+
* 3. Skip disabled tasks only when the invocation is scheduler-generated;
|
|
16
|
+
* explicit manual runs are allowed for catch-up and testing.
|
|
16
17
|
* 4. Dispatch by target kind:
|
|
17
18
|
* • workflow → `startWorkflowRun(ref, params)`
|
|
18
|
-
* • prompt → `
|
|
19
|
+
* • prompt → `executeRunner(engine, prompt, { stdio: "captured" })`
|
|
19
20
|
* 5. Capture stdout / stderr as structured rows in logs.db (task_logs) and,
|
|
20
21
|
* transitionally, as a flat text tail at `<cacheDir>/tasks/logs/<id>/<ts>.log`
|
|
21
|
-
* (
|
|
22
|
+
* (per the #579 logs audit).
|
|
22
23
|
* 6. Write a history row to state.db task_history table.
|
|
23
24
|
*
|
|
24
25
|
* Returns a structured result so the CLI handler can shape it for `output()`
|
|
25
26
|
* and so tests can assert against it without scraping stdout.
|
|
26
27
|
*/
|
|
27
28
|
import fs from "node:fs";
|
|
29
|
+
import os from "node:os";
|
|
28
30
|
import path from "node:path";
|
|
31
|
+
import { shouldSkipUnactivatedTask } from "../core/activation-policy.js";
|
|
29
32
|
import { assertNever } from "../core/assert.js";
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
33
|
+
import { placementSpecFor } from "../core/asset/asset-placement.js";
|
|
34
|
+
import { parseRefInput } from "../core/asset/resolve-ref.js";
|
|
32
35
|
import { loadConfig } from "../core/config/config.js";
|
|
33
|
-
import { NotFoundError, rethrowIfTestIsolationError } from "../core/errors.js";
|
|
36
|
+
import { AkmError, NotFoundError, rethrowIfTestIsolationError } from "../core/errors.js";
|
|
34
37
|
import { buildTaskRunId, insertTaskLogLines, openLogsDatabase, } from "../core/logs-db.js";
|
|
35
38
|
import { getTaskLogDir } from "../core/paths.js";
|
|
39
|
+
import { redactCredentialPatterns } from "../core/redaction.js";
|
|
36
40
|
import { withStateDb } from "../core/state-db.js";
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
41
|
+
import { runManagedSubprocess } from "../core/subprocess.js";
|
|
42
|
+
import { resolveEngine, resolveLlmEngineUse } from "../integrations/agent/engine-resolution.js";
|
|
43
|
+
import { resolveModel } from "../integrations/agent/model-aliases.js";
|
|
44
|
+
import { executeRunner } from "../integrations/agent/runner-dispatch.js";
|
|
45
|
+
import { chatCompletion } from "../llm/client.js";
|
|
42
46
|
import { resolveAssetPath } from "../sources/resolve.js";
|
|
43
|
-
import { getTaskHistory, queryTaskHistory, upsertTaskHistory } from "../storage/repositories/task-history-repository.js";
|
|
47
|
+
import { decodeTaskHistoryMetadata, finalizeTaskHistoryAttempt, getTaskHistory, queryTaskHistory, reserveTaskHistoryAttempt, upsertTaskHistory, } from "../storage/repositories/task-history-repository.js";
|
|
44
48
|
import { startWorkflowRun } from "../workflows/runtime/runs.js";
|
|
49
|
+
import { findBareAkmExecutableIndex } from "./command-executable.js";
|
|
45
50
|
import { parseTaskDocument } from "./parser.js";
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
import { resolveAkmInvocation } from "./resolve-akm-bin.js";
|
|
52
|
+
import { validateTaskId } from "./task-id.js";
|
|
53
|
+
export const INVALID_TASK_ATTEMPT_ID = "_invalid-task-id";
|
|
54
|
+
export async function runTask(id, options) {
|
|
55
|
+
const runAgentImpl = options.runAgentImpl;
|
|
49
56
|
const startWorkflowRunImpl = options.startWorkflowRunImpl ?? startWorkflowRun;
|
|
50
57
|
const now = options.now ?? (() => new Date());
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
: task.target.kind === "command"
|
|
66
|
-
? { kind: "prompt", profile: undefined }
|
|
67
|
-
: { kind: "prompt", profile: task.target.profile };
|
|
68
|
-
const result = {
|
|
69
|
-
id,
|
|
70
|
-
status: "disabled",
|
|
71
|
-
startedAt: startedIso,
|
|
72
|
-
finishedAt: finishedAt.toISOString(),
|
|
73
|
-
durationMs: finishedAt.getTime() - startedAt.getTime(),
|
|
74
|
-
log: logPath,
|
|
75
|
-
target: disabledTarget,
|
|
76
|
-
};
|
|
77
|
-
const disabledLine = `[akm tasks] task "${id}" is disabled — skipping run.`;
|
|
78
|
-
persistRunLog({
|
|
79
|
-
taskId: id,
|
|
80
|
-
startedAtIso: startedIso,
|
|
81
|
-
finishedAtIso: result.finishedAt,
|
|
82
|
-
logPath,
|
|
83
|
-
fileText: `${disabledLine}\n`,
|
|
84
|
-
dbLines: [{ line: disabledLine }],
|
|
58
|
+
const requestedStartedAt = now();
|
|
59
|
+
try {
|
|
60
|
+
validateTaskId(id);
|
|
61
|
+
}
|
|
62
|
+
catch (failure) {
|
|
63
|
+
const attempt = reserveTaskAttempt(INVALID_TASK_ATTEMPT_ID, requestedStartedAt);
|
|
64
|
+
recordTaskAttemptFailure({
|
|
65
|
+
taskId: INVALID_TASK_ATTEMPT_ID,
|
|
66
|
+
reason: "invalid_task_id",
|
|
67
|
+
failure,
|
|
68
|
+
startedAt: attempt.startedAt,
|
|
69
|
+
finishedAt: now(),
|
|
70
|
+
logDir: options.logDir,
|
|
71
|
+
historyReserved: attempt.historyReserved,
|
|
85
72
|
});
|
|
86
|
-
|
|
87
|
-
return result;
|
|
73
|
+
throw failure;
|
|
88
74
|
}
|
|
89
|
-
|
|
90
|
-
|
|
75
|
+
const attempt = reserveTaskAttempt(id, requestedStartedAt);
|
|
76
|
+
const startedAt = attempt.startedAt;
|
|
77
|
+
let failureReason = "task_load_failed";
|
|
78
|
+
try {
|
|
79
|
+
const stashDir = options.stashDir;
|
|
80
|
+
const filePath = await resolveAssetPath(stashDir, "task", id);
|
|
81
|
+
const yaml = fs.readFileSync(filePath, "utf8");
|
|
82
|
+
failureReason = "task_parse_failed";
|
|
83
|
+
const task = parseTaskDocument({ yaml, filePath, id });
|
|
84
|
+
failureReason = "task_dispatch_failed";
|
|
85
|
+
const startedIso = startedAt.toISOString();
|
|
86
|
+
const logPath = resolveTaskLogPath(options.logDir, id, startedIso);
|
|
87
|
+
if (shouldSkipUnactivatedTask({ enabled: task.enabled, scheduled: options.scheduled === true })) {
|
|
88
|
+
const finishedAt = finishAttempt(startedAt, now());
|
|
89
|
+
const disabledTarget = task.target.kind === "workflow"
|
|
90
|
+
? { kind: "workflow", ref: task.target.ref }
|
|
91
|
+
: task.target.kind === "command"
|
|
92
|
+
? { kind: "command", cmd: task.target.cmd }
|
|
93
|
+
: { kind: "prompt", engine: task.target.engine ?? null };
|
|
94
|
+
const result = {
|
|
95
|
+
id,
|
|
96
|
+
status: "disabled",
|
|
97
|
+
startedAt: startedIso,
|
|
98
|
+
finishedAt: finishedAt.toISOString(),
|
|
99
|
+
durationMs: finishedAt.getTime() - startedAt.getTime(),
|
|
100
|
+
log: logPath,
|
|
101
|
+
target: disabledTarget,
|
|
102
|
+
};
|
|
103
|
+
const disabledLine = `[akm task] task "${id}" is disabled — skipping run.`;
|
|
104
|
+
persistRunLog({
|
|
105
|
+
taskId: id,
|
|
106
|
+
startedAtIso: startedIso,
|
|
107
|
+
finishedAtIso: result.finishedAt,
|
|
108
|
+
logPath,
|
|
109
|
+
fileText: `${disabledLine}\n`,
|
|
110
|
+
dbLines: [{ line: disabledLine }],
|
|
111
|
+
});
|
|
112
|
+
appendHistory(result, attempt.historyReserved);
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
if (task.target.kind === "workflow") {
|
|
116
|
+
return await runWorkflowTask({
|
|
117
|
+
task,
|
|
118
|
+
logPath,
|
|
119
|
+
startedAt,
|
|
120
|
+
now,
|
|
121
|
+
startWorkflowRunImpl,
|
|
122
|
+
historyReserved: attempt.historyReserved,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (task.target.kind === "command") {
|
|
126
|
+
return await runCommandTask({
|
|
127
|
+
task,
|
|
128
|
+
logPath,
|
|
129
|
+
startedAt,
|
|
130
|
+
now,
|
|
131
|
+
historyReserved: attempt.historyReserved,
|
|
132
|
+
...(options.spawnFn ? { spawnFn: options.spawnFn } : {}),
|
|
133
|
+
...(options.setTimeoutFn ? { setTimeoutFn: options.setTimeoutFn } : {}),
|
|
134
|
+
...(options.clearTimeoutFn ? { clearTimeoutFn: options.clearTimeoutFn } : {}),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return await runPromptTask({
|
|
91
138
|
task,
|
|
139
|
+
stashDir,
|
|
92
140
|
logPath,
|
|
93
141
|
startedAt,
|
|
94
142
|
now,
|
|
95
|
-
|
|
143
|
+
runAgentImpl,
|
|
144
|
+
agentOptions: options.agentOptions,
|
|
145
|
+
chatCompletionImpl: options.chatCompletionImpl ?? chatCompletion,
|
|
146
|
+
historyReserved: attempt.historyReserved,
|
|
96
147
|
});
|
|
97
148
|
}
|
|
98
|
-
|
|
99
|
-
|
|
149
|
+
catch (failure) {
|
|
150
|
+
recordTaskAttemptFailure({
|
|
151
|
+
taskId: id,
|
|
152
|
+
reason: failureReason,
|
|
153
|
+
failure,
|
|
154
|
+
startedAt,
|
|
155
|
+
finishedAt: now(),
|
|
156
|
+
logDir: options.logDir,
|
|
157
|
+
historyReserved: attempt.historyReserved,
|
|
158
|
+
});
|
|
159
|
+
throw failure;
|
|
100
160
|
}
|
|
101
|
-
// Resolve config once here so runPromptTask does not call loadConfig()
|
|
102
|
-
// on every dispatch in a batch run (Fix C6).
|
|
103
|
-
const config = loadConfig();
|
|
104
|
-
return await runPromptTask({
|
|
105
|
-
task,
|
|
106
|
-
stashDir,
|
|
107
|
-
logPath,
|
|
108
|
-
startedAt,
|
|
109
|
-
now,
|
|
110
|
-
runAgentImpl,
|
|
111
|
-
agentOptions: options.agentOptions,
|
|
112
|
-
agentConfig: config,
|
|
113
|
-
agentTimeoutMs: undefined,
|
|
114
|
-
});
|
|
115
161
|
}
|
|
116
162
|
// ── command target ──────────────────────────────────────────────────────────
|
|
117
163
|
async function runCommandTask(input) {
|
|
118
|
-
const { task, logPath, startedAt, now } = input;
|
|
164
|
+
const { task, logPath, startedAt, now, historyReserved } = input;
|
|
119
165
|
if (task.target.kind !== "command")
|
|
120
166
|
throw new Error("invariant: command target");
|
|
121
167
|
const { cmd } = task.target;
|
|
168
|
+
const spawnCmd = resolveNestedAkmCommand(cmd);
|
|
122
169
|
const timeoutMs = task.timeoutMs !== undefined ? task.timeoutMs : null;
|
|
123
|
-
const header = `[akm
|
|
170
|
+
const header = `[akm task] task=${task.id} kind=command cmd=${cmd.join(" ")}`;
|
|
124
171
|
const logLines = [header];
|
|
125
172
|
const dbLines = [{ line: header }];
|
|
126
|
-
let stdout = "";
|
|
127
|
-
let stderr = "";
|
|
128
173
|
let exitCode = null;
|
|
129
174
|
try {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
175
|
+
// Managed spawn (src/core/subprocess.ts): process-GROUP kill so a timeout
|
|
176
|
+
// reaps the whole command tree (no orphans), and a SIGTERM→SIGKILL ladder
|
|
177
|
+
// so a child that ignores SIGTERM can't wedge the run forever.
|
|
178
|
+
const result = await runManagedSubprocess(spawnCmd, {
|
|
179
|
+
capture: true,
|
|
180
|
+
cwd: process.env.HOME ?? os.tmpdir(),
|
|
135
181
|
// Stamp task-runner provenance so any akm invocation in the command tree
|
|
136
182
|
// records usage events as machine traffic, not user demand (DRIFT-6).
|
|
137
183
|
// A more specific stamp already in the environment (e.g. improve's
|
|
138
184
|
// AKM_EVENT_SOURCE=improve on its child spawns) still wins in children.
|
|
139
185
|
env: { ...process.env, AKM_EVENT_SOURCE: process.env.AKM_EVENT_SOURCE ?? "task" },
|
|
186
|
+
timeoutMs,
|
|
187
|
+
...(input.spawnFn ? { spawnFn: input.spawnFn } : {}),
|
|
188
|
+
...(input.setTimeoutFn ? { setTimeoutFn: input.setTimeoutFn } : {}),
|
|
189
|
+
...(input.clearTimeoutFn ? { clearTimeoutFn: input.clearTimeoutFn } : {}),
|
|
140
190
|
});
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
proc.kill("SIGTERM");
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
/* ignore */
|
|
151
|
-
}
|
|
152
|
-
}, timeoutMs);
|
|
153
|
-
}
|
|
154
|
-
const [stdoutBuf, stderrBuf] = await Promise.all([
|
|
155
|
-
new Response(proc.stdout).text(),
|
|
156
|
-
new Response(proc.stderr).text(),
|
|
157
|
-
]);
|
|
158
|
-
await proc.exited;
|
|
159
|
-
if (timer !== undefined)
|
|
160
|
-
clearTimeout(timer);
|
|
161
|
-
stdout = stdoutBuf;
|
|
162
|
-
stderr = stderrBuf;
|
|
163
|
-
exitCode = proc.exitCode ?? (timedOut ? 143 : 1);
|
|
191
|
+
// A synchronous spawn throw / exit rejection surfaces as spawn_error below.
|
|
192
|
+
if (result.spawnError)
|
|
193
|
+
throw result.spawnError;
|
|
194
|
+
const { stdout, stderr, timedOut } = result;
|
|
195
|
+
exitCode = result.exitCode ?? (timedOut ? 143 : 1);
|
|
164
196
|
if (timedOut) {
|
|
165
197
|
logLines.push(`timed_out=true timeout_ms=${timeoutMs}`);
|
|
166
198
|
dbLines.push({ level: "error", line: `timed_out=true timeout_ms=${timeoutMs}` });
|
|
@@ -184,7 +216,7 @@ async function runCommandTask(input) {
|
|
|
184
216
|
dbLines.push({ level: "error", line: `spawn_error=${msg}` });
|
|
185
217
|
exitCode = 1;
|
|
186
218
|
}
|
|
187
|
-
const finishedAt = now();
|
|
219
|
+
const finishedAt = finishAttempt(startedAt, now());
|
|
188
220
|
persistRunLog({
|
|
189
221
|
taskId: task.id,
|
|
190
222
|
startedAtIso: startedAt.toISOString(),
|
|
@@ -201,18 +233,25 @@ async function runCommandTask(input) {
|
|
|
201
233
|
finishedAt: finishedAt.toISOString(),
|
|
202
234
|
durationMs: finishedAt.getTime() - startedAt.getTime(),
|
|
203
235
|
log: logPath,
|
|
204
|
-
target: { kind: "
|
|
236
|
+
target: { kind: "command", cmd },
|
|
205
237
|
detail: { exitCode },
|
|
206
238
|
};
|
|
207
|
-
appendHistory(result);
|
|
239
|
+
appendHistory(result, historyReserved);
|
|
208
240
|
return result;
|
|
209
241
|
}
|
|
242
|
+
/** Avoid a second PATH lookup when a task invokes the same AKM installation. */
|
|
243
|
+
function resolveNestedAkmCommand(cmd) {
|
|
244
|
+
const akmIndex = findBareAkmExecutableIndex(cmd);
|
|
245
|
+
if (akmIndex === undefined)
|
|
246
|
+
return cmd;
|
|
247
|
+
return [...cmd.slice(0, akmIndex), ...resolveAkmInvocation().argv, ...cmd.slice(akmIndex + 1)];
|
|
248
|
+
}
|
|
210
249
|
// ── workflow target ─────────────────────────────────────────────────────────
|
|
211
250
|
async function runWorkflowTask(input) {
|
|
212
|
-
const { task, logPath, startedAt, now, startWorkflowRunImpl } = input;
|
|
251
|
+
const { task, logPath, startedAt, now, startWorkflowRunImpl, historyReserved } = input;
|
|
213
252
|
if (task.target.kind !== "workflow")
|
|
214
253
|
throw new Error("invariant: workflow target");
|
|
215
|
-
const ref =
|
|
254
|
+
const ref = parseRefInput(task.target.ref);
|
|
216
255
|
if (ref.type !== "workflow") {
|
|
217
256
|
throw new NotFoundError(`Task "${task.id}" workflow target must be a workflow ref (got "${task.target.ref}").`, "WORKFLOW_NOT_FOUND");
|
|
218
257
|
}
|
|
@@ -222,9 +261,11 @@ async function runWorkflowTask(input) {
|
|
|
222
261
|
detail = await startWorkflowRunImpl(task.target.ref, task.target.params);
|
|
223
262
|
}
|
|
224
263
|
catch (e) {
|
|
264
|
+
if (e instanceof AkmError && e.kind === "config")
|
|
265
|
+
throw e;
|
|
225
266
|
error = e instanceof Error ? e : new Error(String(e));
|
|
226
267
|
}
|
|
227
|
-
const finishedAt = now();
|
|
268
|
+
const finishedAt = finishAttempt(startedAt, now());
|
|
228
269
|
const status = error ? "failed" : mapWorkflowStatus(detail?.run.status);
|
|
229
270
|
const log = renderWorkflowLog({ task, detail, error });
|
|
230
271
|
persistRunLog({
|
|
@@ -248,7 +289,7 @@ async function runWorkflowTask(input) {
|
|
|
248
289
|
...(error ? { error: error.message } : {}),
|
|
249
290
|
},
|
|
250
291
|
};
|
|
251
|
-
appendHistory(result);
|
|
292
|
+
appendHistory(result, historyReserved);
|
|
252
293
|
// Don't re-throw on workflow failure: the OS scheduler reads exit codes,
|
|
253
294
|
// not exceptions, and the CLI maps `status: "failed"` to a non-zero exit
|
|
254
295
|
// via exitCodeForStatus(). Throwing here would route through the generic
|
|
@@ -287,7 +328,7 @@ function mapWorkflowStatus(status) {
|
|
|
287
328
|
}
|
|
288
329
|
function renderWorkflowLog(input) {
|
|
289
330
|
const dbLines = [
|
|
290
|
-
{ line: `[akm
|
|
331
|
+
{ line: `[akm task] task=${input.task.id} kind=workflow ref=${input.task.target.ref}` },
|
|
291
332
|
];
|
|
292
333
|
if (input.detail) {
|
|
293
334
|
dbLines.push({ line: `run_id=${input.detail.run.id} status=${input.detail.run.status}` });
|
|
@@ -300,70 +341,70 @@ function renderWorkflowLog(input) {
|
|
|
300
341
|
}
|
|
301
342
|
// ── prompt target ───────────────────────────────────────────────────────────
|
|
302
343
|
async function runPromptTask(input) {
|
|
303
|
-
const { task, stashDir, logPath, startedAt, now,
|
|
344
|
+
const { task, stashDir, logPath, startedAt, now, agentOptions } = input;
|
|
304
345
|
if (task.target.kind !== "prompt")
|
|
305
346
|
throw new Error("invariant: prompt target");
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
else {
|
|
331
|
-
profile = requireAgentProfile(agentCfg, task.target.profile);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
// v1: Task doc explicitly names a profile — honour it directly.
|
|
336
|
-
profile = requireAgentProfile(agentCfg, task.target.profile);
|
|
337
|
-
}
|
|
347
|
+
const promptTarget = task.target;
|
|
348
|
+
const config = loadConfig();
|
|
349
|
+
const engineName = promptTarget.engine ?? config.defaults?.engine;
|
|
350
|
+
if (!engineName)
|
|
351
|
+
throw new NotFoundError(`Task "${task.id}" has no selected engine.`, "ASSET_NOT_FOUND");
|
|
352
|
+
let runner = resolveEngine(engineName, config);
|
|
353
|
+
if (runner.kind === "llm") {
|
|
354
|
+
const resolved = resolveLlmEngineUse(config, [
|
|
355
|
+
{
|
|
356
|
+
engine: engineName,
|
|
357
|
+
...(promptTarget.model !== undefined ? { model: promptTarget.model } : {}),
|
|
358
|
+
...(promptTarget.timeoutMs !== undefined ? { timeoutMs: promptTarget.timeoutMs } : {}),
|
|
359
|
+
...(promptTarget.llm !== undefined ? { llm: promptTarget.llm } : {}),
|
|
360
|
+
},
|
|
361
|
+
]);
|
|
362
|
+
runner = {
|
|
363
|
+
kind: "llm",
|
|
364
|
+
engine: resolved.engine,
|
|
365
|
+
connection: resolved.connection,
|
|
366
|
+
...(resolved.credential ? { credential: resolved.credential } : {}),
|
|
367
|
+
timeoutMs: resolved.timeoutMs,
|
|
368
|
+
};
|
|
338
369
|
}
|
|
339
370
|
else {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
371
|
+
if (promptTarget.llm !== undefined) {
|
|
372
|
+
throw new NotFoundError(`Task "${task.id}" uses llm overrides with non-LLM engine "${engineName}".`, "ASSET_NOT_FOUND");
|
|
373
|
+
}
|
|
374
|
+
const requestedModel = promptTarget.model;
|
|
375
|
+
const platform = runner.profile.platform;
|
|
376
|
+
if (!platform)
|
|
377
|
+
throw new Error(`Engine "${engineName}" resolved without a platform.`);
|
|
378
|
+
const model = requestedModel
|
|
379
|
+
? resolveModel(requestedModel, platform, runner.profile.modelAliases, runner.profile.globalModelAliases)
|
|
380
|
+
: runner.profile.model;
|
|
381
|
+
runner = {
|
|
382
|
+
...runner,
|
|
383
|
+
profile: { ...runner.profile, ...(model ? { model, modelIsExact: true } : {}) },
|
|
384
|
+
...(promptTarget.timeoutMs !== undefined ? { timeoutMs: promptTarget.timeoutMs } : {}),
|
|
385
|
+
};
|
|
344
386
|
}
|
|
345
|
-
// Task-level timeoutMs (including null = disabled) wins over global config.
|
|
346
|
-
// Resolution: task.timeoutMs → process entry timeoutMs → input.agentTimeoutMs → agentCfg.timeoutMs.
|
|
347
|
-
const agentTimeoutMs = task.timeoutMs !== undefined
|
|
348
|
-
? task.timeoutMs
|
|
349
|
-
: processTimeoutMs !== undefined
|
|
350
|
-
? processTimeoutMs
|
|
351
|
-
: input.agentTimeoutMs !== undefined
|
|
352
|
-
? input.agentTimeoutMs
|
|
353
|
-
: undefined;
|
|
354
387
|
const promptText = await resolvePromptText(task, stashDir);
|
|
355
|
-
const result = await
|
|
388
|
+
const result = await executeRunner(runner, promptText, {
|
|
356
389
|
stdio: "captured",
|
|
357
|
-
timeoutMs: agentTimeoutMs,
|
|
358
390
|
cwd: stashDir,
|
|
359
391
|
...agentOptions,
|
|
360
392
|
// Stamp task-runner provenance for any akm invocation the agent makes
|
|
361
393
|
// (DRIFT-6: agent-task traffic must not be recorded as user demand).
|
|
362
394
|
// Caller-supplied env still wins on conflicts.
|
|
363
395
|
env: { AKM_EVENT_SOURCE: "task", ...agentOptions?.env },
|
|
396
|
+
}, {
|
|
397
|
+
...(input.runAgentImpl ? { runAgent: input.runAgentImpl } : {}),
|
|
398
|
+
llm: async (spec, prompt, options) => {
|
|
399
|
+
const started = Date.now();
|
|
400
|
+
const stdout = await input.chatCompletionImpl(spec.connection, [{ role: "user", content: prompt }], {
|
|
401
|
+
...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
|
|
402
|
+
});
|
|
403
|
+
return { ok: true, exitCode: 0, stdout, stderr: "", durationMs: Date.now() - started };
|
|
404
|
+
},
|
|
364
405
|
});
|
|
365
|
-
const finishedAt = now();
|
|
366
|
-
const log = renderPromptLog({ task,
|
|
406
|
+
const finishedAt = finishAttempt(startedAt, now());
|
|
407
|
+
const log = renderPromptLog({ task, engineName, result });
|
|
367
408
|
persistRunLog({
|
|
368
409
|
taskId: task.id,
|
|
369
410
|
startedAtIso: startedAt.toISOString(),
|
|
@@ -380,12 +421,12 @@ async function runPromptTask(input) {
|
|
|
380
421
|
finishedAt: finishedAt.toISOString(),
|
|
381
422
|
durationMs: finishedAt.getTime() - startedAt.getTime(),
|
|
382
423
|
log: logPath,
|
|
383
|
-
target: { kind: "prompt",
|
|
424
|
+
target: { kind: "prompt", engine: engineName },
|
|
384
425
|
detail: result.ok
|
|
385
426
|
? { exitCode: result.exitCode }
|
|
386
427
|
: { reason: result.reason, error: result.error, exitCode: result.exitCode },
|
|
387
428
|
};
|
|
388
|
-
appendHistory(out);
|
|
429
|
+
appendHistory(out, input.historyReserved);
|
|
389
430
|
return out;
|
|
390
431
|
}
|
|
391
432
|
async function resolvePromptText(task, stashDir) {
|
|
@@ -403,14 +444,20 @@ async function resolvePromptText(task, stashDir) {
|
|
|
403
444
|
return fs.readFileSync(filePath, "utf8");
|
|
404
445
|
}
|
|
405
446
|
// asset
|
|
406
|
-
const ref =
|
|
447
|
+
const ref = parseRefInput(src.ref);
|
|
448
|
+
// D11 — see the matching guard in validator.ts: `resolveAssetPath`
|
|
449
|
+
// (src/sources/resolve.ts) is placement-dir-only and cannot route an
|
|
450
|
+
// opaque adapter conceptId, which `parseRefInput` now otherwise accepts.
|
|
451
|
+
if (placementSpecFor(ref.type) === undefined) {
|
|
452
|
+
throw new NotFoundError(`Task "${task.id}" prompt asset ref "${src.ref}" is not an AKM-placed asset — adapter-owned (opaque) prompt sources are not resolvable as task inputs yet.`, "ASSET_NOT_FOUND");
|
|
453
|
+
}
|
|
407
454
|
const assetPath = await resolveAssetPath(stashDir, ref.type, ref.name);
|
|
408
455
|
return fs.readFileSync(assetPath, "utf8");
|
|
409
456
|
}
|
|
410
457
|
function renderPromptLog(input) {
|
|
411
458
|
const lines = [];
|
|
412
459
|
const dbLines = [];
|
|
413
|
-
const header = `[akm
|
|
460
|
+
const header = `[akm task] task=${input.task.id} kind=prompt engine=${input.engineName}`;
|
|
414
461
|
const summary = `ok=${input.result.ok} exit_code=${input.result.exitCode ?? "null"} duration_ms=${input.result.durationMs}`;
|
|
415
462
|
lines.push(header, summary);
|
|
416
463
|
dbLines.push({ line: header }, { level: input.result.ok ? "info" : "error", line: summary });
|
|
@@ -431,6 +478,19 @@ function renderPromptLog(input) {
|
|
|
431
478
|
}
|
|
432
479
|
return { fileText: `${lines.join("\n")}\n`, dbLines };
|
|
433
480
|
}
|
|
481
|
+
function taskLogPath(logDir, taskId, startedAtIso) {
|
|
482
|
+
const tsSlug = startedAtIso.replace(/[:.]/g, "-");
|
|
483
|
+
return path.join(logDir, taskId, `${tsSlug}.log`);
|
|
484
|
+
}
|
|
485
|
+
function resolveTaskLogPath(logDir, taskId, startedAtIso) {
|
|
486
|
+
try {
|
|
487
|
+
return taskLogPath(logDir ?? getTaskLogDir(), taskId, startedAtIso);
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
rethrowIfTestIsolationError(error);
|
|
491
|
+
return "";
|
|
492
|
+
}
|
|
493
|
+
}
|
|
434
494
|
/** Split captured pipe output into per-line logs.db rows (blank lines dropped). */
|
|
435
495
|
function streamLines(text, stream, level) {
|
|
436
496
|
return text
|
|
@@ -443,11 +503,27 @@ function streamLines(text, stream, level) {
|
|
|
443
503
|
* task_history keeps resolving for humans and older consumers) plus
|
|
444
504
|
* structured rows in logs.db keyed by `buildTaskRunId(taskId, startedAt)`.
|
|
445
505
|
*
|
|
506
|
+
* Both sinks are pattern-redacted (`redactCredentialPatterns`) before being
|
|
507
|
+
* written — task output is raw command/agent/LLM text that can echo a
|
|
508
|
+
* credential-bearing URL (e.g. a Discord webhook) nothing upstream expects to
|
|
509
|
+
* scrub.
|
|
510
|
+
*
|
|
446
511
|
* The DB write is best-effort, mirroring {@link appendHistory}: an unwritable
|
|
447
512
|
* logs.db must never fail a task run.
|
|
448
513
|
*/
|
|
449
514
|
function persistRunLog(input) {
|
|
450
|
-
|
|
515
|
+
const fileText = redactCredentialPatterns(input.fileText);
|
|
516
|
+
const dbLines = input.dbLines.map((entry) => ({ ...entry, line: redactCredentialPatterns(entry.line) }));
|
|
517
|
+
if (input.logPath) {
|
|
518
|
+
try {
|
|
519
|
+
fs.mkdirSync(path.dirname(input.logPath), { recursive: true });
|
|
520
|
+
fs.writeFileSync(input.logPath, fileText);
|
|
521
|
+
}
|
|
522
|
+
catch (error) {
|
|
523
|
+
rethrowIfTestIsolationError(error);
|
|
524
|
+
// Transitional file logging is fully best-effort.
|
|
525
|
+
}
|
|
526
|
+
}
|
|
451
527
|
try {
|
|
452
528
|
const db = openLogsDatabase();
|
|
453
529
|
try {
|
|
@@ -455,59 +531,147 @@ function persistRunLog(input) {
|
|
|
455
531
|
taskId: input.taskId,
|
|
456
532
|
runId: buildTaskRunId(input.taskId, input.startedAtIso),
|
|
457
533
|
ts: input.finishedAtIso,
|
|
458
|
-
lines:
|
|
534
|
+
lines: dbLines,
|
|
459
535
|
});
|
|
460
536
|
}
|
|
461
537
|
finally {
|
|
462
538
|
db.close();
|
|
463
539
|
}
|
|
464
540
|
}
|
|
465
|
-
catch (
|
|
466
|
-
rethrowIfTestIsolationError(
|
|
467
|
-
|
|
541
|
+
catch (error) {
|
|
542
|
+
rethrowIfTestIsolationError(error);
|
|
543
|
+
// Structured logging is fully best-effort and must not alter CLI output.
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
/** Reserve a collision-free identity through state.db's existing unique index. */
|
|
547
|
+
function reserveTaskAttempt(taskId, requestedStartedAt) {
|
|
548
|
+
try {
|
|
549
|
+
return withStateDb((db) => {
|
|
550
|
+
for (let offsetMs = 0;; offsetMs++) {
|
|
551
|
+
const startedAt = new Date(requestedStartedAt.getTime() + offsetMs);
|
|
552
|
+
const reserved = reserveTaskHistoryAttempt(db, {
|
|
553
|
+
task_id: taskId,
|
|
554
|
+
status: "active",
|
|
555
|
+
started_at: startedAt.toISOString(),
|
|
556
|
+
completed_at: null,
|
|
557
|
+
failed_at: null,
|
|
558
|
+
log_path: null,
|
|
559
|
+
target_kind: null,
|
|
560
|
+
target_ref: null,
|
|
561
|
+
metadata_json: JSON.stringify({ metadataVersion: 2, durationMs: 0, detail: null }),
|
|
562
|
+
});
|
|
563
|
+
if (reserved)
|
|
564
|
+
return { startedAt, historyReserved: true };
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
catch (error) {
|
|
569
|
+
rethrowIfTestIsolationError(error);
|
|
570
|
+
// Attempt recording cannot prevent or replace task execution.
|
|
571
|
+
return { startedAt: requestedStartedAt, historyReserved: false };
|
|
468
572
|
}
|
|
469
573
|
}
|
|
574
|
+
function finishAttempt(startedAt, observedFinishedAt) {
|
|
575
|
+
return observedFinishedAt.getTime() < startedAt.getTime() ? new Date(startedAt) : observedFinishedAt;
|
|
576
|
+
}
|
|
577
|
+
const SAFE_TASK_ATTEMPT_ERROR_CODES = new Set([
|
|
578
|
+
"CONFIG_DIR_UNRESOLVABLE",
|
|
579
|
+
"STASH_DIR_NOT_FOUND",
|
|
580
|
+
"STASH_DIR_NOT_A_DIRECTORY",
|
|
581
|
+
"STASH_DIR_UNREADABLE",
|
|
582
|
+
"LLM_NOT_CONFIGURED",
|
|
583
|
+
"INVALID_CONFIG_FILE",
|
|
584
|
+
"UNSUPPORTED_CONFIG_VERSION",
|
|
585
|
+
"TEST_ISOLATION_MISSING",
|
|
586
|
+
"INVALID_FLAG_VALUE",
|
|
587
|
+
"MISSING_REQUIRED_ARGUMENT",
|
|
588
|
+
"PATH_ESCAPE_VIOLATION",
|
|
589
|
+
"TASK_SCHEMA_VERSION_UNSUPPORTED",
|
|
590
|
+
"ASSET_NOT_FOUND",
|
|
591
|
+
"WORKFLOW_NOT_FOUND",
|
|
592
|
+
"FILE_NOT_FOUND",
|
|
593
|
+
]);
|
|
594
|
+
function safeTaskAttemptErrorCode(failure) {
|
|
595
|
+
if (failure instanceof AkmError && SAFE_TASK_ATTEMPT_ERROR_CODES.has(failure.code))
|
|
596
|
+
return failure.code;
|
|
597
|
+
return "INTERNAL";
|
|
598
|
+
}
|
|
599
|
+
export function recordTaskAttemptFailure(input) {
|
|
600
|
+
let taskId = input.taskId;
|
|
601
|
+
try {
|
|
602
|
+
validateTaskId(taskId);
|
|
603
|
+
}
|
|
604
|
+
catch {
|
|
605
|
+
taskId = INVALID_TASK_ATTEMPT_ID;
|
|
606
|
+
}
|
|
607
|
+
const attempt = input.historyReserved === undefined
|
|
608
|
+
? reserveTaskAttempt(taskId, input.startedAt)
|
|
609
|
+
: { startedAt: input.startedAt, historyReserved: input.historyReserved };
|
|
610
|
+
const finishedAt = finishAttempt(attempt.startedAt, input.finishedAt ?? new Date());
|
|
611
|
+
const startedAtIso = attempt.startedAt.toISOString();
|
|
612
|
+
const finishedAtIso = finishedAt.toISOString();
|
|
613
|
+
const errorCode = safeTaskAttemptErrorCode(input.failure);
|
|
614
|
+
const logPath = resolveTaskLogPath(input.logDir, taskId, startedAtIso);
|
|
615
|
+
const line = `[akm task] status=failed reason=${input.reason} code=${errorCode}`;
|
|
616
|
+
const result = {
|
|
617
|
+
id: taskId,
|
|
618
|
+
status: "failed",
|
|
619
|
+
startedAt: startedAtIso,
|
|
620
|
+
finishedAt: finishedAtIso,
|
|
621
|
+
durationMs: Math.max(0, finishedAt.getTime() - attempt.startedAt.getTime()),
|
|
622
|
+
log: logPath,
|
|
623
|
+
target: { kind: "unknown" },
|
|
624
|
+
detail: { reason: input.reason, error: errorCode },
|
|
625
|
+
};
|
|
626
|
+
persistRunLog({
|
|
627
|
+
taskId,
|
|
628
|
+
startedAtIso,
|
|
629
|
+
finishedAtIso,
|
|
630
|
+
logPath,
|
|
631
|
+
fileText: `${line}\n`,
|
|
632
|
+
dbLines: [{ level: "error", line }],
|
|
633
|
+
});
|
|
634
|
+
appendHistory(result, attempt.historyReserved);
|
|
635
|
+
}
|
|
470
636
|
// ── history ─────────────────────────────────────────────────────────────────
|
|
471
|
-
function appendHistory(result) {
|
|
637
|
+
function appendHistory(result, historyReserved = false) {
|
|
638
|
+
const row = {
|
|
639
|
+
task_id: result.id,
|
|
640
|
+
status: result.status,
|
|
641
|
+
started_at: result.startedAt,
|
|
642
|
+
completed_at: result.finishedAt,
|
|
643
|
+
failed_at: result.status === "failed" ? result.finishedAt : null,
|
|
644
|
+
log_path: result.log || null,
|
|
645
|
+
target_kind: result.target.kind === "unknown" ? null : result.target.kind,
|
|
646
|
+
target_ref: result.target.kind === "workflow" ? result.target.ref : null,
|
|
647
|
+
metadata_json: JSON.stringify({
|
|
648
|
+
metadataVersion: 2,
|
|
649
|
+
durationMs: result.durationMs,
|
|
650
|
+
detail: result.detail ?? null,
|
|
651
|
+
...(result.target.kind === "prompt" ? { engine: result.target.engine } : {}),
|
|
652
|
+
}),
|
|
653
|
+
};
|
|
472
654
|
try {
|
|
473
655
|
withStateDb((db) => {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
started_at: result.startedAt,
|
|
478
|
-
completed_at: result.finishedAt,
|
|
479
|
-
failed_at: result.status === "failed" ? result.finishedAt : null,
|
|
480
|
-
log_path: result.log,
|
|
481
|
-
target_kind: result.target.kind,
|
|
482
|
-
target_ref: result.target.kind === "workflow" ? result.target.ref : null,
|
|
483
|
-
metadata_json: JSON.stringify({
|
|
484
|
-
durationMs: result.durationMs,
|
|
485
|
-
detail: result.detail ?? null,
|
|
486
|
-
profile: result.target.kind === "prompt" ? result.target.profile : undefined,
|
|
487
|
-
}),
|
|
488
|
-
});
|
|
656
|
+
if (historyReserved && finalizeTaskHistoryAttempt(db, row))
|
|
657
|
+
return;
|
|
658
|
+
upsertTaskHistory(db, row);
|
|
489
659
|
});
|
|
490
660
|
}
|
|
491
|
-
catch (
|
|
492
|
-
rethrowIfTestIsolationError(
|
|
493
|
-
|
|
661
|
+
catch (error) {
|
|
662
|
+
rethrowIfTestIsolationError(error);
|
|
663
|
+
// History recording is fully best-effort and must not alter CLI output.
|
|
494
664
|
}
|
|
495
665
|
}
|
|
496
666
|
export function readTaskHistory(options = {}) {
|
|
497
667
|
return withStateDb((db) => {
|
|
498
|
-
|
|
668
|
+
if (options.limit === 0)
|
|
669
|
+
return [];
|
|
499
670
|
if (options.id) {
|
|
500
671
|
const row = getTaskHistory(db, options.id);
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
else {
|
|
504
|
-
rows = queryTaskHistory(db, {}).map(taskHistoryRowToResult);
|
|
505
|
-
}
|
|
506
|
-
rows.sort((a, b) => (a.startedAt < b.startedAt ? 1 : -1));
|
|
507
|
-
if (options.limit !== undefined && options.limit >= 0) {
|
|
508
|
-
return rows.slice(0, options.limit);
|
|
672
|
+
return row ? [taskHistoryRowToResult(row)] : [];
|
|
509
673
|
}
|
|
510
|
-
return
|
|
674
|
+
return queryTaskHistory(db, options.limit !== undefined && options.limit > 0 ? { limit: options.limit } : {}).map(taskHistoryRowToResult);
|
|
511
675
|
});
|
|
512
676
|
}
|
|
513
677
|
/**
|
|
@@ -515,25 +679,29 @@ export function readTaskHistory(options = {}) {
|
|
|
515
679
|
* that callers of `readTaskHistory()` expect.
|
|
516
680
|
*/
|
|
517
681
|
function taskHistoryRowToResult(row) {
|
|
518
|
-
|
|
519
|
-
try {
|
|
520
|
-
meta = JSON.parse(row.metadata_json);
|
|
521
|
-
}
|
|
522
|
-
catch {
|
|
523
|
-
// ignore corrupt JSON
|
|
524
|
-
}
|
|
682
|
+
const meta = decodeTaskHistoryMetadata(row.metadata_json);
|
|
525
683
|
const target = row.target_kind === "workflow"
|
|
526
684
|
? { kind: "workflow", ref: row.target_ref ?? "" }
|
|
527
|
-
:
|
|
685
|
+
: row.target_kind === "command"
|
|
686
|
+
? { kind: "command" }
|
|
687
|
+
: row.target_kind === "prompt"
|
|
688
|
+
? meta.metadataVersion === 1
|
|
689
|
+
? {
|
|
690
|
+
kind: "prompt",
|
|
691
|
+
engine: null,
|
|
692
|
+
...(meta.legacyProfile !== undefined ? { legacyProfile: meta.legacyProfile } : {}),
|
|
693
|
+
}
|
|
694
|
+
: { kind: "prompt", engine: meta.engine ?? null }
|
|
695
|
+
: { kind: "unknown" };
|
|
528
696
|
return {
|
|
529
697
|
id: row.task_id,
|
|
530
698
|
status: row.status,
|
|
531
699
|
startedAt: row.started_at,
|
|
532
700
|
finishedAt: row.completed_at ?? row.failed_at ?? row.started_at,
|
|
533
|
-
durationMs: meta.durationMs
|
|
701
|
+
durationMs: meta.durationMs,
|
|
534
702
|
log: row.log_path ?? "",
|
|
535
703
|
target,
|
|
536
|
-
...(meta.detail
|
|
704
|
+
...(meta.detail ? { detail: meta.detail } : {}),
|
|
537
705
|
};
|
|
538
706
|
}
|
|
539
707
|
/**
|