akm-cli 0.9.0-rc.8 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1063 -44
- package/README.md +51 -25
- package/SECURITY.md +14 -1
- package/STABILITY.md +497 -0
- package/dist/akm +148 -35
- package/dist/{akm-migrate-storage → akm-migrate} +6 -9
- package/dist/assets/hints/cli-hints-full.md +223 -95
- package/dist/assets/hints/cli-hints-short.md +85 -22
- package/dist/assets/improve-strategies/default.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/stash-skeleton/README.md +6 -5
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
- package/dist/assets/tasks/core/extract.yml +1 -1
- package/dist/assets/tasks/core/version-check.yml +1 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +1 -3
- package/dist/assets/workflows/workflow-template.md +32 -15
- package/dist/cli/invocation.js +40 -15
- package/dist/cli/parse-args.js +0 -22
- package/dist/cli/retired-commands.js +121 -0
- package/dist/cli/shared.js +154 -22
- package/dist/cli/unknown-flags.js +236 -0
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +696 -258
- package/dist/commands/agent/agent-dispatch.js +14 -3
- package/dist/commands/agent/contribute-cli.js +73 -88
- package/dist/commands/completions.js +79 -22
- package/dist/commands/config-cli.js +17 -150
- package/dist/commands/env/env-cli.js +59 -143
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +36 -66
- package/dist/commands/env/secret.js +24 -57
- package/dist/commands/feedback-cli.js +141 -87
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +3 -4
- package/dist/commands/health/checks.js +85 -23
- package/dist/commands/health/html-report.js +7 -10
- package/dist/commands/health/improve-metrics.js +25 -83
- package/dist/commands/health/md-report.js +5 -9
- package/dist/commands/health/metrics.js +62 -20
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +4 -5
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +3 -48
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/commands/health/types-improve.js +7 -0
- package/dist/commands/health.js +99 -28
- package/dist/commands/improve/anti-collapse.js +2 -2
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +41 -40
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +140 -1000
- package/dist/commands/improve/distill/promote-memory.js +12 -12
- package/dist/commands/improve/distill/quality-gate.js +6 -6
- package/dist/commands/improve/distill.js +58 -69
- package/dist/commands/improve/eligibility.js +105 -57
- package/dist/commands/improve/extract-cli.js +14 -133
- package/dist/commands/improve/improve-cli.js +98 -114
- package/dist/commands/improve/improve-result-file.js +1 -28
- package/dist/commands/improve/improve-strategies.js +8 -5
- package/dist/commands/improve/improve.js +128 -91
- package/dist/commands/improve/loop-stages.js +182 -20
- package/dist/commands/improve/memory/derived-ref.js +45 -43
- package/dist/commands/improve/memory/memory-belief.js +1 -1
- package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
- package/dist/commands/improve/memory/memory-improve.js +6 -5
- package/dist/commands/improve/outcome-loop.js +22 -65
- package/dist/commands/improve/preparation.js +114 -123
- package/dist/commands/improve/proactive-maintenance.js +2 -5
- package/dist/commands/improve/reflect.js +56 -160
- package/dist/commands/improve/salience.js +11 -122
- package/dist/commands/improve/source-identity.js +10 -38
- package/dist/commands/lint/base-linter.js +20 -124
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +249 -43
- package/dist/commands/{events.js → log.js} +33 -38
- package/dist/commands/migrate-cli.js +92 -12
- package/dist/commands/migration-tool.js +46 -0
- package/dist/commands/observability-cli.js +70 -209
- package/dist/commands/proposal/drain.js +101 -29
- package/dist/commands/proposal/proposal-cli.js +76 -48
- package/dist/commands/proposal/proposal.js +54 -18
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +23 -15
- package/dist/commands/proposal/repository.js +701 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
- package/dist/commands/proposal/validators/proposal-validators.js +55 -7
- package/dist/commands/proposal/validators/proposals.js +4 -7
- package/dist/commands/read/curate.js +34 -53
- package/dist/commands/read/knowledge.js +150 -95
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +42 -15
- package/dist/commands/read/search-cli.js +180 -78
- package/dist/commands/read/search.js +58 -43
- package/dist/commands/read/show.js +197 -141
- package/dist/commands/registry-cli.js +12 -51
- package/dist/commands/remember.js +14 -57
- package/dist/commands/sources/add-cli.js +100 -31
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +7 -2
- package/dist/commands/sources/info.js +18 -5
- package/dist/commands/sources/init.js +12 -12
- package/dist/commands/sources/installed-stashes.js +382 -98
- package/dist/commands/sources/schema-repair.js +3 -2
- package/dist/commands/sources/self-update.js +131 -38
- package/dist/commands/sources/source-add.js +72 -17
- package/dist/commands/sources/source-clone.js +129 -45
- package/dist/commands/sources/source-manage.js +43 -23
- package/dist/commands/sources/sources-cli.js +57 -208
- package/dist/commands/sources/stash-cli.js +46 -53
- package/dist/commands/tasks/tasks-cli.js +91 -97
- package/dist/commands/tasks/tasks.js +276 -421
- package/dist/commands/workflow-cli.js +175 -450
- package/dist/core/adapter/adapters/akm-adapter.js +47 -28
- package/dist/core/adapter/adapters/akm-lint.js +42 -27
- package/dist/core/adapter/adapters/akm-metadata.js +15 -44
- package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
- package/dist/core/adapter/adapters/index.js +6 -6
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
- package/dist/core/adapter/adapters/okf-adapter.js +187 -19
- package/dist/core/adapter/adapters/shared.js +3 -19
- package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +6 -4
- package/dist/core/adapter/validate-context.js +214 -0
- package/dist/core/asset/akm-markdown.js +63 -0
- package/dist/core/asset/asset-placement.js +20 -6
- package/dist/core/asset/asset-ref.js +11 -9
- package/dist/core/asset/frontmatter-lint.js +30 -0
- package/dist/core/asset/frontmatter.js +37 -9
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +89 -18
- package/dist/core/asset/stash-meta.js +1 -1
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +152 -38
- package/dist/core/config/config-io.js +12 -1
- package/dist/core/config/config-schema.js +35 -8
- package/dist/core/config/config-sources.js +55 -11
- package/dist/core/config/config-walker.js +25 -9
- package/dist/core/config/config.js +9 -48
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +5 -1
- package/dist/core/config/schema/experimental.js +30 -0
- package/dist/core/config/schema/improve-processes.js +0 -6
- package/dist/core/config/schema/improve.js +21 -3
- package/dist/core/config/schema/index-config.js +8 -15
- package/dist/core/config/schema/output.js +4 -1
- package/dist/core/config/schema/setup.js +9 -18
- package/dist/core/config/schema/sources-bundles.js +49 -33
- package/dist/core/config/schema/workflow.js +3 -3
- package/dist/core/env-secret-ref.js +76 -46
- package/dist/core/errors.js +18 -12
- package/dist/core/events.js +46 -128
- package/dist/core/file-change.js +6 -5
- package/dist/core/fs-txn.js +83 -7
- package/dist/core/git-message.js +2 -2
- package/dist/core/improve-result.js +1 -100
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +2 -1
- package/dist/core/migration-operation.js +16 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/parse.js +4 -1
- package/dist/core/paths.js +17 -20
- package/dist/core/recognition-util.js +12 -14
- package/dist/core/redaction.js +34 -0
- package/dist/core/standards/resolve-standards-context.js +2 -14
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +2 -2
- package/dist/core/state/migrations.js +41 -18
- package/dist/core/state-db.js +5 -14
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +6 -4
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/type-presentation.js +3 -3
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +771 -95
- package/dist/indexer/bundle-identity-guard.js +3 -2
- package/dist/indexer/db/graph-db.js +0 -24
- package/dist/indexer/ensure-index.js +1 -0
- package/dist/indexer/graph/graph-boost.js +9 -34
- package/dist/indexer/graph/graph-extraction.js +8 -5
- package/dist/indexer/index-writer-lock.js +53 -17
- package/dist/indexer/index-written-assets.js +16 -22
- package/dist/indexer/indexer.js +497 -239
- package/dist/indexer/installations.js +14 -96
- package/dist/indexer/passes/dir-staleness.js +16 -9
- package/dist/indexer/passes/memory-inference.js +11 -9
- package/dist/indexer/passes/metadata.js +113 -47
- package/dist/indexer/scan/doc-to-entry.js +38 -1
- package/dist/indexer/scan/drain-dir.js +13 -23
- package/dist/indexer/search/db-search.js +99 -54
- package/dist/indexer/search/fts-query.js +47 -24
- package/dist/indexer/search/ranking-contributors.js +42 -20
- package/dist/indexer/search/ranking.js +18 -99
- package/dist/indexer/search/search-fields.js +7 -2
- package/dist/indexer/search/search-source.js +82 -93
- package/dist/indexer/usage/usage-events.js +0 -89
- package/dist/indexer/walk/file-context.js +2 -1
- package/dist/indexer/walk/matchers.js +30 -43
- package/dist/indexer/walk/path-resolver.js +7 -2
- package/dist/indexer/walk/walker.js +38 -12
- package/dist/integrations/agent/builders.js +0 -6
- package/dist/integrations/agent/config.js +2 -2
- package/dist/integrations/agent/detect.js +49 -19
- package/dist/integrations/agent/engine-fallback.js +76 -0
- package/dist/integrations/agent/profiles.js +14 -0
- package/dist/integrations/agent/prompts.js +12 -8
- package/dist/integrations/agent/runner-dispatch.js +4 -2
- package/dist/integrations/agent/runner.js +0 -1
- package/dist/integrations/agent/spawn.js +5 -6
- package/dist/integrations/github.js +1 -1
- package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
- package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
- package/dist/integrations/harnesses/claude/session-log.js +0 -10
- package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
- package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
- package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
- package/dist/integrations/harnesses/index.js +3 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
- package/dist/integrations/harnesses/opencode/session-log.js +0 -15
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
- package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
- package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
- package/dist/integrations/lockfile.js +101 -6
- package/dist/integrations/session-logs/index.js +3 -28
- package/dist/llm/client.js +136 -100
- package/dist/llm/embedders/remote.js +13 -5
- package/dist/llm/feature-gate.js +4 -12
- package/dist/llm/graph-extract.js +5 -11
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +5 -7
- package/dist/llm/structured-call.js +1 -1
- package/dist/llm/usage-persist.js +26 -5
- package/dist/llm/usage-telemetry.js +25 -2
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +259 -0
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -36
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +56 -83
- package/dist/output/shapes/migrate.js +8 -0
- package/dist/output/shapes/passthrough.js +7 -41
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes.js +2 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +164 -96
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/health-format.js +103 -0
- package/dist/output/text/health.js +7 -0
- package/dist/output/text/helpers.js +10 -8
- package/dist/output/text/lint-format.js +43 -0
- package/dist/output/text/{save.js → lint.js} +2 -2
- package/dist/output/text/migrate.js +88 -0
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +44 -72
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +15 -7
- package/dist/output/text/status-list.js +32 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +24 -203
- package/dist/output/text/workflow.js +1 -7
- package/dist/output/text.js +16 -17
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +13 -23
- package/dist/registry/resolve.js +42 -7
- package/dist/registry/semver.js +34 -84
- package/dist/runtime.js +2 -23
- package/dist/scripts/akm-migrate-node.js +60290 -0
- package/dist/scripts/akm-migrate.js +59628 -0
- package/dist/setup/detect.js +42 -15
- package/dist/setup/registry-stash-loader.js +2 -2
- package/dist/setup/setup.js +236 -136
- package/dist/setup/steps/connection.js +7 -9
- package/dist/setup/steps/platforms.js +9 -9
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +12 -13
- package/dist/setup/steps/stashdir.js +2 -3
- package/dist/setup/steps/tasks.js +237 -120
- package/dist/sources/freshness.js +1 -1
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +25 -23
- package/dist/sources/providers/git-stash.js +395 -106
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +7 -4
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +6 -1
- package/dist/sources/resolve.js +6 -5
- package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
- package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
- package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
- package/dist/sources/snapshot-fetchers/github.js +100 -0
- package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
- package/dist/sources/snapshot-fetchers/registry.js +17 -1
- package/dist/sources/snapshot-fetchers/robots.js +348 -0
- package/dist/sources/snapshot-fetchers/rss.js +282 -0
- package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
- package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
- package/dist/sources/snapshot-fetchers/x.js +910 -0
- package/dist/storage/database.js +7 -0
- package/dist/storage/engines/sqlite-migrations.js +23 -111
- package/dist/storage/managed-db.js +2 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +27 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -12
- package/dist/storage/repositories/index-connection.js +17 -6
- package/dist/storage/repositories/index-entries-repository.js +151 -240
- package/dist/storage/repositories/index-entry-mapper.js +15 -11
- package/dist/storage/repositories/index-fts-repository.js +5 -2
- package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
- package/dist/storage/repositories/index-meta-repository.js +2 -3
- package/dist/storage/repositories/index-schema.js +10 -25
- package/dist/storage/repositories/index-utility-repository.js +15 -28
- package/dist/storage/repositories/index-vec-repository.js +6 -1
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +296 -59
- package/dist/storage/repositories/registry-cache.js +19 -0
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +15 -13
- package/dist/storage/repositories/workflow-runs-repository.js +52 -40
- package/dist/tasks/backends/cron.js +105 -15
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +85 -38
- package/dist/tasks/backends/schtasks.js +135 -15
- package/dist/tasks/embedded.js +56 -40
- package/dist/tasks/parser.js +7 -157
- package/dist/tasks/resolve-akm-bin.js +137 -59
- package/dist/tasks/runner.js +79 -42
- package/dist/tasks/scheduler-invocation.js +220 -10
- package/dist/tasks/schema.js +24 -1
- package/dist/tasks/task-id.js +1 -3
- package/dist/tasks/validator.js +20 -6
- package/dist/workflows/authoring/authoring.js +94 -143
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/exec/frozen-judge.js +28 -2
- package/dist/workflows/exec/native-executor.js +77 -57
- package/dist/workflows/exec/param-secrets.js +9 -9
- package/dist/workflows/exec/run-workflow.js +133 -79
- package/dist/workflows/exec/step-work.js +219 -346
- package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
- package/dist/workflows/ir/compile.js +141 -270
- package/dist/workflows/ir/freeze.js +40 -30
- package/dist/workflows/ir/params.js +135 -11
- package/dist/workflows/ir/plan-hash.js +1 -1
- package/dist/workflows/ir/schema.js +25 -26
- package/dist/workflows/parser.js +872 -307
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +7 -10
- package/dist/workflows/renderer.js +95 -68
- package/dist/workflows/resource-limits.js +2 -0
- package/dist/workflows/runtime/checkin.js +3 -3
- package/dist/workflows/runtime/plan-classifier.js +16 -75
- package/dist/workflows/runtime/runs.js +186 -127
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +2 -2
- package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +30 -36
- package/dist/workflows/validator.js +21 -62
- package/docs/README.md +68 -0
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.7.0.md +11 -11
- package/docs/migration/release-notes/0.9.0.md +208 -27
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +564 -208
- package/docs/migration/v0.9.0-troubleshooting.md +561 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/cli.md +2253 -0
- package/docs/reference/configuration.md +358 -0
- package/docs/reference/data-and-telemetry.md +105 -42
- package/docs/reference/workflows.md +647 -0
- package/package.json +22 -11
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +81 -128
- package/schemas/akm-workflow.json +74 -73
- package/dist/assets/tasks/core/backup.yml +0 -5
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/cli/config-migrate.js +0 -1806
- package/dist/cli/config-validate.js +0 -41
- package/dist/commands/backup-cli.js +0 -56
- package/dist/commands/bundle/bundle-cli.js +0 -68
- package/dist/commands/bundle/bundle.js +0 -219
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -489
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/mv-cli.js +0 -1221
- package/dist/commands/sources/history.js +0 -201
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/core/migration-backup.js +0 -1234
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/migrate/legacy/config-source-migration.js +0 -223
- package/dist/migrate/legacy/content-migration.js +0 -305
- package/dist/migrate/legacy/legacy-layout.js +0 -779
- package/dist/migrate/legacy/legacy-paths.js +0 -25
- package/dist/migrate/legacy/legacy-stash-json.js +0 -72
- package/dist/migrate/legacy/proposal-fs-import.js +0 -168
- package/dist/migrate/legacy/task-target-ref-migration.js +0 -272
- package/dist/migrate/legacy/three-db-cutover.js +0 -841
- package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
- package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
- package/dist/migrate/legacy-ref-grammar.js +0 -214
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/registry/build-index.js +0 -382
- package/dist/schemas/akm-config.json +0 -4704
- package/dist/schemas/akm-task.json +0 -87
- package/dist/schemas/akm-workflow.json +0 -372
- package/dist/scripts/migrate-storage.js +0 -3816
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/cli.js +0 -53
- package/dist/workflows/exec/brief.js +0 -481
- package/dist/workflows/exec/report.js +0 -1460
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -813
- package/dist/workflows/program/project.js +0 -104
|
@@ -1,25 +0,0 @@
|
|
|
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
|
-
* @removeIn 0.10.0
|
|
6
|
-
*
|
|
7
|
-
* Legacy on-disk path helpers for the three-DB cutover. akm 0.9.0 chunk-8,
|
|
8
|
-
* WI-8.3.
|
|
9
|
-
*
|
|
10
|
-
* The runtime `getWorkflowDbPath` core helper is DELETED in WI-8.3 (the runtime
|
|
11
|
-
* no longer opens workflow.db — its durable rows live in state.db post-cutover).
|
|
12
|
-
* But the migrator home (`src/migrate/legacy/`), the backup/restore machinery
|
|
13
|
-
* (`src/core/migration-backup.ts` — backup artifacts + the pre-cutover ledger
|
|
14
|
-
* probe) and config-migrate.ts's backward-looking arms still need the physical
|
|
15
|
-
* `<dataDir>/workflow.db` path literal to FIND, roll, merge, back up, and delete
|
|
16
|
-
* a pre-cutover workflow.db. This module is that path literal's only surviving
|
|
17
|
-
* home in live code, quarantined under the migrator directory so the deleted
|
|
18
|
-
* core helper cannot re-appear under another name in live core.
|
|
19
|
-
*/
|
|
20
|
-
import path from "node:path";
|
|
21
|
-
import { getDataDir } from "../../core/paths.js";
|
|
22
|
-
/** Physical path of a pre-cutover workflow.db (`<dataDir>/workflow.db`). */
|
|
23
|
-
export function getLegacyWorkflowDbPath() {
|
|
24
|
-
return path.join(getDataDir(), "workflow.db");
|
|
25
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
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
|
-
* Legacy `.stash.json` sidecar read/write — the pre-0.9.0 per-directory metadata
|
|
6
|
-
* layout. This is 0.8-compat behavior that real stashes still depend on: the
|
|
7
|
-
* indexer merges a directory's sidecar overrides onto the freshly-recognized
|
|
8
|
-
* entries so curated metadata (captured openings, quality, descriptions) is not
|
|
9
|
-
* lost on re-index.
|
|
10
|
-
*
|
|
11
|
-
* MIGRATOR-OWNED HOME (akm 0.9.0 Chunk-5 flip, scope-B ruling; relocated to
|
|
12
|
-
* `src/migrate/legacy/` in Chunk-8 WI-8.5d): the sidecar layout is a pre-0.9
|
|
13
|
-
* on-disk shape, so its reader/writer live under the frozen migrator home
|
|
14
|
-
* alongside the other legacy-layout code rather than in the live indexer passes.
|
|
15
|
-
* After WI-8.5d the live indexer no longer reads the sidecar — the only reader is
|
|
16
|
-
* the `content-migration.ts` migrator step (folds the sidecar into per-file
|
|
17
|
-
* frontmatter, then deletes it), so this module is now migrator-only.
|
|
18
|
-
*
|
|
19
|
-
* The `StashFile` container type and the per-entry `validateStashEntry` gate stay
|
|
20
|
-
* in `indexer/passes/metadata.ts` (they are the live in-memory metadata shape and
|
|
21
|
-
* the shared validator); this module imports them.
|
|
22
|
-
*/
|
|
23
|
-
import fs from "node:fs";
|
|
24
|
-
import path from "node:path";
|
|
25
|
-
import { writeFileAtomic } from "../../core/common.js";
|
|
26
|
-
import { warn } from "../../core/warn.js";
|
|
27
|
-
import { validateStashEntry } from "../../indexer/passes/metadata.js";
|
|
28
|
-
/** The pre-0.9.0 per-directory metadata sidecar filename. */
|
|
29
|
-
const LEGACY_STASH_FILENAME = ".stash.json";
|
|
30
|
-
/** Absolute path of a directory's legacy metadata sidecar. */
|
|
31
|
-
export function legacyStashFilePath(dirPath) {
|
|
32
|
-
return path.join(dirPath, LEGACY_STASH_FILENAME);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Read a directory's legacy metadata sidecar and return its validated entries,
|
|
36
|
-
* or `null` when absent/empty/corrupt. Was `loadStashFile` in `metadata.ts`;
|
|
37
|
-
* relocated verbatim to the migrator home (scope-B ruling) — behavior unchanged.
|
|
38
|
-
*/
|
|
39
|
-
export function readLegacyStashOverrides(dirPath, options) {
|
|
40
|
-
const filePath = legacyStashFilePath(dirPath);
|
|
41
|
-
if (!fs.existsSync(filePath))
|
|
42
|
-
return null;
|
|
43
|
-
try {
|
|
44
|
-
const raw = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
45
|
-
if (!raw || !Array.isArray(raw.entries))
|
|
46
|
-
return null;
|
|
47
|
-
const entries = [];
|
|
48
|
-
for (const e of raw.entries) {
|
|
49
|
-
const validated = validateStashEntry(e);
|
|
50
|
-
if (validated) {
|
|
51
|
-
if (options?.requireFilename && !validated.filename)
|
|
52
|
-
continue;
|
|
53
|
-
entries.push(validated);
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
const name = typeof e === "object" && e !== null && typeof e.name === "string"
|
|
57
|
-
? e.name
|
|
58
|
-
: "(unknown)";
|
|
59
|
-
warn(`Warning: Skipping invalid entry "${name}" in ${filePath}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return entries.length > 0 ? { entries } : null;
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
/** Write a legacy metadata sidecar (test/migrator fixtures). Was `writeStashFile`. */
|
|
69
|
-
export function writeLegacyStashFile(dirPath, stash) {
|
|
70
|
-
const filePath = legacyStashFilePath(dirPath);
|
|
71
|
-
writeFileAtomic(filePath, `${JSON.stringify(stash, null, 2)}\n`);
|
|
72
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
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
|
-
* @removeIn 0.10.0
|
|
6
|
-
*
|
|
7
|
-
* One-time import of pre-0.9.0 filesystem proposals into the migrated state.db
|
|
8
|
-
* `proposals` table (akm 0.9.0 Chunk-5 fold, completed in Chunk-8; plan §3.4).
|
|
9
|
-
*
|
|
10
|
-
* Before 0.9.0 the proposal queue lived as per-uuid JSON directories under
|
|
11
|
-
* `<stashDir>/.akm/proposals/` (live) and `…/proposals/archive/` (archived).
|
|
12
|
-
* This fold USED to run on EVERY proposal operation (through
|
|
13
|
-
* `withProposalsDb`, guarded by a `proposal_fs_imports` ledger). That disk
|
|
14
|
-
* probe is gone from the live path: the import now runs ONCE, as an ADDITIVE
|
|
15
|
-
* filesystem step of `akm migrate apply`'s `cutover-applied` phase — a sibling
|
|
16
|
-
* of the `.stash.json`/D-R6 content migration — AFTER the committed state txn,
|
|
17
|
-
* best-effort (a throw is swallowed + logged by the caller, never aborting a
|
|
18
|
-
* committed cutover) and idempotent.
|
|
19
|
-
*
|
|
20
|
-
* Idempotency without the old ledger: each row lands through
|
|
21
|
-
* {@link insertProposalIfAbsent} (INSERT OR IGNORE keyed on the proposal UUID),
|
|
22
|
-
* so re-walking the still-on-disk legacy files on a resumed or re-run apply
|
|
23
|
-
* inserts nothing new and never duplicates. The legacy files are never modified
|
|
24
|
-
* or deleted — after import they are inert artifacts the operator can remove at
|
|
25
|
-
* leisure. Legacy `backup.<ext>` files are inlined into `backupContent` so
|
|
26
|
-
* `akm proposal revert` keeps working for proposals accepted before 0.9.0.
|
|
27
|
-
*
|
|
28
|
-
* The parsing/backup-inlining logic below is FROZEN pre-0.9.0 behavior, moved
|
|
29
|
-
* verbatim from the deleted `src/commands/proposal/legacy-import.ts`.
|
|
30
|
-
*
|
|
31
|
-
* Migrator-only: opens state.db through the raw storage engine (leaving its
|
|
32
|
-
* journal mode untouched — the apply has already collapsed it to single-file
|
|
33
|
-
* DELETE mode) and never sits on a live indexer or command path.
|
|
34
|
-
*/
|
|
35
|
-
import fs from "node:fs";
|
|
36
|
-
import path from "node:path";
|
|
37
|
-
import { warn } from "../../core/warn.js";
|
|
38
|
-
import { openDatabase } from "../../storage/database.js";
|
|
39
|
-
import { insertProposalIfAbsent } from "../../storage/repositories/proposals-repository.js";
|
|
40
|
-
/** Legacy (pre-0.9.0) proposal directory: `<stashDir>/.akm/proposals[/archive]`. */
|
|
41
|
-
function legacyProposalsRoot(stashDir, archive) {
|
|
42
|
-
const root = path.join(stashDir, ".akm", "proposals");
|
|
43
|
-
return archive ? path.join(root, "archive") : root;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Import every stash root's legacy `proposal.json` files into the state.db at
|
|
47
|
-
* `stateDbPath`. Returns the total number of rows actually inserted (a re-run
|
|
48
|
-
* over the same roots returns 0 — every UUID is already present). Best-effort:
|
|
49
|
-
* a per-root or per-file failure is logged and skipped, and a failure to open
|
|
50
|
-
* state.db at all returns 0 rather than throwing (the committed cutover is
|
|
51
|
-
* unaffected).
|
|
52
|
-
*/
|
|
53
|
-
export function importLegacyProposalsIntoState(stateDbPath, stashRoots) {
|
|
54
|
-
if (!fs.existsSync(stateDbPath))
|
|
55
|
-
return 0;
|
|
56
|
-
let db;
|
|
57
|
-
try {
|
|
58
|
-
db = openDatabase(stateDbPath);
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
warn(`[akm] content-migration: could not open state.db for legacy proposal import: ${errMsg(err)}`);
|
|
62
|
-
return 0;
|
|
63
|
-
}
|
|
64
|
-
try {
|
|
65
|
-
let imported = 0;
|
|
66
|
-
const seen = new Set();
|
|
67
|
-
for (const root of stashRoots) {
|
|
68
|
-
const resolved = path.resolve(root);
|
|
69
|
-
if (seen.has(resolved))
|
|
70
|
-
continue;
|
|
71
|
-
seen.add(resolved);
|
|
72
|
-
imported += importLegacyProposalsForStash(db, resolved);
|
|
73
|
-
}
|
|
74
|
-
return imported;
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
db.close();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Import one stash root's legacy proposal directories (live + archive) into the
|
|
82
|
-
* open state.db. Returns the number of rows inserted for this stash.
|
|
83
|
-
*/
|
|
84
|
-
function importLegacyProposalsForStash(db, stashDir) {
|
|
85
|
-
const liveRoot = legacyProposalsRoot(stashDir, false);
|
|
86
|
-
if (!fs.existsSync(liveRoot))
|
|
87
|
-
return 0;
|
|
88
|
-
let imported = 0;
|
|
89
|
-
for (const archive of [false, true]) {
|
|
90
|
-
const root = legacyProposalsRoot(stashDir, archive);
|
|
91
|
-
let entries;
|
|
92
|
-
try {
|
|
93
|
-
entries = fs.readdirSync(root, { withFileTypes: true });
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
for (const entry of entries) {
|
|
99
|
-
if (!entry.isDirectory() || entry.name === "archive")
|
|
100
|
-
continue;
|
|
101
|
-
const proposalDir = path.join(root, entry.name);
|
|
102
|
-
const proposal = readLegacyProposalFile(proposalDir);
|
|
103
|
-
if (!proposal)
|
|
104
|
-
continue;
|
|
105
|
-
try {
|
|
106
|
-
if (insertProposalIfAbsent(db, proposal, stashDir))
|
|
107
|
-
imported += 1;
|
|
108
|
-
}
|
|
109
|
-
catch (err) {
|
|
110
|
-
warn(`[akm] content-migration: could not import legacy proposal at ${proposalDir}: ${errMsg(err)}`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
if (imported > 0) {
|
|
115
|
-
warn(`[akm] content-migration: imported ${imported} legacy proposal file(s) from ${liveRoot} into state.db`);
|
|
116
|
-
}
|
|
117
|
-
return imported;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Parse one legacy proposal directory into a {@link Proposal}, inlining the
|
|
121
|
-
* backup file (when present) as `backupContent`. Returns undefined — with a
|
|
122
|
-
* warning — when the `proposal.json` is missing, unreadable, or malformed, so
|
|
123
|
-
* a single corrupt legacy entry never blocks the import of the rest.
|
|
124
|
-
*/
|
|
125
|
-
function readLegacyProposalFile(proposalDir) {
|
|
126
|
-
const filePath = path.join(proposalDir, "proposal.json");
|
|
127
|
-
let parsed;
|
|
128
|
-
try {
|
|
129
|
-
parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
130
|
-
}
|
|
131
|
-
catch (err) {
|
|
132
|
-
warn(`[akm] content-migration: skipping legacy proposal at ${filePath}: ${errMsg(err)}`);
|
|
133
|
-
return undefined;
|
|
134
|
-
}
|
|
135
|
-
if (typeof parsed !== "object" ||
|
|
136
|
-
parsed === null ||
|
|
137
|
-
typeof parsed.id !== "string" ||
|
|
138
|
-
typeof parsed.ref !== "string") {
|
|
139
|
-
warn(`[akm] content-migration: skipping legacy proposal at ${filePath}: not a proposal object`);
|
|
140
|
-
return undefined;
|
|
141
|
-
}
|
|
142
|
-
const { backup, ...rest } = parsed;
|
|
143
|
-
let backupContent;
|
|
144
|
-
if (typeof backup === "string" && backup.length > 0) {
|
|
145
|
-
try {
|
|
146
|
-
backupContent = fs.readFileSync(path.join(proposalDir, backup), "utf8");
|
|
147
|
-
}
|
|
148
|
-
catch {
|
|
149
|
-
// Backup file lost — import the proposal anyway; revert for it will
|
|
150
|
-
// surface "no backup available", same as a new-asset proposal.
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return {
|
|
154
|
-
...rest,
|
|
155
|
-
payload: {
|
|
156
|
-
content: rest.payload?.content ?? "",
|
|
157
|
-
...(rest.payload?.frontmatter ? { frontmatter: rest.payload.frontmatter } : {}),
|
|
158
|
-
},
|
|
159
|
-
createdAt: rest.createdAt ?? "",
|
|
160
|
-
updatedAt: rest.updatedAt ?? rest.createdAt ?? "",
|
|
161
|
-
status: rest.status ?? "pending",
|
|
162
|
-
source: rest.source ?? "import",
|
|
163
|
-
...(backupContent !== undefined ? { backupContent } : {}),
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
function errMsg(error) {
|
|
167
|
-
return error instanceof Error ? error.message : String(error);
|
|
168
|
-
}
|
|
@@ -1,272 +0,0 @@
|
|
|
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
|
-
* @removeIn 0.10.0
|
|
6
|
-
*
|
|
7
|
-
* One-time rewrite of persisted 0.8 task `workflow:` targets. This module is
|
|
8
|
-
* migrator-only: live task parsing remains strict 0.9 grammar. Planning parses
|
|
9
|
-
* and resolves every legacy v1 target before `migrate apply` mutates core
|
|
10
|
-
* artifacts; application then replaces only the YAML scalar bytes and uses an
|
|
11
|
-
* atomic write. The apply coordinator journals the batch as a forward-recovery
|
|
12
|
-
* phase, so an interrupted partial batch is safely re-planned and resumed.
|
|
13
|
-
*/
|
|
14
|
-
import crypto from "node:crypto";
|
|
15
|
-
import fs from "node:fs";
|
|
16
|
-
import os from "node:os";
|
|
17
|
-
import path from "node:path";
|
|
18
|
-
import { isMap, isScalar, parseDocument } from "yaml";
|
|
19
|
-
import { bundlesToSourceEntries } from "../../core/config/config.js";
|
|
20
|
-
import { ConfigError } from "../../core/errors.js";
|
|
21
|
-
import { resolveWritable } from "../../core/write-source.js";
|
|
22
|
-
import { resolveEntryContentDir } from "../../indexer/search/search-source.js";
|
|
23
|
-
import { classifyRefGrammar, legacyConceptId, parseAssetRef } from "../legacy-ref-grammar.js";
|
|
24
|
-
import { canonicalizeWorkflowName, resolveAssetPathFromName, resolveSourcesForOrigin, } from "./legacy-layout.js";
|
|
25
|
-
function migrationError(filePath, detail) {
|
|
26
|
-
return new ConfigError(`Cannot migrate persisted task target in ${filePath}: ${detail} ` +
|
|
27
|
-
"Repair or remove this task, then rerun `akm migrate apply`.", "INVALID_CONFIG_FILE");
|
|
28
|
-
}
|
|
29
|
-
function expandTilde(value) {
|
|
30
|
-
if (value === "~")
|
|
31
|
-
return os.homedir();
|
|
32
|
-
if (value.startsWith("~/") || value.startsWith("~\\"))
|
|
33
|
-
return path.join(os.homedir(), value.slice(2));
|
|
34
|
-
return value;
|
|
35
|
-
}
|
|
36
|
-
function bundlesFromConfig(config) {
|
|
37
|
-
const entries = Object.entries(config.bundles ?? {});
|
|
38
|
-
const sourceEntries = new Map((bundlesToSourceEntries(config) ?? []).map((entry) => [entry.name, entry]));
|
|
39
|
-
const defaultId = config.defaultBundle;
|
|
40
|
-
const ordered = defaultId
|
|
41
|
-
? [...entries.filter(([id]) => id === defaultId), ...entries.filter(([id]) => id !== defaultId)]
|
|
42
|
-
: entries;
|
|
43
|
-
const bundles = [];
|
|
44
|
-
const roots = new Map();
|
|
45
|
-
for (const [id, rawEntry] of ordered) {
|
|
46
|
-
const entry = rawEntry;
|
|
47
|
-
const sourceEntry = sourceEntries.get(id);
|
|
48
|
-
if (!sourceEntry)
|
|
49
|
-
continue;
|
|
50
|
-
const contentDir = resolveEntryContentDir(sourceEntry);
|
|
51
|
-
if (!contentDir)
|
|
52
|
-
continue;
|
|
53
|
-
const root = path.resolve(expandTilde(contentDir));
|
|
54
|
-
const rootIdentity = fs.existsSync(root) ? fs.realpathSync(root) : root;
|
|
55
|
-
const prior = roots.get(rootIdentity);
|
|
56
|
-
if (prior && prior !== id) {
|
|
57
|
-
throw new ConfigError(`Cannot migrate persisted task targets because bundles "${prior}" and "${id}" resolve to the same root ${root}. ` +
|
|
58
|
-
"Give each bundle a distinct path, then rerun `akm migrate apply`.", "INVALID_CONFIG_FILE");
|
|
59
|
-
}
|
|
60
|
-
roots.set(rootIdentity, id);
|
|
61
|
-
bundles.push({
|
|
62
|
-
id,
|
|
63
|
-
root,
|
|
64
|
-
...(typeof entry.registryId === "string" && entry.registryId.length > 0 ? { registryId: entry.registryId } : {}),
|
|
65
|
-
primary: id === defaultId,
|
|
66
|
-
writable: resolveWritable(sourceEntry),
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
return bundles;
|
|
70
|
-
}
|
|
71
|
-
function resolveOrigin(origin, bundles, filePath) {
|
|
72
|
-
if (origin === "local" || origin === "stash") {
|
|
73
|
-
const primary = bundles.find((bundle) => bundle.primary);
|
|
74
|
-
if (primary)
|
|
75
|
-
return primary;
|
|
76
|
-
throw migrationError(filePath, `legacy origin "${origin}" has no configured default bundle.`);
|
|
77
|
-
}
|
|
78
|
-
let candidates = bundles.filter((bundle) => bundle.id === origin || bundle.registryId === origin);
|
|
79
|
-
if (candidates.length === 0) {
|
|
80
|
-
const sources = bundles.map((bundle) => ({
|
|
81
|
-
path: bundle.root,
|
|
82
|
-
registryId: bundle.registryId ?? bundle.id,
|
|
83
|
-
}));
|
|
84
|
-
const resolved = resolveSourcesForOrigin(origin, sources);
|
|
85
|
-
candidates = resolved
|
|
86
|
-
.map((source) => bundles[sources.indexOf(source)])
|
|
87
|
-
.filter((bundle) => bundle !== undefined);
|
|
88
|
-
}
|
|
89
|
-
if (candidates.length === 0) {
|
|
90
|
-
throw migrationError(filePath, `legacy workflow origin "${origin}" does not resolve to a configured bundle.`);
|
|
91
|
-
}
|
|
92
|
-
if (candidates.length > 1) {
|
|
93
|
-
throw migrationError(filePath, `legacy workflow origin "${origin}" is ambiguous across bundles ${candidates.map((bundle) => `"${bundle.id}"`).join(", ")}.`);
|
|
94
|
-
}
|
|
95
|
-
const candidate = candidates[0];
|
|
96
|
-
if (!candidate)
|
|
97
|
-
throw migrationError(filePath, `legacy workflow origin "${origin}" did not resolve.`);
|
|
98
|
-
return candidate;
|
|
99
|
-
}
|
|
100
|
-
function assertWorkflowExists(bundle, name, rawRef, filePath) {
|
|
101
|
-
const candidate = resolveAssetPathFromName("workflow", path.join(bundle.root, "workflows"), name);
|
|
102
|
-
if (!fs.existsSync(candidate) || !fs.statSync(candidate).isFile()) {
|
|
103
|
-
throw migrationError(filePath, `legacy target "${rawRef}" was not found in bundle "${bundle.id}" at ${bundle.root}.`);
|
|
104
|
-
}
|
|
105
|
-
const realRoot = fs.realpathSync(bundle.root);
|
|
106
|
-
const realCandidate = fs.realpathSync(candidate);
|
|
107
|
-
const relative = path.relative(realRoot, realCandidate);
|
|
108
|
-
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
109
|
-
throw migrationError(filePath, `legacy target "${rawRef}" resolves outside bundle "${bundle.id}".`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
function assertRealPathWithin(root, candidate, filePath, detail) {
|
|
113
|
-
const relative = path.relative(fs.realpathSync(root), fs.realpathSync(candidate));
|
|
114
|
-
if (relative.startsWith("..") || path.isAbsolute(relative))
|
|
115
|
-
throw migrationError(filePath, detail);
|
|
116
|
-
}
|
|
117
|
-
function renderScalarLike(sourceToken, replacement, filePath) {
|
|
118
|
-
if (sourceToken.startsWith("'") && sourceToken.endsWith("'")) {
|
|
119
|
-
return `'${replacement.replaceAll("'", "''")}'`;
|
|
120
|
-
}
|
|
121
|
-
if (sourceToken.startsWith('"') && sourceToken.endsWith('"'))
|
|
122
|
-
return JSON.stringify(replacement);
|
|
123
|
-
if (/^[^\s#[\]{},&*!|>'"%@`]+$/.test(sourceToken))
|
|
124
|
-
return replacement;
|
|
125
|
-
throw migrationError(filePath, "the legacy workflow target uses an unsupported YAML scalar style.");
|
|
126
|
-
}
|
|
127
|
-
function planTaskFile(filePath, containing, bundles, durabilityPaths) {
|
|
128
|
-
const before = fs.readFileSync(filePath);
|
|
129
|
-
let text;
|
|
130
|
-
try {
|
|
131
|
-
text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(before);
|
|
132
|
-
}
|
|
133
|
-
catch {
|
|
134
|
-
throw migrationError(filePath, "task YAML contains invalid UTF-8 bytes.");
|
|
135
|
-
}
|
|
136
|
-
const doc = parseDocument(text, { uniqueKeys: true });
|
|
137
|
-
const yamlError = doc.errors[0];
|
|
138
|
-
if (yamlError)
|
|
139
|
-
throw migrationError(filePath, `invalid YAML (${yamlError.message}).`);
|
|
140
|
-
if (!isMap(doc.contents))
|
|
141
|
-
throw migrationError(filePath, "task YAML must be a mapping.");
|
|
142
|
-
const version = doc.get("version");
|
|
143
|
-
if (version !== undefined && version !== 1)
|
|
144
|
-
return undefined;
|
|
145
|
-
if (!doc.has("workflow"))
|
|
146
|
-
return undefined;
|
|
147
|
-
const node = doc.get("workflow", true);
|
|
148
|
-
if (!isScalar(node) || typeof node.value !== "string") {
|
|
149
|
-
throw migrationError(filePath, "legacy `workflow` must be a string scalar.");
|
|
150
|
-
}
|
|
151
|
-
const from = node.value.trim();
|
|
152
|
-
if (classifyRefGrammar(from) !== "legacy") {
|
|
153
|
-
durabilityPaths.push(filePath);
|
|
154
|
-
return undefined;
|
|
155
|
-
}
|
|
156
|
-
let parsed;
|
|
157
|
-
try {
|
|
158
|
-
parsed = parseAssetRef(from);
|
|
159
|
-
}
|
|
160
|
-
catch (error) {
|
|
161
|
-
throw migrationError(filePath, `legacy workflow target "${from}" is invalid (${error instanceof Error ? error.message : String(error)}).`);
|
|
162
|
-
}
|
|
163
|
-
if (parsed.type !== "workflow") {
|
|
164
|
-
throw migrationError(filePath, `legacy target "${from}" has type "${parsed.type}", not "workflow".`);
|
|
165
|
-
}
|
|
166
|
-
const name = canonicalizeWorkflowName(parsed.name);
|
|
167
|
-
const targetBundle = parsed.origin ? resolveOrigin(parsed.origin, bundles, filePath) : containing;
|
|
168
|
-
assertWorkflowExists(targetBundle, name, from, filePath);
|
|
169
|
-
const conceptId = legacyConceptId("workflow", name);
|
|
170
|
-
const to = parsed.origin ? `${targetBundle.id}//${conceptId}` : conceptId;
|
|
171
|
-
const range = node.range;
|
|
172
|
-
if (!range)
|
|
173
|
-
throw migrationError(filePath, "the legacy workflow target has no stable source range.");
|
|
174
|
-
const token = text.slice(range[0], range[1]);
|
|
175
|
-
const replacement = renderScalarLike(token, to, filePath);
|
|
176
|
-
const after = Buffer.from(text.slice(0, range[0]) + replacement + text.slice(range[1]));
|
|
177
|
-
return { filePath, from, to, before, after, mode: fs.lstatSync(filePath).mode & 0o777 };
|
|
178
|
-
}
|
|
179
|
-
/** Preflight every persisted v1 task target without changing disk. */
|
|
180
|
-
export function planTaskTargetRefMigration(config) {
|
|
181
|
-
const bundles = bundlesFromConfig(config);
|
|
182
|
-
const rewrites = [];
|
|
183
|
-
const durabilityPaths = [];
|
|
184
|
-
for (const bundle of bundles) {
|
|
185
|
-
if (!bundle.writable)
|
|
186
|
-
continue;
|
|
187
|
-
const tasksDir = path.join(bundle.root, "tasks");
|
|
188
|
-
if (!fs.existsSync(tasksDir))
|
|
189
|
-
continue;
|
|
190
|
-
const tasksStat = fs.lstatSync(tasksDir);
|
|
191
|
-
if (tasksStat.isSymbolicLink()) {
|
|
192
|
-
throw new ConfigError(`Cannot migrate persisted task targets because ${tasksDir} is a symbolic link. Replace it with a real ` +
|
|
193
|
-
"directory, then rerun `akm migrate apply`.", "INVALID_CONFIG_FILE");
|
|
194
|
-
}
|
|
195
|
-
if (!tasksStat.isDirectory()) {
|
|
196
|
-
throw new ConfigError(`Cannot migrate persisted task targets because ${tasksDir} is not a directory. Repair it, then rerun ` +
|
|
197
|
-
"`akm migrate apply`.", "INVALID_CONFIG_FILE");
|
|
198
|
-
}
|
|
199
|
-
assertRealPathWithin(bundle.root, tasksDir, tasksDir, "the tasks directory resolves outside its bundle.");
|
|
200
|
-
for (const entry of fs
|
|
201
|
-
.readdirSync(tasksDir, { withFileTypes: true })
|
|
202
|
-
.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
203
|
-
if (!entry.name.endsWith(".yml"))
|
|
204
|
-
continue;
|
|
205
|
-
const filePath = path.join(tasksDir, entry.name);
|
|
206
|
-
if (!entry.isFile())
|
|
207
|
-
throw migrationError(filePath, "task migration does not follow symbolic links or special files.");
|
|
208
|
-
assertRealPathWithin(bundle.root, filePath, filePath, "the task file resolves outside its bundle.");
|
|
209
|
-
const rewrite = planTaskFile(filePath, bundle, bundles, durabilityPaths);
|
|
210
|
-
if (rewrite)
|
|
211
|
-
rewrites.push(rewrite);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return { rewrites, durabilityPaths };
|
|
215
|
-
}
|
|
216
|
-
function syncParentDirectory(filePath) {
|
|
217
|
-
const fd = fs.openSync(path.dirname(filePath), "r");
|
|
218
|
-
try {
|
|
219
|
-
fs.fsyncSync(fd);
|
|
220
|
-
}
|
|
221
|
-
finally {
|
|
222
|
-
fs.closeSync(fd);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
function writeTaskFileDurably(target, content, mode) {
|
|
226
|
-
const temp = `${target}.tmp-${process.pid}-${crypto.randomBytes(8).toString("hex")}`;
|
|
227
|
-
let renamed = false;
|
|
228
|
-
try {
|
|
229
|
-
const fd = fs.openSync(temp, "wx", mode);
|
|
230
|
-
try {
|
|
231
|
-
fs.fchmodSync(fd, mode);
|
|
232
|
-
let offset = 0;
|
|
233
|
-
while (offset < content.byteLength) {
|
|
234
|
-
const written = fs.writeSync(fd, content, offset, content.byteLength - offset);
|
|
235
|
-
if (written <= 0)
|
|
236
|
-
throw new Error(`Could not make progress writing task migration temp file ${temp}.`);
|
|
237
|
-
offset += written;
|
|
238
|
-
}
|
|
239
|
-
fs.fsyncSync(fd);
|
|
240
|
-
}
|
|
241
|
-
finally {
|
|
242
|
-
fs.closeSync(fd);
|
|
243
|
-
}
|
|
244
|
-
fs.renameSync(temp, target);
|
|
245
|
-
renamed = true;
|
|
246
|
-
syncParentDirectory(target);
|
|
247
|
-
}
|
|
248
|
-
catch (error) {
|
|
249
|
-
if (!renamed)
|
|
250
|
-
fs.rmSync(temp, { force: true });
|
|
251
|
-
throw error;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
/** Apply a preflighted plan with exact-byte fencing and durable atomic writes. */
|
|
255
|
-
export function applyTaskTargetRefMigration(plan) {
|
|
256
|
-
let rewritten = 0;
|
|
257
|
-
for (const rewrite of plan.rewrites) {
|
|
258
|
-
const current = fs.readFileSync(rewrite.filePath);
|
|
259
|
-
if (current.equals(rewrite.after)) {
|
|
260
|
-
syncParentDirectory(rewrite.filePath);
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
if (!current.equals(rewrite.before)) {
|
|
264
|
-
throw migrationError(rewrite.filePath, "the task changed after migration preflight; it was left untouched.");
|
|
265
|
-
}
|
|
266
|
-
writeTaskFileDurably(rewrite.filePath, rewrite.after, rewrite.mode);
|
|
267
|
-
rewritten++;
|
|
268
|
-
}
|
|
269
|
-
for (const filePath of plan.durabilityPaths)
|
|
270
|
-
syncParentDirectory(filePath);
|
|
271
|
-
return rewritten;
|
|
272
|
-
}
|