akm-cli 0.10.261012-beta → 0.10.261014-beta
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 +710 -3
- package/README.md +15 -0
- package/SECURITY.md +11 -10
- package/STABILITY.md +47 -51
- package/dist/assets/hints/cli-hints-full.md +21 -19
- package/dist/assets/hints/cli-hints-short.md +3 -4
- package/dist/assets/opencode/akm-plugin.js +177 -0
- package/dist/assets/stash-skeleton/README.md +1 -1
- package/dist/assets/tasks/core/improve.yml +1 -1
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
- package/dist/assets/ui/config.js +27 -10
- package/dist/assets/workflows/workflow-template.md +2 -2
- package/dist/cli/clack.js +3 -1
- package/dist/cli/selection.js +33 -0
- package/dist/cli/shared.js +14 -1
- package/dist/cli/unknown-flags.js +6 -37
- package/dist/cli.js +69 -48
- package/dist/commands/agent/agent-dispatch.js +17 -25
- package/dist/commands/agent/contribute-cli.js +9 -8
- package/dist/commands/command/command-cli.js +4 -8
- package/dist/commands/command/command-execution.js +25 -39
- package/dist/commands/command/execution-source-loader.js +10 -14
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +14 -5
- package/dist/commands/env/child-env.js +12 -14
- package/dist/commands/env/env-binding.js +47 -58
- package/dist/commands/env/env-cli.js +22 -24
- package/dist/commands/env/env.js +10 -58
- package/dist/commands/env/secret-cli.js +11 -29
- package/dist/commands/env/secret.js +3 -10
- package/dist/commands/health/checks.js +10 -849
- package/dist/commands/health/connections-and-harnesses-check.js +109 -0
- package/dist/commands/health/egress.js +3 -3
- package/dist/commands/health/html-report.js +9 -10
- package/dist/commands/health/plugin-staleness.js +18 -11
- package/dist/commands/health/report-view-model.js +16 -12
- package/dist/commands/health/scheduler-binary.js +1 -1
- package/dist/commands/health/semantic-search-check.js +85 -0
- package/dist/commands/health/type-directory-check.js +0 -3
- package/dist/commands/health.js +30 -42
- package/dist/commands/improve/consolidate/pair-pass.js +10 -25
- package/dist/commands/improve/consolidate.js +10 -15
- package/dist/commands/improve/distill.js +5 -17
- package/dist/commands/improve/eligibility.js +1 -3
- package/dist/commands/improve/execution.js +37 -40
- package/dist/commands/improve/extract-cli.js +6 -11
- package/dist/commands/improve/extract-prompt.js +2 -2
- package/dist/commands/improve/extract.js +67 -97
- package/dist/commands/improve/improve-cli.js +22 -128
- package/dist/commands/improve/improve-report.js +1 -1
- package/dist/commands/improve/improve-strategies.js +25 -108
- package/dist/commands/improve/improve.js +10 -14
- package/dist/commands/improve/loop-stages.js +3 -0
- package/dist/commands/improve/memory/memory-improve.js +1 -1
- package/dist/commands/improve/preparation.js +8 -13
- package/dist/commands/improve/reflect.js +203 -332
- package/dist/commands/improve/retrieval-scope.js +1 -1
- package/dist/commands/improve/session-asset.js +3 -2
- package/dist/commands/improve/stage.js +87 -115
- package/dist/commands/lint/base-linter.js +3 -3
- package/dist/commands/lint/env-key-rules.js +7 -6
- package/dist/commands/lint/index.js +3 -3
- package/dist/commands/models-cli.js +103 -63
- package/dist/commands/proposal/drain.js +26 -39
- package/dist/commands/proposal/proposal-cli.js +14 -18
- package/dist/commands/proposal/propose-cli.js +4 -2
- package/dist/commands/proposal/propose.js +37 -64
- package/dist/commands/proposal/repository.js +17 -17
- package/dist/commands/proposal/validators/proposal-validators.js +3 -6
- package/dist/commands/read/curate.js +10 -6
- package/dist/commands/read/registry-search.js +2 -48
- package/dist/commands/read/search-cli.js +1 -8
- package/dist/commands/read/search.js +5 -6
- package/dist/commands/read/show.js +6 -29
- package/dist/commands/remember.js +25 -40
- package/dist/commands/sources/add-cli.js +8 -63
- package/dist/commands/sources/bundle-cli.js +8 -9
- package/dist/commands/sources/bundle-config-ops.js +2 -2
- package/dist/commands/sources/info.js +12 -1
- package/dist/commands/sources/init.js +1 -1
- package/dist/commands/sources/installed-stashes.js +119 -63
- package/dist/commands/sources/migration-help.js +1 -1
- package/dist/commands/sources/plugin-upgrade.js +8 -15
- package/dist/commands/sources/schema-repair.js +4 -10
- package/dist/commands/sources/source-add.js +2 -2
- package/dist/commands/sources/source-clone.js +31 -7
- package/dist/commands/sources/source-manage.js +4 -4
- package/dist/commands/targets.js +175 -0
- package/dist/commands/tasks/explain.js +104 -69
- package/dist/commands/tasks/tasks-cli.js +9 -11
- package/dist/commands/tasks/tasks.js +75 -97
- package/dist/commands/ui/api.js +11 -3
- package/dist/commands/ui/redact.js +5 -31
- package/dist/commands/ui/workspace-actions.js +1 -1
- package/dist/commands/workflow/plan.js +48 -9
- package/dist/commands/workflow-cli.js +40 -45
- package/dist/core/adapter/adapters/agent-skills-adapter.js +10 -11
- package/dist/core/adapter/adapters/akm-adapter.js +36 -41
- package/dist/core/adapter/adapters/akm-lint.js +10 -12
- package/dist/core/adapter/adapters/akm-metadata.js +2 -2
- package/dist/core/adapter/adapters/akm-task-adapter.js +8 -9
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +5 -5
- package/dist/core/adapter/adapters/claude-adapter.js +1 -1
- package/dist/core/adapter/adapters/dotenv-adapter.js +7 -6
- package/dist/core/adapter/adapters/generic-files-adapter.js +5 -5
- package/dist/core/adapter/adapters/index.js +3 -4
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +12 -14
- package/dist/core/adapter/adapters/okf-adapter.js +8 -10
- package/dist/core/adapter/adapters/opencode-adapter.js +1 -1
- package/dist/core/adapter/adapters/shared.js +3 -3
- package/dist/core/adapter/adapters/tool-dir-shared.js +7 -25
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +3 -3
- package/dist/core/adapter/detect-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +13 -35
- package/dist/core/adapter/registry.js +1 -1
- package/dist/core/adapter/validate-context.js +2 -4
- package/dist/core/asset/asset-placement.js +1 -1
- package/dist/core/asset/asset-ref.js +3 -3
- package/dist/core/asset/resolve-ref.js +5 -0
- package/dist/core/bundle-rename.js +12 -4
- package/dist/core/closest-match.js +37 -0
- package/dist/core/common.js +37 -57
- package/dist/core/config/config-io.js +26 -18
- package/dist/core/config/config-schema.js +19 -106
- package/dist/core/config/config-sources.js +3 -3
- package/dist/core/config/config-types.js +4 -4
- package/dist/core/config/config-walker.js +50 -77
- package/dist/core/config/config.js +438 -109
- package/dist/core/config/convert-engine-references.js +114 -0
- package/dist/core/config/convert-engines-shared.js +40 -0
- package/dist/core/config/convert-engines.js +300 -0
- package/dist/core/config/convert-models-overlay.js +137 -0
- package/dist/core/config/credentials.js +304 -0
- package/dist/core/config/engine-semantics.js +3 -3
- package/dist/core/config/migrate-keys.js +222 -0
- package/dist/core/config/model-aliases.js +37 -0
- package/dist/core/config/models-file.js +34 -0
- package/dist/core/config/retired-engines.js +53 -0
- package/dist/core/config/schema/connections.js +41 -0
- package/dist/core/config/schema/embedding.js +2 -2
- package/dist/core/config/schema/harnesses.js +41 -0
- package/dist/core/config/schema/improve-processes.js +9 -28
- package/dist/core/config/schema/improve.js +36 -1
- package/dist/core/config/schema/index-config.js +18 -20
- package/dist/core/config/schema/primitives.js +42 -17
- package/dist/core/config/schema/search.js +6 -11
- package/dist/core/config/schema/sources-bundles.js +9 -9
- package/dist/core/config/schema/workflow.js +2 -6
- package/dist/core/config/unusable-entries.js +66 -0
- package/dist/core/content-safety.js +3 -6
- package/dist/core/endpoint-url.js +47 -0
- package/dist/core/env-secret-ref.js +84 -73
- package/dist/core/errors.js +10 -16
- package/dist/core/extra-params.js +3 -3
- package/dist/core/improve-result.js +8 -9
- package/dist/core/json-schema.js +1 -1
- package/dist/core/lesson-lint.js +1 -1
- package/dist/core/llm-inference.js +80 -0
- package/dist/core/parse.js +2 -2
- package/dist/core/paths.js +33 -10
- package/dist/core/recognition-util.js +8 -10
- package/dist/core/redaction.js +94 -55
- package/dist/core/ref-token.js +82 -0
- package/dist/core/secret-value.js +14 -0
- package/dist/core/state/migrations.js +17 -22
- package/dist/core/structured.js +2 -68
- package/dist/core/subprocess.js +63 -22
- package/dist/core/type-presentation.js +10 -14
- package/dist/core/write-source.js +20 -4
- package/dist/execution/input-contract.js +3 -6
- package/dist/execution/notices.js +49 -0
- package/dist/execution/resolved-request.js +24 -40
- package/dist/execution/source.js +21 -45
- package/dist/execution/target-ref.js +2 -2
- package/dist/indexer/bundle-identity-guard.js +6 -5
- package/dist/indexer/ensure-index.js +1 -1
- package/dist/indexer/index-writer-lock.js +1 -1
- package/dist/indexer/indexer.js +46 -42
- package/dist/indexer/installations.js +12 -22
- package/dist/indexer/lookup/adapter-concept-owner.js +40 -14
- package/dist/indexer/materialize-embeddings.js +20 -16
- package/dist/indexer/passes/memory-inference.js +21 -50
- package/dist/indexer/passes/metadata.js +5 -5
- package/dist/indexer/scan/doc-to-entry.js +1 -1
- package/dist/indexer/scan/drain-dir.js +9 -11
- package/dist/indexer/search/db-search.js +9 -7
- package/dist/indexer/search/search-source.js +42 -22
- package/dist/indexer/usage/usage-events.js +2 -3
- package/dist/indexer/walk/index-context.js +2 -1
- package/dist/indexer/walk/matchers.js +3 -11
- package/dist/indexer/walk/path-resolver.js +13 -68
- package/dist/indexer/walk/walker.js +32 -26
- package/dist/integrations/agent/akm-read-tools.js +81 -0
- package/dist/integrations/agent/config.js +1 -1
- package/dist/integrations/agent/detect.js +32 -36
- package/dist/integrations/agent/execution.js +130 -428
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +24 -28
- package/dist/integrations/agent/prompts.js +17 -30
- package/dist/integrations/agent/request-lowering.js +67 -101
- package/dist/integrations/agent/resolution.js +332 -0
- package/dist/integrations/agent/runner-dispatch.js +156 -181
- package/dist/integrations/agent/runner.js +20 -70
- package/dist/integrations/agent/runtime-port.js +4 -0
- package/dist/integrations/agent/runtime.js +10 -0
- package/dist/integrations/agent/spawn.js +65 -190
- package/dist/integrations/harnesses/aider/index.js +19 -39
- package/dist/integrations/harnesses/amazonq/index.js +17 -32
- package/dist/integrations/harnesses/claude/index.js +59 -28
- package/dist/integrations/harnesses/claude/session-log.js +7 -5
- package/dist/integrations/harnesses/codex/index.js +19 -31
- package/dist/integrations/harnesses/copilot/index.js +17 -35
- package/dist/integrations/harnesses/gemini/index.js +18 -34
- package/dist/integrations/harnesses/harness.js +36 -0
- package/dist/integrations/harnesses/index.js +20 -51
- package/dist/integrations/harnesses/opencode/agent-builder.js +132 -100
- package/dist/integrations/harnesses/opencode/index.js +11 -33
- package/dist/integrations/harnesses/opencode/roots.js +50 -0
- package/dist/integrations/harnesses/opencode/runtime/binary.js +206 -0
- package/dist/integrations/harnesses/opencode/runtime/command.js +152 -0
- package/dist/integrations/harnesses/opencode/runtime/index.js +177 -0
- package/dist/integrations/harnesses/opencode/runtime/tar.js +107 -0
- package/dist/integrations/harnesses/opencode/session-log-v1.js +15 -7
- package/dist/integrations/harnesses/opencode/session-log-v2.js +72 -48
- package/dist/integrations/harnesses/opencode/session-log.js +58 -137
- package/dist/integrations/harnesses/opencode/version.js +34 -53
- package/dist/integrations/harnesses/openhands/index.js +13 -37
- package/dist/integrations/harnesses/pi/index.js +21 -32
- package/dist/integrations/lockfile.js +1 -1
- package/dist/integrations/session-logs/index.js +11 -31
- package/dist/llm/client.js +93 -111
- package/dist/llm/embedder.js +19 -34
- package/dist/llm/embedders/connection.js +31 -0
- package/dist/llm/embedders/local-model-files.js +56 -0
- package/dist/llm/embedders/local.js +146 -115
- package/dist/llm/embedders/remote.js +26 -23
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/index-passes.js +33 -39
- package/dist/llm/memory-infer.js +67 -77
- package/dist/llm/model-list.js +35 -0
- package/dist/llm/rerank-client.js +8 -14
- package/dist/llm/structured-call.js +45 -99
- package/dist/llm/structured.js +60 -0
- package/dist/output/renderers.js +2 -8
- package/dist/output/shapes/helpers.js +18 -44
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/output/shapes.js +1 -7
- package/dist/output/text/command-format.js +41 -39
- package/dist/output/text/health-format.js +8 -2
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +12 -0
- package/dist/output/text/models.js +3 -2
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +16 -28
- package/dist/output/text/show-format.js +0 -2
- package/dist/output/text/targets-table.js +70 -0
- package/dist/output/text/workflow-format.js +44 -15
- package/dist/output/text.js +1 -1
- package/dist/registry/providers/skills-sh.js +1 -28
- package/dist/registry/providers/static-index.js +1 -71
- package/dist/runtime.js +6 -2
- package/dist/scripts/akm-migrate-node.js +47095 -44905
- package/dist/scripts/akm-migrate.js +46946 -44755
- package/dist/setup/detect.js +28 -273
- package/dist/setup/endpoint.js +36 -0
- package/dist/setup/semantic-assets.js +13 -19
- package/dist/setup/setup-flags.js +77 -0
- package/dist/setup/setup-plan.js +144 -0
- package/dist/setup/setup.js +134 -358
- package/dist/setup/steps/connection-shared.js +49 -101
- package/dist/setup/steps/connection.js +121 -524
- package/dist/setup/steps/embeddings.js +151 -0
- package/dist/setup/steps/harnesses.js +118 -0
- package/dist/setup/steps/platforms.js +2 -81
- package/dist/setup/steps/tasks.js +1 -2
- package/dist/setup/steps.js +10 -0
- package/dist/setup/summary.js +67 -0
- package/dist/sources/freshness.js +16 -21
- package/dist/sources/providers/git-provider.js +2 -9
- package/dist/sources/providers/provider-utils.js +13 -5
- package/dist/sources/resolve.js +12 -16
- package/dist/sources/snapshot-fetchers/robots.js +11 -12
- package/dist/sources/snapshot-fetchers/secret-seam.js +2 -4
- package/dist/sources/snapshot-fetchers/website-ingest.js +8 -15
- package/dist/sources/snapshot-fetchers/x.js +1 -1
- package/dist/standalone/onnxruntime-library.js +52 -0
- package/dist/storage/repositories/improve-ledger-repository.js +1 -1
- package/dist/storage/repositories/improve-runs-repository.js +0 -13
- package/dist/storage/repositories/index-entries-repository.js +2 -2
- package/dist/storage/repositories/proposals-repository.js +2 -2
- package/dist/storage/repositories/task-history-repository.js +2 -2
- package/dist/storage/repositories/workflow-runs-repository.js +44 -129
- package/dist/storage/sqlite-read-snapshot.js +33 -29
- package/dist/tasks/embedded.js +1 -1
- package/dist/tasks/log-redaction.js +7 -119
- package/dist/tasks/prepare/prepare-support.js +8 -7
- package/dist/tasks/prepare/prepare.js +8 -9
- package/dist/tasks/prepare/script-capture.js +9 -25
- package/dist/tasks/run/attempt-lifecycle.js +17 -35
- package/dist/tasks/run/load-task.js +54 -27
- package/dist/tasks/run/run-command-task.js +15 -10
- package/dist/tasks/run/run-native-task.js +8 -21
- package/dist/tasks/run/run-task.js +5 -8
- package/dist/tasks/run/run-workflow-task.js +14 -21
- package/dist/tasks/run/task-history.js +9 -17
- package/dist/tasks/run/task-log.js +1 -5
- package/dist/tasks/scheduler-invocation.js +13 -18
- package/dist/tasks/scheduler-sync.js +0 -1
- package/dist/tasks/source/bounded-document.js +31 -117
- package/dist/tasks/source/parse-task-source.js +0 -1
- package/dist/tasks/source/project-v4.js +5 -3
- package/dist/tasks/source/task-input-diagnostics.js +3 -4
- package/dist/tasks/source/task-source-v4.js +48 -72
- package/dist/tasks/source-v3.js +2 -5
- package/dist/tasks/task-run-reserved-flags.js +1 -2
- package/dist/workflows/authoring/authoring.js +2 -7
- package/dist/workflows/compile.js +1 -15
- package/dist/workflows/concurrency-policy.js +4 -4
- package/dist/workflows/exec/child-workflow.js +1 -4
- package/dist/workflows/exec/dispatch-redaction.js +35 -86
- package/dist/workflows/exec/environment.js +13 -77
- package/dist/workflows/exec/exec-unit.js +14 -55
- package/dist/workflows/exec/frozen-judge.js +26 -28
- package/dist/workflows/exec/native-executor.js +126 -71
- package/dist/workflows/exec/run-workflow.js +38 -42
- package/dist/workflows/exec/step-work.js +13 -17
- package/dist/workflows/exec/unit-dispatch.js +7 -21
- package/dist/workflows/freeze/environment.js +14 -119
- package/dist/workflows/freeze/freeze.js +14 -33
- package/dist/workflows/freeze/step-values.js +6 -13
- package/dist/workflows/freeze/targets/child-workflow.js +3 -5
- package/dist/workflows/freeze/targets/command.js +9 -15
- package/dist/workflows/freeze/targets/shell.js +0 -3
- package/dist/workflows/freeze/task-bindings.js +0 -1
- package/dist/workflows/parser.js +50 -59
- package/dist/workflows/plan.js +8 -2
- package/dist/workflows/renderer.js +83 -9
- package/dist/workflows/resource-limits.js +2 -2
- package/dist/workflows/runtime/run-plan.js +38 -23
- package/dist/workflows/runtime/runs.js +55 -93
- package/dist/workflows/runtime/workflow-asset-loader.js +55 -86
- package/dist/workflows/source-files.js +7 -19
- package/docs/README.md +10 -16
- package/docs/architecture/README.md +2 -37
- package/docs/architecture/adapters.md +2 -2
- package/docs/architecture/akm-core-principles.md +256 -118
- package/docs/architecture/architecture.md +283 -99
- package/docs/architecture/improvement.md +8 -2
- package/docs/architecture/internals/classification.md +1 -3
- package/docs/architecture/internals/fresh-host-rebuild-runbook.md +7 -6
- package/docs/architecture/internals/health-advisories.md +35 -74
- package/docs/architecture/internals/improve-workflow.md +27 -26
- package/docs/architecture/internals/indexing.md +3 -3
- package/docs/architecture/internals/storage-locations.md +48 -15
- package/docs/architecture/persisted-data-compat.md +10 -6
- package/docs/architecture/specs/okf-support.md +9 -11
- package/docs/architecture/specs/ref.md +7 -9
- package/docs/architecture/testing/testing-workflow.md +172 -52
- package/docs/architecture/workflow-engine.md +51 -34
- package/docs/guides/README.md +0 -1
- package/docs/guides/author-bundles.md +15 -20
- package/docs/guides/author-workflows.md +93 -71
- package/docs/guides/bundles.md +20 -16
- package/docs/guides/discover-and-load.md +1 -1
- package/docs/guides/getting-started.md +49 -3
- package/docs/guides/improve-the-library.md +10 -4
- package/docs/guides/recipes/headless-install.md +11 -16
- package/docs/guides/run-workflows.md +29 -20
- package/docs/guides/scheduling.md +2 -2
- package/docs/guides/use-with-any-agent.md +20 -22
- package/docs/integration/bundling-akm.md +19 -9
- package/docs/maintainers/README.md +2 -6
- package/docs/maintainers/release-checklist.md +73 -126
- package/docs/migration/README.md +10 -3
- package/docs/migration/release-notes/0.10.0.md +81 -16
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +1 -1
- package/docs/migration/release-notes/README.md +1 -1
- package/docs/migration/v0.9-to-v0.10.md +300 -60
- package/docs/migration/v0.9.1-to-v0.9.2.md +6 -5
- package/docs/posts/config-v2-lessons-16.md +1 -1
- package/docs/posts/llm-mode-reflect-13.md +1 -1
- package/docs/posts/release-0.6.0.md +11 -11
- package/docs/posts/release-0.8.0.md +4 -4
- package/docs/posts/workflows-vaults-09.md +1 -1
- package/docs/reference/README.md +1 -1
- package/docs/reference/asset-types.md +2 -2
- package/docs/reference/cli.md +477 -388
- package/docs/reference/configuration.md +569 -550
- package/docs/reference/data-and-telemetry.md +9 -6
- package/docs/reference/env-and-secrets.md +72 -15
- package/docs/reference/refs.md +3 -20
- package/docs/reference/registry.md +12 -38
- package/docs/reference/supported-formats.md +1 -1
- package/docs/reference/tasks.md +22 -11
- package/docs/reference/ui-api.md +14 -9
- package/docs/reference/workflow-schema.md +199 -154
- package/docs/reference/workflows.md +4 -6
- package/package.json +9 -11
- package/schemas/akm-config.json +1696 -2922
- package/schemas/akm-task.json +4 -4
- package/schemas/akm-workflow.json +36 -9
- package/ROADMAP.md +0 -112
- package/dist/assets/models.json +0 -35
- package/dist/commands/health/engine-usage.js +0 -45
- package/dist/commands/sources/dangerous-env-audit.js +0 -134
- package/dist/core/activation-policy.js +0 -67
- package/dist/core/config/schema/engines.js +0 -160
- package/dist/core/config/schema/execution.js +0 -23
- package/dist/core/spawn-env.js +0 -268
- package/dist/execution/directory-identity.js +0 -78
- package/dist/integrations/agent/builder-shared.js +0 -33
- package/dist/integrations/agent/builders.js +0 -43
- package/dist/integrations/agent/engine-fallback.js +0 -59
- package/dist/integrations/agent/engine-resolution.js +0 -333
- package/dist/integrations/agent/model-map.js +0 -475
- package/dist/integrations/harnesses/aider/agent-builder.js +0 -107
- package/dist/integrations/harnesses/aider/result-extractor.js +0 -53
- package/dist/integrations/harnesses/amazonq/agent-builder.js +0 -138
- package/dist/integrations/harnesses/amazonq/result-extractor.js +0 -48
- package/dist/integrations/harnesses/claude/agent-builder.js +0 -106
- package/dist/integrations/harnesses/claude/config-import.js +0 -67
- package/dist/integrations/harnesses/claude/result-extractor.js +0 -67
- package/dist/integrations/harnesses/codex/agent-builder.js +0 -150
- package/dist/integrations/harnesses/codex/result-extractor.js +0 -110
- package/dist/integrations/harnesses/copilot/agent-builder.js +0 -117
- package/dist/integrations/harnesses/copilot/result-extractor.js +0 -178
- package/dist/integrations/harnesses/gemini/agent-builder.js +0 -114
- package/dist/integrations/harnesses/gemini/result-extractor.js +0 -149
- package/dist/integrations/harnesses/opencode/config-import.js +0 -149
- package/dist/integrations/harnesses/opencode/model-config.js +0 -33
- package/dist/integrations/harnesses/opencode/model-work-agent.js +0 -115
- package/dist/integrations/harnesses/opencode/session-log-types.js +0 -12
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -44
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +0 -1052
- package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +0 -199
- package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +0 -254
- package/dist/integrations/harnesses/opencode-sdk/wire.js +0 -66
- package/dist/integrations/harnesses/openhands/agent-builder.js +0 -120
- package/dist/integrations/harnesses/openhands/result-extractor.js +0 -135
- package/dist/integrations/harnesses/pi/agent-builder.js +0 -89
- package/dist/integrations/harnesses/pi/result-extractor.js +0 -168
- package/dist/integrations/harnesses/shared.js +0 -18
- package/dist/integrations/harnesses/types.js +0 -55
- package/dist/llm/feature-gate.js +0 -115
- package/dist/output/shapes/models-list.js +0 -16
- package/dist/output/shapes/registry-search.js +0 -10
- package/dist/setup/detected-engines.js +0 -136
- package/dist/setup/engine-config.js +0 -97
- package/dist/setup/harness-config-import.js +0 -47
- package/dist/setup/providers.js +0 -14
- package/dist/setup/steps/semantic.js +0 -39
- package/dist/workflows/authoring/scope-key.js +0 -79
- package/dist/workflows/exec/lowering-notices.js +0 -23
- package/dist/workflows/source-semantics.js +0 -110
- package/docs/architecture/0.10-process-rules.md +0 -832
- package/docs/architecture/akm-architecture-decision-history.md +0 -2055
- package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +0 -550
- package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +0 -72
- package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +0 -142
- package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +0 -189
- package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +0 -97
- package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +0 -108
- package/docs/architecture/decisions/0006-task-source-version-routing.md +0 -124
- package/docs/architecture/decisions/0007-workflow-composition-bounds.md +0 -83
- package/docs/architecture/decisions/0008-task-binding-normalization.md +0 -88
- package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +0 -80
- package/docs/architecture/decisions/0010-driver-protocol-cut.md +0 -36
- package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +0 -125
- package/docs/architecture/decisions/README.md +0 -62
- package/docs/architecture/internals/functional-contract-patterns.md +0 -340
- package/docs/architecture/internals/registry-network-boundary.md +0 -57
- package/docs/architecture/internals/search.md +0 -248
- package/docs/architecture/reviews/env-secret-access.md +0 -319
- package/docs/architecture/runtime-boundary-design.md +0 -153
- package/docs/architecture/specs/0.9.0-close-out-plan.md +0 -361
- package/docs/architecture/specs/0.9.0-decisions.md +0 -532
- package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +0 -745
- package/docs/architecture/specs/0.9.0-open-items-register.md +0 -135
- package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +0 -740
- package/docs/architecture/specs/0.9.0-release-surface-review.md +0 -636
- package/docs/architecture/specs/agent-command-engine-model-design.md +0 -513
- package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +0 -501
- package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +0 -291
- package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +0 -2059
- package/docs/architecture/specs/di-seams-plan.md +0 -539
- package/docs/architecture/specs/driver-protocol-keep-or-cut.md +0 -275
- package/docs/architecture/specs/fact-asset-type.md +0 -142
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +0 -634
- package/docs/architecture/specs/reviews/task-workflow-unification/README.md +0 -72
- package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +0 -152
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +0 -352
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +0 -300
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +0 -402
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +0 -758
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +0 -645
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +0 -602
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +0 -74
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +0 -15
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +0 -132
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +0 -147
- package/docs/architecture/specs/stash-conventions-code-spec.md +0 -275
- package/docs/architecture/specs/stash-organization-conventions.md +0 -377
- package/docs/architecture/specs/task-workflow-format-unification.md +0 -721
- package/docs/architecture/specs/workflow-engine-buy-vs-build.md +0 -231
- package/docs/architecture/specs/workflow-format-unification.md +0 -432
- package/docs/architecture/testing/manual-testing-checklist.md +0 -3411
- package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +0 -924
- package/docs/architecture/testing/task-workflow-manual-tests.md +0 -1720
- package/docs/guides/claude-code-vs-akm-workflows.md +0 -29
- package/docs/guides/knowledge-management.md +0 -18
- package/docs/maintainers/curate-workmap.md +0 -335
- package/docs/migration/v0.5-to-v0.6.md +0 -759
- package/docs/migration/v0.7-to-v0.8.md +0 -1378
- package/docs/plans/0.9.2-agent-command-workflow-plan.md +0 -423
package/dist/sources/resolve.js
CHANGED
|
@@ -6,11 +6,14 @@ import path from "node:path";
|
|
|
6
6
|
import { recognizeMatch } from "../core/adapter/recognize-match.js";
|
|
7
7
|
import { assetPathForName, deriveCanonicalAssetNameFromStashRoot, isRelevantAssetFile, stashDirFor, } from "../core/asset/asset-placement.js";
|
|
8
8
|
import { conceptIdFromTypeName } from "../core/asset/resolve-ref.js";
|
|
9
|
-
import { hasErrnoCode,
|
|
9
|
+
import { hasErrnoCode, isContainedResolvedPath } from "../core/common.js";
|
|
10
10
|
import { NotFoundError, UsageError } from "../core/errors.js";
|
|
11
11
|
import { walkStashFlat } from "../indexer/walk/walker.js";
|
|
12
12
|
/**
|
|
13
|
-
* Resolve an asset path from a stash directory, type, and name.
|
|
13
|
+
* Resolve an asset path from a stash directory, type, and name. The path keeps
|
|
14
|
+
* the authored spelling, not the symlink target's: an asset that links to a
|
|
15
|
+
* file with another name (or none) is still the kind its own name says, and a
|
|
16
|
+
* read through it reaches the same bytes.
|
|
14
17
|
*/
|
|
15
18
|
export async function resolveAssetPath(stashDir, type, name) {
|
|
16
19
|
try {
|
|
@@ -31,25 +34,24 @@ export async function resolveAssetPath(stashDir, type, name) {
|
|
|
31
34
|
function resolveInTypeDir(stashDir, typeDir, type, name) {
|
|
32
35
|
const root = path.join(stashDir, typeDir);
|
|
33
36
|
const target = assetPathForName(type, root, name);
|
|
34
|
-
|
|
37
|
+
resolveAndValidateTypeRoot(root, type, name);
|
|
35
38
|
const resolvedTarget = path.resolve(target);
|
|
36
|
-
|
|
39
|
+
// Name grammar: the name must not climb out of the type directory (`..` or
|
|
40
|
+
// an absolute name). Lexical only: an asset that is a symlink to a file
|
|
41
|
+
// elsewhere resolves, because installing a bundle is the trust decision.
|
|
42
|
+
if (!isContainedResolvedPath(resolvedTarget, path.resolve(root))) {
|
|
37
43
|
throw new UsageError("Ref resolves outside the stash root.", "PATH_ESCAPE_VIOLATION");
|
|
38
44
|
}
|
|
39
45
|
if (!fs.existsSync(resolvedTarget) || !fs.statSync(resolvedTarget).isFile()) {
|
|
40
46
|
throw new NotFoundError(`Stash asset not found for ref: ${conceptIdFromTypeName(type, name)}`, "ASSET_NOT_FOUND");
|
|
41
47
|
}
|
|
42
|
-
const realTarget = fs.realpathSync(resolvedTarget);
|
|
43
|
-
if (!isWithin(realTarget, resolvedRoot)) {
|
|
44
|
-
throw new UsageError("Ref resolves outside the stash root.", "PATH_ESCAPE_VIOLATION");
|
|
45
|
-
}
|
|
46
48
|
if (!isRelevantAssetFile(type, path.basename(resolvedTarget))) {
|
|
47
49
|
if (type === "script") {
|
|
48
50
|
throw new NotFoundError("Script ref must resolve to a file with a supported script extension. Refer to the akm documentation for the complete list of supported script extensions.");
|
|
49
51
|
}
|
|
50
52
|
throw new NotFoundError(`Stash asset not found for ref: ${conceptIdFromTypeName(type, name)}`, "ASSET_NOT_FOUND");
|
|
51
53
|
}
|
|
52
|
-
return
|
|
54
|
+
return resolvedTarget;
|
|
53
55
|
}
|
|
54
56
|
function resolveAndValidateTypeRoot(root, type, name) {
|
|
55
57
|
const rootStat = readTypeRootStat(root, type, name);
|
|
@@ -57,7 +59,6 @@ function resolveAndValidateTypeRoot(root, type, name) {
|
|
|
57
59
|
throw new NotFoundError(`Asset directory for ${type} assets is not accessible — got a file where a directory was expected for ref: ${conceptIdFromTypeName(type, name)}. ` +
|
|
58
60
|
"Run `akm index` to rebuild the index, or check your source configuration.", "ASSET_NOT_FOUND", "Run `akm bundle list` to see your configured sources and verify the source path exists.");
|
|
59
61
|
}
|
|
60
|
-
return fs.realpathSync(root);
|
|
61
62
|
}
|
|
62
63
|
function readTypeRootStat(root, type, name) {
|
|
63
64
|
try {
|
|
@@ -79,12 +80,7 @@ async function resolveByCanonicalName(stashDir, type, name) {
|
|
|
79
80
|
const canonicalName = deriveCanonicalAssetNameFromStashRoot(type, stashDir, ctx.absPath);
|
|
80
81
|
if (canonicalName !== normalizedName)
|
|
81
82
|
continue;
|
|
82
|
-
|
|
83
|
-
const resolvedRoot = fs.realpathSync(stashDir);
|
|
84
|
-
if (!isWithin(realTarget, resolvedRoot)) {
|
|
85
|
-
throw new UsageError("Ref resolves outside the stash root.", "PATH_ESCAPE_VIOLATION");
|
|
86
|
-
}
|
|
87
|
-
return realTarget;
|
|
83
|
+
return ctx.absPath;
|
|
88
84
|
}
|
|
89
85
|
return undefined;
|
|
90
86
|
}
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* robots.txt parsing, matching, and a crawl-scoped fetch/cache policy.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* module is a clean rewrite against akm's contracts, not a port of any
|
|
7
|
+
* This module is a clean rewrite against akm's contracts, not a port of any
|
|
9
8
|
* upstream source file.
|
|
10
9
|
*
|
|
11
10
|
* Pure by design: no fetching happens here (see `RobotsTxtLoader`/
|
|
@@ -14,7 +13,7 @@
|
|
|
14
13
|
* `createRobotsPolicy` returns so it dies with the crawl that created it —
|
|
15
14
|
* a module-level `origin -> RobotsRuleSet` map would leak `disallowAll`
|
|
16
15
|
* results across crawls and across the test suite's process-wide `bun test`
|
|
17
|
-
* run
|
|
16
|
+
* run. The module-level `WeakMap` below is a different
|
|
18
17
|
* category: it memoizes a pure function of an individual rule object's own
|
|
19
18
|
* `pattern` field, keyed by that object's identity. It cannot leak meaning
|
|
20
19
|
* between origins or tests — distinct `parseRobotsTxt` calls (even for
|
|
@@ -40,7 +39,7 @@ export const ROBOTS_USER_AGENT_HEADER = "akm-cli website provider";
|
|
|
40
39
|
/**
|
|
41
40
|
* Frozen so a stray mutation (e.g. an accidental `.rules.push(...)` somewhere
|
|
42
41
|
* that borrows one of these as a starting point) can never poison every other
|
|
43
|
-
* crawl sharing this instance
|
|
42
|
+
* crawl sharing this instance.
|
|
44
43
|
*/
|
|
45
44
|
const EMPTY_ROBOTS_RULES = Object.freeze([]);
|
|
46
45
|
export const ALLOW_ALL_RULES = Object.freeze({
|
|
@@ -128,8 +127,8 @@ export function parseRobotsTxt(text) {
|
|
|
128
127
|
pattern: value,
|
|
129
128
|
specificity: value.length,
|
|
130
129
|
};
|
|
131
|
-
// Compile once, here, at parse time — not on every URL check
|
|
132
|
-
//
|
|
130
|
+
// Compile once, here, at parse time — not on every URL check. See
|
|
131
|
+
// `compiledPatternCache`.
|
|
133
132
|
compiledPatternCache.set(rule, compilePatternSegments(value));
|
|
134
133
|
current.rules.push(rule);
|
|
135
134
|
continue;
|
|
@@ -185,7 +184,7 @@ function isUnreservedByte(byte) {
|
|
|
185
184
|
* fallback) and match targets (`isPathAllowedByRobots`), so a percent-encoded
|
|
186
185
|
* alias of a disallowed path — e.g. a link written as `/%73ecret/` — cannot
|
|
187
186
|
* bypass `Disallow: /secret/` simply because `URL.pathname` preserves
|
|
188
|
-
* %-escapes verbatim. Reserved-octet patterns like
|
|
187
|
+
* %-escapes verbatim. Reserved-octet patterns like
|
|
189
188
|
* `/caf%C3%A9` are untouched on both sides (0xC3/0xA9 are not unreserved),
|
|
190
189
|
* so they keep matching themselves exactly as before.
|
|
191
190
|
*/
|
|
@@ -211,10 +210,10 @@ function compilePatternSegments(pattern) {
|
|
|
211
210
|
}
|
|
212
211
|
/**
|
|
213
212
|
* Per-rule-object cache of the compiled pattern (see the file-level doc
|
|
214
|
-
* comment for why this is not "module-level state" in the sense
|
|
215
|
-
*
|
|
216
|
-
* each `RobotsPathRule` — the compile-once requirement
|
|
217
|
-
*
|
|
213
|
+
* comment for why this is not "module-level state" in the sense that comment
|
|
214
|
+
* rules out). `parseRobotsTxt` populates this eagerly, once, when it creates
|
|
215
|
+
* each `RobotsPathRule` — the compile-once requirement.
|
|
216
|
+
* `compiledPatternFor` below is a defensive
|
|
218
217
|
* fallback for `RobotsRuleSet`s assembled by hand (e.g. test fixtures)
|
|
219
218
|
* rather than via `parseRobotsTxt`; it still compiles at most once per rule
|
|
220
219
|
* object, just lazily on first use instead of at parse time.
|
|
@@ -324,7 +323,7 @@ export function createRobotsPolicy(load) {
|
|
|
324
323
|
const pending = load(robotsUrl).then(outcomeToRuleSet);
|
|
325
324
|
// A rejected fetch must not poison the cache: the next lookup for this
|
|
326
325
|
// origin should retry the loader rather than replaying the same failure
|
|
327
|
-
// forever
|
|
326
|
+
// forever.
|
|
328
327
|
pending.catch(() => {
|
|
329
328
|
if (cache.get(origin) === pending)
|
|
330
329
|
cache.delete(origin);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import fs from "node:fs";
|
|
5
4
|
import { resolveSecretPath } from "../../core/env-secret-ref.js";
|
|
5
|
+
import { readValue } from "../../core/secret-value.js";
|
|
6
6
|
/**
|
|
7
7
|
* Reads a secret out of akm's secret store for the fetcher `resolveSecret`
|
|
8
8
|
* seam (see `FetcherContext.resolveSecret`).
|
|
@@ -21,9 +21,7 @@ import { resolveSecretPath } from "../../core/env-secret-ref.js";
|
|
|
21
21
|
export function resolveSecretFromStore(ref) {
|
|
22
22
|
try {
|
|
23
23
|
const { absPath } = resolveSecretPath(ref);
|
|
24
|
-
|
|
25
|
-
return null;
|
|
26
|
-
return fs.readFileSync(absPath, "utf8").trim() || null;
|
|
24
|
+
return readValue(absPath) || null;
|
|
27
25
|
}
|
|
28
26
|
catch {
|
|
29
27
|
return null;
|
|
@@ -15,10 +15,6 @@ import { escapeMarkdownStructure } from "./fetcher-util.js";
|
|
|
15
15
|
import { assertResolvedHostAllowed, assertWebsiteRequestUrl } from "./host-guard.js";
|
|
16
16
|
import { loadWikiSnapshotFetchers } from "./registry.js";
|
|
17
17
|
import { createAllowAllRobotsPolicy, createRobotsPolicy, isPathAllowedByRobots, ROBOTS_BODY_TIMEOUT_MS, ROBOTS_BYTE_CAP, } from "./robots.js";
|
|
18
|
-
/** Refresh website snapshots every 12 hours to balance freshness with scraping load. */
|
|
19
|
-
const CACHE_REFRESH_INTERVAL_MS = 12 * 60 * 60 * 1000;
|
|
20
|
-
/** Allow up to 7 days of stale snapshots when refresh fails so search remains available during outages. */
|
|
21
|
-
const CACHE_STALE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
22
18
|
/** Allow limited breadth-first expansion without letting the crawl queue grow unbounded. */
|
|
23
19
|
const QUEUE_EXPANSION_FACTOR = 5;
|
|
24
20
|
const MAX_PAGES_DEFAULT = 50;
|
|
@@ -80,8 +76,6 @@ export async function ensureWebsiteMirror(config, options) {
|
|
|
80
76
|
const requireStashDir = options?.requireStashDir === true;
|
|
81
77
|
await withFreshnessCache({
|
|
82
78
|
markerPath: cachePaths.manifestPath,
|
|
83
|
-
ttlMs: CACHE_REFRESH_INTERVAL_MS,
|
|
84
|
-
staleMs: CACHE_STALE_MS,
|
|
85
79
|
force: options?.force === true,
|
|
86
80
|
isUsable: () => !requireStashDir || hasExtractedSite(cachePaths.stashDir),
|
|
87
81
|
refresh: async () => {
|
|
@@ -465,7 +459,7 @@ async function resolveCrawlRobotsDecision(robots, normalizedUrl, rawUrl) {
|
|
|
465
459
|
return decideRobotsAllowance(rules, normalizedUrl, rawUrl);
|
|
466
460
|
}
|
|
467
461
|
/**
|
|
468
|
-
*
|
|
462
|
+
* Fail fast, before any page fetch, when the start URL itself is
|
|
469
463
|
* off-limits per an actually-parsed robots.txt rule. A 5xx on robots.txt
|
|
470
464
|
* itself no longer reaches this as `disallowAll`: `loadRobotsTxt` reports it the same way a
|
|
471
465
|
* 4xx is reported (`ALLOW_ALL_RULES`), with its own warning, rather than
|
|
@@ -478,7 +472,7 @@ async function resolveCrawlRobotsDecision(robots, normalizedUrl, rawUrl) {
|
|
|
478
472
|
* `normalizeSiteUrl` stripped any trailing slash — via
|
|
479
473
|
* `decideRobotsAllowance`. Without this, a start URL typed as `.../secret/`
|
|
480
474
|
* under `Disallow: /secret/` would never match that rule and would be
|
|
481
|
-
* crawled instead of rejected with
|
|
475
|
+
* crawled instead of rejected with a UsageError; conversely,
|
|
482
476
|
* a start URL typed as `.../docs/` under `Disallow: / \n Allow: /docs/`
|
|
483
477
|
* would be normalized to `.../docs`, fail to match `Allow: /docs/`, and be
|
|
484
478
|
* rejected even though the site owner explicitly opened `/docs/` to
|
|
@@ -748,7 +742,7 @@ async function websitePageFromResponse(fetched, pageUrl, options) {
|
|
|
748
742
|
// `Disallow: /secret/` correctly lets `/secret` through that gate; if the
|
|
749
743
|
// server then redirects to `/secret/` (a common trailing-slash
|
|
750
744
|
// canonicalization), the disallowed page would otherwise be fetched and
|
|
751
|
-
// stored without ever being weighed against robots.txt.
|
|
745
|
+
// stored without ever being weighed against robots.txt.
|
|
752
746
|
// Checks `rawFinalUrl` (the un-normalized `response.url`, slash intact) as
|
|
753
747
|
// well as `finalUrl`, per `isCrawlUrlAllowedByRobots` — `normalizeCrawlUrl`
|
|
754
748
|
// would otherwise strip the very trailing slash a `Disallow: /secret/`
|
|
@@ -821,8 +815,7 @@ async function fetchWebsiteResponse(pageUrl, redirectCount = 0, options) {
|
|
|
821
815
|
// `/secret/` even when robots.txt disallows it, because that hop is
|
|
822
816
|
// never the queue URL and never the final URL. Only gated when a
|
|
823
817
|
// `RobotsPolicy` was actually threaded in (`crawlWebsite`); single-URL
|
|
824
|
-
// `fetchWebsiteMarkdownSnapshot` fetches stay deliberately ungated
|
|
825
|
-
// spec §1.
|
|
818
|
+
// `fetchWebsiteMarkdownSnapshot` fetches stay deliberately ungated.
|
|
826
819
|
if (options?.robots) {
|
|
827
820
|
const normalizedNext = normalizeCrawlUrl(nextUrl);
|
|
828
821
|
if (!normalizedNext) {
|
|
@@ -850,15 +843,15 @@ async function fetchWebsiteResponse(pageUrl, redirectCount = 0, options) {
|
|
|
850
843
|
}
|
|
851
844
|
/**
|
|
852
845
|
* Fetches and classifies `<origin>/robots.txt`. Reuses `fetchWebsiteResponse`
|
|
853
|
-
* (
|
|
846
|
+
* (no second fetch path) so robots.txt gets the exact same SSRF
|
|
854
847
|
* guards, retry, and redirect handling as a page fetch.
|
|
855
848
|
*
|
|
856
849
|
* Steps 1–2 (the guard on the INITIAL URL) run OUTSIDE the try/catch on
|
|
857
850
|
* purpose: a guard rejection there must propagate as-is, never be downgraded
|
|
858
|
-
* to "unavailable"
|
|
851
|
+
* to "unavailable". Guard rejections on a LATER
|
|
859
852
|
* redirect hop happen inside `fetchWebsiteResponse`, which the try/catch
|
|
860
853
|
* below does cover — the guard has already refused to fetch that host, so
|
|
861
|
-
* only the error *reporting* is downgraded
|
|
854
|
+
* only the error *reporting* is downgraded.
|
|
862
855
|
*/
|
|
863
856
|
export async function loadRobotsTxt(robotsUrl, options) {
|
|
864
857
|
assertWebsiteRequestUrl(robotsUrl, UsageError, options);
|
|
@@ -883,7 +876,7 @@ export async function loadRobotsTxt(robotsUrl, options) {
|
|
|
883
876
|
}
|
|
884
877
|
if (response.status >= 500 && response.status < 600) {
|
|
885
878
|
await response.body?.cancel().catch(() => undefined);
|
|
886
|
-
//
|
|
879
|
+
// RFC 9309 §2.3.1.4 recommends treating an
|
|
887
880
|
// unreachable robots.txt as a full disallow, but for a personal tool
|
|
888
881
|
// crawling a site the operator explicitly chose, a transient 5xx on
|
|
889
882
|
// the site's OWN robots.txt is not a site owner's Disallow — it is the
|
|
@@ -89,7 +89,7 @@ export function resolveXBearerToken(context) {
|
|
|
89
89
|
if (fromEnv)
|
|
90
90
|
return fromEnv;
|
|
91
91
|
try {
|
|
92
|
-
return context?.resolveSecret?.(X_BEARER_TOKEN_SECRET_REF)
|
|
92
|
+
return context?.resolveSecret?.(X_BEARER_TOKEN_SECRET_REF) || null;
|
|
93
93
|
}
|
|
94
94
|
catch {
|
|
95
95
|
return null;
|
|
@@ -0,0 +1,52 @@
|
|
|
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 ONNX Runtime shared library for a compiled standalone binary.
|
|
6
|
+
*
|
|
7
|
+
* `onnxruntime-node`'s addon links a shared library that sits beside it in the
|
|
8
|
+
* package. A Bun executable extracts an embedded addon at load but not the
|
|
9
|
+
* library it links, so the addon cannot start. The standalone build embeds the
|
|
10
|
+
* library for its target (`src/standalone/native/`, chosen by
|
|
11
|
+
* `scripts/build-standalone.ts`); this copies it once into akm's cache and
|
|
12
|
+
* loads it with `bun:ffi`, after which the addon's own link to it is already
|
|
13
|
+
* satisfied.
|
|
14
|
+
*
|
|
15
|
+
* Outside a standalone binary (`bun src/cli.ts`, the Node build) nothing here
|
|
16
|
+
* is defined and nothing is evaluated: the package's own files are used.
|
|
17
|
+
*/
|
|
18
|
+
import fs from "node:fs";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
import { getCacheDir } from "../core/paths.js";
|
|
21
|
+
/**
|
|
22
|
+
* Put the embedded library on disk and load it, before `onnxruntime-node` is
|
|
23
|
+
* imported. Throws when the library cannot be loaded; the caller reports that
|
|
24
|
+
* as the embedding runtime being unavailable.
|
|
25
|
+
*/
|
|
26
|
+
export async function preloadOnnxRuntimeLibrary() {
|
|
27
|
+
if (typeof AKM_STANDALONE_NATIVE_MODULE === "undefined")
|
|
28
|
+
return;
|
|
29
|
+
// The specifier is a build constant, so the standalone build bundles this one module and no other build bundles any.
|
|
30
|
+
const { embeddedPath, fileName } = (await import(AKM_STANDALONE_NATIVE_MODULE));
|
|
31
|
+
if (!embeddedPath || !fileName)
|
|
32
|
+
return;
|
|
33
|
+
const directory = path.join(getCacheDir(), "onnxruntime", `${AKM_ONNXRUNTIME_VERSION}-${process.platform}-${process.arch}`);
|
|
34
|
+
const library = path.join(directory, fileName);
|
|
35
|
+
const size = fs.statSync(embeddedPath).size;
|
|
36
|
+
if (!fs.existsSync(library) || fs.statSync(library).size !== size) {
|
|
37
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
38
|
+
const partial = `${library}.${process.pid}.tmp`;
|
|
39
|
+
fs.writeFileSync(partial, fs.readFileSync(embeddedPath));
|
|
40
|
+
try {
|
|
41
|
+
fs.renameSync(partial, library);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
// Another akm process copied it first and has it loaded, which Windows will not replace: use that copy.
|
|
45
|
+
fs.rmSync(partial, { force: true });
|
|
46
|
+
if (!fs.existsSync(library) || fs.statSync(library).size !== size)
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const { dlopen } = await import("bun:ffi");
|
|
51
|
+
dlopen(library, { OrtGetApiBase: { args: [], returns: "ptr" } });
|
|
52
|
+
}
|
|
@@ -233,7 +233,7 @@ export function forgetImproveLedgerDecision(db, stashDir, proposalId) {
|
|
|
233
233
|
db.prepare("DELETE FROM improve_ledger WHERE stash_dir = ? AND proposal_id = ?").run(stashDir, proposalId);
|
|
234
234
|
}
|
|
235
235
|
/**
|
|
236
|
-
*
|
|
236
|
+
* A read-only or dry-run open never
|
|
237
237
|
* migrates, so it can land on a state.db from before migration 029 added
|
|
238
238
|
* `content_hash` — reading it there threw "no such column", which
|
|
239
239
|
* `loadRetrievalScope`'s own catch then reported as "usage history
|
|
@@ -127,19 +127,6 @@ export function listRecentImproveRuns(db, limit) {
|
|
|
127
127
|
.prepare("SELECT id, started_at, completed_at, ok, scope_mode, scope_value, strategy, result_json FROM improve_runs WHERE dry_run = 0 ORDER BY started_at DESC LIMIT ?")
|
|
128
128
|
.all(limit);
|
|
129
129
|
}
|
|
130
|
-
/**
|
|
131
|
-
* #950: count real (non-dry-run) improve_runs rows whose `started_at` falls
|
|
132
|
-
* in `[since, now)` — same filter as {@link queryImproveRuns}, but a `SELECT
|
|
133
|
-
* COUNT(*)` for a caller (the `engine-last-used` gate) that only needs to
|
|
134
|
-
* know whether any run happened, not the rows themselves (which would pull
|
|
135
|
-
* every `result_json` blob in the window just to test for zero).
|
|
136
|
-
*/
|
|
137
|
-
export function countImproveRunsSince(db, since) {
|
|
138
|
-
const row = db
|
|
139
|
-
.prepare("SELECT COUNT(*) AS cnt FROM improve_runs WHERE started_at >= ? AND dry_run = 0")
|
|
140
|
-
.get(since);
|
|
141
|
-
return row.cnt;
|
|
142
|
-
}
|
|
143
130
|
/**
|
|
144
131
|
* Delete improve_runs rows older than `retentionDays` (default: 90). Mirrors
|
|
145
132
|
* {@link purgeOldEvents} — same default, same return shape (number of rows
|
|
@@ -760,10 +760,10 @@ export function isRefLiveInSnapshot(snapshot, ref) {
|
|
|
760
760
|
}
|
|
761
761
|
/**
|
|
762
762
|
* The fully-qualified `item_ref` (`<bundle>//<conceptId>`, the durable stored
|
|
763
|
-
* spelling
|
|
763
|
+
* spelling) for an entry `id`, or `null` when the row is gone.
|
|
764
764
|
* The usage-event / salience / feedback writers derive the durable
|
|
765
765
|
* key from this so a stored key is always the resolved entry's canonical ref,
|
|
766
|
-
* never raw input (
|
|
766
|
+
* never raw input (durable keys are never derived from input).
|
|
767
767
|
*/
|
|
768
768
|
export function getItemRefById(db, id) {
|
|
769
769
|
const row = db.prepare("SELECT item_ref FROM entries WHERE id = ?").get(id);
|
|
@@ -525,8 +525,8 @@ export function renameProposalsBundleRef(db, oldBundleId, newBundleId) {
|
|
|
525
525
|
const prefix = `${escapeLikePattern(oldBundleId)}//`;
|
|
526
526
|
return db.transaction(() => {
|
|
527
527
|
const refs = Number(db
|
|
528
|
-
.prepare(`UPDATE proposals SET ref = ? || substr(ref, ?) WHERE ref LIKE ? ESCAPE '\\'`)
|
|
529
|
-
.run(newBundleId, oldBundleId
|
|
528
|
+
.prepare(`UPDATE proposals SET ref = ? || substr(ref, length(?) + 1) WHERE ref LIKE ? ESCAPE '\\'`)
|
|
529
|
+
.run(newBundleId, oldBundleId, `${prefix}%`).changes);
|
|
530
530
|
const targets = Number(db
|
|
531
531
|
.prepare(`UPDATE proposals SET metadata_json = json_set(metadata_json, '$.proposedTarget.source', ?)
|
|
532
532
|
WHERE json_extract(metadata_json, '$.proposedTarget.source') = ?`)
|
|
@@ -221,6 +221,6 @@ export function countTaskHistoryTargetRefs(db, oldBundleId) {
|
|
|
221
221
|
export function renameTaskHistoryTargetRefs(db, oldBundleId, newBundleId) {
|
|
222
222
|
const prefix = `${escapeLikePattern(oldBundleId)}//`;
|
|
223
223
|
return Number(db
|
|
224
|
-
.prepare(`UPDATE task_history SET target_ref = ? || substr(target_ref, ?) WHERE target_ref LIKE ? ESCAPE '\\'`)
|
|
225
|
-
.run(newBundleId, oldBundleId
|
|
224
|
+
.prepare(`UPDATE task_history SET target_ref = ? || substr(target_ref, length(?) + 1) WHERE target_ref LIKE ? ESCAPE '\\'`)
|
|
225
|
+
.run(newBundleId, oldBundleId, `${prefix}%`).changes);
|
|
226
226
|
}
|
|
@@ -42,75 +42,10 @@ export class WorkflowRunsRepository {
|
|
|
42
42
|
return withImmediateTransaction(this.db, () => fn(this.db));
|
|
43
43
|
}
|
|
44
44
|
// ── reads (fully materialised) ─────────────────────────────────────────────
|
|
45
|
-
/**
|
|
46
|
-
* The top-level start guard `publishWorkflowRunV4` uses to refuse starting
|
|
47
|
-
* a SECOND active run of the same ref in the same scope. `AND
|
|
48
|
-
* parent_run_id IS NULL` (B-N10's FOURTH site, code-review round 4 finding
|
|
49
|
-
* 2 / Review log R2): a child run carries the PARENT's `scope_key` (P3a
|
|
50
|
-
* §5.2), so once a parent publishes a child of some ref, starting a
|
|
51
|
-
* TOP-LEVEL run of that same ref in that scope must never resolve to the
|
|
52
|
-
* child — the child is not "already an active run in this scope" from a
|
|
53
|
-
* fresh top-level invocation's point of view; the PARENT, if anything, is.
|
|
54
|
-
* Before this filter, `publishWorkflowRunV4` refused with
|
|
55
|
-
* `RESOURCE_ALREADY_EXISTS` naming the CHILD's own run id, instructing the
|
|
56
|
-
* operator to `akm workflow abandon` a child a parent is actively driving.
|
|
57
|
-
* For any database with no child rows the result is byte-identical, same
|
|
58
|
-
* as the other three B-N10 sites below.
|
|
59
|
-
*
|
|
60
|
-
* Always scope-local: `scopeKey` is a real scope, never "every scope" — see
|
|
61
|
-
* {@link findActiveRunOutsideScope} for the cross-scope warning's query.
|
|
62
|
-
*/
|
|
63
|
-
findActiveRunForScope(workflowRefs, scopeKey) {
|
|
64
|
-
const refs = typeof workflowRefs === "string" ? [workflowRefs] : [...workflowRefs];
|
|
65
|
-
if (refs.length === 0)
|
|
66
|
-
return undefined;
|
|
67
|
-
return this.db
|
|
68
|
-
.prepare(`SELECT id, current_step_id FROM workflow_runs WHERE workflow_ref IN (${refs.map(() => "?").join(", ")}) AND scope_key = ? AND status = 'active' AND parent_run_id IS NULL ORDER BY updated_at DESC, created_at DESC LIMIT 1`)
|
|
69
|
-
.get(...refs, scopeKey);
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* The cross-scope start warning's query (#942): the most recently active
|
|
73
|
-
* run of these refs OUTSIDE `scopeKey` — i.e. `scope_key IS NULL OR
|
|
74
|
-
* scope_key != scopeKey`, not merely "the most recent active run of these
|
|
75
|
-
* refs anywhere". A same-scope active row must never win the `LIMIT 1` and
|
|
76
|
-
* mask a DIFFERENT scope's run: with `--new`/`--force`, the caller's own
|
|
77
|
-
* active run could otherwise sort first (most recently updated) and hide a
|
|
78
|
-
* third scope's run entirely, so `startWorkflowRun` silently warned about
|
|
79
|
-
* nothing while a genuinely stale run in another scope went unreported.
|
|
80
|
-
* `findActiveRunForScope` deliberately stays scope-local and is never used
|
|
81
|
-
* for this purpose.
|
|
82
|
-
*/
|
|
83
|
-
findActiveRunOutsideScope(workflowRefs, scopeKey) {
|
|
84
|
-
const refs = typeof workflowRefs === "string" ? [workflowRefs] : [...workflowRefs];
|
|
85
|
-
if (refs.length === 0)
|
|
86
|
-
return undefined;
|
|
87
|
-
return (this.db
|
|
88
|
-
.prepare(`SELECT * FROM workflow_runs WHERE workflow_ref IN (${refs.map(() => "?").join(", ")}) AND (scope_key IS NULL OR scope_key != ?) AND status = 'active' AND parent_run_id IS NULL ORDER BY updated_at DESC, created_at DESC LIMIT 1`)
|
|
89
|
-
.get(...refs, scopeKey) ?? undefined);
|
|
90
|
-
}
|
|
91
45
|
getRunById(runId) {
|
|
92
46
|
return (this.db.prepare("SELECT * FROM workflow_runs WHERE id = ?").get(runId) ??
|
|
93
47
|
undefined);
|
|
94
48
|
}
|
|
95
|
-
/**
|
|
96
|
-
* The scope-attach lookup `akm workflow run <ref>` uses to find an
|
|
97
|
-
* in-progress top-level run to resume instead of starting a new one.
|
|
98
|
-
* `AND parent_run_id IS NULL` (B-N10): a child run must never be attached
|
|
99
|
-
* to directly through this path — a parent-driven child would then have
|
|
100
|
-
* TWO drivers. For any database with no child rows the result is
|
|
101
|
-
* byte-identical.
|
|
102
|
-
*
|
|
103
|
-
* Always scope-local: `scopeKey` is a real scope, never "every scope" — see
|
|
104
|
-
* {@link findActiveRunOutsideScope} for the cross-scope warning's query.
|
|
105
|
-
*/
|
|
106
|
-
getActiveRunRowForScope(workflowRefs, scopeKey) {
|
|
107
|
-
const refs = typeof workflowRefs === "string" ? [workflowRefs] : [...workflowRefs];
|
|
108
|
-
if (refs.length === 0)
|
|
109
|
-
return undefined;
|
|
110
|
-
return (this.db
|
|
111
|
-
.prepare(`SELECT * FROM workflow_runs WHERE workflow_ref IN (${refs.map(() => "?").join(", ")}) AND scope_key = ? AND status = 'active' AND parent_run_id IS NULL ORDER BY updated_at DESC, created_at DESC LIMIT 1`)
|
|
112
|
-
.get(...refs, scopeKey) ?? undefined);
|
|
113
|
-
}
|
|
114
49
|
hasRun(runId) {
|
|
115
50
|
const row = this.db.prepare("SELECT 1 FROM workflow_runs WHERE id = ? LIMIT 1").get(runId);
|
|
116
51
|
return !!row;
|
|
@@ -128,16 +63,9 @@ export class WorkflowRunsRepository {
|
|
|
128
63
|
}
|
|
129
64
|
throw new NotFoundError(`Workflow run "${prefix}" not found.`, "WORKFLOW_NOT_FOUND");
|
|
130
65
|
}
|
|
131
|
-
listRuns(filter) {
|
|
66
|
+
listRuns(filter = {}) {
|
|
132
67
|
const filters = [];
|
|
133
68
|
const params = [];
|
|
134
|
-
// `scopeKey: null` (#942) is "every scope" — the predicate is omitted
|
|
135
|
-
// rather than bound as SQL NULL (which would match nothing, since a real
|
|
136
|
-
// `scope_key` column value is never NULL for a fresh run).
|
|
137
|
-
if (filter.scopeKey !== null) {
|
|
138
|
-
filters.push("scope_key = ?");
|
|
139
|
-
params.push(filter.scopeKey);
|
|
140
|
-
}
|
|
141
69
|
if (filter.workflowRef) {
|
|
142
70
|
filters.push("workflow_ref = ?");
|
|
143
71
|
params.push(filter.workflowRef);
|
|
@@ -152,11 +80,7 @@ export class WorkflowRunsRepository {
|
|
|
152
80
|
// human `resume`), so it must never appear under `--active`, or a script
|
|
153
81
|
// treating `--active` output as executable work would pick up a blocked
|
|
154
82
|
// run (owner manual-validation finding 1). Blocked runs stay visible in
|
|
155
|
-
// plain `list` (all statuses) with their `blocked` status.
|
|
156
|
-
// active-OR-blocked scope semantics some call sites want (the `akm show`
|
|
157
|
-
// scope guard, which surfaces a blocked run as the scope's occupant) live
|
|
158
|
-
// in the SEPARATE {@link findActiveOrBlockedRunForScope} — never folded
|
|
159
|
-
// into this shared list filter.
|
|
83
|
+
// plain `list` (all statuses) with their `blocked` status.
|
|
160
84
|
filters.push("status = 'active'");
|
|
161
85
|
}
|
|
162
86
|
// B-N10: a child run is invisible to this scope query unless the caller
|
|
@@ -178,32 +102,20 @@ export class WorkflowRunsRepository {
|
|
|
178
102
|
getStep(runId, stepId) {
|
|
179
103
|
return this.db.prepare("SELECT * FROM workflow_run_steps WHERE run_id = ? AND step_id = ?").get(runId, stepId);
|
|
180
104
|
}
|
|
181
|
-
/**
|
|
182
|
-
* The `akm show` active-run guard: which run (if any) currently occupies
|
|
183
|
-
* this scope. `AND parent_run_id IS NULL` (B-N10) — a child a parent is
|
|
184
|
-
* driving must never be reported as "the" active run; the PARENT is. For
|
|
185
|
-
* any database with no child rows the result is byte-identical.
|
|
186
|
-
*/
|
|
187
|
-
findActiveOrBlockedRunForScope(scopeKey) {
|
|
188
|
-
return (this.db
|
|
189
|
-
.prepare("SELECT id, current_step_id, workflow_ref FROM workflow_runs WHERE scope_key = ? AND status IN ('active', 'blocked') AND parent_run_id IS NULL ORDER BY updated_at DESC LIMIT 1")
|
|
190
|
-
.get(scopeKey) ?? null);
|
|
191
|
-
}
|
|
192
105
|
// ── writes ─────────────────────────────────────────────────────────────────
|
|
193
106
|
insertRun(input) {
|
|
194
|
-
//
|
|
195
|
-
// this 12-column list is hand-duplicated by publishChildWorkflowRun's own
|
|
107
|
+
// This column list is hand-duplicated by publishChildWorkflowRun's own
|
|
196
108
|
// INSERT below, which extends it with parent_run_id/parent_unit_id/
|
|
197
|
-
// invocation_key
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
//
|
|
109
|
+
// invocation_key; one shared INSERT builder was deliberately not introduced.
|
|
110
|
+
// Keep both column lists in sync by hand. `scope_key` and
|
|
111
|
+
// `workflow_entry_id` are legacy columns: read tolerantly, never written
|
|
112
|
+
// (#1239), so a fresh row carries NULL in both.
|
|
201
113
|
this.db
|
|
202
114
|
.prepare(`INSERT INTO workflow_runs (
|
|
203
|
-
id, workflow_ref,
|
|
115
|
+
id, workflow_ref, workflow_title, status, params_json, current_step_id, created_at, updated_at,
|
|
204
116
|
agent_harness, agent_session_id
|
|
205
|
-
) VALUES (?, ?, ?,
|
|
206
|
-
.run(input.id, input.workflowRef, input.
|
|
117
|
+
) VALUES (?, ?, ?, 'active', ?, ?, ?, ?, ?, ?)`)
|
|
118
|
+
.run(input.id, input.workflowRef, input.workflowTitle, input.paramsJson, input.currentStepId, input.createdAt, input.updatedAt, input.agentHarness, input.agentSessionId);
|
|
207
119
|
}
|
|
208
120
|
insertSteps(steps) {
|
|
209
121
|
const insertStep = this.db.prepare(`INSERT INTO workflow_run_steps (
|
|
@@ -252,22 +164,6 @@ export class WorkflowRunsRepository {
|
|
|
252
164
|
*/
|
|
253
165
|
publishWorkflowRunV4(input) {
|
|
254
166
|
this.immediateTransaction((db) => {
|
|
255
|
-
if (!input.force) {
|
|
256
|
-
// The uniqueness guard must never silently skip its scope predicate
|
|
257
|
-
// (#942) — every real caller (`startWorkflowRun`) stamps a concrete
|
|
258
|
-
// scope key, so a null one here means the caller is misusing this
|
|
259
|
-
// top-level guard, not that scoping should be waived.
|
|
260
|
-
if (input.run.scopeKey === null) {
|
|
261
|
-
throw new Error("publishWorkflowRunV4: run.scopeKey must not be null for the scope uniqueness guard.");
|
|
262
|
-
}
|
|
263
|
-
const existing = this.findActiveRunForScope(input.workflowRefs, input.run.scopeKey);
|
|
264
|
-
if (existing) {
|
|
265
|
-
throw new UsageError(`Workflow ${input.run.workflowRef} already has an active run in this scope ` +
|
|
266
|
-
`(id=${existing.id}, scope=${input.run.scopeKey}, step=${existing.current_step_id ?? "—"}). ` +
|
|
267
|
-
`Use 'akm workflow run ${input.run.workflowRef}' to resume it or ` +
|
|
268
|
-
`'akm workflow abandon ${existing.id}' to give up on it.`, "RESOURCE_ALREADY_EXISTS");
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
167
|
this.insertRun(input.run);
|
|
272
168
|
this.insertSteps(input.steps);
|
|
273
169
|
db.prepare("UPDATE workflow_runs SET plan_json = ?, plan_hash = ?, plan_ir_version = ? WHERE id = ?").run(input.planJson, input.planHash, WORKFLOW_PLAN_VERSION, input.run.id);
|
|
@@ -294,13 +190,10 @@ export class WorkflowRunsRepository {
|
|
|
294
190
|
* (`plan_ir_version` = the current plan version), and append its
|
|
295
191
|
* `workflow_started` event — then return the freshly-inserted row.
|
|
296
192
|
*
|
|
297
|
-
*
|
|
298
|
-
* `RESOURCE_ALREADY_EXISTS` (top-level scope-conflict rules do not apply to
|
|
299
|
-
* a child), and reads no source: the child plan was frozen into the parent's.
|
|
193
|
+
* Reads no source: the child plan was frozen into the parent's.
|
|
300
194
|
*
|
|
301
195
|
* This method's serialization guarantee holds only when it is the
|
|
302
|
-
* OUTERMOST transaction on the connection
|
|
303
|
-
* docs/plans/specs/p3a-plan-v5-child-freeze.md). `withImmediateTransaction`
|
|
196
|
+
* OUTERMOST transaction on the connection. `withImmediateTransaction`
|
|
304
197
|
* (src/core/state-db.ts) has a re-entrancy guard: if a transaction is
|
|
305
198
|
* already open on the connection, it SILENTLY JOINS that transaction
|
|
306
199
|
* instead of issuing its own `BEGIN IMMEDIATE`.
|
|
@@ -318,11 +211,10 @@ export class WorkflowRunsRepository {
|
|
|
318
211
|
* same `(parentRunId, invocationKey)` serialize on SQLite's write lock: the
|
|
319
212
|
* first to acquire it inserts and commits, and the second's own SELECT —
|
|
320
213
|
* which can only run once it has acquired the lock in turn — finds and
|
|
321
|
-
* returns the first's row rather than inserting a duplicate or throwing
|
|
322
|
-
*
|
|
214
|
+
* returns the first's row rather than inserting a duplicate or throwing.
|
|
215
|
+
* Calling this twice with the same key, including across a crash
|
|
323
216
|
* between publish and parent-side recording, is therefore safe and returns
|
|
324
|
-
* the same child both times, with exactly one event and one step set
|
|
325
|
-
* (C-08).
|
|
217
|
+
* the same child both times, with exactly one event and one step set.
|
|
326
218
|
*/
|
|
327
219
|
publishChildWorkflowRun(input) {
|
|
328
220
|
return this.immediateTransaction((db) => {
|
|
@@ -331,15 +223,13 @@ export class WorkflowRunsRepository {
|
|
|
331
223
|
.get(input.parentRunId, input.invocationKey);
|
|
332
224
|
if (existing)
|
|
333
225
|
return existing;
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
// column list above (hand-duplicated, not shared, by deliberate choice
|
|
337
|
-
// — see docs/architecture/decisions/0009-child-run-publication-column-parity.md).
|
|
226
|
+
// The first 10 columns here must stay byte-identical to insertRun's own
|
|
227
|
+
// column list above (hand-duplicated, not shared, by deliberate choice).
|
|
338
228
|
// Keep both column lists in sync by hand.
|
|
339
229
|
db.prepare(`INSERT INTO workflow_runs (
|
|
340
|
-
id, workflow_ref,
|
|
230
|
+
id, workflow_ref, workflow_title, status, params_json, current_step_id, created_at, updated_at,
|
|
341
231
|
agent_harness, agent_session_id, parent_run_id, parent_unit_id, invocation_key
|
|
342
|
-
) VALUES (?, ?, ?,
|
|
232
|
+
) VALUES (?, ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.run.id, input.run.workflowRef, input.run.workflowTitle, input.run.paramsJson, input.run.currentStepId, input.run.createdAt, input.run.updatedAt, input.run.agentHarness, input.run.agentSessionId, input.parentRunId, input.spawnedByUnitId, input.invocationKey);
|
|
343
233
|
this.insertSteps(input.steps);
|
|
344
234
|
db.prepare("UPDATE workflow_runs SET plan_json = ?, plan_hash = ?, plan_ir_version = ? WHERE id = ?").run(input.planJson, input.planHash, WORKFLOW_PLAN_VERSION, input.run.id);
|
|
345
235
|
insertEventOnce(db, {
|
|
@@ -543,6 +433,31 @@ export class WorkflowRunsRepository {
|
|
|
543
433
|
return this.db.prepare("SELECT * FROM workflow_run_units WHERE run_id = ? AND unit_id = ?").get(runId, unitId);
|
|
544
434
|
}
|
|
545
435
|
}
|
|
436
|
+
/**
|
|
437
|
+
* Preview counterpart of {@link renameWorkflowRunRefs} for `akm bundle rename`:
|
|
438
|
+
* how many run rows name `oldBundleId`, and which of them are still `active`
|
|
439
|
+
* or `blocked` (their frozen `plan_json` keeps the old qualified refs, so the operator
|
|
440
|
+
* finishes or abandons them — the rename lists them rather than touching them).
|
|
441
|
+
*/
|
|
442
|
+
export function countWorkflowRunRefsForRename(db, oldBundleId) {
|
|
443
|
+
const like = `${escapeLikePattern(oldBundleId)}//%`;
|
|
444
|
+
const refs = db.prepare(`SELECT COUNT(*) AS n FROM workflow_runs WHERE workflow_ref LIKE ? ESCAPE '\\'`).get(like).n;
|
|
445
|
+
const active = db
|
|
446
|
+
.prepare(`SELECT id, workflow_ref AS workflowRef, status FROM workflow_runs WHERE workflow_ref LIKE ? ESCAPE '\\' AND status IN ('active', 'blocked') ORDER BY updated_at DESC, created_at DESC`)
|
|
447
|
+
.all(like);
|
|
448
|
+
return { refs, active };
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Rewrite every `workflow_runs.workflow_ref` naming `oldBundleId` to
|
|
452
|
+
* `newBundleId` (`akm bundle rename`). A legacy unqualified ref is not matched
|
|
453
|
+
* by the `LIKE` prefix and is left alone. Returns the number of rows rewritten.
|
|
454
|
+
*/
|
|
455
|
+
export function renameWorkflowRunRefs(db, oldBundleId, newBundleId) {
|
|
456
|
+
const prefix = `${escapeLikePattern(oldBundleId)}//`;
|
|
457
|
+
return Number(db
|
|
458
|
+
.prepare(`UPDATE workflow_runs SET workflow_ref = ? || substr(workflow_ref, length(?) + 1) WHERE workflow_ref LIKE ? ESCAPE '\\'`)
|
|
459
|
+
.run(newBundleId, oldBundleId, `${prefix}%`).changes);
|
|
460
|
+
}
|
|
546
461
|
/**
|
|
547
462
|
* Run `fn` against a {@link WorkflowRunsRepository} bound to state.db
|
|
548
463
|
* ({@link StorageLocations.stateDb}, the post-cutover home of the
|