akm-cli 0.9.0-rc.9 → 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 +95 -55
- 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 +25 -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 +88 -7
- 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 -1878
- 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 -1231
- 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 -257
- package/dist/migrate/legacy/content-migration.js +0 -350
- 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 -80
- package/dist/migrate/legacy/proposal-fs-import.js +0 -168
- package/dist/migrate/legacy/task-target-ref-migration.js +0 -278
- package/dist/migrate/legacy/three-db-cutover.js +0 -845
- 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
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
* heuristic derivation, LLM enrichment) is testable in isolation and the
|
|
9
9
|
* CLI entry point stays focused on argument parsing + output routing.
|
|
10
10
|
*/
|
|
11
|
-
import { getParsedInvocation } from "../cli/invocation.js";
|
|
12
11
|
import { serializeFrontmatter } from "../core/asset/asset-serialize.js";
|
|
13
12
|
import { toErrorMessage, tryReadStdinText } from "../core/common.js";
|
|
14
13
|
import { loadConfig } from "../core/config/config.js";
|
|
15
14
|
import { UsageError } from "../core/errors.js";
|
|
15
|
+
import { parseEmbeddedJsonResponse } from "../core/parse.js";
|
|
16
16
|
import { DURATION_UNITS, parseDuration as parseDurationSpec } from "../core/time.js";
|
|
17
17
|
import { warn } from "../core/warn.js";
|
|
18
18
|
import { SCOPE_KEYS } from "../indexer/passes/metadata.js";
|
|
@@ -150,7 +150,7 @@ export async function runLlmEnrich(body) {
|
|
|
150
150
|
warn("Warning: --enrich requires an LLM to be configured. Run `akm setup` to configure one.");
|
|
151
151
|
return { tags: [] };
|
|
152
152
|
}
|
|
153
|
-
const { chatCompletion
|
|
153
|
+
const { chatCompletion } = await import("../llm/client.js");
|
|
154
154
|
// #576: attribute this entry point's LLM call to the `remember` stage. The
|
|
155
155
|
// wrapper is ambient — if a usage sink is active it tags the record; if not,
|
|
156
156
|
// it is a no-op.
|
|
@@ -185,7 +185,7 @@ Return ONLY the JSON object, no prose, no markdown fences.`;
|
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
})();
|
|
188
|
-
const parsed =
|
|
188
|
+
const parsed = parseEmbeddedJsonResponse(result);
|
|
189
189
|
if (!parsed) {
|
|
190
190
|
warn("Warning: --enrich received invalid JSON from the LLM. Writing memory without enrichment.");
|
|
191
191
|
return { tags: [] };
|
|
@@ -204,57 +204,14 @@ Return ONLY the JSON object, no prose, no markdown fences.`;
|
|
|
204
204
|
return { tags: [] };
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
return undefined;
|
|
219
|
-
const invocation = getParsedInvocation();
|
|
220
|
-
const parsedFormat = invocation.getFlagValue("--format");
|
|
221
|
-
if (parsedFormat !== undefined &&
|
|
222
|
-
content === parsedFormat &&
|
|
223
|
-
wasRememberFlagValueConsumedAsContent(content, parsedFormat, "--format")) {
|
|
224
|
-
return undefined;
|
|
225
|
-
}
|
|
226
|
-
const parsedDetail = invocation.getFlagValue("--detail");
|
|
227
|
-
if (parsedDetail !== undefined &&
|
|
228
|
-
content === parsedDetail &&
|
|
229
|
-
wasRememberFlagValueConsumedAsContent(content, parsedDetail, "--detail")) {
|
|
230
|
-
return undefined;
|
|
231
|
-
}
|
|
232
|
-
return content;
|
|
233
|
-
}
|
|
234
|
-
function wasRememberFlagValueConsumedAsContent(content, flagValue, flagName) {
|
|
235
|
-
const argv = getParsedInvocation().userArgs;
|
|
236
|
-
const rememberIndex = argv.indexOf("remember");
|
|
237
|
-
const tokens = rememberIndex >= 0 ? argv.slice(rememberIndex + 1) : argv;
|
|
238
|
-
let flagIndex = -1;
|
|
239
|
-
let flagConsumesNextToken = false;
|
|
240
|
-
for (let i = 0; i < tokens.length; i += 1) {
|
|
241
|
-
const token = tokens[i];
|
|
242
|
-
if (token === flagName) {
|
|
243
|
-
flagIndex = i;
|
|
244
|
-
flagConsumesNextToken = true;
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
if (token === `${flagName}=${flagValue}`) {
|
|
248
|
-
flagIndex = i;
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
if (flagIndex === -1)
|
|
253
|
-
return false;
|
|
254
|
-
if (tokens.slice(0, flagIndex).includes(content))
|
|
255
|
-
return false;
|
|
256
|
-
const firstTokenAfterFlag = flagIndex + (flagConsumesNextToken ? 2 : 1);
|
|
257
|
-
if (tokens.slice(firstTokenAfterFlag).includes(content))
|
|
258
|
-
return false;
|
|
259
|
-
return true;
|
|
260
|
-
}
|
|
207
|
+
// R-061(c): `resolveRememberContentArg` / `wasRememberFlagValueConsumedAsContent`
|
|
208
|
+
// used to live here — a heuristic guarding against citty consuming a global
|
|
209
|
+
// flag's value (`--format`/`--detail`) as the `content` positional. That guard
|
|
210
|
+
// predated `rememberCommand` declaring `GLOBAL_OUTPUT_ARGS` (via
|
|
211
|
+
// `defineJsonCommand`): once the leaf command itself declares `format`/
|
|
212
|
+
// `detail` args, citty's parser consumes their space-separated values as the
|
|
213
|
+
// flag's own value and never assigns them to `content` in the first place, so
|
|
214
|
+
// the heuristic no longer has anything to guard against. Verified: `akm
|
|
215
|
+
// remember "yaml" --format yaml` and `akm remember "brief" --detail brief`
|
|
216
|
+
// both write the literal content unchanged. Deleted rather than kept as
|
|
217
|
+
// defense-in-depth per the cleanup program's dead-code policy.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import * as p from "../../cli/clack.js";
|
|
7
|
+
import { getStringArg, parsePositiveIntFlag } from "../../cli/parse-args.js";
|
|
7
8
|
import { defineJsonCommand, output } from "../../cli/shared.js";
|
|
8
9
|
import { decideDangerousKeyInstall } from "../../core/activation-policy.js";
|
|
9
10
|
import { UsageError } from "../../core/errors.js";
|
|
@@ -14,12 +15,11 @@ import { akmAdd } from "./source-add.js";
|
|
|
14
15
|
import { addStash } from "./source-manage.js";
|
|
15
16
|
// ── Shared website-options helper ──────────
|
|
16
17
|
export function buildWebsiteOptions(args) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return websiteOptions;
|
|
18
|
+
// getStringArg maps absent/blank to undefined; parsePositiveIntFlag maps
|
|
19
|
+
// undefined to undefined — so an unsupplied flag simply omits the key.
|
|
20
|
+
const maxPages = parsePositiveIntFlag(getStringArg(args, "max-pages"), "--max-pages");
|
|
21
|
+
const maxDepth = parsePositiveIntFlag(getStringArg(args, "max-depth"), "--max-depth");
|
|
22
|
+
return { ...(maxPages !== undefined ? { maxPages } : {}), ...(maxDepth !== undefined ? { maxDepth } : {}) };
|
|
23
23
|
}
|
|
24
24
|
// ── HTTP safety check ─────────────────────────────────────────────────────────
|
|
25
25
|
export function shouldWarnOnPlainHttp(ref) {
|
|
@@ -38,24 +38,84 @@ export function shouldWarnOnPlainHttp(ref) {
|
|
|
38
38
|
return true;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Recursively enumerate every real env FILE under `rootDir` (a stash's
|
|
43
|
+
* `env/` directory). "Real env file" is the SAME test used everywhere else
|
|
44
|
+
* in akm decides what `akm env run` / `akm env list` / the indexer will
|
|
45
|
+
* actually load as environment variables — `fileName === ".env" ||
|
|
46
|
+
* fileName.endsWith(".env")` — see `src/indexer/walk/matchers.ts` and
|
|
47
|
+
* `listEnvsRecursive` in `src/commands/env/env-cli.ts`. Reusing that exact
|
|
48
|
+
* rule here (rather than inventing a second, possibly-divergent one) is what
|
|
49
|
+
* closes the nested-directory bypass: `env/nested/inner.env` IS loaded by
|
|
50
|
+
* `akm env run` today via that same recursive walk, so it must be scanned
|
|
51
|
+
* too (previously only a flat, non-recursive `env/*.env` listing was
|
|
52
|
+
* scanned).
|
|
53
|
+
*
|
|
54
|
+
* Deliberately excludes files that do NOT end in `.env` (e.g.
|
|
55
|
+
* `env/notes.txt`). Such a file is never sourced as environment variables by
|
|
56
|
+
* any akm codepath, so a dangerous key sitting in its contents cannot hijack
|
|
57
|
+
* process execution via `akm env run` — there is no live attack through this
|
|
58
|
+
* gate for it. Residual gap: this scanner does not protect against an
|
|
59
|
+
* operator later renaming/copying that file to a `*.env` name, or feeding it
|
|
60
|
+
* into `akm env run` through some other mechanism outside akm; closing that
|
|
61
|
+
* would mean content-sniffing every byte of every file in the stash (README,
|
|
62
|
+
* lockfiles, binaries, …) for a vector that requires a subsequent human
|
|
63
|
+
* action to become live, which is a materially different and much more
|
|
64
|
+
* expensive check than "is this a file `akm` will actually source".
|
|
65
|
+
*/
|
|
66
|
+
function collectEnvFilePathsRecursive(rootDir) {
|
|
67
|
+
const results = [];
|
|
68
|
+
const walk = (dir) => {
|
|
69
|
+
let entries;
|
|
70
|
+
try {
|
|
71
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
const full = path.join(dir, entry.name);
|
|
78
|
+
if (entry.isDirectory()) {
|
|
79
|
+
walk(full);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (!entry.isFile())
|
|
83
|
+
continue;
|
|
84
|
+
if (entry.name !== ".env" && !entry.name.endsWith(".env"))
|
|
85
|
+
continue;
|
|
86
|
+
results.push(full);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
walk(rootDir);
|
|
90
|
+
return results;
|
|
91
|
+
}
|
|
92
|
+
/** Scan every real env file (recursively, see {@link collectEnvFilePathsRecursive}) in the freshly-installed stash for dangerous env keys. */
|
|
42
93
|
function collectDangerousKeyFindings(installedStashRoot, checkEnvForDangerousKeys) {
|
|
43
94
|
const allFindings = [];
|
|
44
95
|
const subdir = "env";
|
|
45
96
|
const prefix = "env";
|
|
46
97
|
const dir = path.join(installedStashRoot, subdir);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
98
|
+
if (!fs.existsSync(dir))
|
|
99
|
+
return allFindings;
|
|
100
|
+
for (const envPath of collectEnvFilePathsRecursive(dir)) {
|
|
101
|
+
const relToEnvDir = path.relative(dir, envPath);
|
|
102
|
+
// Only the LAST path segment carries the ".env" suffix / dotfile-default
|
|
103
|
+
// naming rule; intermediate directory segments pass through unchanged.
|
|
104
|
+
// e.g. "nested/inner.env" -> "nested/inner", "nested/.env" ->
|
|
105
|
+
// "nested/default" (not "nested/", which is what naively stripping the
|
|
106
|
+
// suffix from the whole relative path would produce).
|
|
107
|
+
const segments = relToEnvDir.split(path.sep);
|
|
108
|
+
const lastSegment = segments[segments.length - 1] ?? "";
|
|
109
|
+
const lastSegmentBase = lastSegment.endsWith(".env") ? lastSegment.slice(0, -".env".length) : lastSegment;
|
|
110
|
+
const refSegments = [...segments.slice(0, -1), lastSegmentBase === "" ? "default" : lastSegmentBase];
|
|
111
|
+
const envRef = `${prefix}/${refSegments.join("/")}`;
|
|
112
|
+
const relPath = path.join(subdir, relToEnvDir);
|
|
113
|
+
const findings = checkEnvForDangerousKeys(envPath, relPath, envRef);
|
|
54
114
|
for (const finding of findings) {
|
|
55
115
|
// Extract the key name from the detail string for the summary line.
|
|
56
116
|
const keyMatch = finding.detail.match(/Env key `([^`]+)`/);
|
|
57
117
|
const keyName = keyMatch ? keyMatch[1] : finding.file;
|
|
58
|
-
allFindings.push({
|
|
118
|
+
allFindings.push({ envRef, keyName, relPath });
|
|
59
119
|
}
|
|
60
120
|
}
|
|
61
121
|
return allFindings;
|
|
@@ -91,7 +151,7 @@ export async function auditInstalledStashForDangerousKeys(opts) {
|
|
|
91
151
|
if (stance === "warn-allow") {
|
|
92
152
|
// Operator has explicitly accepted the risk — warn and continue.
|
|
93
153
|
for (const f of allFindings) {
|
|
94
|
-
warn(`[dangerous-
|
|
154
|
+
warn(`[dangerous-env-key] ${f.relPath}: key \`${f.keyName}\` in ${f.envRef} can hijack process execution via \`akm env run\`. Proceeding because --allow-insecure was set.`);
|
|
95
155
|
}
|
|
96
156
|
return { blocked: false };
|
|
97
157
|
}
|
|
@@ -105,7 +165,7 @@ export async function auditInstalledStashForDangerousKeys(opts) {
|
|
|
105
165
|
}
|
|
106
166
|
catch (_rollbackErr) {
|
|
107
167
|
return (`Rollback failed — stash may still be installed at ${installedStashRoot}. ` +
|
|
108
|
-
`Remove it manually with: akm remove ${rollbackTarget}`);
|
|
168
|
+
`Remove it manually with: akm bundle remove ${rollbackTarget}`);
|
|
109
169
|
}
|
|
110
170
|
}
|
|
111
171
|
if (isTTY) {
|
|
@@ -113,14 +173,14 @@ export async function auditInstalledStashForDangerousKeys(opts) {
|
|
|
113
173
|
// Guard on stdin (not stdout) because p.confirm() reads from stdin;
|
|
114
174
|
// stdout may be a TTY while stdin is piped, which would cause a hang.
|
|
115
175
|
const stashLabel = ref;
|
|
116
|
-
const
|
|
176
|
+
const groupedByEnv = new Map();
|
|
117
177
|
for (const f of allFindings) {
|
|
118
|
-
const existing =
|
|
178
|
+
const existing = groupedByEnv.get(f.envRef) ?? [];
|
|
119
179
|
existing.push(f.keyName);
|
|
120
|
-
|
|
180
|
+
groupedByEnv.set(f.envRef, existing);
|
|
121
181
|
}
|
|
122
|
-
for (const [
|
|
123
|
-
warn(`[warn] Env "${
|
|
182
|
+
for (const [envRef, keys] of groupedByEnv) {
|
|
183
|
+
warn(`[warn] Env "${envRef}" in stash "${stashLabel}" contains potentially dangerous keys:`);
|
|
124
184
|
for (const key of keys) {
|
|
125
185
|
warn(` - ${key}: can hijack process execution via \`akm env run\``);
|
|
126
186
|
}
|
|
@@ -134,7 +194,7 @@ export async function auditInstalledStashForDangerousKeys(opts) {
|
|
|
134
194
|
console.error(JSON.stringify({
|
|
135
195
|
ok: false,
|
|
136
196
|
error: "Install aborted: stash contains dangerous env keys. Remove the keys or re-run with --allow-insecure to bypass.",
|
|
137
|
-
code: "
|
|
197
|
+
code: "DANGEROUS_ENV_KEY",
|
|
138
198
|
...(rollbackWarning ? { rollbackWarning } : {}),
|
|
139
199
|
}, null, 2));
|
|
140
200
|
return { blocked: true, exitCode: 1 };
|
|
@@ -144,11 +204,11 @@ export async function auditInstalledStashForDangerousKeys(opts) {
|
|
|
144
204
|
}
|
|
145
205
|
// Non-interactive path without bypass flag: fail hard.
|
|
146
206
|
const rollbackWarning = await rollback();
|
|
147
|
-
const keyList = allFindings.map((f) => ` - ${f.keyName} (${f.
|
|
207
|
+
const keyList = allFindings.map((f) => ` - ${f.keyName} (${f.envRef})`).join("\n");
|
|
148
208
|
console.error(JSON.stringify({
|
|
149
209
|
ok: false,
|
|
150
210
|
error: `Install blocked: stash "${ref}" contains dangerous env keys that can hijack process execution via \`akm env run\`:\n${keyList}\nRe-run with --allow-insecure to bypass this check after reviewing the env file.`,
|
|
151
|
-
code: "
|
|
211
|
+
code: "DANGEROUS_ENV_KEY",
|
|
152
212
|
...(rollbackWarning ? { rollbackWarning } : {}),
|
|
153
213
|
}, null, 2));
|
|
154
214
|
return { blocked: true, exitCode: 1 };
|
|
@@ -170,14 +230,14 @@ export const addCommand = defineJsonCommand({
|
|
|
170
230
|
name: { type: "string", description: "Human-friendly name for the source" },
|
|
171
231
|
writable: {
|
|
172
232
|
type: "boolean",
|
|
173
|
-
description: "Mark a git
|
|
233
|
+
description: "Mark a git bundle as writable so changes can be pushed back",
|
|
174
234
|
default: false,
|
|
175
235
|
},
|
|
176
236
|
"max-pages": { type: "string", description: "Maximum pages to crawl for website sources (default: 50)" },
|
|
177
237
|
"max-depth": { type: "string", description: "Maximum crawl depth for website sources (default: 3)" },
|
|
178
238
|
"allow-insecure": {
|
|
179
239
|
type: "boolean",
|
|
180
|
-
description: "Allow a plain HTTP source URL and skip confirmation for dangerous env keys (e.g. LD_PRELOAD, PATH). Use only after explicitly reviewing the
|
|
240
|
+
description: "Allow a plain HTTP source URL and skip confirmation for dangerous env keys (e.g. LD_PRELOAD, PATH). Use only after explicitly reviewing the bundle.",
|
|
181
241
|
default: false,
|
|
182
242
|
},
|
|
183
243
|
},
|
|
@@ -185,7 +245,9 @@ export const addCommand = defineJsonCommand({
|
|
|
185
245
|
const ref = args.ref.trim();
|
|
186
246
|
const allowInsecure = args["allow-insecure"];
|
|
187
247
|
const allowDangerousKeys = allowInsecure;
|
|
188
|
-
//
|
|
248
|
+
// --provider → declarative bundle source (URL for git/website; bare
|
|
249
|
+
// package spec for npm — R-013). Config-only write; content is not
|
|
250
|
+
// synced until a later `akm update`.
|
|
189
251
|
if (args.provider) {
|
|
190
252
|
if (shouldWarnOnPlainHttp(ref)) {
|
|
191
253
|
if (!allowInsecure) {
|
|
@@ -257,8 +319,14 @@ export const addCommand = defineJsonCommand({
|
|
|
257
319
|
// Use the canonical installed id (most reliably resolved by akmRemove) rather
|
|
258
320
|
// than the raw user-supplied ref which may not match after URL normalisation.
|
|
259
321
|
const rollbackTarget = result.installed?.id ?? result.sourceAdded?.stashRoot ?? ref;
|
|
260
|
-
// The audit RETURNS its decision; we decide
|
|
261
|
-
// any catch, so the abort cannot be lost to a swallowed
|
|
322
|
+
// The audit RETURNS its decision; we decide the exit outcome here,
|
|
323
|
+
// OUTSIDE any catch, so the abort cannot be lost to a swallowed
|
|
324
|
+
// exception (C3). F4: `process.exitCode = …; return;` instead of
|
|
325
|
+
// `process.exit(...)` — the DANGEROUS_ENV_KEY error envelope has
|
|
326
|
+
// already been written to stderr by the audit itself (or is about to
|
|
327
|
+
// be), so an explicit `return` here (skipping the success `output("add",
|
|
328
|
+
// …)` below) is load-bearing, not merely cosmetic: it is what stops a
|
|
329
|
+
// blocked install from ALSO printing a success envelope.
|
|
262
330
|
const decision = await auditInstalledStashForDangerousKeys({
|
|
263
331
|
installedStashRoot,
|
|
264
332
|
ref,
|
|
@@ -267,7 +335,8 @@ export const addCommand = defineJsonCommand({
|
|
|
267
335
|
isTTY: process.stdin.isTTY === true,
|
|
268
336
|
});
|
|
269
337
|
if (decision.blocked) {
|
|
270
|
-
process.
|
|
338
|
+
process.exitCode = decision.exitCode;
|
|
339
|
+
return;
|
|
271
340
|
}
|
|
272
341
|
}
|
|
273
342
|
output("add", result);
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* `akm bundle` command group — 0.9 CLI overhaul (S7).
|
|
6
|
+
*
|
|
7
|
+
* Consolidates the five former top-level bundle-lifecycle commands under one
|
|
8
|
+
* group, hard break, no alias kept at the top level:
|
|
9
|
+
* - `create` (= old top-level `init`, src/commands/sources/init.ts)
|
|
10
|
+
* - `add` (= old top-level `add`, src/commands/sources/add-cli.ts — the
|
|
11
|
+
* command definition moved here; `add-cli.ts` keeps its exported helpers,
|
|
12
|
+
* including `auditInstalledStashForDangerousKeys`, which a test imports
|
|
13
|
+
* directly)
|
|
14
|
+
* - `list` (= old top-level `list`)
|
|
15
|
+
* - `remove` (= old top-level `remove`)
|
|
16
|
+
* - `update` (= old top-level `update`)
|
|
17
|
+
* - `show <name>` — NEW: a single-bundle detail view of the `list` payload.
|
|
18
|
+
*
|
|
19
|
+
* `add`/`list`/`remove`/`update` are pure relocations (payload and output
|
|
20
|
+
* shape unchanged: `SourceEntry`/`RemoveResponse`/`UpdateResponse` keep their
|
|
21
|
+
* bare `add`/`list`/`remove`/`update` output shape). `create` is a genuine
|
|
22
|
+
* verb rename (was `init`), so its output shape is renamed to `bundle-create`
|
|
23
|
+
* to match (the same convention S8 used for `propose` -> `proposal new`'s
|
|
24
|
+
* `proposal-new` shape). `show` is a new shape, `bundle-show`.
|
|
25
|
+
*/
|
|
26
|
+
import { defineGroupCommand, defineJsonCommand, output } from "../../cli/shared.js";
|
|
27
|
+
import { NotFoundError, UsageError } from "../../core/errors.js";
|
|
28
|
+
import { appendEvent } from "../../core/events.js";
|
|
29
|
+
import { addCommand } from "./add-cli.js";
|
|
30
|
+
import { akmInit } from "./init.js";
|
|
31
|
+
import { akmListSources, akmRemove, akmUpdate } from "./installed-stashes.js";
|
|
32
|
+
const VALID_SOURCE_KINDS = new Set(["filesystem", "git", "npm", "website"]);
|
|
33
|
+
function parseKindFilter(raw) {
|
|
34
|
+
if (!raw)
|
|
35
|
+
return undefined;
|
|
36
|
+
const kinds = raw.split(",").map((s) => s.trim());
|
|
37
|
+
for (const k of kinds) {
|
|
38
|
+
if (!VALID_SOURCE_KINDS.has(k)) {
|
|
39
|
+
throw new UsageError(`Invalid --kind value: "${k}". Expected one of: filesystem, git, npm, website`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return kinds;
|
|
43
|
+
}
|
|
44
|
+
const createCommand = defineJsonCommand({
|
|
45
|
+
meta: {
|
|
46
|
+
name: "create",
|
|
47
|
+
description: "Initialize akm's working bundle directory and persist it in config",
|
|
48
|
+
},
|
|
49
|
+
args: {
|
|
50
|
+
dir: { type: "string", description: "Custom bundle directory path (default: ~/akm)" },
|
|
51
|
+
"set-default": {
|
|
52
|
+
type: "boolean",
|
|
53
|
+
description: "Make --dir the default bundle. Without this, `akm bundle create --dir X` scaffolds X but leaves your existing default bundle unchanged.",
|
|
54
|
+
default: false,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
async run({ args }) {
|
|
58
|
+
const result = await akmInit({
|
|
59
|
+
dir: args.dir,
|
|
60
|
+
setDefault: args["set-default"],
|
|
61
|
+
});
|
|
62
|
+
output("bundle-create", result);
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
const listCommand = defineJsonCommand({
|
|
66
|
+
meta: { name: "list", description: "List configured bundles and their resolved source state" },
|
|
67
|
+
args: {
|
|
68
|
+
kind: {
|
|
69
|
+
type: "string",
|
|
70
|
+
description: "Filter by source provider (filesystem, git, npm, website). Comma-separated.",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
async run({ args }) {
|
|
74
|
+
const kind = parseKindFilter(args.kind);
|
|
75
|
+
const result = await akmListSources({ kind });
|
|
76
|
+
output("list", result);
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
const showCommand = defineJsonCommand({
|
|
80
|
+
meta: { name: "show", description: "Show detail for a single configured bundle" },
|
|
81
|
+
args: {
|
|
82
|
+
name: { type: "positional", description: "Bundle name (as reported by `akm bundle list`)", required: true },
|
|
83
|
+
},
|
|
84
|
+
async run({ args }) {
|
|
85
|
+
const { sources } = await akmListSources();
|
|
86
|
+
const entry = sources.find((s) => s.name === args.name);
|
|
87
|
+
if (!entry) {
|
|
88
|
+
throw new NotFoundError(`No configured bundle named "${args.name}"`, "SOURCE_NOT_FOUND");
|
|
89
|
+
}
|
|
90
|
+
output("bundle-show", entry);
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
const removeCommand = defineJsonCommand({
|
|
94
|
+
meta: { name: "remove", description: "Remove a bundle by id, ref, path, URL, or name" },
|
|
95
|
+
args: {
|
|
96
|
+
target: { type: "positional", description: "Bundle to remove (id, ref, path, URL, or name)", required: true },
|
|
97
|
+
yes: { type: "boolean", alias: "y", description: "Skip confirmation prompt", default: false },
|
|
98
|
+
},
|
|
99
|
+
async run({ args }) {
|
|
100
|
+
const { confirmDestructive } = await import("../../cli/confirm.js");
|
|
101
|
+
const confirmed = await confirmDestructive(`Remove bundle "${args.target}"? This cannot be undone.`, {
|
|
102
|
+
yes: args.yes === true,
|
|
103
|
+
});
|
|
104
|
+
if (!confirmed) {
|
|
105
|
+
process.stderr.write("Aborted.\n");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const result = await akmRemove({ target: args.target });
|
|
109
|
+
appendEvent({
|
|
110
|
+
eventType: "remove",
|
|
111
|
+
metadata: {
|
|
112
|
+
target: args.target,
|
|
113
|
+
ref: typeof result.removed?.ref === "string" ? result.removed.ref : null,
|
|
114
|
+
id: typeof result.removed?.id === "string" ? result.removed.id : null,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
output("remove", result);
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
const updateCommand = defineJsonCommand({
|
|
121
|
+
meta: { name: "update", description: "Update one or all managed bundles" },
|
|
122
|
+
args: {
|
|
123
|
+
target: { type: "positional", description: "Bundle to update (id or ref)", required: false },
|
|
124
|
+
all: { type: "boolean", description: "Update all installed entries", default: false },
|
|
125
|
+
force: { type: "boolean", description: "Force fresh download even if version is unchanged", default: false },
|
|
126
|
+
// F1/R-058: gates ONLY the rare branch where the resolved content
|
|
127
|
+
// directory moves and the previous `localRoot` is deleted — a normal
|
|
128
|
+
// refresh (the overwhelming majority of updates) deletes nothing and
|
|
129
|
+
// never consults this flag. Mirrors `remove`'s `-y/--yes`.
|
|
130
|
+
yes: {
|
|
131
|
+
type: "boolean",
|
|
132
|
+
alias: "y",
|
|
133
|
+
description: "Skip the confirmation prompt when an update needs to delete a previous install directory (because the resolved content location moved). No effect on a normal refresh, which deletes nothing.",
|
|
134
|
+
default: false,
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
async run({ args }) {
|
|
138
|
+
const result = await akmUpdate({ target: args.target, all: args.all, force: args.force, yes: args.yes });
|
|
139
|
+
appendEvent({
|
|
140
|
+
eventType: "update",
|
|
141
|
+
metadata: {
|
|
142
|
+
target: args.target ?? null,
|
|
143
|
+
all: args.all === true,
|
|
144
|
+
force: args.force === true,
|
|
145
|
+
processed: Array.isArray(result.processed)
|
|
146
|
+
? result.processed.length
|
|
147
|
+
: 0,
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
output("update", result);
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
export const bundleCommand = defineGroupCommand({
|
|
154
|
+
meta: {
|
|
155
|
+
name: "bundle",
|
|
156
|
+
description: "Create, add to, inspect, and manage your bundles (working bundle + configured sources)",
|
|
157
|
+
},
|
|
158
|
+
subCommands: {
|
|
159
|
+
create: createCommand,
|
|
160
|
+
add: addCommand,
|
|
161
|
+
list: listCommand,
|
|
162
|
+
show: showCommand,
|
|
163
|
+
remove: removeCommand,
|
|
164
|
+
update: updateCommand,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* The `stashDir`/`sources[]`/`installed[]` trio is retired: every source is now
|
|
8
8
|
* a `bundles.<slug>` entry, and the primary working stash is the `defaultBundle`.
|
|
9
|
-
* These helpers give the source writers (`akm
|
|
9
|
+
* These helpers give the source writers (`akm bundle create`, `akm setup`, `akm bundle add`,
|
|
10
10
|
* `akm sources add/remove`) one place to derive slug-legal bundle keys (via the
|
|
11
11
|
* shared {@link deriveBundleId} — D-R5), locate an existing bundle by its source
|
|
12
12
|
* descriptor, and set/repoint the primary bundle — without duplicating the
|
|
@@ -28,7 +28,12 @@ export function withPrimaryBundle(config, stashDir) {
|
|
|
28
28
|
if (!key || !(key in bundles) || typeof bundles[key]?.path !== "string") {
|
|
29
29
|
key = deriveBundleId(undefined, stashDir, new Set(Object.keys(bundles)));
|
|
30
30
|
}
|
|
31
|
-
bundles[key] = {
|
|
31
|
+
bundles[key] = {
|
|
32
|
+
...bundles[key],
|
|
33
|
+
path: stashDir,
|
|
34
|
+
writable: true,
|
|
35
|
+
components: { main: { root: ".", adapter: "akm", writable: true } },
|
|
36
|
+
};
|
|
32
37
|
return { ...config, bundles, defaultBundle: key };
|
|
33
38
|
}
|
|
34
39
|
/** Existing bundle key whose filesystem descriptor resolves to `resolvedPath`, or `undefined`. */
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import { placementTypes } from "../../core/asset/asset-placement.js";
|
|
6
|
+
import { resolveStashDir } from "../../core/common.js";
|
|
6
7
|
import { getSources, loadConfig } from "../../core/config/config.js";
|
|
7
8
|
import { getDbPath } from "../../core/paths.js";
|
|
9
|
+
import { error } from "../../core/warn.js";
|
|
8
10
|
import { getEffectiveSemanticStatus, readSemanticStatus } from "../../indexer/search/semantic-status.js";
|
|
9
11
|
import { closeDatabase, openExistingDatabase } from "../../storage/repositories/index-connection.js";
|
|
10
|
-
import { getEntryCount } from "../../storage/repositories/index-entries-repository.js";
|
|
12
|
+
import { getEntryCount, getEntryCountByType } from "../../storage/repositories/index-entries-repository.js";
|
|
11
13
|
import { getMeta } from "../../storage/repositories/index-meta-repository.js";
|
|
12
14
|
import { isVecAvailable } from "../../storage/repositories/index-vec-repository.js";
|
|
13
15
|
import { pkgVersion } from "../../version.js";
|
|
@@ -19,6 +21,11 @@ import { pkgVersion } from "../../version.js";
|
|
|
19
21
|
*/
|
|
20
22
|
export function assembleInfo(options) {
|
|
21
23
|
const config = loadConfig();
|
|
24
|
+
// Primary stash directory + default bundle name — same resolution
|
|
25
|
+
// `akm sources list` uses (R-057), so `akm info` and `akm sources list`
|
|
26
|
+
// agree on which stash is primary.
|
|
27
|
+
const stashDir = resolveStashDir();
|
|
28
|
+
const defaultBundle = config.defaultBundle ?? null;
|
|
22
29
|
// Asset types (copy into a mutable array — `placementTypes()` returns readonly)
|
|
23
30
|
const assetTypes = [...placementTypes()];
|
|
24
31
|
const semanticRuntime = readSemanticStatus();
|
|
@@ -45,14 +52,16 @@ export function assembleInfo(options) {
|
|
|
45
52
|
...(s.url ? { url: s.url } : {}),
|
|
46
53
|
...(s.enabled !== undefined ? { enabled: s.enabled } : {}),
|
|
47
54
|
}));
|
|
48
|
-
// Index stats —
|
|
49
|
-
//
|
|
50
|
-
//
|
|
55
|
+
// Index stats — `options.dbPath` is a test-only override (see the param
|
|
56
|
+
// doc above); real callers fall through to the same `getDbPath()` that
|
|
57
|
+
// health and search use, so info reads the same database they do.
|
|
51
58
|
const resolvedDbPath = options?.dbPath ?? getDbPath();
|
|
52
59
|
const indexStats = readIndexStats(resolvedDbPath);
|
|
53
60
|
return {
|
|
54
61
|
schemaVersion: 1,
|
|
55
62
|
version: pkgVersion,
|
|
63
|
+
bundleDir: stashDir,
|
|
64
|
+
defaultBundle,
|
|
56
65
|
assetTypes,
|
|
57
66
|
searchModes,
|
|
58
67
|
semanticSearch: {
|
|
@@ -69,6 +78,7 @@ export function assembleInfo(options) {
|
|
|
69
78
|
function readIndexStats(resolvedPath) {
|
|
70
79
|
const EMPTY = {
|
|
71
80
|
entryCount: 0,
|
|
81
|
+
byType: {},
|
|
72
82
|
lastBuiltAt: null,
|
|
73
83
|
hasEmbeddings: false,
|
|
74
84
|
vecAvailable: false,
|
|
@@ -80,6 +90,7 @@ function readIndexStats(resolvedPath) {
|
|
|
80
90
|
db = openExistingDatabase(resolvedPath);
|
|
81
91
|
return {
|
|
82
92
|
entryCount: getEntryCount(db),
|
|
93
|
+
byType: getEntryCountByType(db),
|
|
83
94
|
lastBuiltAt: getMeta(db, "builtAt") ?? null,
|
|
84
95
|
hasEmbeddings: getMeta(db, "hasEmbeddings") === "1",
|
|
85
96
|
vecAvailable: isVecAvailable(db),
|
|
@@ -88,7 +99,9 @@ function readIndexStats(resolvedPath) {
|
|
|
88
99
|
catch (err) {
|
|
89
100
|
// Surface the error so operators can diagnose mismatches between
|
|
90
101
|
// `akm info` and `akm health` rather than silently returning zeros.
|
|
91
|
-
|
|
102
|
+
// Routed through core/warn's `error()` (not a raw process.stderr.write)
|
|
103
|
+
// so `--quiet`/`setQuiet()` actually gate this line (R-057).
|
|
104
|
+
error(`[akm info] failed to read index stats from ${resolvedPath}: ${String(err)}`);
|
|
92
105
|
return EMPTY;
|
|
93
106
|
}
|
|
94
107
|
finally {
|