akm-cli 0.9.0-rc.8 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1063 -44
- package/README.md +51 -25
- package/SECURITY.md +14 -1
- package/STABILITY.md +497 -0
- package/dist/akm +148 -35
- package/dist/{akm-migrate-storage → akm-migrate} +6 -9
- package/dist/assets/hints/cli-hints-full.md +223 -95
- package/dist/assets/hints/cli-hints-short.md +85 -22
- package/dist/assets/improve-strategies/default.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/stash-skeleton/README.md +6 -5
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
- package/dist/assets/tasks/core/extract.yml +1 -1
- package/dist/assets/tasks/core/version-check.yml +1 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +1 -3
- package/dist/assets/workflows/workflow-template.md +32 -15
- package/dist/cli/invocation.js +40 -15
- package/dist/cli/parse-args.js +0 -22
- package/dist/cli/retired-commands.js +121 -0
- package/dist/cli/shared.js +154 -22
- package/dist/cli/unknown-flags.js +236 -0
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +696 -258
- package/dist/commands/agent/agent-dispatch.js +14 -3
- package/dist/commands/agent/contribute-cli.js +73 -88
- package/dist/commands/completions.js +79 -22
- package/dist/commands/config-cli.js +17 -150
- package/dist/commands/env/env-cli.js +59 -143
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +36 -66
- package/dist/commands/env/secret.js +24 -57
- package/dist/commands/feedback-cli.js +141 -87
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +3 -4
- package/dist/commands/health/checks.js +85 -23
- package/dist/commands/health/html-report.js +7 -10
- package/dist/commands/health/improve-metrics.js +25 -83
- package/dist/commands/health/md-report.js +5 -9
- package/dist/commands/health/metrics.js +62 -20
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +4 -5
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +3 -48
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/commands/health/types-improve.js +7 -0
- package/dist/commands/health.js +99 -28
- package/dist/commands/improve/anti-collapse.js +2 -2
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +41 -40
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +140 -1000
- package/dist/commands/improve/distill/promote-memory.js +12 -12
- package/dist/commands/improve/distill/quality-gate.js +6 -6
- package/dist/commands/improve/distill.js +58 -69
- package/dist/commands/improve/eligibility.js +105 -57
- package/dist/commands/improve/extract-cli.js +14 -133
- package/dist/commands/improve/improve-cli.js +98 -114
- package/dist/commands/improve/improve-result-file.js +1 -28
- package/dist/commands/improve/improve-strategies.js +8 -5
- package/dist/commands/improve/improve.js +128 -91
- package/dist/commands/improve/loop-stages.js +182 -20
- package/dist/commands/improve/memory/derived-ref.js +45 -43
- package/dist/commands/improve/memory/memory-belief.js +1 -1
- package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
- package/dist/commands/improve/memory/memory-improve.js +6 -5
- package/dist/commands/improve/outcome-loop.js +22 -65
- package/dist/commands/improve/preparation.js +114 -123
- package/dist/commands/improve/proactive-maintenance.js +2 -5
- package/dist/commands/improve/reflect.js +56 -160
- package/dist/commands/improve/salience.js +11 -122
- package/dist/commands/improve/source-identity.js +10 -38
- package/dist/commands/lint/base-linter.js +20 -124
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +249 -43
- package/dist/commands/{events.js → log.js} +33 -38
- package/dist/commands/migrate-cli.js +92 -12
- package/dist/commands/migration-tool.js +46 -0
- package/dist/commands/observability-cli.js +70 -209
- package/dist/commands/proposal/drain.js +101 -29
- package/dist/commands/proposal/proposal-cli.js +76 -48
- package/dist/commands/proposal/proposal.js +54 -18
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +23 -15
- package/dist/commands/proposal/repository.js +701 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
- package/dist/commands/proposal/validators/proposal-validators.js +55 -7
- package/dist/commands/proposal/validators/proposals.js +4 -7
- package/dist/commands/read/curate.js +34 -53
- package/dist/commands/read/knowledge.js +150 -95
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +42 -15
- package/dist/commands/read/search-cli.js +180 -78
- package/dist/commands/read/search.js +58 -43
- package/dist/commands/read/show.js +197 -141
- package/dist/commands/registry-cli.js +12 -51
- package/dist/commands/remember.js +14 -57
- package/dist/commands/sources/add-cli.js +100 -31
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +7 -2
- package/dist/commands/sources/info.js +18 -5
- package/dist/commands/sources/init.js +12 -12
- package/dist/commands/sources/installed-stashes.js +382 -98
- package/dist/commands/sources/schema-repair.js +3 -2
- package/dist/commands/sources/self-update.js +131 -38
- package/dist/commands/sources/source-add.js +72 -17
- package/dist/commands/sources/source-clone.js +129 -45
- package/dist/commands/sources/source-manage.js +43 -23
- package/dist/commands/sources/sources-cli.js +57 -208
- package/dist/commands/sources/stash-cli.js +46 -53
- package/dist/commands/tasks/tasks-cli.js +91 -97
- package/dist/commands/tasks/tasks.js +276 -421
- package/dist/commands/workflow-cli.js +175 -450
- package/dist/core/adapter/adapters/akm-adapter.js +47 -28
- package/dist/core/adapter/adapters/akm-lint.js +42 -27
- package/dist/core/adapter/adapters/akm-metadata.js +15 -44
- package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
- package/dist/core/adapter/adapters/index.js +6 -6
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
- package/dist/core/adapter/adapters/okf-adapter.js +187 -19
- package/dist/core/adapter/adapters/shared.js +3 -19
- package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +6 -4
- package/dist/core/adapter/validate-context.js +214 -0
- package/dist/core/asset/akm-markdown.js +63 -0
- package/dist/core/asset/asset-placement.js +20 -6
- package/dist/core/asset/asset-ref.js +11 -9
- package/dist/core/asset/frontmatter-lint.js +30 -0
- package/dist/core/asset/frontmatter.js +37 -9
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +89 -18
- package/dist/core/asset/stash-meta.js +1 -1
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +152 -38
- package/dist/core/config/config-io.js +12 -1
- package/dist/core/config/config-schema.js +35 -8
- package/dist/core/config/config-sources.js +55 -11
- package/dist/core/config/config-walker.js +25 -9
- package/dist/core/config/config.js +9 -48
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +5 -1
- package/dist/core/config/schema/experimental.js +30 -0
- package/dist/core/config/schema/improve-processes.js +0 -6
- package/dist/core/config/schema/improve.js +21 -3
- package/dist/core/config/schema/index-config.js +8 -15
- package/dist/core/config/schema/output.js +4 -1
- package/dist/core/config/schema/setup.js +9 -18
- package/dist/core/config/schema/sources-bundles.js +49 -33
- package/dist/core/config/schema/workflow.js +3 -3
- package/dist/core/env-secret-ref.js +76 -46
- package/dist/core/errors.js +18 -12
- package/dist/core/events.js +46 -128
- package/dist/core/file-change.js +6 -5
- package/dist/core/fs-txn.js +83 -7
- package/dist/core/git-message.js +2 -2
- package/dist/core/improve-result.js +1 -100
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +2 -1
- package/dist/core/migration-operation.js +16 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/parse.js +4 -1
- package/dist/core/paths.js +17 -20
- package/dist/core/recognition-util.js +12 -14
- package/dist/core/redaction.js +34 -0
- package/dist/core/standards/resolve-standards-context.js +2 -14
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +2 -2
- package/dist/core/state/migrations.js +41 -18
- package/dist/core/state-db.js +5 -14
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +6 -4
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/type-presentation.js +3 -3
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +771 -95
- package/dist/indexer/bundle-identity-guard.js +3 -2
- package/dist/indexer/db/graph-db.js +0 -24
- package/dist/indexer/ensure-index.js +1 -0
- package/dist/indexer/graph/graph-boost.js +9 -34
- package/dist/indexer/graph/graph-extraction.js +8 -5
- package/dist/indexer/index-writer-lock.js +53 -17
- package/dist/indexer/index-written-assets.js +16 -22
- package/dist/indexer/indexer.js +497 -239
- package/dist/indexer/installations.js +14 -96
- package/dist/indexer/passes/dir-staleness.js +16 -9
- package/dist/indexer/passes/memory-inference.js +11 -9
- package/dist/indexer/passes/metadata.js +113 -47
- package/dist/indexer/scan/doc-to-entry.js +38 -1
- package/dist/indexer/scan/drain-dir.js +13 -23
- package/dist/indexer/search/db-search.js +99 -54
- package/dist/indexer/search/fts-query.js +47 -24
- package/dist/indexer/search/ranking-contributors.js +42 -20
- package/dist/indexer/search/ranking.js +18 -99
- package/dist/indexer/search/search-fields.js +7 -2
- package/dist/indexer/search/search-source.js +82 -93
- package/dist/indexer/usage/usage-events.js +0 -89
- package/dist/indexer/walk/file-context.js +2 -1
- package/dist/indexer/walk/matchers.js +30 -43
- package/dist/indexer/walk/path-resolver.js +7 -2
- package/dist/indexer/walk/walker.js +38 -12
- package/dist/integrations/agent/builders.js +0 -6
- package/dist/integrations/agent/config.js +2 -2
- package/dist/integrations/agent/detect.js +49 -19
- package/dist/integrations/agent/engine-fallback.js +76 -0
- package/dist/integrations/agent/profiles.js +14 -0
- package/dist/integrations/agent/prompts.js +12 -8
- package/dist/integrations/agent/runner-dispatch.js +4 -2
- package/dist/integrations/agent/runner.js +0 -1
- package/dist/integrations/agent/spawn.js +5 -6
- package/dist/integrations/github.js +1 -1
- package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
- package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
- package/dist/integrations/harnesses/claude/session-log.js +0 -10
- package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
- package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
- package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
- package/dist/integrations/harnesses/index.js +3 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
- package/dist/integrations/harnesses/opencode/session-log.js +0 -15
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
- package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
- package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
- package/dist/integrations/lockfile.js +101 -6
- package/dist/integrations/session-logs/index.js +3 -28
- package/dist/llm/client.js +136 -100
- package/dist/llm/embedders/remote.js +13 -5
- package/dist/llm/feature-gate.js +4 -12
- package/dist/llm/graph-extract.js +5 -11
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +5 -7
- package/dist/llm/structured-call.js +1 -1
- package/dist/llm/usage-persist.js +26 -5
- package/dist/llm/usage-telemetry.js +25 -2
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +259 -0
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -36
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +56 -83
- package/dist/output/shapes/migrate.js +8 -0
- package/dist/output/shapes/passthrough.js +7 -41
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes.js +2 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +164 -96
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/health-format.js +103 -0
- package/dist/output/text/health.js +7 -0
- package/dist/output/text/helpers.js +10 -8
- package/dist/output/text/lint-format.js +43 -0
- package/dist/output/text/{save.js → lint.js} +2 -2
- package/dist/output/text/migrate.js +88 -0
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +44 -72
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +15 -7
- package/dist/output/text/status-list.js +32 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +24 -203
- package/dist/output/text/workflow.js +1 -7
- package/dist/output/text.js +16 -17
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +13 -23
- package/dist/registry/resolve.js +42 -7
- package/dist/registry/semver.js +34 -84
- package/dist/runtime.js +2 -23
- package/dist/scripts/akm-migrate-node.js +60290 -0
- package/dist/scripts/akm-migrate.js +59628 -0
- package/dist/setup/detect.js +42 -15
- package/dist/setup/registry-stash-loader.js +2 -2
- package/dist/setup/setup.js +236 -136
- package/dist/setup/steps/connection.js +7 -9
- package/dist/setup/steps/platforms.js +9 -9
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +12 -13
- package/dist/setup/steps/stashdir.js +2 -3
- package/dist/setup/steps/tasks.js +237 -120
- package/dist/sources/freshness.js +1 -1
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +25 -23
- package/dist/sources/providers/git-stash.js +395 -106
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +7 -4
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +6 -1
- package/dist/sources/resolve.js +6 -5
- package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
- package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
- package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
- package/dist/sources/snapshot-fetchers/github.js +100 -0
- package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
- package/dist/sources/snapshot-fetchers/registry.js +17 -1
- package/dist/sources/snapshot-fetchers/robots.js +348 -0
- package/dist/sources/snapshot-fetchers/rss.js +282 -0
- package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
- package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
- package/dist/sources/snapshot-fetchers/x.js +910 -0
- package/dist/storage/database.js +7 -0
- package/dist/storage/engines/sqlite-migrations.js +23 -111
- package/dist/storage/managed-db.js +2 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +27 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -12
- package/dist/storage/repositories/index-connection.js +17 -6
- package/dist/storage/repositories/index-entries-repository.js +151 -240
- package/dist/storage/repositories/index-entry-mapper.js +15 -11
- package/dist/storage/repositories/index-fts-repository.js +5 -2
- package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
- package/dist/storage/repositories/index-meta-repository.js +2 -3
- package/dist/storage/repositories/index-schema.js +10 -25
- package/dist/storage/repositories/index-utility-repository.js +15 -28
- package/dist/storage/repositories/index-vec-repository.js +6 -1
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +296 -59
- package/dist/storage/repositories/registry-cache.js +19 -0
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +15 -13
- package/dist/storage/repositories/workflow-runs-repository.js +52 -40
- package/dist/tasks/backends/cron.js +105 -15
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +85 -38
- package/dist/tasks/backends/schtasks.js +135 -15
- package/dist/tasks/embedded.js +56 -40
- package/dist/tasks/parser.js +7 -157
- package/dist/tasks/resolve-akm-bin.js +137 -59
- package/dist/tasks/runner.js +79 -42
- package/dist/tasks/scheduler-invocation.js +220 -10
- package/dist/tasks/schema.js +24 -1
- package/dist/tasks/task-id.js +1 -3
- package/dist/tasks/validator.js +20 -6
- package/dist/workflows/authoring/authoring.js +94 -143
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/exec/frozen-judge.js +28 -2
- package/dist/workflows/exec/native-executor.js +77 -57
- package/dist/workflows/exec/param-secrets.js +9 -9
- package/dist/workflows/exec/run-workflow.js +133 -79
- package/dist/workflows/exec/step-work.js +219 -346
- package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
- package/dist/workflows/ir/compile.js +141 -270
- package/dist/workflows/ir/freeze.js +40 -30
- package/dist/workflows/ir/params.js +135 -11
- package/dist/workflows/ir/plan-hash.js +1 -1
- package/dist/workflows/ir/schema.js +25 -26
- package/dist/workflows/parser.js +872 -307
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +7 -10
- package/dist/workflows/renderer.js +95 -68
- package/dist/workflows/resource-limits.js +2 -0
- package/dist/workflows/runtime/checkin.js +3 -3
- package/dist/workflows/runtime/plan-classifier.js +16 -75
- package/dist/workflows/runtime/runs.js +186 -127
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +2 -2
- package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +30 -36
- package/dist/workflows/validator.js +21 -62
- package/docs/README.md +68 -0
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.7.0.md +11 -11
- package/docs/migration/release-notes/0.9.0.md +208 -27
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +564 -208
- package/docs/migration/v0.9.0-troubleshooting.md +561 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/cli.md +2253 -0
- package/docs/reference/configuration.md +358 -0
- package/docs/reference/data-and-telemetry.md +105 -42
- package/docs/reference/workflows.md +647 -0
- package/package.json +22 -11
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +81 -128
- package/schemas/akm-workflow.json +74 -73
- package/dist/assets/tasks/core/backup.yml +0 -5
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/cli/config-migrate.js +0 -1806
- package/dist/cli/config-validate.js +0 -41
- package/dist/commands/backup-cli.js +0 -56
- package/dist/commands/bundle/bundle-cli.js +0 -68
- package/dist/commands/bundle/bundle.js +0 -219
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -489
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/mv-cli.js +0 -1221
- package/dist/commands/sources/history.js +0 -201
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/core/migration-backup.js +0 -1234
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/migrate/legacy/config-source-migration.js +0 -223
- package/dist/migrate/legacy/content-migration.js +0 -305
- package/dist/migrate/legacy/legacy-layout.js +0 -779
- package/dist/migrate/legacy/legacy-paths.js +0 -25
- package/dist/migrate/legacy/legacy-stash-json.js +0 -72
- package/dist/migrate/legacy/proposal-fs-import.js +0 -168
- package/dist/migrate/legacy/task-target-ref-migration.js +0 -272
- package/dist/migrate/legacy/three-db-cutover.js +0 -841
- package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
- package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
- package/dist/migrate/legacy-ref-grammar.js +0 -214
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/registry/build-index.js +0 -382
- package/dist/schemas/akm-config.json +0 -4704
- package/dist/schemas/akm-task.json +0 -87
- package/dist/schemas/akm-workflow.json +0 -372
- package/dist/scripts/migrate-storage.js +0 -3816
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/cli.js +0 -53
- package/dist/workflows/exec/brief.js +0 -481
- package/dist/workflows/exec/report.js +0 -1460
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -813
- package/dist/workflows/program/project.js +0 -104
|
@@ -1,98 +1,8 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import { conceptIdFromTypeName } from "../../core/asset/resolve-ref.js";
|
|
6
|
-
import { acquireMaintenanceActivitySync } from "../../core/maintenance-barrier.js";
|
|
7
|
-
import { getStateDbPath } from "../../core/state-db.js";
|
|
8
|
-
import { openDatabase } from "../../storage/database.js";
|
|
9
4
|
import { getUtilityScoresByIds } from "../../storage/repositories/index-utility-repository.js";
|
|
10
5
|
import { applyBeliefStateScoreCeiling, applyContributorAblation, applyScoreContributors, applyUtilityContributors, defaultRankingContributors, defaultUtilityRankingContributors, } from "./ranking-contributors.js";
|
|
11
|
-
/**
|
|
12
|
-
* R2 — best-effort load of `asset_salience.rank_score` from state.db for the
|
|
13
|
-
* ranked items. Fail-open: any error (state.db locked by a concurrent improve
|
|
14
|
-
* run, missing table, unreadable path) returns an empty map, which makes the
|
|
15
|
-
* salience contributor a no-op — byte-identical to pre-R2 ranking.
|
|
16
|
-
*
|
|
17
|
-
* Deliberately NOT `openStateDatabase()`: that helper runs migrations and sets
|
|
18
|
-
* a 30 s busy timeout — too heavy for a search hot path. This opens read-only,
|
|
19
|
-
* never creates or migrates state.db (missing file / missing table = empty
|
|
20
|
-
* map), and caps lock waits at 250 ms so a concurrent improve run can only
|
|
21
|
-
* ever cost the search a quarter second, not a stall.
|
|
22
|
-
*/
|
|
23
|
-
export function loadSalienceRankScores(items) {
|
|
24
|
-
const result = new Map();
|
|
25
|
-
if (items.length === 0)
|
|
26
|
-
return result;
|
|
27
|
-
try {
|
|
28
|
-
const dbPath = getStateDbPath();
|
|
29
|
-
if (!fs.existsSync(dbPath))
|
|
30
|
-
return result; // improve loop has never run here
|
|
31
|
-
const releaseActivity = acquireMaintenanceActivitySync("state-db");
|
|
32
|
-
// Fold both durable salience spellings into the single `IN` query, keyed
|
|
33
|
-
// back to the entry id (Chunk-8 WI-8.5c — the legacy `type:name` arm is
|
|
34
|
-
// retired):
|
|
35
|
-
// • the fully-qualified `item_ref` (`<bundle>//<conceptId>`) — what the
|
|
36
|
-
// improve writer keys salience by when the planner resolved provenance;
|
|
37
|
-
// • the bare conceptId — the write-key fallback for entries with no
|
|
38
|
-
// resolved `item_ref` (`item_ref` NULL is the bare form of the same key).
|
|
39
|
-
// Output is keyed by id, so a fully-qualified match wins over the bare-conceptId
|
|
40
|
-
// match for the same asset id.
|
|
41
|
-
const idByRef = new Map();
|
|
42
|
-
try {
|
|
43
|
-
for (const item of items) {
|
|
44
|
-
// Bare-conceptId arm (the item_ref-absent write-key fallback).
|
|
45
|
-
idByRef.set(conceptIdFromTypeName(item.entry.type, item.entry.name), { id: item.id, isNew: false });
|
|
46
|
-
// Fully-qualified `item_ref` arm (skipped for NULL-provenance rows).
|
|
47
|
-
if (item.itemRef)
|
|
48
|
-
idByRef.set(item.itemRef, { id: item.id, isNew: true });
|
|
49
|
-
}
|
|
50
|
-
const stateDb = openDatabase(dbPath, { readonly: true });
|
|
51
|
-
try {
|
|
52
|
-
try {
|
|
53
|
-
stateDb.exec("PRAGMA busy_timeout = 250");
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
// pragma failure on a readonly handle is fine — default timeout applies
|
|
57
|
-
}
|
|
58
|
-
const refs = [...idByRef.keys()];
|
|
59
|
-
const CHUNK = 500;
|
|
60
|
-
const newHits = new Set();
|
|
61
|
-
for (let i = 0; i < refs.length; i += CHUNK) {
|
|
62
|
-
const chunk = refs.slice(i, i + CHUNK);
|
|
63
|
-
const placeholders = chunk.map(() => "?").join(",");
|
|
64
|
-
const rows = stateDb
|
|
65
|
-
.prepare(`SELECT asset_ref, rank_score FROM asset_salience WHERE asset_ref IN (${placeholders})`)
|
|
66
|
-
.all(...chunk);
|
|
67
|
-
for (const row of rows) {
|
|
68
|
-
const target = idByRef.get(row.asset_ref);
|
|
69
|
-
if (!target)
|
|
70
|
-
continue;
|
|
71
|
-
// New-grammar match wins over a stale legacy row for the same id;
|
|
72
|
-
// a legacy match applies only when no new row has claimed the id.
|
|
73
|
-
if (target.isNew) {
|
|
74
|
-
result.set(target.id, row.rank_score);
|
|
75
|
-
newHits.add(target.id);
|
|
76
|
-
}
|
|
77
|
-
else if (!newHits.has(target.id)) {
|
|
78
|
-
result.set(target.id, row.rank_score);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
finally {
|
|
84
|
-
stateDb.close();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
finally {
|
|
88
|
-
releaseActivity();
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
// Fail open — search must never break because state.db is unavailable.
|
|
93
|
-
}
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
96
6
|
export function normalizeFtsScores(results) {
|
|
97
7
|
const ftsScoreMap = new Map();
|
|
98
8
|
if (results.length === 0)
|
|
@@ -124,6 +34,8 @@ export function combineSearchScores(options) {
|
|
|
124
34
|
score: combinedScore,
|
|
125
35
|
rankingMode: embedScore !== undefined ? "hybrid" : "fts",
|
|
126
36
|
itemRef: result.itemRef,
|
|
37
|
+
bundleId: result.bundleId,
|
|
38
|
+
conceptId: result.conceptId,
|
|
127
39
|
});
|
|
128
40
|
}
|
|
129
41
|
for (const [id, cosine] of options.embedScoreMap) {
|
|
@@ -144,6 +56,8 @@ export function combineSearchScores(options) {
|
|
|
144
56
|
score: cosine * VEC_WEIGHT,
|
|
145
57
|
rankingMode: "semantic",
|
|
146
58
|
itemRef: found.itemRef,
|
|
59
|
+
bundleId: found.bundleId,
|
|
60
|
+
conceptId: found.conceptId,
|
|
147
61
|
});
|
|
148
62
|
}
|
|
149
63
|
return scored;
|
|
@@ -159,21 +73,26 @@ export function applyRankingRules(options) {
|
|
|
159
73
|
graphContext: options.graphContext,
|
|
160
74
|
projectContext: options.projectContext,
|
|
161
75
|
};
|
|
162
|
-
// Eval/debug only:
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
|
|
76
|
+
// Eval/debug only: lets the ablation harness drop named contributors to
|
|
77
|
+
// measure their effect. Resolved once per query; a no-op (full lists) when
|
|
78
|
+
// unset — see applyContributorAblation. C9: DI via
|
|
79
|
+
// `options.ablateContributors` is now the primary path (see the field's
|
|
80
|
+
// doc comment on RankEntriesOptions); AKM_ABLATE_CONTRIBUTORS is a
|
|
81
|
+
// temporary fallback for the one caller that cannot yet thread the option
|
|
82
|
+
// through (see that doc comment for why).
|
|
83
|
+
const ablateEnv = options.ablateContributors ?? process.env.AKM_ABLATE_CONTRIBUTORS;
|
|
166
84
|
const activeScoreContributors = applyContributorAblation(defaultRankingContributors, ablateEnv);
|
|
167
85
|
const activeUtilityContributors = applyContributorAblation(defaultUtilityRankingContributors, ablateEnv);
|
|
168
86
|
for (const item of options.items) {
|
|
169
87
|
applyScoreContributors(item, rankingContext, activeScoreContributors);
|
|
170
88
|
}
|
|
171
89
|
const { global: utilScoresMap, scoped: scopedUtilScoresMap } = getUtilityScoresByIds(options.db, options.items.map((item) => item.id), options.scopeKey);
|
|
172
|
-
// R2
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
90
|
+
// R2 / #692 — salience-ranking is not in defaultUtilityRankingContributors
|
|
91
|
+
// (see ranking-contributors.ts), so this is never consumed by the default
|
|
92
|
+
// ranking path below; it exists only for a caller that explicitly builds a
|
|
93
|
+
// contributor list including salienceRankingContributor. undefined/null
|
|
94
|
+
// both normalize to "no data" — there is no state.db fallback load.
|
|
95
|
+
const salienceRankScores = options.salienceRankScores ?? new Map();
|
|
177
96
|
const utilityContext = {
|
|
178
97
|
...rankingContext,
|
|
179
98
|
utilityScores: utilScoresMap,
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
// scored via FTS against it. Changing what buildSearchFields includes shifts
|
|
18
18
|
// the detector's recall baseline for ALL existing canary sets — coordinate
|
|
19
19
|
// with src/commands/improve/collapse-detector.ts (buildCanaryQuery) and expect
|
|
20
|
-
// operators to re-mint via `
|
|
20
|
+
// operators to re-mint via `bun scripts/refresh-canary-set.ts --refresh` after
|
|
21
|
+
// such a change.
|
|
21
22
|
export function buildSearchFields(entry) {
|
|
22
23
|
const name = entry.name.replace(/[-_]/g, " ").toLowerCase();
|
|
23
24
|
const description = (entry.description ?? "").toLowerCase();
|
|
@@ -28,6 +29,8 @@ export function buildSearchFields(entry) {
|
|
|
28
29
|
tagParts.push(entry.aliases.join(" "));
|
|
29
30
|
const tags = tagParts.join(" ").toLowerCase();
|
|
30
31
|
const hintParts = [];
|
|
32
|
+
if (entry.hints)
|
|
33
|
+
hintParts.push(entry.hints.join(" "));
|
|
31
34
|
if (entry.searchHints)
|
|
32
35
|
hintParts.push(entry.searchHints.join(" "));
|
|
33
36
|
if (entry.examples)
|
|
@@ -50,6 +53,8 @@ export function buildSearchFields(entry) {
|
|
|
50
53
|
hintParts.push(entry.whenToUse);
|
|
51
54
|
const hints = hintParts.join(" ").toLowerCase();
|
|
52
55
|
const contentParts = [];
|
|
56
|
+
if (entry.content)
|
|
57
|
+
contentParts.push(entry.content);
|
|
53
58
|
if (entry.toc) {
|
|
54
59
|
contentParts.push(entry.toc.map((h) => h.text).join(" "));
|
|
55
60
|
}
|
|
@@ -74,7 +79,7 @@ export function buildSearchFields(entry) {
|
|
|
74
79
|
}
|
|
75
80
|
/**
|
|
76
81
|
* Build a single concatenated search text string for an entry.
|
|
77
|
-
* Used for the `search_text` column in the entries table
|
|
82
|
+
* Used for the `search_text` column in the entries table.
|
|
78
83
|
* and for generating embedding text.
|
|
79
84
|
*/
|
|
80
85
|
export function buildSearchText(entry) {
|
|
@@ -4,85 +4,101 @@
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { isSourceWriteActivated } from "../../core/activation-policy.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { lockContentRootFor, readLockfile } from "../../integrations/lockfile.js";
|
|
7
|
+
import { isWithin, resolveStashDir } from "../../core/common.js";
|
|
8
|
+
import { bundleComponentConfig, bundlesToSourceEntries, getSources, loadConfig } from "../../core/config/config.js";
|
|
9
|
+
import { resolveGitContentRoot, resolveWritable } from "../../core/write-source.js";
|
|
10
|
+
import { lockContentRootFor } from "../../integrations/lockfile.js";
|
|
12
11
|
import { resolveSourceProviderFactory } from "../../sources/provider-factory.js";
|
|
13
12
|
// Eager side-effect imports so all built-in source providers self-register
|
|
14
13
|
// before resolveEntryContentDir() runs.
|
|
15
14
|
import "../../sources/providers/index.js";
|
|
16
15
|
import { warn } from "../../core/warn.js";
|
|
17
|
-
// Legacy "context-hub" / "github" type aliases are normalized to "git" at
|
|
18
|
-
// config-load time (see src/config.ts), so this set only contains the canonical
|
|
19
|
-
// type.
|
|
20
|
-
const GIT_STASH_TYPES = new Set(["git"]);
|
|
21
16
|
// ── Resolution ──────────────────────────────────────────────────────────────
|
|
22
17
|
/**
|
|
23
18
|
* Build the ordered list of stash sources, walking every configured stash
|
|
24
19
|
* once. Iteration order:
|
|
25
20
|
*
|
|
26
|
-
* 1.
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* 2. Each entry in `config.sources[]` (in declared order), excluding the
|
|
30
|
-
* one already emitted as the primary.
|
|
31
|
-
* 3. Each entry in `config.installed[]` (registry-managed stashes).
|
|
21
|
+
* 1. An explicit argument or `AKM_BUNDLE_DIR`, when present.
|
|
22
|
+
* 2. The configured `defaultBundle`, after component-root validation.
|
|
23
|
+
* 3. Remaining configured bundles in installation-priority order.
|
|
32
24
|
*
|
|
33
25
|
* Replaces the previous four-pass loop that walked `stashes[]` separately
|
|
34
|
-
* for each provider kind. Disabled entries (`enabled: false`)
|
|
35
|
-
*
|
|
26
|
+
* for each provider kind. Disabled entries (`enabled: false`) are filtered
|
|
27
|
+
* after deduplication. Missing configured roots remain in the result so the
|
|
28
|
+
* indexer can classify their scan as incomplete instead of mistaking them for
|
|
29
|
+
* removed sources.
|
|
36
30
|
*/
|
|
37
31
|
export function resolveSourceEntries(overrideStashDir, existingConfig) {
|
|
38
|
-
const stashDir = overrideStashDir ?? resolveStashDir();
|
|
39
32
|
const config = existingConfig ?? loadConfig();
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
|
|
33
|
+
const configuredEntries = bundlesToSourceEntries(config) ?? [];
|
|
34
|
+
const envOverride = process.env.AKM_BUNDLE_DIR?.trim();
|
|
35
|
+
const implicitStashDir = overrideStashDir !== undefined
|
|
36
|
+
? path.resolve(overrideStashDir)
|
|
37
|
+
: envOverride
|
|
38
|
+
? resolveStashDir()
|
|
39
|
+
: config.defaultBundle
|
|
40
|
+
? undefined
|
|
41
|
+
: resolveStashDir();
|
|
42
|
+
// Explicit and environment overrides stay first. Without either override,
|
|
43
|
+
// the configured default enters through the validated loop below.
|
|
44
|
+
const sources = implicitStashDir ? [{ path: implicitStashDir, writable: true }] : [];
|
|
45
|
+
const seen = new Set(implicitStashDir ? [implicitStashDir] : []);
|
|
46
|
+
const addSource = (dir, registryId, writable, type, adapterId, unresolved = false) => {
|
|
44
47
|
const resolved = path.resolve(dir);
|
|
45
48
|
if (seen.has(resolved)) {
|
|
46
49
|
// Already in the source list — typically the primary stash injected at
|
|
47
50
|
// sources[0] before this loop. Enrich that entry with whatever metadata
|
|
48
|
-
// the matching config source carries so `--
|
|
51
|
+
// the matching config source carries so `--from <config-name>` can
|
|
49
52
|
// find it via registryId. Without this, the primary stash entry stays
|
|
50
53
|
// identity-less and a user-named primary source ("name": "my-stash")
|
|
51
54
|
// would validate but match zero entries when filtering.
|
|
52
55
|
const existing = sources.find((s) => s.path === resolved);
|
|
53
|
-
if (existing) {
|
|
54
|
-
if (registryId
|
|
56
|
+
if (existing && existing.type === undefined) {
|
|
57
|
+
if (registryId)
|
|
55
58
|
existing.registryId = registryId;
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
existing.type = type;
|
|
60
|
+
existing.writable = writable;
|
|
61
|
+
existing.adapterId = adapterId;
|
|
58
62
|
}
|
|
63
|
+
if (existing && unresolved)
|
|
64
|
+
existing.unresolved = true;
|
|
59
65
|
return;
|
|
60
66
|
}
|
|
61
67
|
seen.add(resolved);
|
|
62
68
|
if (isSuspiciousStashRoot(dir)) {
|
|
63
69
|
warn(`Warning: stash root "${dir}" appears to be a system directory. This may be unintentional.`);
|
|
64
70
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
})
|
|
71
|
-
|
|
71
|
+
sources.push({
|
|
72
|
+
path: resolved,
|
|
73
|
+
...(registryId ? { registryId } : {}),
|
|
74
|
+
writable,
|
|
75
|
+
type,
|
|
76
|
+
...(adapterId ? { adapterId } : {}),
|
|
77
|
+
...(unresolved ? { unresolved: true } : {}),
|
|
78
|
+
});
|
|
72
79
|
};
|
|
73
80
|
// 0.9.0 shape (spec §10.1 / D-R5): resolve from `bundles` + `defaultBundle`.
|
|
74
|
-
// `bundlesToSourceEntries` returns the
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
// == the bundle id. A config with no bundles yields just the primary stash.
|
|
79
|
-
for (const entry of bundlesToSourceEntries(config) ?? []) {
|
|
81
|
+
// `bundlesToSourceEntries` returns the configured default first, then map
|
|
82
|
+
// insertion order. Each entry is validated before insertion so a component
|
|
83
|
+
// root can never escape its provider's materialized content root.
|
|
84
|
+
for (const entry of configuredEntries) {
|
|
80
85
|
if (entry.enabled === false)
|
|
81
86
|
continue;
|
|
82
|
-
const
|
|
83
|
-
|
|
87
|
+
const component = bundleComponentConfig(config.bundles?.[entry.name ?? ""]);
|
|
88
|
+
const contentRoot = resolveEntryContentDir(entry);
|
|
89
|
+
if (contentRoot == null) {
|
|
90
|
+
const unresolvedPath = path.join(implicitStashDir ?? process.cwd(), ".akm", "unresolved-sources", entry.name ?? entry.type);
|
|
91
|
+
addSource(unresolvedPath, entry.name, component?.writable ?? resolveWritable(entry), entry.type, component?.adapter, true);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const dir = path.resolve(contentRoot, component?.root ?? ".");
|
|
95
|
+
if (!isWithin(dir, contentRoot)) {
|
|
96
|
+
warn(`Warning: component root "${component?.root}" escapes bundle "${entry.name}"; skipping source.`);
|
|
97
|
+
const unresolvedPath = path.join(contentRoot, ".akm", "unresolved-sources", entry.name ?? entry.type);
|
|
98
|
+
addSource(unresolvedPath, entry.name, component?.writable ?? resolveWritable(entry), entry.type, component?.adapter, true);
|
|
84
99
|
continue;
|
|
85
|
-
|
|
100
|
+
}
|
|
101
|
+
addSource(dir, entry.name, component?.writable ?? resolveWritable(entry), entry.type, component?.adapter);
|
|
86
102
|
}
|
|
87
103
|
return sources;
|
|
88
104
|
}
|
|
@@ -138,7 +154,7 @@ export function resolveEntryContentDir(entry) {
|
|
|
138
154
|
// layout puts indexable files under `<repo>/content/`, so the walker needs
|
|
139
155
|
// that subdirectory. This is a content-layout convention, not a provider
|
|
140
156
|
// capability — keep it here.
|
|
141
|
-
if (
|
|
157
|
+
if (entry.type === "git") {
|
|
142
158
|
return resolveGitContentRoot(dir);
|
|
143
159
|
}
|
|
144
160
|
return dir;
|
|
@@ -151,11 +167,6 @@ export function resolveAllStashDirs(overrideStashDir) {
|
|
|
151
167
|
}
|
|
152
168
|
/**
|
|
153
169
|
* Return the resolved absolute paths of all writable stash sources.
|
|
154
|
-
*
|
|
155
|
-
* The primary stash is always writable. Filesystem/git sources that have
|
|
156
|
-
* `writable: true` in config are also included. Registry-cached sources
|
|
157
|
-
* (installed without `writable: true`) are excluded because they are
|
|
158
|
-
* overwritten on `akm update` and must never be mutated.
|
|
159
170
|
*/
|
|
160
171
|
export function getWritableStashDirs(overrideStashDir, existingConfig) {
|
|
161
172
|
return resolveSourceEntries(overrideStashDir, existingConfig)
|
|
@@ -194,46 +205,22 @@ export function getPrimarySource(sources) {
|
|
|
194
205
|
}
|
|
195
206
|
// ── Editability ─────────────────────────────────────────────────────────────
|
|
196
207
|
/**
|
|
197
|
-
* Determine whether
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* is not explicitly `writable` — `akm update` overwrites them without warning.
|
|
202
|
-
* The read-only decision is re-expressed via bundle `writable` + lock `localRoot`
|
|
203
|
-
* (replacing the retired `installed[].cacheDir` scan); a writable git/filesystem
|
|
204
|
-
* bundle stays editable, and a source with no lock entry (a plain filesystem
|
|
205
|
-
* bundle / local project dir) is the user's domain to manage.
|
|
208
|
+
* Determine whether AKM policy allows modifying this exact file in place.
|
|
209
|
+
* Ownership is resolved by longest source-root match and unknown ownership
|
|
210
|
+
* fails closed. Resolved sources already carry canonical `resolveWritable()`
|
|
211
|
+
* semantics; editability is never persisted in the index.
|
|
206
212
|
*/
|
|
207
|
-
export function isEditable(filePath, config) {
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
const isWin = process.platform === "win32";
|
|
211
|
-
const bundles = cfg.bundles ?? {};
|
|
212
|
-
const startsWithin = (root) => {
|
|
213
|
-
const base = path.resolve(root);
|
|
214
|
-
return isWin
|
|
215
|
-
? resolved.toLowerCase().startsWith(base.toLowerCase() + path.sep)
|
|
216
|
-
: resolved.startsWith(base + path.sep);
|
|
217
|
-
};
|
|
218
|
-
for (const lock of readLockfile()) {
|
|
219
|
-
if (!lock.localRoot)
|
|
220
|
-
continue;
|
|
221
|
-
// The lock is keyed by bundle id, so writability comes from that bundle.
|
|
222
|
-
const writable = bundles[lock.id]?.writable === true;
|
|
223
|
-
if (!writable && startsWithin(lock.localRoot))
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
return true;
|
|
213
|
+
export function isEditable(filePath, config, sources) {
|
|
214
|
+
const resolvedSources = sources ?? resolveSourceEntries(undefined, config ?? loadConfig());
|
|
215
|
+
return findSourceForPath(filePath, resolvedSources)?.writable === true;
|
|
227
216
|
}
|
|
228
217
|
/**
|
|
229
218
|
* Build an actionable hint for the agent when a file is not editable.
|
|
230
219
|
* Callers must check `isEditable()` before calling — this function
|
|
231
220
|
* unconditionally returns the hint string.
|
|
232
221
|
*/
|
|
233
|
-
export function buildEditHint(
|
|
234
|
-
|
|
235
|
-
const ref = displayRef({ type: assetType, name: assetName, bundleId: origin });
|
|
236
|
-
return `This asset is managed by akm and may be overwritten on update. To edit, run: akm clone ${ref}`;
|
|
222
|
+
export function buildEditHint(ref) {
|
|
223
|
+
return `This asset is read-only under current AKM source policy. To make an editable copy, run: akm clone ${ref}`;
|
|
237
224
|
}
|
|
238
225
|
// ── Validation ──────────────────────────────────────────────────────────────
|
|
239
226
|
const SUSPICIOUS_ROOTS = new Set(["/", "/etc", "/bin", "/sbin", "/usr", "/var", "/tmp", "/dev", "/proc", "/sys"]);
|
|
@@ -250,15 +237,6 @@ function isSuspiciousStashRoot(dir) {
|
|
|
250
237
|
}
|
|
251
238
|
return false;
|
|
252
239
|
}
|
|
253
|
-
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
254
|
-
function isValidDirectory(dir) {
|
|
255
|
-
try {
|
|
256
|
-
return fs.statSync(dir).isDirectory();
|
|
257
|
-
}
|
|
258
|
-
catch {
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
240
|
// ── Stash cache integration ─────────────────────────────────────────────────
|
|
263
241
|
/**
|
|
264
242
|
* Ensure all cache-backed stash providers are refreshed so their cache
|
|
@@ -295,6 +273,17 @@ export async function ensureSourceCaches(config, options) {
|
|
|
295
273
|
for (const entry of getSources(cfg)) {
|
|
296
274
|
if (entry.enabled === false)
|
|
297
275
|
continue;
|
|
276
|
+
const lockedRoot = lockContentRootFor(entry.name, entry.type);
|
|
277
|
+
if (lockedRoot) {
|
|
278
|
+
if (!isMaterializedDir(lockedRoot)) {
|
|
279
|
+
warn(`Warning: managed source "${entry.name}" is missing its locked materialization at ${lockedRoot}; ` +
|
|
280
|
+
`run \`akm bundle update ${entry.name}\` to restore it.`);
|
|
281
|
+
}
|
|
282
|
+
// Managed installs are refreshed only by add/update. Hydrating the URL-
|
|
283
|
+
// derived provider cache here would create a second checkout while reads
|
|
284
|
+
// and writes continue using the lock root.
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
298
287
|
const factory = resolveSourceProviderFactory(entry.type);
|
|
299
288
|
if (!factory)
|
|
300
289
|
continue;
|
|
@@ -315,7 +304,7 @@ export async function ensureSourceCaches(config, options) {
|
|
|
315
304
|
continue;
|
|
316
305
|
}
|
|
317
306
|
try {
|
|
318
|
-
await provider.sync({ force });
|
|
307
|
+
await provider.sync({ force, secrets: options?.secrets });
|
|
319
308
|
}
|
|
320
309
|
catch (err) {
|
|
321
310
|
warn(`Warning: failed to refresh ${provider.kind} source "${provider.name}": ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -355,5 +344,5 @@ function warnIfSourceUnavailableForRead(entry, providerName) {
|
|
|
355
344
|
if (dir && isMaterializedDir(dir))
|
|
356
345
|
return;
|
|
357
346
|
warn(`Warning: source "${providerName}" is not materialized locally; skipping it for this read. ` +
|
|
358
|
-
"Run `akm index` (or `akm
|
|
347
|
+
"Run `akm index` (or `akm bundle update`) to fetch it.");
|
|
359
348
|
}
|
|
@@ -1,14 +1,6 @@
|
|
|
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
|
-
* Usage event helpers for telemetry and utility-based re-ranking.
|
|
6
|
-
*
|
|
7
|
-
* Schema (created by ensureUsageEventsSchema):
|
|
8
|
-
* id, event_type, query, entry_id (nullable), entry_ref, signal, metadata, source, created_at
|
|
9
|
-
*/
|
|
10
|
-
import { stashDirFor } from "../../core/asset/asset-placement.js";
|
|
11
|
-
import { typeNameFromConceptId } from "../../core/asset/resolve-ref.js";
|
|
12
4
|
const USAGE_EVENT_SOURCES = new Set(["user", "improve", "task", "audit", "unknown"]);
|
|
13
5
|
/** Resolve subprocess provenance without treating an invalid value as user demand. */
|
|
14
6
|
export function resolveUsageEventSource(env = process.env) {
|
|
@@ -51,88 +43,7 @@ export function insertUsageEvent(db, event) {
|
|
|
51
43
|
/* fire-and-forget: silently ignore errors */
|
|
52
44
|
}
|
|
53
45
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Bare-form candidates a bare `entry_ref` filter matches a stored row under.
|
|
56
|
-
* The durable `usage_events.entry_ref` column straddles the F5 ref-grammar flip:
|
|
57
|
-
* F4c-indexed rows carry the new-grammar conceptId (`memories/alpha`) while
|
|
58
|
-
* transitional / not-yet-re-keyed rows still carry the legacy `type:name`
|
|
59
|
-
* (`memory:alpha`). Both name the SAME asset, so a bare filter in EITHER grammar
|
|
60
|
-
* must bridge to the other spelling — otherwise a history/telemetry query misses
|
|
61
|
-
* half the asset's own events across the flip boundary. (Fully-qualified filters
|
|
62
|
-
* apply this bridge under a fixed origin — see getUsageEvents.)
|
|
63
|
-
*/
|
|
64
|
-
function usageEventBareCandidates(ref) {
|
|
65
|
-
const trimmed = ref.trim();
|
|
66
|
-
const out = new Set([trimmed]);
|
|
67
|
-
// New-grammar conceptId (`memories/alpha`) → its legacy `type:name` sibling.
|
|
68
|
-
const legacy = typeNameFromConceptId(trimmed);
|
|
69
|
-
if (legacy)
|
|
70
|
-
out.add(`${legacy.type}:${legacy.name}`);
|
|
71
|
-
// Legacy `type:name` (`memory:alpha`) → its new-grammar `stashDir/name` sibling.
|
|
72
|
-
const colon = trimmed.indexOf(":");
|
|
73
|
-
if (colon > 0) {
|
|
74
|
-
const dir = stashDirFor(trimmed.slice(0, colon));
|
|
75
|
-
if (dir)
|
|
76
|
-
out.add(`${dir}/${trimmed.slice(colon + 1)}`);
|
|
77
|
-
}
|
|
78
|
-
return [...out];
|
|
79
|
-
}
|
|
80
46
|
// ── Query ────────────────────────────────────────────────────────────────────
|
|
81
|
-
/**
|
|
82
|
-
* Retrieve usage events, optionally filtered by event_type and/or entry_ref.
|
|
83
|
-
*/
|
|
84
|
-
export function getUsageEvents(db, filters) {
|
|
85
|
-
const conditions = [];
|
|
86
|
-
const params = [];
|
|
87
|
-
if (filters?.event_type) {
|
|
88
|
-
conditions.push("event_type = ?");
|
|
89
|
-
params.push(filters.event_type);
|
|
90
|
-
}
|
|
91
|
-
if (filters?.entry_ref) {
|
|
92
|
-
if (filters.entry_ref.includes("//")) {
|
|
93
|
-
// Fully-qualified filter (`bundle//conceptId` or legacy `origin//type:name`)
|
|
94
|
-
// — the user named a specific bundle/origin, so match that origin exactly,
|
|
95
|
-
// but bridge the bare tail across the F5 grammar flip (see
|
|
96
|
-
// usageEventBareCandidates) so a `stash//memories/alpha` filter also matches
|
|
97
|
-
// an un-re-keyed `stash//memory:alpha` row (and vice versa).
|
|
98
|
-
const boundary = filters.entry_ref.indexOf("//");
|
|
99
|
-
const origin = filters.entry_ref.slice(0, boundary);
|
|
100
|
-
const bareTail = filters.entry_ref.slice(boundary + 2);
|
|
101
|
-
const quals = usageEventBareCandidates(bareTail).map((bare) => `${origin}//${bare}`);
|
|
102
|
-
conditions.push(`entry_ref IN (${quals.map(() => "?").join(", ")})`);
|
|
103
|
-
params.push(...quals);
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
// Bare filter — match the stored bare form (everything after the first
|
|
107
|
-
// `//`, or the whole value when un-qualified) against the conceptId the
|
|
108
|
-
// filter normalizes to.
|
|
109
|
-
const candidates = usageEventBareCandidates(filters.entry_ref);
|
|
110
|
-
const placeholders = candidates.map(() => "?").join(", ");
|
|
111
|
-
conditions.push(`(CASE WHEN instr(entry_ref, '//') > 0 THEN substr(entry_ref, instr(entry_ref, '//') + 2) ELSE entry_ref END) ` +
|
|
112
|
-
`IN (${placeholders})`);
|
|
113
|
-
params.push(...candidates);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (filters?.source) {
|
|
117
|
-
if (filters.source === "unknown") {
|
|
118
|
-
conditions.push("(source = 'unknown' OR source IS NULL OR source = '')");
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
conditions.push("source = ?");
|
|
122
|
-
params.push(filters.source);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
if (filters?.since) {
|
|
126
|
-
conditions.push("created_at >= ?");
|
|
127
|
-
params.push(filters.since);
|
|
128
|
-
}
|
|
129
|
-
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
130
|
-
const sql = `SELECT id, event_type, query, entry_id, entry_ref, signal, metadata, source, created_at
|
|
131
|
-
FROM usage_events ${where}
|
|
132
|
-
ORDER BY id ASC`;
|
|
133
|
-
const rows = db.prepare(sql).all(...params);
|
|
134
|
-
return rows.map((row) => ({ ...row, source: row.source || "unknown" }));
|
|
135
|
-
}
|
|
136
47
|
/**
|
|
137
48
|
* Aggregate positive/negative feedback counts for a single entry.
|
|
138
49
|
*
|
|
@@ -107,11 +107,12 @@ export async function getAllRenderers() {
|
|
|
107
107
|
* Build a RenderContext by merging a FileContext with its winning MatchResult
|
|
108
108
|
* and the list of stash search paths.
|
|
109
109
|
*/
|
|
110
|
-
export function buildRenderContext(ctx, match, stashDirs, origin) {
|
|
110
|
+
export function buildRenderContext(ctx, match, stashDirs, origin, defaultBundle) {
|
|
111
111
|
return {
|
|
112
112
|
...ctx,
|
|
113
113
|
matchResult: match,
|
|
114
114
|
stashDirs,
|
|
115
115
|
origin,
|
|
116
|
+
defaultBundle,
|
|
116
117
|
};
|
|
117
118
|
}
|