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
package/dist/core/fs-txn.js
CHANGED
|
@@ -59,6 +59,10 @@ function requireKind(kind) {
|
|
|
59
59
|
throw new Error(`No transaction handler registered for kind "${kind}".`);
|
|
60
60
|
return handler;
|
|
61
61
|
}
|
|
62
|
+
/** True when `kind` has a registered handler (see {@link recoverTxnsForRoot}). */
|
|
63
|
+
function hasKind(kind) {
|
|
64
|
+
return kinds.has(kind);
|
|
65
|
+
}
|
|
62
66
|
// ── Test seam ────────────────────────────────────────────────────────────────
|
|
63
67
|
let mutationHookForTests;
|
|
64
68
|
/** TEST-ONLY crash-window hook used by subprocess recovery tests. */
|
|
@@ -187,13 +191,24 @@ export function cleanupTxn(dir) {
|
|
|
187
191
|
}
|
|
188
192
|
}
|
|
189
193
|
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
194
|
+
* Grace period (ms) before a transaction directory/journal with no other
|
|
195
|
+
* evidence of activity is treated as stale rather than possibly belonging to
|
|
196
|
+
* a still-running operation. Shared by {@link sweepJournallessTxnDir} (racing
|
|
197
|
+
* a sibling's mkdir→journal window, and the unknown-kind sweep in
|
|
198
|
+
* {@link recoverTxnsForRoot}) and by read-only reporting such as `akm
|
|
199
|
+
* health`'s stale-journal advisory (see {@link listTxnJournalsTolerant}).
|
|
200
|
+
*/
|
|
201
|
+
export const TXN_SWEEP_GRACE_MS = 300_000;
|
|
202
|
+
/**
|
|
203
|
+
* Sweep a transaction directory that cannot be recovered — it has NO journal,
|
|
204
|
+
* or (from {@link recoverTxnsForRoot}) a journal whose kind has no registered
|
|
205
|
+
* handler — but only when it is demonstrably stale. All kinds share one
|
|
206
|
+
* namespace per root, so a scanner may encounter a SIBLING transaction inside
|
|
207
|
+
* `beginTxn`'s mkdir→journal window, or one whose registrar this process
|
|
208
|
+
* simply has not imported yet; a grace period keeps the sweep from racing
|
|
209
|
+
* either. Returns true when the directory was removed.
|
|
195
210
|
*/
|
|
196
|
-
export function sweepJournallessTxnDir(dir, graceMs =
|
|
211
|
+
export function sweepJournallessTxnDir(dir, graceMs = TXN_SWEEP_GRACE_MS) {
|
|
197
212
|
try {
|
|
198
213
|
const age = Date.now() - fs.statSync(dir).mtimeMs;
|
|
199
214
|
if (age < graceMs)
|
|
@@ -250,7 +265,20 @@ export function isCommittedPhase(journal) {
|
|
|
250
265
|
* the kind's `finalize`. Fully-finalized directories are swept. The domain
|
|
251
266
|
* registrar (which registers the kinds) must be imported by the caller.
|
|
252
267
|
*
|
|
253
|
-
* `
|
|
268
|
+
* A journal whose `kind` has NO registered handler is SWEPT (same stale-dir
|
|
269
|
+
* grace period as {@link sweepJournallessTxnDir}) rather than thrown on. A
|
|
270
|
+
* kind can disappear for good — 0.9.0 deleted `akm mv` and with it the
|
|
271
|
+
* `kind:"mv"` handler — and an unrecoverable leftover journal must never
|
|
272
|
+
* brick every later recovery scan (index refresh, proposal accept/reject) run
|
|
273
|
+
* against the same root. Kinds that ARE registered keep failing LOUDLY on any
|
|
274
|
+
* fence violation: those journals may fence an interrupted, irreversible
|
|
275
|
+
* mutation. The grace period also covers the transient case where the caller
|
|
276
|
+
* has not imported a live kind's registrar yet.
|
|
277
|
+
*
|
|
278
|
+
* `filter` optionally narrows recovery (e.g. one kind, one proposal id). The
|
|
279
|
+
* unknown-kind sweep runs BEFORE the filter: such a journal is garbage no
|
|
280
|
+
* matter what the caller asked to recover, and leaving it behind is what
|
|
281
|
+
* bricks the next scan.
|
|
254
282
|
*/
|
|
255
283
|
export async function recoverTxnsForRoot(root, filter) {
|
|
256
284
|
const nsDir = txnNamespaceDir(root);
|
|
@@ -267,6 +295,12 @@ export async function recoverTxnsForRoot(root, filter) {
|
|
|
267
295
|
continue;
|
|
268
296
|
}
|
|
269
297
|
const journal = readJournal(journalPath);
|
|
298
|
+
if (!hasKind(journal.kind)) {
|
|
299
|
+
if (sweepJournallessTxnDir(dir)) {
|
|
300
|
+
warn(`[txn] swept unrecoverable journal of unregistered kind "${journal.kind}" at ${journalPath}.`);
|
|
301
|
+
}
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
270
304
|
if (filter && !filter(journal))
|
|
271
305
|
continue;
|
|
272
306
|
fenceJournal(journal, dir, root, journalPath);
|
|
@@ -314,3 +348,45 @@ export function listTxnJournals(predicate) {
|
|
|
314
348
|
}
|
|
315
349
|
return matches;
|
|
316
350
|
}
|
|
351
|
+
/**
|
|
352
|
+
* Read-only, best-effort sibling of {@link listTxnJournals} for reporting
|
|
353
|
+
* (e.g. `akm health`'s stale-journal advisory): a corrupt `journal.json` is
|
|
354
|
+
* counted rather than thrown, so one damaged journal doesn't abort the whole
|
|
355
|
+
* scan. Recovery call sites (which must decide how to roll a journal forward
|
|
356
|
+
* or back) keep using {@link listTxnJournals} — it fails loudly on purpose,
|
|
357
|
+
* since silently skipping a damaged journal there could leave an interrupted,
|
|
358
|
+
* irreversible mutation unrecovered.
|
|
359
|
+
*/
|
|
360
|
+
export function listTxnJournalsTolerant(predicate) {
|
|
361
|
+
const home = path.join(getDataDir(), "txn");
|
|
362
|
+
const matches = [];
|
|
363
|
+
const unreadableMtimes = [];
|
|
364
|
+
if (!fs.existsSync(home))
|
|
365
|
+
return { matches, unreadableMtimes };
|
|
366
|
+
for (const ns of fs.readdirSync(home, { withFileTypes: true })) {
|
|
367
|
+
if (!ns.isDirectory())
|
|
368
|
+
continue;
|
|
369
|
+
const nsDir = path.join(home, ns.name);
|
|
370
|
+
for (const entry of fs.readdirSync(nsDir, { withFileTypes: true })) {
|
|
371
|
+
if (!entry.isDirectory())
|
|
372
|
+
continue;
|
|
373
|
+
const journalPath = path.join(nsDir, entry.name, "journal.json");
|
|
374
|
+
let mtimeMs;
|
|
375
|
+
try {
|
|
376
|
+
mtimeMs = fs.statSync(journalPath).mtimeMs;
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
continue; // no journal.json here, or it vanished mid-scan
|
|
380
|
+
}
|
|
381
|
+
try {
|
|
382
|
+
const journal = readJournal(journalPath);
|
|
383
|
+
if (predicate(journal))
|
|
384
|
+
matches.push({ journal, mtimeMs });
|
|
385
|
+
}
|
|
386
|
+
catch {
|
|
387
|
+
unreadableMtimes.push(mtimeMs);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return { matches, unreadableMtimes };
|
|
392
|
+
}
|
package/dist/core/git-message.js
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
* barrel, by value) does not need to import back into `write-source.ts` just
|
|
11
11
|
* for this helper — that back-edge was a 3-file static-graph cycle
|
|
12
12
|
* (write-source.ts → git.ts → git-stash.ts → write-source.ts; chunk 9 WI-9.8
|
|
13
|
-
* KILL 6 sever).
|
|
14
|
-
*
|
|
13
|
+
* KILL 6 sever). Callers import `sanitizeCommitMessage` directly so
|
|
14
|
+
* the dependency graph stays acyclic.
|
|
15
15
|
*/
|
|
16
16
|
/**
|
|
17
17
|
* Maximum length of a sanitized git commit message. Git itself imposes no
|
|
@@ -37,40 +37,12 @@ const COMMON_FIELDS = [
|
|
|
37
37
|
"gateAutoAcceptFailedCount",
|
|
38
38
|
"triage",
|
|
39
39
|
"proactiveMaintenance",
|
|
40
|
-
// Retired producers still exist in the persisted 90-day improve-run ledger.
|
|
41
|
-
"recombination",
|
|
42
|
-
"proceduralCompilation",
|
|
43
40
|
"cycleMetrics",
|
|
44
41
|
"runId",
|
|
45
42
|
"sync",
|
|
46
43
|
"terminated",
|
|
47
44
|
];
|
|
48
|
-
const V1_FIELDS = new Set([
|
|
49
|
-
...COMMON_FIELDS,
|
|
50
|
-
"profile",
|
|
51
|
-
"profileFilteredRefs",
|
|
52
|
-
"stalenessDetection",
|
|
53
|
-
"executionLogCandidates",
|
|
54
|
-
]);
|
|
55
45
|
const V2_FIELDS = new Set([...COMMON_FIELDS, "strategy", "strategyFilteredRefs"]);
|
|
56
|
-
const STALENESS_DETECTION_FIELDS = new Set([
|
|
57
|
-
"considered",
|
|
58
|
-
"deprecated",
|
|
59
|
-
"confirmed",
|
|
60
|
-
"skipped",
|
|
61
|
-
"durationMs",
|
|
62
|
-
"warnings",
|
|
63
|
-
]);
|
|
64
|
-
const INTERRUPTED_V1_FIELDS = new Set([
|
|
65
|
-
"schemaVersion",
|
|
66
|
-
"ok",
|
|
67
|
-
"profile",
|
|
68
|
-
"scope",
|
|
69
|
-
"dryRun",
|
|
70
|
-
"plannedRefs",
|
|
71
|
-
"actions",
|
|
72
|
-
"terminated",
|
|
73
|
-
]);
|
|
74
46
|
function fail(message) {
|
|
75
47
|
throw new Error(`invalid improve-result envelope: ${message}`);
|
|
76
48
|
}
|
|
@@ -82,33 +54,6 @@ function requireExactFields(value, allowed) {
|
|
|
82
54
|
if (unknown.length > 0)
|
|
83
55
|
fail(`unknown field${unknown.length === 1 ? "" : "s"}: ${unknown.sort().join(", ")}`);
|
|
84
56
|
}
|
|
85
|
-
function isKnownInterruptedV1Partial(value) {
|
|
86
|
-
if (Object.keys(value).some((key) => !INTERRUPTED_V1_FIELDS.has(key)))
|
|
87
|
-
return false;
|
|
88
|
-
if (value.ok !== false || typeof value.dryRun !== "boolean")
|
|
89
|
-
return false;
|
|
90
|
-
if (value.profile !== undefined && typeof value.profile !== "string")
|
|
91
|
-
return false;
|
|
92
|
-
if (!Array.isArray(value.plannedRefs) || value.plannedRefs.length !== 0)
|
|
93
|
-
return false;
|
|
94
|
-
if (!Array.isArray(value.actions) || value.actions.length !== 0)
|
|
95
|
-
return false;
|
|
96
|
-
if (!isRecord(value.scope))
|
|
97
|
-
return false;
|
|
98
|
-
if (Object.keys(value.scope).some((key) => key !== "mode" && key !== "value"))
|
|
99
|
-
return false;
|
|
100
|
-
if (value.scope.mode !== "all" && value.scope.mode !== "type" && value.scope.mode !== "ref")
|
|
101
|
-
return false;
|
|
102
|
-
if (value.scope.value !== undefined && typeof value.scope.value !== "string")
|
|
103
|
-
return false;
|
|
104
|
-
if (!isRecord(value.terminated))
|
|
105
|
-
return false;
|
|
106
|
-
if (Object.keys(value.terminated).some((key) => !["reason", "at", "errorMessage"].includes(key)))
|
|
107
|
-
return false;
|
|
108
|
-
if (typeof value.terminated.reason !== "string" || typeof value.terminated.at !== "string")
|
|
109
|
-
return false;
|
|
110
|
-
return value.terminated.errorMessage === undefined || typeof value.terminated.errorMessage === "string";
|
|
111
|
-
}
|
|
112
57
|
function validateCommon(value) {
|
|
113
58
|
if (typeof value.ok !== "boolean")
|
|
114
59
|
fail("ok must be a boolean");
|
|
@@ -138,7 +83,6 @@ function validateCommon(value) {
|
|
|
138
83
|
"extract",
|
|
139
84
|
"coverageGaps",
|
|
140
85
|
"deadUrls",
|
|
141
|
-
"executionLogCandidates",
|
|
142
86
|
]) {
|
|
143
87
|
if (value[field] !== undefined && !Array.isArray(value[field]))
|
|
144
88
|
fail(`${field} must be an array`);
|
|
@@ -175,8 +119,6 @@ function validateCommon(value) {
|
|
|
175
119
|
"graphExtraction",
|
|
176
120
|
"triage",
|
|
177
121
|
"proactiveMaintenance",
|
|
178
|
-
"recombination",
|
|
179
|
-
"proceduralCompilation",
|
|
180
122
|
"cycleMetrics",
|
|
181
123
|
"sync",
|
|
182
124
|
"terminated",
|
|
@@ -194,24 +136,7 @@ function validateCommon(value) {
|
|
|
194
136
|
}
|
|
195
137
|
}
|
|
196
138
|
}
|
|
197
|
-
|
|
198
|
-
if (value === undefined)
|
|
199
|
-
return;
|
|
200
|
-
if (!isRecord(value))
|
|
201
|
-
fail("stalenessDetection must be an object");
|
|
202
|
-
const unknown = Object.keys(value).filter((key) => !STALENESS_DETECTION_FIELDS.has(key));
|
|
203
|
-
if (unknown.length > 0) {
|
|
204
|
-
fail(`stalenessDetection has unknown field${unknown.length === 1 ? "" : "s"}: ${unknown.sort().join(", ")}`);
|
|
205
|
-
}
|
|
206
|
-
for (const field of ["considered", "deprecated", "confirmed", "skipped", "durationMs"]) {
|
|
207
|
-
if (typeof value[field] !== "number")
|
|
208
|
-
fail(`stalenessDetection.${field} must be a number`);
|
|
209
|
-
}
|
|
210
|
-
if (!Array.isArray(value.warnings) || value.warnings.some((warning) => typeof warning !== "string")) {
|
|
211
|
-
fail("stalenessDetection.warnings must be an array of strings");
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
/** Decode the persisted public v1/v2 contract without guessing across versions. */
|
|
139
|
+
/** Decode the persisted public result contract. */
|
|
215
140
|
export function decodeImproveResult(input) {
|
|
216
141
|
let parsed = input;
|
|
217
142
|
if (typeof input === "string") {
|
|
@@ -224,28 +149,6 @@ export function decodeImproveResult(input) {
|
|
|
224
149
|
}
|
|
225
150
|
if (!isRecord(parsed))
|
|
226
151
|
fail("root must be an object");
|
|
227
|
-
if (parsed.schemaVersion === 1) {
|
|
228
|
-
let normalized = parsed;
|
|
229
|
-
let normalizedLegacyPartial = false;
|
|
230
|
-
if (normalized.memorySummary === undefined && isKnownInterruptedV1Partial(normalized)) {
|
|
231
|
-
normalized = { ...normalized, memorySummary: { eligible: 0, derived: 0 } };
|
|
232
|
-
normalizedLegacyPartial = true;
|
|
233
|
-
}
|
|
234
|
-
requireExactFields(normalized, V1_FIELDS);
|
|
235
|
-
validateCommon(normalized);
|
|
236
|
-
validateV1StalenessDetection(normalized.stalenessDetection);
|
|
237
|
-
if (normalized.profile !== undefined && typeof normalized.profile !== "string")
|
|
238
|
-
fail("profile must be a string");
|
|
239
|
-
if (normalized.profileFilteredRefs !== undefined && !Array.isArray(normalized.profileFilteredRefs)) {
|
|
240
|
-
fail("profileFilteredRefs must be an array");
|
|
241
|
-
}
|
|
242
|
-
return {
|
|
243
|
-
envelope: normalized,
|
|
244
|
-
strategy: null,
|
|
245
|
-
legacyProfile: typeof normalized.profile === "string" ? normalized.profile : null,
|
|
246
|
-
normalizedLegacyPartial,
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
152
|
if (parsed.schemaVersion === 2) {
|
|
250
153
|
requireExactFields(parsed, V2_FIELDS);
|
|
251
154
|
validateCommon(parsed);
|
|
@@ -258,8 +161,6 @@ export function decodeImproveResult(input) {
|
|
|
258
161
|
return {
|
|
259
162
|
envelope: parsed,
|
|
260
163
|
strategy: parsed.strategy,
|
|
261
|
-
legacyProfile: null,
|
|
262
|
-
normalizedLegacyPartial: false,
|
|
263
164
|
};
|
|
264
165
|
}
|
|
265
166
|
fail(`unsupported schemaVersion: ${String(parsed.schemaVersion)}`);
|
package/dist/core/lesson-lint.js
CHANGED
|
@@ -13,9 +13,7 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Lint produces structured findings rather than throwing so callers can
|
|
15
15
|
* batch-validate (e.g. `akm proposal accept` over a queue) and surface every
|
|
16
|
-
* violation in a single pass.
|
|
17
|
-
* a `UsageError` for call sites that want a fail-fast contract — most
|
|
18
|
-
* notably the proposal-accept path described in v1 spec §13.1.
|
|
16
|
+
* violation in a single pass.
|
|
19
17
|
*
|
|
20
18
|
* The lint is intentionally side-effect free and does not import the indexer
|
|
21
19
|
* or filesystem walker; it operates on a single file path + raw string. This
|
|
@@ -24,7 +22,6 @@
|
|
|
24
22
|
*/
|
|
25
23
|
import fs from "node:fs";
|
|
26
24
|
import { parseFrontmatter } from "./asset/frontmatter.js";
|
|
27
|
-
import { UsageError } from "./errors.js";
|
|
28
25
|
function isNonEmptyString(value) {
|
|
29
26
|
return typeof value === "string" && value.trim().length > 0;
|
|
30
27
|
}
|
|
@@ -74,16 +71,3 @@ export function lintLessonFile(filePath) {
|
|
|
74
71
|
const raw = fs.readFileSync(filePath, "utf8");
|
|
75
72
|
return lintLessonContent(raw, filePath);
|
|
76
73
|
}
|
|
77
|
-
/**
|
|
78
|
-
* Strict variant: throws a `UsageError` if any finding is present. The thrown
|
|
79
|
-
* error carries the full set of findings on its message and a hint pointing
|
|
80
|
-
* at v1 spec §13. The first finding's `field` becomes the error's primary
|
|
81
|
-
* field for callers that want to highlight the first violation.
|
|
82
|
-
*/
|
|
83
|
-
export function assertLessonValid(filePath) {
|
|
84
|
-
const report = lintLessonFile(filePath);
|
|
85
|
-
if (report.findings.length === 0)
|
|
86
|
-
return;
|
|
87
|
-
const message = report.findings.map((f) => f.message).join("\n");
|
|
88
|
-
throw new UsageError(message, "MISSING_REQUIRED_ARGUMENT", "Lessons require non-empty `description` and `when_to_use` frontmatter fields. See v1 spec §13.");
|
|
89
|
-
}
|
package/dist/core/logs-db.js
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
* @module logs-db
|
|
39
39
|
*/
|
|
40
40
|
import path from "node:path";
|
|
41
|
-
import { runMigrations as runSqliteMigrations } from "../storage/engines/sqlite-migrations.js";
|
|
41
|
+
import { assertMigrationRegistry, runMigrations as runSqliteMigrations, } from "../storage/engines/sqlite-migrations.js";
|
|
42
42
|
import { openManagedDatabase } from "../storage/managed-db.js";
|
|
43
43
|
import { getDataDir } from "./paths.js";
|
|
44
44
|
// ── Path helper ──────────────────────────────────────────────────────────────
|
|
@@ -130,6 +130,7 @@ const MIGRATIONS = [
|
|
|
130
130
|
`,
|
|
131
131
|
},
|
|
132
132
|
];
|
|
133
|
+
assertMigrationRegistry(MIGRATIONS);
|
|
133
134
|
/**
|
|
134
135
|
* Apply every pending migration. Called automatically by
|
|
135
136
|
* {@link openLogsDatabase}; exported for the same test seams state-db exposes.
|
|
@@ -29,6 +29,22 @@ export function getMigrationRestoreJournalPath() {
|
|
|
29
29
|
export function getMigrationApplyJournalPath() {
|
|
30
30
|
return path.join(getMigrationOperationRoot(), "apply-active.json");
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Predictable path for the config `akm migrate apply` auto-generates when no
|
|
34
|
+
* `--config` is given and the active config still carries the pre-cutover
|
|
35
|
+
* `stashDir`/`sources[]`/`installed[]` shape (see `config-migrate.ts`'s
|
|
36
|
+
* `buildMigrationPlan`/`writeGeneratedTargetConfig`). Deliberately NOT the
|
|
37
|
+
* live `config.json` — the live 0.8 file must stay byte-for-byte untouched
|
|
38
|
+
* until `publishConfigLast` performs its normal atomic install, so the
|
|
39
|
+
* generated draft lives here instead, next to the apply/restore sentinels.
|
|
40
|
+
* Stable across invocations (keyed only by installation id, not a run id) so
|
|
41
|
+
* a second `migrate apply`/`migrate status` with still no `--config` finds
|
|
42
|
+
* the same file an operator may have hand-edited (e.g. to add `engines`)
|
|
43
|
+
* after the first run generated it.
|
|
44
|
+
*/
|
|
45
|
+
export function getMigrationGeneratedConfigPath() {
|
|
46
|
+
return path.join(getMigrationOperationRoot(), "generated-config.json");
|
|
47
|
+
}
|
|
32
48
|
export function assertNoPendingMigrationOperation() {
|
|
33
49
|
for (const [kind, journalPath] of [
|
|
34
50
|
["restore", getMigrationRestoreJournalPath()],
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
import path from "node:path";
|
|
5
|
+
import { deriveInstallations } from "../indexer/installations.js";
|
|
6
|
+
import { resolveSourceEntries } from "../indexer/search/search-source.js";
|
|
7
|
+
import { displayRef } from "./asset/resolve-ref.js";
|
|
8
|
+
import { UsageError } from "./errors.js";
|
|
9
|
+
import { prepareWriteTargetForMutation, resolveWorkingStashTarget, resolveWriteTarget, } from "./write-source.js";
|
|
10
|
+
function canonicalSources(config) {
|
|
11
|
+
const sources = resolveSourceEntries(undefined, config);
|
|
12
|
+
const installations = deriveInstallations(sources);
|
|
13
|
+
return sources.flatMap((source, index) => {
|
|
14
|
+
const bundleId = installations[index]?.id;
|
|
15
|
+
return bundleId ? [{ bundleId, source }] : [];
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function targetForCanonicalSource(config, canonical, options) {
|
|
19
|
+
const target = canonical.source.registryId
|
|
20
|
+
? resolveWriteTarget(config, canonical.source.registryId, options)
|
|
21
|
+
: resolveWorkingStashTarget(config, options);
|
|
22
|
+
if (path.resolve(target.source.path) !== path.resolve(canonical.source.path)) {
|
|
23
|
+
throw new UsageError(`Bundle "${canonical.bundleId}" no longer resolves to its indexed source root.`);
|
|
24
|
+
}
|
|
25
|
+
return target;
|
|
26
|
+
}
|
|
27
|
+
/** Resolve the canonical bundle id currently assigned to a write target. */
|
|
28
|
+
export function canonicalBundleIdForTarget(config, target) {
|
|
29
|
+
return (canonicalSources(config).find((candidate) => path.resolve(candidate.source.path) === path.resolve(target.source.path))?.bundleId ?? target.source.name);
|
|
30
|
+
}
|
|
31
|
+
/** Resolve a canonical bundle qualifier to its writable target without preparing a Git boundary. */
|
|
32
|
+
export function resolveBundleWriteTarget(config, bundleId, options = {}) {
|
|
33
|
+
const canonical = canonicalSources(config).find((candidate) => candidate.bundleId === bundleId);
|
|
34
|
+
if (!canonical) {
|
|
35
|
+
throw new UsageError(`Bundle "${bundleId}" is not configured.`, "INVALID_FLAG_VALUE");
|
|
36
|
+
}
|
|
37
|
+
const target = targetForCanonicalSource(config, canonical, options);
|
|
38
|
+
return { ...target, source: { ...target.source, name: canonical.bundleId } };
|
|
39
|
+
}
|
|
40
|
+
function resolveExplicitMutationTarget(config, explicitTarget, options) {
|
|
41
|
+
try {
|
|
42
|
+
return resolveWriteTarget(config, explicitTarget, options);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
try {
|
|
46
|
+
return resolveBundleWriteTarget(config, explicitTarget, options);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Reconcile a qualified mutation ref with `--target`, then resolve the write destination. */
|
|
54
|
+
export function resolveMutationTarget(config, ref, explicitTarget, options = {}) {
|
|
55
|
+
const writeOptions = { requireWritable: options.requireWritable };
|
|
56
|
+
const qualifiedTarget = ref.origin ? resolveBundleWriteTarget(config, ref.origin, writeOptions) : undefined;
|
|
57
|
+
const explicitResolved = explicitTarget
|
|
58
|
+
? resolveExplicitMutationTarget(config, explicitTarget, writeOptions)
|
|
59
|
+
: undefined;
|
|
60
|
+
if (qualifiedTarget &&
|
|
61
|
+
explicitResolved &&
|
|
62
|
+
path.resolve(qualifiedTarget.source.path) !== path.resolve(explicitResolved.source.path)) {
|
|
63
|
+
throw new UsageError(`Qualified ref bundle "${ref.origin}" conflicts with --target "${explicitTarget}".`, "INVALID_FLAG_VALUE", `Drop --target or select the same bundle.`);
|
|
64
|
+
}
|
|
65
|
+
let target = qualifiedTarget ?? explicitResolved ?? resolveWriteTarget(config, undefined, writeOptions);
|
|
66
|
+
const bundleId = ref.origin ?? canonicalBundleIdForTarget(config, target);
|
|
67
|
+
target = prepareWriteTargetForMutation({ ...target, source: { ...target.source, name: bundleId } }, { allowedAdapters: options.allowedAdapters });
|
|
68
|
+
const stableRef = { ...ref, origin: bundleId };
|
|
69
|
+
const defaultBundle = defaultBundleForTarget(config);
|
|
70
|
+
return {
|
|
71
|
+
target,
|
|
72
|
+
ref: stableRef,
|
|
73
|
+
displayRef: displayRef({ type: stableRef.type, name: stableRef.name, bundleId: stableRef.origin }, defaultBundle),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export function defaultBundleForTarget(config) {
|
|
77
|
+
return config.defaultBundle;
|
|
78
|
+
}
|
package/dist/core/parse.js
CHANGED
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
* models). Also strips leading/trailing whitespace.
|
|
24
24
|
*/
|
|
25
25
|
export function stripThinkBlocks(raw) {
|
|
26
|
-
return raw
|
|
26
|
+
return raw
|
|
27
|
+
.replace(/<think>[\s\S]*?<\/think>/gi, "")
|
|
28
|
+
.replace(/^[\s\S]*?<\/think>/i, "")
|
|
29
|
+
.trim();
|
|
27
30
|
}
|
|
28
31
|
/**
|
|
29
32
|
* Strips markdown code fences (``` or ~~~, with optional language tag).
|
package/dist/core/paths.js
CHANGED
|
@@ -30,7 +30,7 @@ function isUnderBunTest(env) {
|
|
|
30
30
|
* Returns true when the given path is in a directory family the OS may
|
|
31
31
|
* reap (or that the user has clearly designated as a sandbox by virtue
|
|
32
32
|
* of placing it under `/tmp` or a macOS per-user temp dir). Used to
|
|
33
|
-
* decide whether `
|
|
33
|
+
* decide whether `AKM_BUNDLE_DIR=$tmpdir` should also isolate config +
|
|
34
34
|
* cache writes (so a test harness's `akm setup --yes --dir .` cannot
|
|
35
35
|
* silently clobber the user's `~/.config/akm/config.json`). See
|
|
36
36
|
* the 2026-05-23 setup-clobbers-user-config incident
|
|
@@ -67,7 +67,7 @@ export function getConfigDir(env = process.env, platform = process.platform) {
|
|
|
67
67
|
return override;
|
|
68
68
|
// Explicit XDG override wins next — tests and operators that pre-arrange
|
|
69
69
|
// an isolated config dir via XDG_CONFIG_HOME (or %APPDATA% on Windows)
|
|
70
|
-
// must be honored as set, so the
|
|
70
|
+
// must be honored as set, so the AKM_BUNDLE_DIR transient-isolation rule
|
|
71
71
|
// below does not silently move config away from where they pointed it.
|
|
72
72
|
if (platform === "win32") {
|
|
73
73
|
const appData = env.APPDATA?.trim();
|
|
@@ -79,16 +79,16 @@ export function getConfigDir(env = process.env, platform = process.platform) {
|
|
|
79
79
|
if (xdgConfigHome)
|
|
80
80
|
return path.join(xdgConfigHome, "akm");
|
|
81
81
|
}
|
|
82
|
-
// Isolation safety: when
|
|
82
|
+
// Isolation safety: when AKM_BUNDLE_DIR points at a transient/sandbox path
|
|
83
83
|
// (/tmp, /var/tmp, /private/var/folders) AND no explicit config dir
|
|
84
|
-
// override is set, route config writes into `${
|
|
84
|
+
// override is set, route config writes into `${AKM_BUNDLE_DIR}/.akm`
|
|
85
85
|
// instead of the user's host ~/.config/akm. This prevents the documented
|
|
86
86
|
// isolation pattern
|
|
87
|
-
// AKM_DATA_DIR=/tmp/x
|
|
87
|
+
// AKM_DATA_DIR=/tmp/x AKM_BUNDLE_DIR=/tmp/x akm setup --yes --dir .
|
|
88
88
|
// from silently clobbering the host config. See
|
|
89
89
|
// the 2026-05-23 setup-clobbers-user-config incident.
|
|
90
|
-
// Daily users with a persistent
|
|
91
|
-
const stashOverride = env.
|
|
90
|
+
// Daily users with a persistent AKM_BUNDLE_DIR=~/my-stash are unaffected.
|
|
91
|
+
const stashOverride = env.AKM_BUNDLE_DIR?.trim();
|
|
92
92
|
if (stashOverride && isTransientStashPath(stashOverride)) {
|
|
93
93
|
return path.join(stashOverride, ".akm");
|
|
94
94
|
}
|
|
@@ -122,7 +122,7 @@ export function getCacheDir(env = process.env) {
|
|
|
122
122
|
// Explicit XDG/platform overrides win before the transient-stash isolation
|
|
123
123
|
// rule below — tests and operators that pre-arrange XDG_CACHE_HOME (or
|
|
124
124
|
// %LOCALAPPDATA% / %USERPROFILE% / %APPDATA% on Windows) must be honored
|
|
125
|
-
// as set, so the
|
|
125
|
+
// as set, so the AKM_BUNDLE_DIR transient rule does not silently move cache
|
|
126
126
|
// writes away from where they pointed them.
|
|
127
127
|
if (IS_WINDOWS) {
|
|
128
128
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
@@ -145,12 +145,12 @@ export function getCacheDir(env = process.env) {
|
|
|
145
145
|
if (xdgCacheHome)
|
|
146
146
|
return path.join(xdgCacheHome, "akm");
|
|
147
147
|
}
|
|
148
|
-
// Isolation safety (mirrors getConfigDir): when
|
|
148
|
+
// Isolation safety (mirrors getConfigDir): when AKM_BUNDLE_DIR points at a
|
|
149
149
|
// transient path AND no explicit cache override is set, route cache writes
|
|
150
|
-
// into `${
|
|
150
|
+
// into `${AKM_BUNDLE_DIR}/.akm/cache` so that config backups, registry-index
|
|
151
151
|
// cache, and other regenerable artifacts do not pollute the user's host
|
|
152
152
|
// ~/.cache/akm directory.
|
|
153
|
-
const stashOverride = env.
|
|
153
|
+
const stashOverride = env.AKM_BUNDLE_DIR?.trim();
|
|
154
154
|
if (stashOverride && isTransientStashPath(stashOverride)) {
|
|
155
155
|
return path.join(stashOverride, ".akm", "cache");
|
|
156
156
|
}
|
|
@@ -184,7 +184,7 @@ export function getDataDir(env = process.env, platform = process.platform) {
|
|
|
184
184
|
// user's real $XDG_DATA_HOME / ~/.local/share/akm under any condition.
|
|
185
185
|
// Any test that needs a data dir must point it at a mktemp-d directory
|
|
186
186
|
// via XDG_DATA_HOME (or AKM_DATA_DIR). The previous carve-out that only
|
|
187
|
-
// fired when
|
|
187
|
+
// fired when AKM_BUNDLE_DIR was set was a loophole: tests calling
|
|
188
188
|
// openDatabase() or getDbPath() without overriding any env var silently
|
|
189
189
|
// wrote into ~/.local/share/akm/index.db (observed: 4,183-row
|
|
190
190
|
// registry-cache pollution). Item 5 of the 0.8.x critical-review plan.
|
|
@@ -225,9 +225,9 @@ export function getMaintenanceBarrierPath() {
|
|
|
225
225
|
export function getStateDbPathInDataDir() {
|
|
226
226
|
return path.join(getDataDir(), "state.db");
|
|
227
227
|
}
|
|
228
|
-
/**
|
|
229
|
-
export function
|
|
230
|
-
return path.join(getDataDir(), "tasks", "
|
|
228
|
+
/** Content-addressed scheduler runtime descriptors. */
|
|
229
|
+
export function getTaskContextDir(env = process.env) {
|
|
230
|
+
return path.join(getDataDir(env), "tasks", "context");
|
|
231
231
|
}
|
|
232
232
|
/** Path to the akm.lock file in $DATA. */
|
|
233
233
|
export function getLockfilePath() {
|
|
@@ -246,9 +246,6 @@ export function getRegistryCacheDir() {
|
|
|
246
246
|
export function getRegistryIndexCacheDir() {
|
|
247
247
|
return path.join(getCacheDir(), "registry-index");
|
|
248
248
|
}
|
|
249
|
-
export function getBinDir() {
|
|
250
|
-
return path.join(getCacheDir(), "bin");
|
|
251
|
-
}
|
|
252
249
|
// ── Scheduled-task runtime directories (logs + history) ──────────────────────
|
|
253
250
|
export function getTaskLogDir() {
|
|
254
251
|
return path.join(getCacheDir(), "tasks", "logs");
|
|
@@ -258,7 +255,7 @@ export function getTaskHistoryDir() {
|
|
|
258
255
|
}
|
|
259
256
|
// ── Default stash directory ──────────────────────────────────────────────────
|
|
260
257
|
export function getDefaultStashDir(env = process.env) {
|
|
261
|
-
const override = env.
|
|
258
|
+
const override = env.AKM_BUNDLE_DIR?.trim();
|
|
262
259
|
if (override)
|
|
263
260
|
return override;
|
|
264
261
|
if (IS_WINDOWS) {
|
|
@@ -269,7 +266,7 @@ export function getDefaultStashDir(env = process.env) {
|
|
|
269
266
|
}
|
|
270
267
|
const home = env.HOME?.trim();
|
|
271
268
|
if (!home) {
|
|
272
|
-
throw new ConfigError("Unable to determine default
|
|
269
|
+
throw new ConfigError("Unable to determine default bundle directory. Set HOME.", "STASH_DIR_NOT_FOUND");
|
|
273
270
|
}
|
|
274
271
|
return path.join(home, "akm");
|
|
275
272
|
}
|
|
@@ -34,22 +34,20 @@ export const SCRIPT_EXTENSIONS = new Set([
|
|
|
34
34
|
".kts",
|
|
35
35
|
]);
|
|
36
36
|
/**
|
|
37
|
-
* Recognized workflow asset extensions
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* (redesign addendum, R1). `workflows/<name>` refs resolve against this list.
|
|
37
|
+
* Recognized workflow asset extensions. One format now (workflow-format-
|
|
38
|
+
* unification): orchestration graph in frontmatter, prose in the body.
|
|
39
|
+
* `workflows/<name>` refs resolve against this list.
|
|
41
40
|
*/
|
|
42
|
-
export const WORKFLOW_EXTENSIONS = [".md"
|
|
41
|
+
export const WORKFLOW_EXTENSIONS = [".md"];
|
|
43
42
|
/**
|
|
44
|
-
* Strip
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* unchanged.
|
|
43
|
+
* Strip the recognized workflow extension (`.md`) from a workflow asset
|
|
44
|
+
* *name* so `foo` and `foo.md` collapse to one canonical identity — the same
|
|
45
|
+
* collapse `workflowSpec.toCanonicalName` performs on a resolved file path.
|
|
46
|
+
* Callers that turn a `workflows/<name>` ref into run identity (the
|
|
47
|
+
* active-run guard, list/status filters) MUST route the name through this so
|
|
48
|
+
* an aliased spelling (`workflows/foo.md`) and the canonical `workflows/foo`
|
|
49
|
+
* cannot start or hide parallel runs of the same workflow. Names without the
|
|
50
|
+
* extension pass through unchanged.
|
|
53
51
|
*/
|
|
54
52
|
export function canonicalizeWorkflowName(name) {
|
|
55
53
|
const lower = name.toLowerCase();
|
package/dist/core/redaction.js
CHANGED
|
@@ -297,6 +297,40 @@ function addMappedMatches(coverageDelta, haystack, needle) {
|
|
|
297
297
|
offset = match + Math.max(needle.length, 1);
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Redact credential-shaped substrings from arbitrary text by pattern alone —
|
|
302
|
+
* unlike {@link redactSensitiveText}, which requires the exact secret value
|
|
303
|
+
* up front, this catches credentials no caller ever knew to list. No
|
|
304
|
+
* truncation is applied; callers that need a length cap (e.g.
|
|
305
|
+
* {@link redactErrorBody} in src/llm/client.ts) apply it themselves.
|
|
306
|
+
*
|
|
307
|
+
* Targets:
|
|
308
|
+
* - `Bearer <token>` headers echoed back by a provider
|
|
309
|
+
* - `sk-…` / `sk_…` style API keys (OpenAI / Anthropic-shaped)
|
|
310
|
+
* - `key-…` / `key_…` shorthand keys
|
|
311
|
+
* - `"api_key": "…"` / `"apiKey": "…"` JSON fields
|
|
312
|
+
* - Discord webhook URLs (`discord.com/api/webhooks/<id>/<token>`) — the id
|
|
313
|
+
* is kept, only the token segment is redacted
|
|
314
|
+
* - Slack incoming-webhook URLs (`hooks.slack.com/services/<team>/<channel>/<token>`)
|
|
315
|
+
* — the team/channel ids are kept, only the trailing token is redacted
|
|
316
|
+
*/
|
|
317
|
+
export function redactCredentialPatterns(input) {
|
|
318
|
+
if (!input)
|
|
319
|
+
return "";
|
|
320
|
+
return (input
|
|
321
|
+
// Bearer tokens (case-insensitive)
|
|
322
|
+
.replace(/\bBearer\s+[A-Za-z0-9._\-+/=]+/gi, "Bearer [REDACTED]")
|
|
323
|
+
// sk-/sk_ style keys
|
|
324
|
+
.replace(/\bsk[-_][A-Za-z0-9._-]{6,}/g, "[REDACTED]")
|
|
325
|
+
// key-/key_ shorthand keys
|
|
326
|
+
.replace(/\bkey[-_][A-Za-z0-9._-]{6,}/g, "[REDACTED]")
|
|
327
|
+
// JSON-style "api_key": "...", "apiKey": "...", "api-key": "..."
|
|
328
|
+
.replace(/("(?:api[_-]?key|apiKey|authorization|token)"\s*:\s*")([^"]*)(")/gi, "$1[REDACTED]$3")
|
|
329
|
+
// Discord webhook URLs: keep the webhook id, redact the token segment.
|
|
330
|
+
.replace(/(discord(?:app)?\.com\/api\/webhooks\/\d+\/)[A-Za-z0-9_-]+/gi, "$1[REDACTED]")
|
|
331
|
+
// Slack incoming-webhook URLs: keep the team/channel ids, redact the token.
|
|
332
|
+
.replace(/(hooks\.slack\.com\/services\/[A-Za-z0-9]+\/[A-Za-z0-9]+\/)[A-Za-z0-9]+/gi, "$1[REDACTED]"));
|
|
333
|
+
}
|
|
300
334
|
/**
|
|
301
335
|
* Replace exact sensitive values in text. Longer values are replaced first so
|
|
302
336
|
* an overlapping prefix cannot expose the suffix of a longer credential.
|