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
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* `config-schema.ts` monolith — no behavior change.
|
|
7
7
|
*/
|
|
8
8
|
import { z } from "zod";
|
|
9
|
-
import { positiveInt } from "./primitives.js";
|
|
9
|
+
import { engineName, positiveInt } from "./primitives.js";
|
|
10
10
|
// ── Workflow engine ─────────────────────────────────────────────────────────
|
|
11
11
|
/**
|
|
12
12
|
* Workflow-engine settings (`workflow`).
|
|
@@ -19,11 +19,11 @@ import { positiveInt } from "./primitives.js";
|
|
|
19
19
|
* `[1, WORKFLOW_MAX_CONCURRENCY_CEILING]` (64). Values above the ceiling
|
|
20
20
|
* are clamped, not rejected, so a config shared across machines with wildly
|
|
21
21
|
* different core counts never hard-fails validation.
|
|
22
|
-
* The R3 brief/report driver surface does NOT consult this — drivers own their
|
|
23
|
-
* own parallelism (the engine only caps native dispatch).
|
|
24
22
|
*/
|
|
25
23
|
export const WorkflowConfigSchema = z
|
|
26
24
|
.object({
|
|
27
25
|
maxConcurrency: positiveInt.optional(),
|
|
26
|
+
/** Named LLM or agent engine frozen into every criteria-bearing gate. */
|
|
27
|
+
judgeEngine: engineName.optional(),
|
|
28
28
|
})
|
|
29
29
|
.passthrough();
|
|
@@ -11,15 +11,18 @@
|
|
|
11
11
|
* helpers only resolve refs to absolute paths and guard against directory
|
|
12
12
|
* traversal.
|
|
13
13
|
*/
|
|
14
|
+
import fs from "node:fs";
|
|
14
15
|
import path from "node:path";
|
|
15
16
|
import { resolveSourceEntries } from "../indexer/search/search-source.js";
|
|
17
|
+
import { resolveSourcesForOrigin } from "../registry/origin-resolve.js";
|
|
16
18
|
import { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath } from "./asset/asset-create.js";
|
|
17
19
|
import { assetPathForName } from "./asset/asset-placement.js";
|
|
18
20
|
import { displayRef, isFullRefInput, parseRefInput } from "./asset/resolve-ref.js";
|
|
19
21
|
import { isWithin } from "./common.js";
|
|
20
22
|
import { loadConfig } from "./config/config.js";
|
|
21
23
|
import { NotFoundError, UsageError } from "./errors.js";
|
|
22
|
-
import {
|
|
24
|
+
import { resolveMutationTarget } from "./mutation-target.js";
|
|
25
|
+
import { formatRefForMessage, withWriteTargetMutation } from "./write-source.js";
|
|
23
26
|
/**
|
|
24
27
|
* The `vault` asset type was removed in 0.9.0. The env/secret input path no
|
|
25
28
|
* longer routes through the legacy stored-ref parser (which carries the removal
|
|
@@ -31,25 +34,58 @@ function assertNotRemovedVaultRef(ref) {
|
|
|
31
34
|
const boundary = ref.indexOf("//");
|
|
32
35
|
const bare = boundary >= 0 ? ref.slice(boundary + 2) : ref;
|
|
33
36
|
if (/^vault[:/]/.test(bare.trim())) {
|
|
34
|
-
throw new UsageError("The `vault` asset type was removed in 0.9.0 — use `env
|
|
37
|
+
throw new UsageError("The `vault` asset type was removed in 0.9.0 — use `env/` (whole .env config) or `secrets/` (a single value).", "INVALID_FLAG_VALUE");
|
|
35
38
|
}
|
|
36
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Q-08 ruling: the pre-0.9.0 `type:name` ref grammar taught `env:<name>` /
|
|
42
|
+
* `secret:<name>` (help text and docs also implied `environment:`/`secrets:`
|
|
43
|
+
* variants) as the way to address a single env/secret. That grammar is GONE —
|
|
44
|
+
* NO alias, no re-acceptance (same rule as the retired `vault:` prefix above).
|
|
45
|
+
* Left unchecked, a colon-prefixed ref does not error here at all: it falls
|
|
46
|
+
* through to the "bare name" convenience below and gets silently qualified
|
|
47
|
+
* into a literal `env/env:name` (or `secrets/secret:name`) file that can never
|
|
48
|
+
* exist — a confusing not-found that hides the real mistake instead of naming
|
|
49
|
+
* it. Reject it here, loudly, before that happens.
|
|
50
|
+
*/
|
|
51
|
+
function assertNotColonRef(ref, aliases, replacement) {
|
|
52
|
+
const boundary = ref.indexOf("//");
|
|
53
|
+
const bare = (boundary >= 0 ? ref.slice(boundary + 2) : ref).trim();
|
|
54
|
+
const colon = bare.indexOf(":");
|
|
55
|
+
if (colon <= 0)
|
|
56
|
+
return;
|
|
57
|
+
const head = bare.slice(0, colon).toLowerCase();
|
|
58
|
+
if (!aliases.includes(head))
|
|
59
|
+
return;
|
|
60
|
+
const name = bare.slice(colon + 1);
|
|
61
|
+
throw new UsageError(`The \`${head}:\` ref spelling was removed in 0.9.0 — use the slash form instead: \`${replacement}${name}\`.`, "INVALID_FLAG_VALUE");
|
|
62
|
+
}
|
|
37
63
|
export function parseEnvRef(ref) {
|
|
38
64
|
// Accept a bare env name (`prod`, `sub/prod`) or the new-grammar
|
|
39
65
|
// `[bundle//]env/name` conceptId. A bare name's leading segment maps to no
|
|
40
66
|
// asset type, so it is qualified with the `env/` conceptId prefix; anything
|
|
41
67
|
// already a full new-grammar ref is parsed as-is.
|
|
42
68
|
assertNotRemovedVaultRef(ref);
|
|
69
|
+
assertNotColonRef(ref, ["env", "environment"], "env/");
|
|
43
70
|
return parseRefInput(isFullRefInput(ref) ? ref : `env/${ref}`);
|
|
44
71
|
}
|
|
45
|
-
export function findEnvSource(origin) {
|
|
72
|
+
export function findEnvSource(origin, type, name) {
|
|
46
73
|
const sources = resolveSourceEntries(undefined, loadConfig());
|
|
47
74
|
if (sources.length === 0) {
|
|
48
|
-
throw new UsageError("No
|
|
75
|
+
throw new UsageError("No bundles configured. Run `akm bundle create` to create your working bundle.");
|
|
76
|
+
}
|
|
77
|
+
const candidates = origin ? resolveSourcesForOrigin(origin, sources) : sources;
|
|
78
|
+
const typeDir = type === "env" ? "env" : "secrets";
|
|
79
|
+
const member = candidates.find((source) => fs.existsSync(assetPathForName(type, path.join(source.path, typeDir), name)));
|
|
80
|
+
if (member)
|
|
81
|
+
return member;
|
|
82
|
+
if (!origin) {
|
|
83
|
+
const fallback = candidates[0];
|
|
84
|
+
if (fallback)
|
|
85
|
+
return fallback;
|
|
86
|
+
throw new UsageError("No bundles configured. Run `akm bundle create` to create your working bundle.");
|
|
49
87
|
}
|
|
50
|
-
|
|
51
|
-
return sources[0];
|
|
52
|
-
const named = sources.find((source) => source.registryId === origin);
|
|
88
|
+
const named = candidates[0];
|
|
53
89
|
if (!named) {
|
|
54
90
|
throw new NotFoundError(`Source not found for origin: ${origin}`);
|
|
55
91
|
}
|
|
@@ -58,19 +94,21 @@ export function findEnvSource(origin) {
|
|
|
58
94
|
export function makeEnvRef(name, source) {
|
|
59
95
|
// F4b output-spelling flip: `env/name` in the primary stash, `bundle//env/name`
|
|
60
96
|
// for a slug-clean named source.
|
|
61
|
-
return displayRef({ type: "env", name, bundleId: source?.registryId });
|
|
97
|
+
return displayRef({ type: "env", name, bundleId: source?.registryId }, displayDefaultBundle(source));
|
|
62
98
|
}
|
|
63
99
|
/**
|
|
64
|
-
* Resolve an env ref to an absolute `.env` path. Accepts `env
|
|
65
|
-
*
|
|
66
|
-
*
|
|
100
|
+
* Resolve an env ref to an absolute `.env` path. Accepts the `env/<name>`
|
|
101
|
+
* conceptId (or a bare name, auto-qualified into it) — the retired
|
|
102
|
+
* `env:`/`environment:` colon spelling is rejected loudly (Q-08), never
|
|
103
|
+
* silently resolved. The path is returned even when the file does not yet
|
|
104
|
+
* exist (so `create` writes under `env/`).
|
|
67
105
|
*/
|
|
68
106
|
export function resolveEnvPath(ref) {
|
|
69
107
|
const parsed = parseEnvRef(ref);
|
|
70
108
|
if (parsed.type !== "env") {
|
|
71
|
-
throw new UsageError(`Expected an env ref (env
|
|
109
|
+
throw new UsageError(`Expected an env ref (env/<name>); got "${ref}".`);
|
|
72
110
|
}
|
|
73
|
-
const source = findEnvSource(parsed.origin);
|
|
111
|
+
const source = findEnvSource(parsed.origin, "env", parsed.name);
|
|
74
112
|
const envRoot = path.join(source.path, "env");
|
|
75
113
|
const envPath = assetPathForName("env", envRoot, parsed.name);
|
|
76
114
|
// Defense-in-depth: ensure the resolved path stays inside the env directory.
|
|
@@ -86,12 +124,20 @@ export function parseSecretRef(ref) {
|
|
|
86
124
|
// Same bare-name-vs-full-ref rule as parseEnvRef; a bare name is qualified
|
|
87
125
|
// with the `secrets/` conceptId prefix (secret's stash subdir).
|
|
88
126
|
assertNotRemovedVaultRef(ref);
|
|
127
|
+
assertNotColonRef(ref, ["secret", "secrets"], "secrets/");
|
|
89
128
|
return parseRefInput(isFullRefInput(ref) ? ref : `secrets/${ref}`);
|
|
90
129
|
}
|
|
91
130
|
export function makeSecretRef(name, source) {
|
|
92
131
|
// F4b output-spelling flip: `secrets/name` in the primary stash,
|
|
93
132
|
// `bundle//secrets/name` for a slug-clean named source.
|
|
94
|
-
return displayRef({ type: "secret", name, bundleId: source?.registryId });
|
|
133
|
+
return displayRef({ type: "secret", name, bundleId: source?.registryId }, displayDefaultBundle(source));
|
|
134
|
+
}
|
|
135
|
+
function displayDefaultBundle(source) {
|
|
136
|
+
const config = loadConfig();
|
|
137
|
+
if (config.defaultBundle || !source)
|
|
138
|
+
return config.defaultBundle;
|
|
139
|
+
const primary = resolveSourceEntries(undefined, config)[0];
|
|
140
|
+
return primary && path.resolve(primary.path) === path.resolve(source.path) ? source.registryId : undefined;
|
|
95
141
|
}
|
|
96
142
|
export function resolveSecretPath(ref,
|
|
97
143
|
// Create-only (`secret set`): enforce a flat ref name and apply `--path` as
|
|
@@ -99,14 +145,14 @@ export function resolveSecretPath(ref,
|
|
|
99
145
|
create) {
|
|
100
146
|
const parsed = parseSecretRef(ref);
|
|
101
147
|
if (parsed.type !== "secret") {
|
|
102
|
-
throw new UsageError(`Expected a secret ref (
|
|
148
|
+
throw new UsageError(`Expected a secret ref (secrets/<name>); got "${ref}".`);
|
|
103
149
|
}
|
|
104
150
|
if (create) {
|
|
105
151
|
assertFlatAssetName(parsed.name);
|
|
106
152
|
parsed.name = combineCreatePath(normalizeCreateSubPath(create.subPath), parsed.name);
|
|
107
153
|
}
|
|
108
154
|
// Source resolution is identical for every asset type; reuse the env helper.
|
|
109
|
-
const source = findEnvSource(parsed.origin);
|
|
155
|
+
const source = findEnvSource(parsed.origin, "secret", parsed.name);
|
|
110
156
|
const typeRoot = path.join(source.path, "secrets");
|
|
111
157
|
const absPath = assetPathForName("secret", typeRoot, parsed.name);
|
|
112
158
|
// Defense-in-depth: ensure the resolved path stays inside the secrets dir.
|
|
@@ -115,26 +161,6 @@ create) {
|
|
|
115
161
|
}
|
|
116
162
|
return { name: parsed.name, absPath, source };
|
|
117
163
|
}
|
|
118
|
-
// ── Write-target resolution (env/secret mutations) ───────────────────────────
|
|
119
|
-
//
|
|
120
|
-
// READS (`env run`/`show`/`list`/`path`, `secret run`/`path`/`list`) keep the
|
|
121
|
-
// origin-aware, all-sources `findEnvSource` resolution above. WRITES route
|
|
122
|
-
// through the canonical `resolveWriteTarget` selection every other write command
|
|
123
|
-
// (remember/import/tasks/knowledge) shares: explicit `--target` wins, else
|
|
124
|
-
// `defaultWriteTarget`, else the working stash, and the chosen source must be
|
|
125
|
-
// writable (a non-writable `--target`/`defaultWriteTarget` fails fast with the
|
|
126
|
-
// shared typed ConfigError). Env/secret VALUES are still never read or surfaced
|
|
127
|
-
// here — these helpers only resolve the write target and the absolute path.
|
|
128
|
-
/**
|
|
129
|
-
* Spell an env/secret ref for a resolved write target. `target.selector` is the
|
|
130
|
-
* config source name for a `--target`/`defaultWriteTarget` destination and
|
|
131
|
-
* undefined for the working-stash fallback; `displayRef` suppresses the
|
|
132
|
-
* `local`/`stash`/default sentinels, so the primary stash still spells the bare
|
|
133
|
-
* `env/name` while a named bundle spells `bundle//env/name`.
|
|
134
|
-
*/
|
|
135
|
-
export function writeTargetDisplaySource(target) {
|
|
136
|
-
return { path: target.source.path, ...(target.selector ? { registryId: target.selector } : {}) };
|
|
137
|
-
}
|
|
138
164
|
/**
|
|
139
165
|
* Resolve the destination for an env mutation. Mirrors {@link resolveEnvPath}
|
|
140
166
|
* but selects the source via {@link resolveWriteTarget} (writability-checked)
|
|
@@ -144,19 +170,20 @@ export function writeTargetDisplaySource(target) {
|
|
|
144
170
|
export function resolveEnvWriteTarget(ref, writeTarget, create) {
|
|
145
171
|
const parsed = parseEnvRef(ref);
|
|
146
172
|
if (parsed.type !== "env") {
|
|
147
|
-
throw new UsageError(`Expected an env ref (env
|
|
173
|
+
throw new UsageError(`Expected an env ref (env/<name>); got "${ref}".`);
|
|
148
174
|
}
|
|
149
175
|
if (create) {
|
|
150
176
|
assertFlatAssetName(parsed.name);
|
|
151
177
|
parsed.name = combineCreatePath(normalizeCreateSubPath(create.subPath), parsed.name);
|
|
152
178
|
}
|
|
153
|
-
const
|
|
179
|
+
const resolved = resolveMutationTarget(loadConfig(), parsed, writeTarget, { allowedAdapters: ["akm", "dotenv"] });
|
|
180
|
+
const { target } = resolved;
|
|
154
181
|
const envRoot = path.join(target.source.path, "env");
|
|
155
182
|
const absPath = assetPathForName("env", envRoot, parsed.name);
|
|
156
183
|
if (!isWithin(absPath, envRoot)) {
|
|
157
184
|
throw new UsageError(`Env name "${parsed.name}" escapes the env directory.`);
|
|
158
185
|
}
|
|
159
|
-
return { name: parsed.name, absPath, target, parsedRef:
|
|
186
|
+
return { name: parsed.name, absPath, target, parsedRef: resolved.ref, ref: resolved.displayRef };
|
|
160
187
|
}
|
|
161
188
|
/**
|
|
162
189
|
* Resolve the destination for a secret mutation. Mirrors
|
|
@@ -167,19 +194,20 @@ export function resolveEnvWriteTarget(ref, writeTarget, create) {
|
|
|
167
194
|
export function resolveSecretWriteTarget(ref, writeTarget, create) {
|
|
168
195
|
const parsed = parseSecretRef(ref);
|
|
169
196
|
if (parsed.type !== "secret") {
|
|
170
|
-
throw new UsageError(`Expected a secret ref (
|
|
197
|
+
throw new UsageError(`Expected a secret ref (secrets/<name>); got "${ref}".`);
|
|
171
198
|
}
|
|
172
199
|
if (create) {
|
|
173
200
|
assertFlatAssetName(parsed.name);
|
|
174
201
|
parsed.name = combineCreatePath(normalizeCreateSubPath(create.subPath), parsed.name);
|
|
175
202
|
}
|
|
176
|
-
const
|
|
203
|
+
const resolved = resolveMutationTarget(loadConfig(), parsed, writeTarget, { allowedAdapters: ["akm", "dotenv"] });
|
|
204
|
+
const { target } = resolved;
|
|
177
205
|
const typeRoot = path.join(target.source.path, "secrets");
|
|
178
206
|
const absPath = assetPathForName("secret", typeRoot, parsed.name);
|
|
179
207
|
if (!isWithin(absPath, typeRoot)) {
|
|
180
208
|
throw new UsageError(`Secret name "${parsed.name}" escapes the secrets directory.`);
|
|
181
209
|
}
|
|
182
|
-
return { name: parsed.name, absPath, target };
|
|
210
|
+
return { name: parsed.name, absPath, target, ref: resolved.displayRef };
|
|
183
211
|
}
|
|
184
212
|
/**
|
|
185
213
|
* Land an env/secret mutation on its write target's git boundary. Mirrors the
|
|
@@ -188,8 +216,10 @@ export function resolveSecretWriteTarget(ref, writeTarget, create) {
|
|
|
188
216
|
* primary stash included) and for `env/` paths a stash `.gitignore` excludes, so
|
|
189
217
|
* callers invoke it unconditionally after every create/ingest/set/remove.
|
|
190
218
|
*/
|
|
191
|
-
export function
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
219
|
+
export function withEnvSecretWrite(target, ref, op, paths, mutate) {
|
|
220
|
+
return withWriteTargetMutation(target, paths, {
|
|
221
|
+
ignored: "local-only",
|
|
222
|
+
purpose: `${ref.type}-${op.toLowerCase()}`,
|
|
223
|
+
message: `${op} ${formatRefForMessage({ type: ref.type, name: ref.name, origin: target.source.name })}`,
|
|
224
|
+
}, mutate);
|
|
195
225
|
}
|
package/dist/core/errors.js
CHANGED
|
@@ -6,33 +6,39 @@
|
|
|
6
6
|
* imperative. Returning undefined means "no canned hint".
|
|
7
7
|
*/
|
|
8
8
|
const CONFIG_HINTS = {
|
|
9
|
-
STASH_DIR_NOT_FOUND: "Run `akm setup` to create and configure your
|
|
10
|
-
STASH_DIR_NOT_A_DIRECTORY: "The configured
|
|
11
|
-
STASH_DIR_UNREADABLE: "Check the path exists and your user has read permission, or update
|
|
9
|
+
STASH_DIR_NOT_FOUND: "Run `akm setup` to create and configure your bundle, or configure a defaultBundle path.",
|
|
10
|
+
STASH_DIR_NOT_A_DIRECTORY: "The configured default bundle path exists but isn't a directory. Update it to point at a folder.",
|
|
11
|
+
STASH_DIR_UNREADABLE: "Check the path exists and your user has read permission, or update the default bundle path.",
|
|
12
12
|
EMBEDDING_NOT_CONFIGURED: 'Run `akm config set embedding \'{"endpoint":"...","model":"..."}\'` to enable embeddings.',
|
|
13
13
|
LLM_NOT_CONFIGURED: 'Run `akm setup` or configure an `engines` entry with `kind: "llm"`, then select it with `defaults.llmEngine`.',
|
|
14
|
-
TEST_ISOLATION_MISSING: "Under bun test, when
|
|
15
|
-
SETUP_TMP_STASH_REFUSED: "Use a persistent directory, or set AKM_FORCE_SETUP_TMP_STASH=1 to opt in to a sandboxed setup (setup also pre-sets
|
|
16
|
-
UNSAFE_STASH_DIR: "Choose a path inside your home directory (e.g. ~/akm) or another empty workspace. The
|
|
14
|
+
TEST_ISOLATION_MISSING: "Under bun test, when AKM_BUNDLE_DIR is set you MUST also set XDG_DATA_HOME (or AKM_DATA_DIR) and XDG_STATE_HOME (or AKM_STATE_DIR) to temp directories so the test does not touch the developer's real ~/.local/share/akm or ~/.local/state/akm.",
|
|
15
|
+
SETUP_TMP_STASH_REFUSED: "Use a persistent directory, or set AKM_FORCE_SETUP_TMP_STASH=1 to opt in to a sandboxed setup (setup also pre-sets AKM_BUNDLE_DIR so config and cache writes auto-isolate into $stashDir/.akm/ — host config is preserved).",
|
|
16
|
+
UNSAFE_STASH_DIR: "Choose a path inside your home directory (e.g. ~/akm) or another empty workspace. The bundle directory cannot be the filesystem root, your home directory itself, or a sensitive system path like /etc, /var, ~/.config, or ~/.ssh.",
|
|
17
17
|
UNKNOWN_IMPROVE_STRATEGY: "Pass one of the listed strategy names to `--strategy`, or define it under `improve.strategies`. Names are case-sensitive.",
|
|
18
18
|
};
|
|
19
19
|
/** Default hint for each UsageError code. */
|
|
20
20
|
const USAGE_HINTS = {
|
|
21
21
|
INVALID_FLAG_VALUE: "Run `akm <command> --help` to see accepted values.",
|
|
22
|
-
INVALID_SOURCE_VALUE: "Pick one of:
|
|
23
|
-
INVALID_FORMAT_VALUE: "Pick one of: json, jsonl, text,
|
|
22
|
+
INVALID_SOURCE_VALUE: "Pick one of: local, registry, all, or a configured source name.",
|
|
23
|
+
INVALID_FORMAT_VALUE: "Pick one of: json, jsonl, yaml, text, md, html.",
|
|
24
24
|
INVALID_DETAIL_VALUE: "Pick one of: brief, normal, full. For agent/summary projections use --shape.",
|
|
25
25
|
INVALID_SHAPE_VALUE: "Pick one of: human, agent, summary (summary is only valid on `akm show`).",
|
|
26
26
|
INVALID_JSON_CONFIG_VALUE: 'Quote JSON values in your shell, for example: akm config set embedding \'{"endpoint":"http://localhost:11434/v1/embeddings","model":"nomic-embed-text"}\'.',
|
|
27
|
-
MISSING_OR_AMBIGUOUS_TARGET: "Use `akm update --all` or pass a target like `akm update npm:@scope/pkg` (not both).",
|
|
28
|
-
TARGET_NOT_UPDATABLE: "Run `akm list` to view your sources, then retry with one of those values.",
|
|
27
|
+
MISSING_OR_AMBIGUOUS_TARGET: "Use `akm bundle update --all` or pass a target like `akm bundle update npm:@scope/pkg` (not both).",
|
|
28
|
+
TARGET_NOT_UPDATABLE: "Run `akm bundle list` to view your sources, then retry with one of those values.",
|
|
29
29
|
MISSING_REQUIRED_ARGUMENT: "Refs use the form [bundle//]conceptId, e.g. `akm show knowledge/guide.md` or `akm show skills/deploy`.",
|
|
30
|
+
UNKNOWN_COMMAND: "Run `akm --help` to see available commands.",
|
|
31
|
+
UNKNOWN_FLAG: "Run the command with `--help` to see its accepted flags.",
|
|
30
32
|
};
|
|
31
33
|
/** Default hint for each NotFoundError code. */
|
|
32
34
|
const NOT_FOUND_HINTS = {
|
|
33
35
|
ASSET_NOT_FOUND: "Run `akm search <query>` or `akm index` to refresh the index.",
|
|
34
|
-
SOURCE_NOT_FOUND: "Run `akm list` to view your sources, then retry with one of those values.",
|
|
36
|
+
SOURCE_NOT_FOUND: "Run `akm bundle list` to view your sources, then retry with one of those values.",
|
|
35
37
|
WORKFLOW_NOT_FOUND: "Run `akm workflow list --active` to see runs.",
|
|
38
|
+
// A proposal is addressed by id or ref, never by path — reusing
|
|
39
|
+
// FILE_NOT_FOUND here handed users "check the path exists and is readable"
|
|
40
|
+
// for a mistyped id, which points at the wrong thing entirely.
|
|
41
|
+
PROPOSAL_NOT_FOUND: "Run `akm proposal list` to see pending proposals and their ids.",
|
|
36
42
|
FILE_NOT_FOUND: "Check the path exists and is readable.",
|
|
37
43
|
};
|
|
38
44
|
/**
|
|
@@ -97,7 +103,7 @@ export class NotFoundError extends AkmError {
|
|
|
97
103
|
* Test-isolation guard helper.
|
|
98
104
|
*
|
|
99
105
|
* `src/core/paths.ts` throws `ConfigError("TEST_ISOLATION_MISSING")` under
|
|
100
|
-
* `bun test` when `
|
|
106
|
+
* `bun test` when `AKM_BUNDLE_DIR` is set without a paired data-dir or
|
|
101
107
|
* state-dir override. That throw must never be swallowed by best-effort
|
|
102
108
|
* catches around DB/data-dir operations — otherwise the guard's loud failure
|
|
103
109
|
* silently degrades into a "no result" outcome (cold cache, missing snapshot,
|
package/dist/core/events.js
CHANGED
|
@@ -1,52 +1,19 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* Append-only events stream — backed by state.db (#204, Phase 3).
|
|
6
|
-
*
|
|
7
|
-
* Every mutating CLI verb funnels through `appendEvent` so external
|
|
8
|
-
* observers (sync, replication, audit, dashboards) can react to stash
|
|
9
|
-
* changes. Events are stored in the `events` table in `state.db`
|
|
10
|
-
* (SQLite, WAL mode) instead of a flat `events.jsonl` file.
|
|
11
|
-
*
|
|
12
|
-
* The helper is the only thing in akm that writes to the events table. It
|
|
13
|
-
* accepts an injectable `dbPath` (via `EventsContext`) so tests can pin a
|
|
14
|
-
* tmpdir without any global mutation.
|
|
15
|
-
*
|
|
16
|
-
* Format (each EventEnvelope):
|
|
17
|
-
* { "schemaVersion": 1, "id": <number>, "ts": "<ISO>",
|
|
18
|
-
* "eventType": "<verb>", "ref"?: "<asset-ref>", ... }
|
|
19
|
-
*
|
|
20
|
-
* - `id` is a monotonic SQLite AUTOINCREMENT rowid. Callers can persist it
|
|
21
|
-
* as a durable cursor for `--since` resumption (replaces the old byte-offset
|
|
22
|
-
* cursor). The public API still surfaces this as `nextOffset` (an opaque
|
|
23
|
-
* number) for backward compatibility with callers that stored byte-offset
|
|
24
|
-
* cursors.
|
|
25
|
-
* - `ts` is ISO-8601 (UTC, millisecond precision).
|
|
26
|
-
*/
|
|
27
|
-
import path from "node:path";
|
|
28
4
|
import { insertEvent, readStateEvents } from "../storage/repositories/events-repository.js";
|
|
29
5
|
import { rethrowIfTestIsolationError } from "./errors.js";
|
|
30
|
-
import {
|
|
31
|
-
import { openStateDatabase, withStateDb } from "./state-db.js";
|
|
6
|
+
import { getStateDbPath, openStateDatabase, withStateDb } from "./state-db.js";
|
|
32
7
|
import { error } from "./warn.js";
|
|
33
|
-
/**
|
|
34
|
-
* Legacy events.jsonl path — used only by the migration script
|
|
35
|
-
* (`scripts/migrate-storage.ts`) to import existing event history into
|
|
36
|
-
* state.db. No events are written here by akm v0.9+.
|
|
37
|
-
*/
|
|
38
|
-
export function getEventsPath() {
|
|
39
|
-
return path.join(getDataDir(), "events.jsonl");
|
|
40
|
-
}
|
|
41
8
|
/**
|
|
42
9
|
* Resolve the state.db path from context:
|
|
43
10
|
* 1. `ctx.dbPath` — explicit override (test seam)
|
|
44
|
-
* 2. default —
|
|
11
|
+
* 2. default — the canonical state.db path
|
|
45
12
|
*/
|
|
46
13
|
function resolveDbPath(ctx) {
|
|
47
14
|
if (ctx?.dbPath)
|
|
48
15
|
return ctx.dbPath;
|
|
49
|
-
return
|
|
16
|
+
return getStateDbPath();
|
|
50
17
|
}
|
|
51
18
|
function resolveNow(ctx) {
|
|
52
19
|
return ctx?.now ?? Date.now;
|
|
@@ -100,6 +67,17 @@ export function appendEvent(input, ctx) {
|
|
|
100
67
|
error(`akm: appendEvent failed: ${String(err)}`);
|
|
101
68
|
}
|
|
102
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* 0.9.0 breaking change (owner ruling 12): `akm sync` used to persist
|
|
72
|
+
* `eventType: "save"`; it now writes `"sync"` instead (matching the command
|
|
73
|
+
* name). Existing `state.db` rows — and any user script running
|
|
74
|
+
* `akm log --type save` — still carry the old spelling. Rather than
|
|
75
|
+
* rewriting historical rows (a migration users never asked for, on data we
|
|
76
|
+
* don't get to touch at rest), reads treat the two names as synonyms: asking
|
|
77
|
+
* for either "save" or "sync" returns rows written under both names. Only
|
|
78
|
+
* the WRITE path (sources-cli.ts's `runSyncBody`) changed.
|
|
79
|
+
*/
|
|
80
|
+
const SAVE_SYNC_EVENT_TYPE_ALIASES = new Set(["save", "sync"]);
|
|
103
81
|
/**
|
|
104
82
|
* Read all events matching the filter. Returns a `nextOffset` that callers
|
|
105
83
|
* can persist between processes for monotonic resumption.
|
|
@@ -117,14 +95,37 @@ export function readEvents(options = {}, ctx) {
|
|
|
117
95
|
return { events: [], nextOffset: 0 };
|
|
118
96
|
}
|
|
119
97
|
try {
|
|
98
|
+
// A "save"/"sync" query can't be expressed as a single SQL `event_type =
|
|
99
|
+
// ?` match (see SAVE_SYNC_EVENT_TYPE_ALIASES above), so widen the SQL
|
|
100
|
+
// filter to "no type filter" for that one case and apply the alias match
|
|
101
|
+
// client-side alongside the existing tag post-filter below.
|
|
102
|
+
const typeIsAliased = options.type !== undefined && SAVE_SYNC_EVENT_TYPE_ALIASES.has(options.type);
|
|
103
|
+
// D-38: a JS-side post-filter (the type alias above, or the tag filters
|
|
104
|
+
// below) runs AFTER the SQL read, so a SQL-level LIMIT applied before it
|
|
105
|
+
// could drop rows the post-filter would have kept out anyway, silently
|
|
106
|
+
// returning fewer than `limit` (or the wrong — oldest-in-the-SQL-window —
|
|
107
|
+
// events). Only push `limit` into SQL (readStateEvents) when nothing
|
|
108
|
+
// downstream can shrink the result further; otherwise read unbounded (the
|
|
109
|
+
// pre-existing behavior) and apply `limit` ourselves, below, AFTER the
|
|
110
|
+
// post-filter runs.
|
|
111
|
+
const needsPostFilter = typeIsAliased ||
|
|
112
|
+
(options.excludeTags?.length ?? 0) > 0 ||
|
|
113
|
+
(options.includeTags?.length ?? 0) > 0 ||
|
|
114
|
+
options.runId !== undefined;
|
|
115
|
+
const pushLimitToSql = options.limit !== undefined && !needsPostFilter;
|
|
120
116
|
const { events: rawEvents, nextId } = readStateEvents(db, {
|
|
121
117
|
sinceId: options.sinceOffset,
|
|
122
118
|
since: options.since,
|
|
123
|
-
type: options.type,
|
|
119
|
+
type: typeIsAliased ? undefined : options.type,
|
|
124
120
|
ref: options.ref,
|
|
121
|
+
...(pushLimitToSql ? { limit: options.limit } : {}),
|
|
125
122
|
});
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
const filtered = rawEvents.filter((envelope) => {
|
|
124
|
+
if (typeIsAliased && !SAVE_SYNC_EVENT_TYPE_ALIASES.has(envelope.eventType))
|
|
125
|
+
return false;
|
|
126
|
+
if (options.runId !== undefined && envelope.metadata?.runId !== options.runId)
|
|
127
|
+
return false;
|
|
128
|
+
// Apply tag filters after the indexed state.db read.
|
|
128
129
|
const tags = envelope.metadata?.tags ?? [];
|
|
129
130
|
if (options.excludeTags?.some((t) => tags.includes(t)))
|
|
130
131
|
return false;
|
|
@@ -132,98 +133,15 @@ export function readEvents(options = {}, ctx) {
|
|
|
132
133
|
return false;
|
|
133
134
|
return true;
|
|
134
135
|
});
|
|
136
|
+
// `filtered` is ascending by id; slicing off the end keeps the MOST
|
|
137
|
+
// RECENT `limit` events post-filter, matching the SQL-pushdown path's
|
|
138
|
+
// semantics exactly. `nextOffset` intentionally stays `nextId` — the
|
|
139
|
+
// durable resume cursor tracks the underlying SQL read, not this
|
|
140
|
+
// display-only truncation.
|
|
141
|
+
const events = options.limit !== undefined && !pushLimitToSql ? filtered.slice(-options.limit) : filtered;
|
|
135
142
|
return { events, nextOffset: nextId };
|
|
136
143
|
}
|
|
137
144
|
finally {
|
|
138
145
|
db.close();
|
|
139
146
|
}
|
|
140
147
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Follow the events table in state.db. Polls at `intervalMs` (default 75ms)
|
|
143
|
-
* and emits every new event to `onEvent`. Resolves when `signal` aborts, when
|
|
144
|
-
* `maxEvents` events have been observed, or when `maxDurationMs` elapses.
|
|
145
|
-
*
|
|
146
|
-
* The polling cursor is a monotonic SQLite rowid so concurrent writers cannot
|
|
147
|
-
* cause skips: between two reads we always pick up everything inserted since
|
|
148
|
-
* the last `nextOffset`.
|
|
149
|
-
*/
|
|
150
|
-
export async function tailEvents(options = {}, ctx) {
|
|
151
|
-
const intervalMs = options.intervalMs ?? 75;
|
|
152
|
-
const collected = [];
|
|
153
|
-
let cursor = options.sinceOffset ?? 0;
|
|
154
|
-
// Seed the cursor: if the caller passed --since (timestamp) but no
|
|
155
|
-
// sinceOffset, do an initial filtered read so they see history before
|
|
156
|
-
// we start polling. This matches the documented behaviour of `tail
|
|
157
|
-
// --since`: emit existing events that match, then follow.
|
|
158
|
-
if (options.sinceOffset === undefined) {
|
|
159
|
-
const initial = readEvents({
|
|
160
|
-
since: options.since,
|
|
161
|
-
type: options.type,
|
|
162
|
-
ref: options.ref,
|
|
163
|
-
excludeTags: options.excludeTags,
|
|
164
|
-
includeTags: options.includeTags,
|
|
165
|
-
}, ctx);
|
|
166
|
-
for (const event of initial.events) {
|
|
167
|
-
collected.push(event);
|
|
168
|
-
options.onEvent?.(event);
|
|
169
|
-
if (options.maxEvents !== undefined && collected.length >= options.maxEvents) {
|
|
170
|
-
return { events: collected, nextOffset: initial.nextOffset, reason: "maxEvents" };
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
cursor = initial.nextOffset;
|
|
174
|
-
}
|
|
175
|
-
const startedAt = Date.now();
|
|
176
|
-
return new Promise((resolve) => {
|
|
177
|
-
let resolved = false;
|
|
178
|
-
let timer;
|
|
179
|
-
function finish(reason) {
|
|
180
|
-
if (resolved)
|
|
181
|
-
return;
|
|
182
|
-
resolved = true;
|
|
183
|
-
if (timer)
|
|
184
|
-
clearInterval(timer);
|
|
185
|
-
resolve({ events: collected, nextOffset: cursor, reason });
|
|
186
|
-
}
|
|
187
|
-
function tick() {
|
|
188
|
-
try {
|
|
189
|
-
const result = readEvents({
|
|
190
|
-
sinceOffset: cursor,
|
|
191
|
-
type: options.type,
|
|
192
|
-
ref: options.ref,
|
|
193
|
-
excludeTags: options.excludeTags,
|
|
194
|
-
includeTags: options.includeTags,
|
|
195
|
-
}, ctx);
|
|
196
|
-
cursor = result.nextOffset;
|
|
197
|
-
for (const event of result.events) {
|
|
198
|
-
// Apply --since filter inside the polling loop too — the cursor is
|
|
199
|
-
// rowid-based so it can hand us events the user filtered out.
|
|
200
|
-
if (options.since && event.ts && event.ts < options.since)
|
|
201
|
-
continue;
|
|
202
|
-
collected.push(event);
|
|
203
|
-
options.onEvent?.(event);
|
|
204
|
-
if (options.maxEvents !== undefined && collected.length >= options.maxEvents) {
|
|
205
|
-
finish("maxEvents");
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
catch {
|
|
211
|
-
// Non-fatal: stay in the loop.
|
|
212
|
-
}
|
|
213
|
-
if (options.maxDurationMs !== undefined && Date.now() - startedAt >= options.maxDurationMs) {
|
|
214
|
-
finish("maxDuration");
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
if (options.signal) {
|
|
218
|
-
if (options.signal.aborted) {
|
|
219
|
-
finish("signal");
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
options.signal.addEventListener("abort", () => finish("signal"), { once: true });
|
|
223
|
-
}
|
|
224
|
-
timer = setInterval(tick, intervalMs);
|
|
225
|
-
// Run one tick immediately so callers don't have to wait an interval
|
|
226
|
-
// for events written in the same tick as the tail starts.
|
|
227
|
-
tick();
|
|
228
|
-
});
|
|
229
|
-
}
|
package/dist/core/file-change.js
CHANGED
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
*
|
|
7
7
|
* By construction `changes[0].after === payload.content`; consumers read
|
|
8
8
|
* through this accessor so the single-content assumption lives in ONE place
|
|
9
|
-
* once multi-file proposals (consolidate ops) ride the envelope.
|
|
10
|
-
*
|
|
11
|
-
* Typed structurally (not against `Proposal`) so this module stays
|
|
12
|
-
* dependency-free.
|
|
9
|
+
* once multi-file proposals (consolidate ops) ride the envelope. Typed
|
|
10
|
+
* structurally (not against `Proposal`) so this module stays dependency-free.
|
|
13
11
|
*/
|
|
14
12
|
export function proposalContent(p) {
|
|
15
|
-
|
|
13
|
+
const content = p.changes[0]?.after;
|
|
14
|
+
if (content === undefined)
|
|
15
|
+
throw new Error("Proposal primary change has no content.");
|
|
16
|
+
return content;
|
|
16
17
|
}
|