akm-cli 0.9.0-rc.4 → 0.9.0-rc.6
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 +122 -26
- package/README.md +7 -7
- package/SECURITY.md +11 -10
- package/dist/akm +2 -2
- package/dist/akm-migrate-storage +2 -2
- package/dist/assets/hints/cli-hints-full.md +60 -73
- package/dist/assets/hints/cli-hints-short.md +8 -12
- package/dist/assets/improve-strategies/default.json +5 -7
- package/dist/assets/improve-strategies/frequent.json +2 -2
- package/dist/assets/improve-strategies/proactive-maintenance.json +2 -2
- package/dist/assets/improve-strategies/quick.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +3 -3
- package/dist/assets/improve-strategies/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +5 -5
- package/dist/assets/prompts/extract-session.md +2 -6
- package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
- package/dist/assets/prompts/reflect-output-repair.md +3 -0
- package/dist/assets/stash-skeleton/README.md +10 -11
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +1 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +1 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +1 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -2
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -2
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +1 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -2
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +1 -1
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +18 -18
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +8 -9
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +13 -15
- package/dist/assets/tasks/core/extract.yml +2 -2
- package/dist/assets/tasks/core/improve.yml +1 -1
- package/dist/assets/templates/html/health.html +2 -3
- package/dist/cli/config-migrate.js +1328 -101
- package/dist/cli/invocation.js +255 -0
- package/dist/cli/parse-args.js +20 -83
- package/dist/cli/shared.js +15 -37
- package/dist/cli.js +18 -49
- package/dist/commands/agent/agent-dispatch.js +2 -2
- package/dist/commands/agent/contribute-cli.js +5 -4
- package/dist/commands/bundle/bundle-cli.js +68 -0
- package/dist/commands/bundle/bundle.js +219 -0
- package/dist/commands/completions.js +2 -2
- package/dist/commands/config-cli.js +6 -3
- package/dist/commands/env/env-binding.js +13 -9
- package/dist/commands/env/env-cli.js +49 -48
- package/dist/commands/env/secret-cli.js +24 -10
- package/dist/commands/events.js +2 -2
- package/dist/commands/feedback-cli.js +59 -33
- package/dist/commands/graph/graph.js +6 -4
- package/dist/commands/health/advisories.js +4 -4
- package/dist/commands/health/html-report.js +190 -593
- package/dist/commands/health/improve-metrics.js +240 -188
- package/dist/commands/health/metrics.js +9 -17
- package/dist/commands/health/report-view-model.js +509 -0
- package/dist/commands/health/surfaces.js +6 -3
- package/dist/commands/health/types-checks.js +4 -0
- package/dist/commands/health/types-improve.js +22 -0
- package/dist/commands/health/types-metrics.js +4 -0
- package/dist/commands/health/types-result.js +7 -0
- package/dist/commands/health/types-runs.js +4 -0
- package/dist/commands/health/types-session-log.js +4 -0
- package/dist/commands/health/types-windows.js +4 -0
- package/dist/commands/health/types.js +26 -21
- package/dist/commands/health/windows.js +1 -2
- package/dist/commands/health.js +219 -161
- package/dist/commands/improve/collapse-detector.js +25 -14
- package/dist/commands/improve/consolidate/chunking.js +7 -5
- package/dist/commands/improve/consolidate.js +640 -740
- package/dist/commands/improve/content-hash.js +39 -0
- package/dist/commands/improve/distill/content-repair.js +4 -10
- package/dist/commands/improve/distill/promote-memory.js +79 -49
- package/dist/commands/improve/distill/quality-gate.js +113 -35
- package/dist/commands/improve/distill-promotion-policy.js +24 -885
- package/dist/commands/improve/distill.js +565 -337
- package/dist/commands/improve/eligibility.js +75 -36
- package/dist/commands/improve/extract-cli.js +6 -6
- package/dist/commands/improve/extract-prompt.js +5 -34
- package/dist/commands/improve/extract.js +526 -357
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +11 -20
- package/dist/commands/improve/improve-result-file.js +7 -6
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +3 -9
- package/dist/commands/improve/improve.js +822 -727
- package/dist/commands/improve/locks.js +27 -95
- package/dist/commands/improve/loop-stages.js +941 -963
- package/dist/commands/improve/memory/derived-ref.js +122 -0
- package/dist/commands/improve/memory/memory-contradiction-detect.js +35 -38
- package/dist/commands/improve/memory/memory-improve.js +24 -37
- package/dist/commands/improve/outcome-loop.js +13 -33
- package/dist/commands/improve/preparation.js +889 -691
- package/dist/commands/improve/proactive-maintenance.js +37 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +974 -588
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +8 -4
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -40
- package/dist/commands/improve/source-identity.js +39 -26
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +288 -295
- package/dist/commands/lint/index.js +132 -19
- package/dist/commands/mv-cli.js +257 -234
- package/dist/commands/observability-cli.js +2 -1
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +17 -16
- package/dist/commands/proposal/proposal-cli.js +40 -77
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +39 -1
- package/dist/commands/proposal/propose.js +41 -19
- package/dist/commands/proposal/repository.js +566 -486
- package/dist/commands/proposal/validators/proposal-quality-validators.js +22 -6
- package/dist/commands/proposal/validators/proposal-validators.js +6 -5
- package/dist/commands/proposal/validators/proposals.js +5 -4
- package/dist/commands/read/curate.js +50 -28
- package/dist/commands/read/knowledge.js +25 -16
- package/dist/commands/read/remember-cli.js +12 -4
- package/dist/commands/read/search-cli.js +33 -33
- package/dist/commands/read/search.js +68 -55
- package/dist/commands/read/show.js +54 -135
- package/dist/commands/remember.js +7 -5
- package/dist/commands/sources/add-cli.js +10 -24
- package/dist/commands/sources/bundle-config-ops.js +58 -0
- package/dist/commands/sources/history.js +13 -8
- package/dist/commands/sources/info.js +10 -11
- package/dist/commands/sources/init.js +12 -21
- package/dist/commands/sources/installed-stashes.js +151 -138
- package/dist/commands/sources/schema-repair.js +5 -3
- package/dist/commands/sources/self-update.js +9 -7
- package/dist/commands/sources/source-add.js +116 -154
- package/dist/commands/sources/source-clone.js +33 -14
- package/dist/commands/sources/source-manage.js +43 -32
- package/dist/commands/sources/sources-cli.js +12 -7
- package/dist/commands/sources/stash-cli.js +12 -5
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/default-tasks.js +13 -13
- package/dist/commands/tasks/tasks-cli.js +3 -3
- package/dist/commands/tasks/tasks.js +71 -31
- package/dist/commands/workflow-cli.js +22 -26
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/activation-policy.js +49 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
- package/dist/core/adapter/adapters/akm-adapter.js +509 -0
- package/dist/core/adapter/adapters/akm-lint.js +381 -0
- package/dist/core/adapter/adapters/akm-metadata.js +416 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +150 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +196 -0
- package/dist/core/adapter/adapters/claude-adapter.js +61 -0
- package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
- package/dist/core/adapter/adapters/generic-files-adapter.js +117 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +413 -0
- package/dist/core/adapter/adapters/okf-adapter.js +223 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
- package/dist/core/adapter/adapters/shared.js +286 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +212 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +154 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/recognize-match.js +42 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/asset-placement.js +229 -0
- package/dist/core/asset/asset-ref.js +107 -78
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +1 -1
- package/dist/core/asset/resolve-ref.js +223 -0
- package/dist/core/asset/stash-meta.js +1 -1
- package/dist/core/common.js +141 -49
- package/dist/core/config/config-io.js +0 -108
- package/dist/core/config/config-schema.js +94 -1039
- package/dist/core/config/config-sources.js +115 -36
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-walker.js +4 -2
- package/dist/core/config/config.js +21 -26
- package/dist/core/config/engine-semantics.js +0 -4
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +395 -0
- package/dist/core/config/schema/improve.js +76 -0
- package/dist/core/config/schema/index-config.js +183 -0
- package/dist/core/config/schema/output.js +15 -0
- package/dist/core/config/schema/primitives.js +94 -0
- package/dist/core/config/schema/search.js +30 -0
- package/dist/core/config/schema/setup.js +27 -0
- package/dist/core/config/schema/sources-bundles.js +164 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +113 -8
- package/dist/core/errors.js +1 -1
- package/dist/core/events-types.js +4 -0
- package/dist/core/extra-params.js +1 -0
- package/dist/core/file-change.js +16 -0
- package/dist/core/fs-txn.js +316 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +9 -1
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +16 -0
- package/dist/core/migration-backup.js +332 -160
- package/dist/core/paths.js +3 -6
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +130 -0
- package/dist/core/redaction.js +2 -2
- package/dist/core/standards/resolve-standards-context.js +47 -64
- package/dist/core/standards/resolve-type-conventions.js +3 -3
- package/dist/core/state/migrations.js +201 -8
- package/dist/core/state-db.js +38 -2
- package/dist/core/subprocess.js +303 -0
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/write-source.js +39 -67
- package/dist/indexer/bundle-identity-guard.js +91 -0
- package/dist/indexer/db/graph-db.js +1 -1
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +29 -9
- package/dist/indexer/graph/graph-boost.js +28 -24
- package/dist/indexer/graph/graph-extraction.js +5 -6
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-written-assets.js +44 -17
- package/dist/indexer/indexer.js +289 -153
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +224 -0
- package/dist/indexer/passes/dir-staleness.js +2 -1
- package/dist/indexer/passes/memory-inference.js +8 -4
- package/dist/indexer/passes/metadata.js +96 -243
- package/dist/indexer/scan/doc-to-entry.js +123 -0
- package/dist/indexer/scan/drain-dir.js +144 -0
- package/dist/indexer/search/db-search.js +171 -99
- package/dist/indexer/search/fts-query.js +1 -1
- package/dist/indexer/search/ranking-contributors.js +57 -7
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +31 -6
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +109 -52
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/unmigrated-vaults-guard.js +2 -1
- package/dist/indexer/usage/usage-events.js +72 -9
- package/dist/indexer/walk/file-context.js +1 -44
- package/dist/indexer/walk/matchers.js +16 -32
- package/dist/indexer/walk/path-resolver.js +6 -5
- package/dist/indexer/walk/walker.js +4 -2
- package/dist/integrations/agent/engine-resolution.js +22 -0
- package/dist/integrations/agent/model-aliases.js +1 -1
- package/dist/integrations/agent/prompts.js +35 -11
- package/dist/integrations/agent/spawn.js +41 -270
- package/dist/integrations/harnesses/aider/agent-builder.js +2 -2
- package/dist/integrations/harnesses/aider/index.js +2 -11
- package/dist/integrations/harnesses/amazonq/agent-builder.js +1 -9
- package/dist/integrations/harnesses/amazonq/index.js +3 -16
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +1 -12
- package/dist/integrations/harnesses/claude/session-log.js +27 -65
- package/dist/integrations/harnesses/codex/agent-builder.js +1 -2
- package/dist/integrations/harnesses/codex/index.js +2 -12
- package/dist/integrations/harnesses/copilot/agent-builder.js +2 -3
- package/dist/integrations/harnesses/copilot/index.js +1 -12
- package/dist/integrations/harnesses/gemini/agent-builder.js +1 -3
- package/dist/integrations/harnesses/gemini/index.js +1 -12
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +27 -2
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +1 -12
- package/dist/integrations/harnesses/opencode/session-log.js +67 -110
- package/dist/integrations/harnesses/opencode-sdk/harness.js +2 -11
- package/dist/integrations/harnesses/openhands/agent-builder.js +3 -3
- package/dist/integrations/harnesses/openhands/index.js +2 -11
- package/dist/integrations/harnesses/pi/agent-builder.js +3 -11
- package/dist/integrations/harnesses/pi/index.js +3 -15
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +37 -2
- package/dist/integrations/lockfile.js +36 -0
- package/dist/integrations/session-logs/index.js +21 -12
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +7 -5
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +8 -4
- package/dist/llm/graph-extract.js +7 -2
- package/dist/llm/metadata-enhance.js +43 -26
- package/dist/llm/structured-call.js +15 -7
- package/dist/migrate/legacy/config-source-migration.js +223 -0
- package/dist/migrate/legacy/content-migration.js +305 -0
- package/dist/migrate/legacy/legacy-layout.js +779 -0
- package/dist/migrate/legacy/legacy-paths.js +25 -0
- package/dist/migrate/legacy/legacy-stash-json.js +72 -0
- package/dist/migrate/legacy/proposal-fs-import.js +168 -0
- package/dist/migrate/legacy/task-target-ref-migration.js +272 -0
- package/dist/migrate/legacy/three-db-cutover.js +840 -0
- package/dist/migrate/legacy/workflow-migrations-bodies.js +52 -0
- package/dist/migrate/legacy/workflow-migrations-frozen.js +21 -0
- package/dist/migrate/legacy-ref-grammar.js +209 -0
- package/dist/output/command-registry.js +27 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/renderers.js +32 -276
- package/dist/output/shapes/passthrough.js +3 -9
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/text/command-format.js +547 -0
- package/dist/output/text/helpers.js +15 -1377
- package/dist/output/text/proposal-format.js +230 -0
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +107 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/workflow-format.js +345 -0
- package/dist/output/text.js +1 -3
- package/dist/registry/build-index.js +13 -17
- package/dist/registry/providers/static-index.js +2 -2
- package/dist/registry/resolve.js +4 -90
- package/dist/registry/semver.js +93 -0
- package/dist/runtime.js +90 -0
- package/dist/schemas/akm-config.json +2956 -14890
- package/dist/schemas/akm-task.json +2 -2
- package/dist/schemas/akm-workflow.json +2 -2
- package/dist/scripts/migrate-storage.js +2312 -19642
- package/dist/setup/detect.js +5 -7
- package/dist/setup/engine-config.js +2 -1
- package/dist/setup/registry-stash-loader.js +1 -1
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +109 -39
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +50 -274
- package/dist/setup/steps/platforms.js +1 -0
- package/dist/setup/steps/sources.js +13 -6
- package/dist/setup/steps/stashdir.js +5 -2
- package/dist/sources/freshness.js +39 -0
- package/dist/sources/providers/git-provider.js +29 -33
- package/dist/sources/providers/git-stash.js +10 -5
- package/dist/sources/providers/provider-utils.js +40 -18
- package/dist/sources/providers/website.js +1 -1
- package/dist/sources/resolve.js +5 -5
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +105 -39
- package/dist/storage/database.js +47 -3
- package/dist/storage/engines/sqlite-migrations.js +34 -16
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/improve-runs-repository.js +0 -20
- package/dist/storage/repositories/index-connection.js +80 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +952 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +15 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +164 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +109 -0
- package/dist/storage/repositories/index-meta-repository.js +50 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +241 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +369 -0
- package/dist/storage/repositories/index-vec-repository.js +245 -0
- package/dist/storage/repositories/proposals-repository.js +41 -50
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/workflow-runs-repository.js +17 -11
- package/dist/tasks/backends/cron.js +5 -5
- package/dist/tasks/backends/exec-utils.js +21 -0
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +16 -17
- package/dist/tasks/backends/schtasks.js +33 -41
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/parser.js +25 -5
- package/dist/tasks/runner.js +33 -39
- package/dist/tasks/validator.js +5 -6
- package/dist/workflows/authoring/authoring.js +8 -11
- package/dist/workflows/exec/brief.js +10 -7
- package/dist/workflows/exec/report.js +261 -156
- package/dist/workflows/exec/run-workflow.js +2 -1
- package/dist/workflows/exec/step-work.js +3 -9
- package/dist/workflows/program/parser.js +4 -60
- package/dist/workflows/renderer.js +11 -60
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +7 -4
- package/dist/workflows/runtime/runs.js +11 -10
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +27 -16
- package/dist/workflows/validate-summary.js +2 -2
- package/dist/workflows/validator.js +18 -2
- package/docs/migration/release-notes/0.9.0.md +45 -3
- package/docs/migration/v0.8-to-v0.9.md +466 -262
- package/docs/{data-and-telemetry.md → reference/data-and-telemetry.md} +61 -17
- package/package.json +10 -9
- package/schemas/akm-config.json +2956 -14890
- package/schemas/akm-task.json +2 -2
- package/schemas/akm-workflow.json +2 -2
- package/dist/assets/help/help-accept.md +0 -12
- package/dist/assets/help/help-improve.md +0 -84
- package/dist/assets/help/help-proposals.md +0 -17
- package/dist/assets/help/help-propose.md +0 -17
- package/dist/assets/help/help-reject.md +0 -11
- package/dist/assets/improve-strategies/recombine-only.json +0 -23
- package/dist/assets/improve-strategies/synthesize.json +0 -17
- package/dist/assets/prompts/procedural-system.md +0 -44
- package/dist/assets/prompts/recombine-system.md +0 -40
- package/dist/assets/prompts/staleness-detect-system.md +0 -6
- package/dist/assets/templates/html/default.html +0 -78
- package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
- package/dist/assets/wiki/index-template.md +0 -12
- package/dist/assets/wiki/ingest-workflow-template.md +0 -83
- package/dist/assets/wiki/log-template.md +0 -8
- package/dist/assets/wiki/schema-template.md +0 -61
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -262
- package/dist/commands/improve/procedural.js +0 -403
- package/dist/commands/improve/recombine.js +0 -843
- package/dist/commands/improve/schema-similarity-gate.js +0 -168
- package/dist/commands/lint/agent-linter.js +0 -44
- package/dist/commands/lint/command-linter.js +0 -44
- package/dist/commands/lint/default-linter.js +0 -16
- package/dist/commands/lint/fact-linter.js +0 -39
- package/dist/commands/lint/knowledge-linter.js +0 -16
- package/dist/commands/lint/memory-linter.js +0 -61
- package/dist/commands/lint/registry.js +0 -41
- package/dist/commands/lint/skill-linter.js +0 -45
- package/dist/commands/lint/task-linter.js +0 -50
- package/dist/commands/lint/workflow-linter.js +0 -81
- package/dist/commands/proposal/legacy-import.js +0 -115
- package/dist/commands/wiki-cli.js +0 -291
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -316
- package/dist/core/eval/rank-metrics.js +0 -113
- package/dist/core/ripgrep/install.js +0 -163
- package/dist/core/ripgrep/resolve.js +0 -81
- package/dist/indexer/db/db.js +0 -1585
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
- package/dist/output/text/wiki.js +0 -16
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -18228
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/storage/repositories/consolidation-repository.js +0 -38
- package/dist/storage/repositories/recombine-repository.js +0 -213
- package/dist/wiki/wiki-templates.js +0 -15
- package/dist/wiki/wiki.js +0 -1013
- package/dist/workflows/db.js +0 -413
- package/docs/README.md +0 -103
- package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
|
@@ -11,18 +11,20 @@
|
|
|
11
11
|
* a registry search behind `--source registry|both`, and log a usage event.
|
|
12
12
|
* Provider `search()` methods do not exist.
|
|
13
13
|
*/
|
|
14
|
-
import {
|
|
15
|
-
import { loadConfig } from "../../core/config/config.js";
|
|
14
|
+
import { getSources, loadConfig } from "../../core/config/config.js";
|
|
16
15
|
import { rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
|
|
17
16
|
import { appendEvent } from "../../core/events.js";
|
|
18
17
|
import { isTransientStashPath } from "../../core/paths.js";
|
|
19
|
-
import { bumpUtilityScoresBatch, getEntryIdByFilePath } from "../../indexer/db/db.js";
|
|
20
18
|
import { resolveReadSources } from "../../indexer/read-preflight.js";
|
|
21
19
|
import { searchLocal } from "../../indexer/search/db-search.js";
|
|
20
|
+
import { getSearchHitAttribution, usageEventAttributionMetadata, } from "../../indexer/search/search-attribution.js";
|
|
21
|
+
import { getEntryIdByFilePath, getItemRefById } from "../../storage/repositories/index-entries-repository.js";
|
|
22
|
+
import { bumpUtilityScoresBatch } from "../../storage/repositories/index-utility-repository.js";
|
|
22
23
|
import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
|
|
23
24
|
// Eagerly import source providers to trigger self-registration before the
|
|
24
25
|
// indexer or path-resolution code runs.
|
|
25
26
|
import "../../sources/providers/index.js";
|
|
27
|
+
import { withStateDbTelemetry } from "../../core/state-db.js";
|
|
26
28
|
import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
|
|
27
29
|
import { TELEMETRY_BUSY_TIMEOUT_MS, withIndexDb } from "../../storage/repositories/index-db.js";
|
|
28
30
|
import { searchRegistry } from "./registry-search.js";
|
|
@@ -36,23 +38,14 @@ export async function akmSearch(input) {
|
|
|
36
38
|
const parsedSource = parseSearchSource(input.source ?? "stash");
|
|
37
39
|
const config = loadConfig();
|
|
38
40
|
// Named-source filter: when --source is not a standard enum value, treat it
|
|
39
|
-
// as a named source
|
|
41
|
+
// as a named source (a `bundles` key). Validated early (before
|
|
40
42
|
// resolveSourceEntries, which can throw STASH_DIR_NOT_FOUND) so that a bad
|
|
41
43
|
// --source name always produces INVALID_SOURCE_VALUE regardless of stash state.
|
|
42
44
|
let namedSourceName;
|
|
43
45
|
let source;
|
|
44
46
|
if (parsedSource !== "stash" && parsedSource !== "registry" && parsedSource !== "both") {
|
|
45
47
|
namedSourceName = parsedSource;
|
|
46
|
-
|
|
47
|
-
const configSources = config.sources ?? [];
|
|
48
|
-
const foundInConfig = configSources.some((s) => s.name === namedSourceName) || configSources.some((s) => s.path === namedSourceName);
|
|
49
|
-
if (!foundInConfig) {
|
|
50
|
-
const validNames = configSources.map((s) => s.name).filter((n) => Boolean(n));
|
|
51
|
-
const hint = validNames.length > 0
|
|
52
|
-
? `Known source names: ${validNames.join(", ")}`
|
|
53
|
-
: "No named sources are configured. Run `akm list` to see installed stashes.";
|
|
54
|
-
throw new UsageError(`Unknown source name: "${namedSourceName}". ${hint}`, "INVALID_SOURCE_VALUE");
|
|
55
|
-
}
|
|
48
|
+
assertNamedSourceExists(config, namedSourceName);
|
|
56
49
|
source = "stash";
|
|
57
50
|
}
|
|
58
51
|
else {
|
|
@@ -79,8 +72,7 @@ export async function akmSearch(input) {
|
|
|
79
72
|
warnings: ["No stashes configured. Run `akm init` to create your working stash."],
|
|
80
73
|
timing: { totalMs: Date.now() - t0 },
|
|
81
74
|
};
|
|
82
|
-
|
|
83
|
-
logSearchEvent(query, response, undefined, input.eventSource);
|
|
75
|
+
maybeLogSearchEvent(input, query, response);
|
|
84
76
|
return response;
|
|
85
77
|
}
|
|
86
78
|
// Primary stash directory — used for DB path lookups and as the default
|
|
@@ -126,9 +118,7 @@ export async function akmSearch(input) {
|
|
|
126
118
|
warnings: localResult?.warnings?.length ? localResult.warnings : undefined,
|
|
127
119
|
timing: { totalMs: Date.now() - t0, rankMs: localResult?.rankMs, embedMs: localResult?.embedMs },
|
|
128
120
|
};
|
|
129
|
-
|
|
130
|
-
logSearchEvent(query, response, localResult?.mode ?? "keyword", input.eventSource, input.disableScopedUtility === true);
|
|
131
|
-
}
|
|
121
|
+
maybeLogSearchEvent(input, query, response, localResult?.mode ?? "keyword");
|
|
132
122
|
return response;
|
|
133
123
|
}
|
|
134
124
|
const registryHits = (registryResult?.hits ?? []).map((hit) => {
|
|
@@ -162,8 +152,7 @@ export async function akmSearch(input) {
|
|
|
162
152
|
warnings: registryResult?.warnings.length ? registryResult.warnings : undefined,
|
|
163
153
|
timing: { totalMs: Date.now() - t0 },
|
|
164
154
|
};
|
|
165
|
-
|
|
166
|
-
logSearchEvent(query, response, undefined, input.eventSource, input.disableScopedUtility === true);
|
|
155
|
+
maybeLogSearchEvent(input, query, response);
|
|
167
156
|
return response;
|
|
168
157
|
}
|
|
169
158
|
// source === "both"
|
|
@@ -180,10 +169,14 @@ export async function akmSearch(input) {
|
|
|
180
169
|
warnings: warnings.length ? warnings : undefined,
|
|
181
170
|
timing: { totalMs: Date.now() - t0 },
|
|
182
171
|
};
|
|
183
|
-
|
|
184
|
-
logSearchEvent(query, response, undefined, input.eventSource, input.disableScopedUtility === true);
|
|
172
|
+
maybeLogSearchEvent(input, query, response);
|
|
185
173
|
return response;
|
|
186
174
|
}
|
|
175
|
+
function maybeLogSearchEvent(input, query, response, mode) {
|
|
176
|
+
if (input.skipLogging)
|
|
177
|
+
return;
|
|
178
|
+
logSearchEvent(query, response, mode, input.eventSource, input.disableScopedUtility === true, input.attributionProjection);
|
|
179
|
+
}
|
|
187
180
|
/**
|
|
188
181
|
* Resolve entry IDs by file_path lookup (exact match, not LIKE).
|
|
189
182
|
*/
|
|
@@ -193,9 +186,13 @@ function resolveEntryIds(db, hits) {
|
|
|
193
186
|
try {
|
|
194
187
|
const entryId = getEntryIdByFilePath(db, hit.path);
|
|
195
188
|
if (entryId !== undefined) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
189
|
+
// F4c: persist the DURABLE fully-qualified `bundle//conceptId` spelling,
|
|
190
|
+
// derived from the resolved entry row's `item_ref` (D-R3: durable keys
|
|
191
|
+
// come from the resolved item, never raw input).
|
|
192
|
+
const itemRef = getItemRefById(db, entryId);
|
|
193
|
+
if (itemRef !== null) {
|
|
194
|
+
results.push({ entryId, ref: itemRef, hit });
|
|
195
|
+
}
|
|
199
196
|
}
|
|
200
197
|
}
|
|
201
198
|
catch {
|
|
@@ -219,7 +216,7 @@ function resolveEntryIds(db, hits) {
|
|
|
219
216
|
* Per-entry events are recorded only for stash hits because registry hits
|
|
220
217
|
* have no local entry_id to reference.
|
|
221
218
|
*/
|
|
222
|
-
function logSearchEvent(query, response, mode = "keyword", eventSource = "user", disableScopedUtility = false) {
|
|
219
|
+
function logSearchEvent(query, response, mode = "keyword", eventSource = "user", disableScopedUtility = false, attributionProjection = "full") {
|
|
223
220
|
// Emit a structured event to events.jsonl so workflow-trace consumers
|
|
224
221
|
// detect akm search invocations without relying on stdout scraping.
|
|
225
222
|
const stashHits = response.hits.filter((h) => h.type !== "registry");
|
|
@@ -236,21 +233,42 @@ function logSearchEvent(query, response, mode = "keyword", eventSource = "user",
|
|
|
236
233
|
// Under contention these usage hints are skipped, not waited for.
|
|
237
234
|
withIndexDb((db) => {
|
|
238
235
|
const resolved = resolveEntryIds(db, stashHits.slice(0, 50));
|
|
239
|
-
|
|
240
|
-
|
|
236
|
+
// usage_events telemetry now writes to state.db (Chunk-8 WI-8.3);
|
|
237
|
+
// entry_id/entry_ref are resolved from index.db above and carried across.
|
|
238
|
+
const stashHitCount = response.hits.length;
|
|
239
|
+
const registryHitCount = Array.isArray(response.registryHits) ? response.registryHits.length : 0;
|
|
240
|
+
withStateDbTelemetry((stateDb) => {
|
|
241
|
+
for (const { entryId, ref, hit } of resolved) {
|
|
242
|
+
insertUsageEvent(stateDb, {
|
|
243
|
+
event_type: "search",
|
|
244
|
+
query,
|
|
245
|
+
entry_id: entryId,
|
|
246
|
+
entry_ref: ref,
|
|
247
|
+
metadata: usageEventAttributionMetadata(getSearchHitAttribution(hit), ref, attributionProjection),
|
|
248
|
+
source: eventSource,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
// Count registry hits separately so registry-only searches record a
|
|
252
|
+
// non-zero resultCount. response.hits is always [] when source="registry".
|
|
253
|
+
insertUsageEvent(stateDb, {
|
|
241
254
|
event_type: "search",
|
|
242
255
|
query,
|
|
243
|
-
|
|
244
|
-
|
|
256
|
+
metadata: JSON.stringify({
|
|
257
|
+
resultCount: stashHitCount + registryHitCount,
|
|
258
|
+
stashHitCount,
|
|
259
|
+
registryHitCount,
|
|
260
|
+
resolvedCount: resolved.length,
|
|
261
|
+
mode,
|
|
262
|
+
}),
|
|
245
263
|
source: eventSource,
|
|
246
264
|
});
|
|
247
|
-
}
|
|
265
|
+
}, TELEMETRY_BUSY_TIMEOUT_MS);
|
|
248
266
|
// Bump utility scores for all resolved entries (MemRL retrieval signal).
|
|
249
267
|
// The indexer overwrites these at next reindex; bumps are temporary hints.
|
|
250
268
|
// Gated to user-sourced events: pipeline searches (improve probes, task
|
|
251
269
|
// runner) must not feed the utility signal (meta-review 05 DRIFT-6 —
|
|
252
270
|
// the bump previously fired unconditionally, so even correctly-tagged
|
|
253
|
-
// machine traffic inflated utility).
|
|
271
|
+
// machine traffic inflated utility). utility_scores stays in index.db.
|
|
254
272
|
const resolvedIds = eventSource === "user" ? resolved.map((r) => r.entryId).filter((id) => id !== undefined) : [];
|
|
255
273
|
if (resolvedIds.length > 0) {
|
|
256
274
|
let scopeKey;
|
|
@@ -264,22 +282,6 @@ function logSearchEvent(query, response, mode = "keyword", eventSource = "user",
|
|
|
264
282
|
}
|
|
265
283
|
bumpUtilityScoresBatch(db, resolvedIds, 1.0, 0.1, scopeKey);
|
|
266
284
|
}
|
|
267
|
-
// Count registry hits separately so registry-only searches record a
|
|
268
|
-
// non-zero resultCount. response.hits is always [] when source="registry".
|
|
269
|
-
const stashHitCount = response.hits.length;
|
|
270
|
-
const registryHitCount = Array.isArray(response.registryHits) ? response.registryHits.length : 0;
|
|
271
|
-
insertUsageEvent(db, {
|
|
272
|
-
event_type: "search",
|
|
273
|
-
query,
|
|
274
|
-
metadata: JSON.stringify({
|
|
275
|
-
resultCount: stashHitCount + registryHitCount,
|
|
276
|
-
stashHitCount,
|
|
277
|
-
registryHitCount,
|
|
278
|
-
resolvedCount: resolved.length,
|
|
279
|
-
mode,
|
|
280
|
-
}),
|
|
281
|
-
source: eventSource,
|
|
282
|
-
});
|
|
283
285
|
}, { busyTimeoutMs: TELEMETRY_BUSY_TIMEOUT_MS });
|
|
284
286
|
}
|
|
285
287
|
catch (err) {
|
|
@@ -288,6 +290,23 @@ function logSearchEvent(query, response, mode = "keyword", eventSource = "user",
|
|
|
288
290
|
}
|
|
289
291
|
}
|
|
290
292
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
293
|
+
/**
|
|
294
|
+
* Validate a named `--source` against the bundle-derived source list (0.9.0
|
|
295
|
+
* spec §10.1: a named source is a `bundles` key, matched via its derived
|
|
296
|
+
* source entry's `name`, or an exact path). Throws INVALID_SOURCE_VALUE with
|
|
297
|
+
* the known names before any stash access can fail differently.
|
|
298
|
+
*/
|
|
299
|
+
function assertNamedSourceExists(config, namedSourceName) {
|
|
300
|
+
const configSources = getSources(config);
|
|
301
|
+
const foundInConfig = configSources.some((s) => s.name === namedSourceName) || configSources.some((s) => s.path === namedSourceName);
|
|
302
|
+
if (!foundInConfig) {
|
|
303
|
+
const validNames = configSources.map((s) => s.name).filter((n) => Boolean(n));
|
|
304
|
+
const hint = validNames.length > 0
|
|
305
|
+
? `Known source names: ${validNames.join(", ")}`
|
|
306
|
+
: "No named sources are configured. Run `akm list` to see installed stashes.";
|
|
307
|
+
throw new UsageError(`Unknown source name: "${namedSourceName}". ${hint}`, "INVALID_SOURCE_VALUE");
|
|
308
|
+
}
|
|
309
|
+
}
|
|
291
310
|
function normalizeLimit(limit) {
|
|
292
311
|
if (typeof limit !== "number" || Number.isNaN(limit) || limit <= 0) {
|
|
293
312
|
return DEFAULT_LIMIT;
|
|
@@ -399,9 +418,3 @@ export function entryMatchesScopeFilters(scope, filters) {
|
|
|
399
418
|
}
|
|
400
419
|
return true;
|
|
401
420
|
}
|
|
402
|
-
/**
|
|
403
|
-
* Merge stash hits and registry hits via simple concatenation.
|
|
404
|
-
*/
|
|
405
|
-
export function mergeSearchHits(localHits, registryHits, limit) {
|
|
406
|
-
return [...localHits, ...registryHits].slice(0, limit);
|
|
407
|
-
}
|
|
@@ -8,100 +8,45 @@
|
|
|
8
8
|
*
|
|
9
9
|
* show(ref) → indexer.lookup(ref) → readFile(entry.filePath)
|
|
10
10
|
*
|
|
11
|
-
* The richer presentation logic (matchers, renderers,
|
|
12
|
-
*
|
|
11
|
+
* The richer presentation logic (matchers, renderers, edit-hints,
|
|
12
|
+
* summary-detail truncation) lives below in this file. The flow:
|
|
13
13
|
*
|
|
14
|
-
* 1.
|
|
15
|
-
* 2.
|
|
16
|
-
* 3.
|
|
17
|
-
* 4. Render the file via the matcher/renderer pipeline.
|
|
14
|
+
* 1. Auto-index when stale so the index is current.
|
|
15
|
+
* 2. Ask `indexer.lookup(ref)` for the row in the FTS index.
|
|
16
|
+
* 3. Render the file via the matcher/renderer pipeline.
|
|
18
17
|
*/
|
|
19
18
|
import fs from "node:fs";
|
|
20
|
-
import path from "node:path";
|
|
21
19
|
import { findCittyTopLevelCommandIndex } from "../../cli/parse-args.js";
|
|
22
|
-
import {
|
|
20
|
+
import { recognizeMatch } from "../../core/adapter/recognize-match.js";
|
|
23
21
|
import { parseFrontmatter } from "../../core/asset/frontmatter.js";
|
|
22
|
+
import { displayRef, parseQualifiedRefInput } from "../../core/asset/resolve-ref.js";
|
|
24
23
|
import { META_DIR, parseMetaRef, resolveMetaFilePath } from "../../core/asset/stash-meta.js";
|
|
25
24
|
import { asNonEmptyString } from "../../core/common.js";
|
|
26
25
|
import { getIndexPassConfig, loadConfig } from "../../core/config/config.js";
|
|
27
26
|
import { NotFoundError, rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
|
|
28
27
|
import { appendEvent, readEvents } from "../../core/events.js";
|
|
29
|
-
import {
|
|
28
|
+
import { withStateDbTelemetry } from "../../core/state-db.js";
|
|
30
29
|
import { hasGraphData } from "../../indexer/db/graph-db.js";
|
|
31
30
|
import { listRelatedPathsForFile } from "../../indexer/graph/graph-boost.js";
|
|
32
31
|
import { extractGraphForSingleFile } from "../../indexer/graph/graph-extraction.js";
|
|
33
32
|
import { lookup } from "../../indexer/indexer.js";
|
|
34
33
|
import { ensurePrimaryIndexForRead, resolveReadSources } from "../../indexer/read-preflight.js";
|
|
34
|
+
import { usageEventAttributionMetadata } from "../../indexer/search/search-attribution.js";
|
|
35
35
|
import { buildEditHint, findSourceForPath, isEditable, resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
36
36
|
import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
|
|
37
|
-
import { buildFileContext, buildRenderContext, getRenderer
|
|
37
|
+
import { buildFileContext, buildRenderContext, getRenderer } from "../../indexer/walk/file-context.js";
|
|
38
38
|
import { resolveAssetPath } from "../../indexer/walk/path-resolver.js";
|
|
39
39
|
import { resolveIndexPassLLM } from "../../llm/index-passes.js";
|
|
40
40
|
import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
|
|
41
41
|
import { resolveStorageLocations } from "../../storage/locations.js";
|
|
42
|
+
import { closeDatabase, openExistingDatabase } from "../../storage/repositories/index-connection.js";
|
|
42
43
|
import { TELEMETRY_BUSY_TIMEOUT_MS, withIndexDb } from "../../storage/repositories/index-db.js";
|
|
44
|
+
import { findEntryIdByRef, getEntryById, getEntryIdByFilePath, getItemRefById, } from "../../storage/repositories/index-entries-repository.js";
|
|
45
|
+
import { computeBodyHash } from "../../storage/repositories/index-llm-cache-repository.js";
|
|
43
46
|
// Eagerly import source providers to trigger self-registration.
|
|
44
47
|
import "../../sources/providers/index.js";
|
|
45
48
|
import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
|
|
46
49
|
import { getActiveWorkflowRun } from "../../workflows/runtime/runs.js";
|
|
47
|
-
/**
|
|
48
|
-
* Show a wiki root (no page path) — returns the same payload as
|
|
49
|
-
* `akm wiki show <name>`.
|
|
50
|
-
*/
|
|
51
|
-
async function showWikiRoot(stashDir, wikiName) {
|
|
52
|
-
const { showWiki } = await import("../../wiki/wiki.js");
|
|
53
|
-
const result = showWiki(stashDir, wikiName);
|
|
54
|
-
return {
|
|
55
|
-
type: "wiki",
|
|
56
|
-
name: result.ref,
|
|
57
|
-
path: result.path,
|
|
58
|
-
...(result.description ? { description: result.description } : {}),
|
|
59
|
-
origin: null,
|
|
60
|
-
editable: false,
|
|
61
|
-
pages: result.pages,
|
|
62
|
-
raws: result.raws,
|
|
63
|
-
...(result.lastModified ? { lastModified: result.lastModified } : {}),
|
|
64
|
-
recentLog: result.recentLog,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
async function showWikiRootForSource(stashDir, source, wikiName) {
|
|
68
|
-
const { showWikiAtPath } = await import("../../wiki/wiki.js");
|
|
69
|
-
if (source.wikiName === wikiName) {
|
|
70
|
-
const result = showWikiAtPath(wikiName, source.path);
|
|
71
|
-
return {
|
|
72
|
-
type: "wiki",
|
|
73
|
-
name: result.ref,
|
|
74
|
-
path: result.path,
|
|
75
|
-
...(result.description ? { description: result.description } : {}),
|
|
76
|
-
origin: null,
|
|
77
|
-
editable: false,
|
|
78
|
-
pages: result.pages,
|
|
79
|
-
raws: result.raws,
|
|
80
|
-
...(result.lastModified ? { lastModified: result.lastModified } : {}),
|
|
81
|
-
recentLog: result.recentLog,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
return showWikiRoot(stashDir, wikiName);
|
|
85
|
-
}
|
|
86
|
-
function resolveRegisteredWikiAssetPath(wikiRoot, wikiName, assetName) {
|
|
87
|
-
const pageName = assetName === wikiName ? "" : assetName.slice(wikiName.length + 1);
|
|
88
|
-
if (!pageName) {
|
|
89
|
-
throw new NotFoundError(`Wiki page not found: wiki:${assetName}`);
|
|
90
|
-
}
|
|
91
|
-
const candidate = path.resolve(wikiRoot, `${pageName}.md`);
|
|
92
|
-
const resolvedRoot = fs.realpathSync(wikiRoot);
|
|
93
|
-
if (!candidate.startsWith(resolvedRoot + path.sep)) {
|
|
94
|
-
throw new UsageError("Ref resolves outside the stash root.", "PATH_ESCAPE_VIOLATION");
|
|
95
|
-
}
|
|
96
|
-
if (!fs.existsSync(candidate) || !fs.statSync(candidate).isFile()) {
|
|
97
|
-
throw new NotFoundError(`Stash asset not found for ref: wiki:${assetName}`);
|
|
98
|
-
}
|
|
99
|
-
const realTarget = fs.realpathSync(candidate);
|
|
100
|
-
if (!realTarget.startsWith(resolvedRoot + path.sep)) {
|
|
101
|
-
throw new UsageError("Ref resolves outside the stash root.", "PATH_ESCAPE_VIOLATION");
|
|
102
|
-
}
|
|
103
|
-
return realTarget;
|
|
104
|
-
}
|
|
105
50
|
/**
|
|
106
51
|
* Unified show: queries the local FTS5 index, then falls back to on-disk
|
|
107
52
|
* type-dir resolution if the index has no row. Spec §6.2; no remote provider
|
|
@@ -122,30 +67,6 @@ export async function akmShowUnified(input) {
|
|
|
122
67
|
if (metaRef)
|
|
123
68
|
return showStashMeta(metaRef);
|
|
124
69
|
}
|
|
125
|
-
// 0. Wiki-root shortcut: `wiki:<name>` with no page path routes to the
|
|
126
|
-
// wiki summary (same payload as `akm wiki show <name>`). Honour
|
|
127
|
-
// `parsed.origin` by resolving against the matching stash source(s),
|
|
128
|
-
// falling back to the primary stash when no origin is given.
|
|
129
|
-
{
|
|
130
|
-
const parsed = parseAssetRef(ref);
|
|
131
|
-
if (parsed.type === "wiki" && !parsed.name.includes("/")) {
|
|
132
|
-
const allSources = resolveSourceEntries();
|
|
133
|
-
const searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
|
|
134
|
-
let lastError;
|
|
135
|
-
for (const source of searchSources) {
|
|
136
|
-
try {
|
|
137
|
-
return await showWikiRootForSource(allSources[0]?.path ?? source.path, source, parsed.name);
|
|
138
|
-
}
|
|
139
|
-
catch (err) {
|
|
140
|
-
if (!(err instanceof NotFoundError))
|
|
141
|
-
throw err;
|
|
142
|
-
lastError = err;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
throw (lastError ??
|
|
146
|
-
new NotFoundError(`Wiki not found: ${parsed.name}. Run \`akm wiki create ${parsed.name}\` to create it.`));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
70
|
// Auto-index when stale so the index is current before lookup.
|
|
150
71
|
const { primarySource } = resolveReadSources();
|
|
151
72
|
await ensurePrimaryIndexForRead(primarySource);
|
|
@@ -159,11 +80,13 @@ export async function akmShowUnified(input) {
|
|
|
159
80
|
enforceScopeOrThrow(result.path, ref, input.scope);
|
|
160
81
|
}
|
|
161
82
|
// Count prior shows of this ref before logging the current one.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
83
|
+
if (!input.skipLogging) {
|
|
84
|
+
const priorShowCount = recentShowCount(ref);
|
|
85
|
+
logShowEvent(ref, input.eventSource, result.path, result.origin);
|
|
86
|
+
if (priorShowCount >= 2) {
|
|
87
|
+
// Agent has shown this same asset 3+ times — inject a loop-break hint.
|
|
88
|
+
result.showLoopWarning = priorShowCount + 1;
|
|
89
|
+
}
|
|
167
90
|
}
|
|
168
91
|
return result;
|
|
169
92
|
}
|
|
@@ -260,8 +183,10 @@ function recentShowCount(ref) {
|
|
|
260
183
|
function logShowEvent(ref, eventSource = "user", filePath, origin) {
|
|
261
184
|
// Emit a structured event to events.jsonl so workflow-trace consumers
|
|
262
185
|
// detect akm show invocations without relying on stdout scraping.
|
|
263
|
-
const parsed =
|
|
264
|
-
|
|
186
|
+
const parsed = parseQualifiedRefInput(ref);
|
|
187
|
+
// New-grammar display ref: also the lookup key below, which `findEntryIdByRef`
|
|
188
|
+
// resolves against `item_ref`.
|
|
189
|
+
const eventRef = displayRef({ type: parsed.type, name: parsed.name, bundleId: parsed.origin ?? origin ?? undefined });
|
|
265
190
|
appendEvent({ eventType: "show", ref: eventRef, metadata: { type: parsed.type, name: parsed.name } });
|
|
266
191
|
// Detect if this show is a selection from a recent search result.
|
|
267
192
|
try {
|
|
@@ -294,12 +219,22 @@ function logShowEvent(ref, eventSource = "user", filePath, origin) {
|
|
|
294
219
|
}
|
|
295
220
|
try {
|
|
296
221
|
withIndexDb((db) => {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
222
|
+
const entryId = filePath ? getEntryIdByFilePath(db, filePath) : findEntryIdByRef(db, eventRef);
|
|
223
|
+
// The DURABLE usage-event key is the resolved entry's fully-qualified
|
|
224
|
+
// `item_ref`; the new-grammar `eventRef` is the fallback for an
|
|
225
|
+
// unresolved / not-yet-indexed show. entry_id/item_ref resolve from
|
|
226
|
+
// index.db (`db`); the usage_events write lands in state.db (WI-8.3).
|
|
227
|
+
const entryRef = (entryId !== undefined ? getItemRefById(db, entryId) : null) ?? eventRef;
|
|
228
|
+
const entry = entryId !== undefined ? getEntryById(db, entryId) : undefined;
|
|
229
|
+
withStateDbTelemetry((stateDb) => {
|
|
230
|
+
insertUsageEvent(stateDb, {
|
|
231
|
+
event_type: "show",
|
|
232
|
+
entry_ref: entryRef,
|
|
233
|
+
entry_id: entryId,
|
|
234
|
+
metadata: usageEventAttributionMetadata(entry?.entry.derivedFrom ? { memoryInference: { exposure: "direct" } } : undefined, entryRef),
|
|
235
|
+
source: eventSource,
|
|
236
|
+
});
|
|
237
|
+
}, TELEMETRY_BUSY_TIMEOUT_MS);
|
|
303
238
|
}, { busyTimeoutMs: TELEMETRY_BUSY_TIMEOUT_MS });
|
|
304
239
|
}
|
|
305
240
|
catch (err) {
|
|
@@ -309,51 +244,34 @@ function logShowEvent(ref, eventSource = "user", filePath, origin) {
|
|
|
309
244
|
}
|
|
310
245
|
/** @internal Use akmShowUnified() for all external callers. */
|
|
311
246
|
export async function showLocal(input) {
|
|
312
|
-
const parsed =
|
|
247
|
+
const parsed = parseQualifiedRefInput(input.ref);
|
|
313
248
|
const displayType = parsed.type;
|
|
314
249
|
const config = loadConfig();
|
|
315
250
|
const allSources = resolveSourceEntries(input.stashDir);
|
|
316
251
|
const searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
|
|
317
252
|
const allSourceDirs = searchSources.map((s) => s.path);
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
assetPath = resolveRegisteredWikiAssetPath(matchedSource.path, matchedSource.wikiName, parsed.name);
|
|
324
|
-
}
|
|
325
|
-
catch (err) {
|
|
326
|
-
lastError = err instanceof Error ? err : new Error(String(err));
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
if (!assetPath) {
|
|
330
|
-
const resolvedAssetPath = await resolveAssetPath(parsed, {
|
|
331
|
-
stashDir: input.stashDir,
|
|
332
|
-
mode: "index-first",
|
|
333
|
-
});
|
|
334
|
-
assetPath = resolvedAssetPath ?? undefined;
|
|
335
|
-
}
|
|
253
|
+
const resolvedAssetPath = await resolveAssetPath(parsed, {
|
|
254
|
+
stashDir: input.stashDir,
|
|
255
|
+
mode: "index-first",
|
|
256
|
+
});
|
|
257
|
+
const assetPath = resolvedAssetPath ?? undefined;
|
|
336
258
|
if (!assetPath && parsed.origin && searchSources.length === 0) {
|
|
337
259
|
const installCmd = `akm add ${parsed.origin}`;
|
|
338
260
|
throw new NotFoundError(`Stash asset not found for ref: ${displayType}:${parsed.name}. ` +
|
|
339
261
|
`Stash "${parsed.origin}" is not installed. Run: ${installCmd}`);
|
|
340
262
|
}
|
|
341
263
|
if (!assetPath) {
|
|
342
|
-
throw (
|
|
343
|
-
|
|
344
|
-
"Check the name with `akm search` or verify the asset exists in your stash."));
|
|
264
|
+
throw new NotFoundError(`Stash asset not found for ref: ${displayType}:${parsed.name}. ` +
|
|
265
|
+
"Check the name with `akm search` or verify the asset exists in your stash.");
|
|
345
266
|
}
|
|
346
|
-
const source =
|
|
267
|
+
const source = findSourceForPath(assetPath, allSources);
|
|
347
268
|
const sourceStashDir = source?.path ?? allSourceDirs[0];
|
|
348
269
|
if (!sourceStashDir) {
|
|
349
270
|
throw new UsageError(`Could not determine stash root for asset: ${displayType}:${parsed.name}. ` +
|
|
350
271
|
"Run `akm init` to create the stash directory, or check `akm stash list` for configured paths.");
|
|
351
272
|
}
|
|
352
273
|
const fileCtx = buildFileContext(sourceStashDir, assetPath);
|
|
353
|
-
const
|
|
354
|
-
? { type: "wiki", specificity: 20, renderer: "wiki-md", meta: {} }
|
|
355
|
-
: undefined;
|
|
356
|
-
const match = forcedWikiMatch ?? (await runMatchers(fileCtx));
|
|
274
|
+
const match = recognizeMatch(fileCtx);
|
|
357
275
|
if (!match) {
|
|
358
276
|
throw new UsageError(`Could not display asset "${displayType}:${parsed.name}" — unsupported file type or unrecognized layout`);
|
|
359
277
|
}
|
|
@@ -477,7 +395,7 @@ async function maybeExtractGraphInline(config, sourceStashDir, assetPath) {
|
|
|
477
395
|
* renderer graph. Spec §6.2's literal flow.
|
|
478
396
|
*/
|
|
479
397
|
export async function showByRef(ref) {
|
|
480
|
-
const parsed =
|
|
398
|
+
const parsed = parseQualifiedRefInput(ref);
|
|
481
399
|
const entry = await lookup(parsed);
|
|
482
400
|
if (!entry) {
|
|
483
401
|
throw new NotFoundError(`Asset not found for ref: ${parsed.type}:${parsed.name}`);
|
|
@@ -587,8 +505,9 @@ export function normalizeShowArgv(argv) {
|
|
|
587
505
|
}
|
|
588
506
|
if (arg === "--format" || arg === "--detail" || arg === "--shape") {
|
|
589
507
|
globalFlags.push(arg);
|
|
590
|
-
|
|
591
|
-
|
|
508
|
+
const nextArg = rest[i + 1];
|
|
509
|
+
if (nextArg !== undefined) {
|
|
510
|
+
globalFlags.push(nextArg);
|
|
592
511
|
i++;
|
|
593
512
|
}
|
|
594
513
|
continue;
|
|
@@ -8,14 +8,15 @@
|
|
|
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";
|
|
11
12
|
import { serializeFrontmatter } from "../core/asset/asset-serialize.js";
|
|
12
13
|
import { toErrorMessage, tryReadStdinText } from "../core/common.js";
|
|
13
|
-
import {
|
|
14
|
+
import { loadConfig } from "../core/config/config.js";
|
|
14
15
|
import { UsageError } from "../core/errors.js";
|
|
15
16
|
import { DURATION_UNITS, parseDuration as parseDurationSpec } from "../core/time.js";
|
|
16
17
|
import { warn } from "../core/warn.js";
|
|
17
18
|
import { SCOPE_KEYS } from "../indexer/passes/metadata.js";
|
|
18
|
-
import {
|
|
19
|
+
import { getDefaultLlmConfig } from "../integrations/agent/engine-resolution.js";
|
|
19
20
|
/**
|
|
20
21
|
* Parse a shorthand duration string to a number of milliseconds.
|
|
21
22
|
* Supports the CLI-wide canonical grammar: `30d` (days), `12h` (hours),
|
|
@@ -215,13 +216,14 @@ Return ONLY the JSON object, no prose, no markdown fences.`;
|
|
|
215
216
|
export function resolveRememberContentArg(content) {
|
|
216
217
|
if (content === undefined)
|
|
217
218
|
return undefined;
|
|
218
|
-
const
|
|
219
|
+
const invocation = getParsedInvocation();
|
|
220
|
+
const parsedFormat = invocation.getFlagValue("--format");
|
|
219
221
|
if (parsedFormat !== undefined &&
|
|
220
222
|
content === parsedFormat &&
|
|
221
223
|
wasRememberFlagValueConsumedAsContent(content, parsedFormat, "--format")) {
|
|
222
224
|
return undefined;
|
|
223
225
|
}
|
|
224
|
-
const parsedDetail =
|
|
226
|
+
const parsedDetail = invocation.getFlagValue("--detail");
|
|
225
227
|
if (parsedDetail !== undefined &&
|
|
226
228
|
content === parsedDetail &&
|
|
227
229
|
wasRememberFlagValueConsumedAsContent(content, parsedDetail, "--detail")) {
|
|
@@ -230,7 +232,7 @@ export function resolveRememberContentArg(content) {
|
|
|
230
232
|
return content;
|
|
231
233
|
}
|
|
232
234
|
function wasRememberFlagValueConsumedAsContent(content, flagValue, flagName) {
|
|
233
|
-
const argv =
|
|
235
|
+
const argv = getParsedInvocation().userArgs;
|
|
234
236
|
const rememberIndex = argv.indexOf("remember");
|
|
235
237
|
const tokens = rememberIndex >= 0 ? argv.slice(rememberIndex + 1) : argv;
|
|
236
238
|
let flagIndex = -1;
|
|
@@ -5,13 +5,14 @@ import fs from "node:fs";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import * as p from "../../cli/clack.js";
|
|
7
7
|
import { defineJsonCommand, output } from "../../cli/shared.js";
|
|
8
|
+
import { decideDangerousKeyInstall } from "../../core/activation-policy.js";
|
|
8
9
|
import { UsageError } from "../../core/errors.js";
|
|
9
10
|
import { appendEvent } from "../../core/events.js";
|
|
10
11
|
import { warn } from "../../core/warn.js";
|
|
11
12
|
import { akmRemove } from "./installed-stashes.js";
|
|
12
13
|
import { akmAdd } from "./source-add.js";
|
|
13
14
|
import { addStash } from "./source-manage.js";
|
|
14
|
-
// ── Shared website-options helper
|
|
15
|
+
// ── Shared website-options helper ──────────
|
|
15
16
|
export function buildWebsiteOptions(args) {
|
|
16
17
|
const websiteOptions = {};
|
|
17
18
|
if (typeof args["max-pages"] === "string" && args["max-pages"].length > 0)
|
|
@@ -79,9 +80,15 @@ export async function auditInstalledStashForDangerousKeys(opts) {
|
|
|
79
80
|
catch {
|
|
80
81
|
return { blocked: false };
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
+
// The workspace activation policy fixes the baseline stance; the interactive
|
|
84
|
+
// confirm / rollback below is layered on top of the `"gate"` stance only.
|
|
85
|
+
const stance = decideDangerousKeyInstall({
|
|
86
|
+
findingsPresent: allFindings.length > 0,
|
|
87
|
+
allowInsecure: allowDangerousKeys,
|
|
88
|
+
});
|
|
89
|
+
if (stance === "allow")
|
|
83
90
|
return { blocked: false };
|
|
84
|
-
if (
|
|
91
|
+
if (stance === "warn-allow") {
|
|
85
92
|
// Operator has explicitly accepted the risk — warn and continue.
|
|
86
93
|
for (const f of allFindings) {
|
|
87
94
|
warn(`[dangerous-vault-key] ${f.relPath}: key \`${f.keyName}\` in ${f.vaultRef} can hijack process execution via \`akm env run\`. Proceeding because --allow-insecure was set.`);
|
|
@@ -166,10 +173,6 @@ export const addCommand = defineJsonCommand({
|
|
|
166
173
|
description: "Mark a git stash as writable so changes can be pushed back",
|
|
167
174
|
default: false,
|
|
168
175
|
},
|
|
169
|
-
type: {
|
|
170
|
-
type: "string",
|
|
171
|
-
description: "Override asset type for all files in this stash (currently supports: wiki)",
|
|
172
|
-
},
|
|
173
176
|
"max-pages": { type: "string", description: "Maximum pages to crawl for website sources (default: 50)" },
|
|
174
177
|
"max-depth": { type: "string", description: "Maximum crawl depth for website sources (default: 3)" },
|
|
175
178
|
"allow-insecure": {
|
|
@@ -228,25 +231,9 @@ export const addCommand = defineJsonCommand({
|
|
|
228
231
|
warn("Warning: source URL uses plain HTTP (not HTTPS). --allow-insecure was set; an on-path attacker could substitute a malicious payload.");
|
|
229
232
|
}
|
|
230
233
|
const websiteOptions = buildWebsiteOptions(args);
|
|
231
|
-
if (args.type === "wiki") {
|
|
232
|
-
const { registerWikiSource } = await import("./source-add.js");
|
|
233
|
-
const result = await registerWikiSource({
|
|
234
|
-
ref,
|
|
235
|
-
name: args.name,
|
|
236
|
-
options: Object.keys(websiteOptions).length > 0 ? websiteOptions : undefined,
|
|
237
|
-
writable: args.writable,
|
|
238
|
-
});
|
|
239
|
-
appendEvent({
|
|
240
|
-
eventType: "add",
|
|
241
|
-
metadata: { target: ref, type: "wiki", name: args.name ?? null, writable: args.writable === true },
|
|
242
|
-
});
|
|
243
|
-
output("add", result);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
234
|
const result = await akmAdd({
|
|
247
235
|
ref,
|
|
248
236
|
name: args.name,
|
|
249
|
-
overrideType: args.type,
|
|
250
237
|
options: Object.keys(websiteOptions).length > 0 ? websiteOptions : undefined,
|
|
251
238
|
writable: args.writable,
|
|
252
239
|
});
|
|
@@ -255,7 +242,6 @@ export const addCommand = defineJsonCommand({
|
|
|
255
242
|
metadata: {
|
|
256
243
|
target: ref,
|
|
257
244
|
name: args.name ?? null,
|
|
258
|
-
overrideType: args.type ?? null,
|
|
259
245
|
writable: args.writable === true,
|
|
260
246
|
},
|
|
261
247
|
});
|