akm-cli 0.9.0-rc.1 → 0.9.0-rc.13
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 +1190 -52
- package/README.md +62 -37
- package/SECURITY.md +46 -31
- package/dist/akm +162 -38
- package/dist/akm-migrate +44 -0
- package/dist/assets/backends/schtasks-template.xml +2 -1
- package/dist/assets/hints/cli-hints-full.md +268 -118
- package/dist/assets/hints/cli-hints-short.md +87 -24
- package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
- package/dist/assets/improve-strategies/frequent.json +15 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
- package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
- package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
- package/dist/assets/improve-strategies/reflect-distill.json +30 -0
- package/dist/assets/{profiles → 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/memory-infer-user.md +2 -3
- 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 +38 -10
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
- package/dist/assets/tasks/core/extract.yml +3 -2
- package/dist/assets/tasks/core/improve.yml +2 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +2 -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 +5 -4
- package/dist/assets/workflows/workflow-template.md +31 -15
- package/dist/cli/invocation.js +279 -0
- package/dist/cli/parse-args.js +5 -90
- package/dist/cli/retired-commands.js +78 -0
- package/dist/cli/shared.js +158 -48
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +747 -293
- package/dist/commands/agent/agent-dispatch.js +19 -18
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +43 -97
- package/dist/commands/completions.js +80 -23
- package/dist/commands/config-cli.js +44 -281
- package/dist/commands/env/env-binding.js +13 -9
- package/dist/commands/env/env-cli.js +76 -159
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +45 -61
- package/dist/commands/env/secret.js +32 -62
- package/dist/commands/feedback-cli.js +179 -85
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +7 -8
- package/dist/commands/health/checks.js +279 -94
- package/dist/commands/health/html-report.js +197 -578
- package/dist/commands/health/improve-metrics.js +277 -246
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +16 -7
- package/dist/commands/health/metrics.js +67 -32
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +508 -0
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +16 -56
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
- package/dist/commands/health/types-improve.js +29 -0
- package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
- 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 +2 -3
- package/dist/commands/health.js +296 -167
- package/dist/commands/improve/anti-collapse.js +5 -5
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +65 -52
- package/dist/commands/improve/consolidate/chunking.js +9 -7
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +454 -1354
- 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 +89 -64
- package/dist/commands/improve/distill/quality-gate.js +118 -42
- package/dist/commands/improve/distill-guards.js +1 -1
- package/dist/commands/improve/distill-promotion-policy.js +33 -888
- package/dist/commands/improve/distill.js +607 -363
- package/dist/commands/improve/eligibility.js +165 -79
- package/dist/commands/improve/extract-cli.js +35 -126
- package/dist/commands/improve/extract-prompt.js +6 -35
- package/dist/commands/improve/extract.js +640 -391
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +134 -135
- package/dist/commands/improve/improve-result-file.js +30 -50
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +135 -0
- package/dist/commands/improve/improve.js +904 -701
- package/dist/commands/improve/locks.js +64 -111
- package/dist/commands/improve/loop-stages.js +1110 -923
- package/dist/commands/improve/memory/derived-ref.js +124 -0
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
- package/dist/commands/improve/memory/memory-improve.js +25 -37
- package/dist/commands/improve/outcome-loop.js +25 -88
- package/dist/commands/improve/preparation.js +1034 -813
- package/dist/commands/improve/proactive-maintenance.js +34 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +983 -794
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +24 -127
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -34
- package/dist/commands/improve/source-identity.js +28 -0
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +340 -313
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +185 -30
- package/dist/commands/{events.js → log.js} +28 -38
- package/dist/commands/migrate-cli.js +54 -0
- package/dist/commands/migration-tool.js +55 -0
- package/dist/commands/observability-cli.js +70 -208
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +91 -40
- package/dist/commands/proposal/proposal-cli.js +134 -132
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +83 -65
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +105 -88
- package/dist/commands/proposal/repository.js +1303 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
- package/dist/commands/proposal/validators/proposal-validators.js +61 -12
- package/dist/commands/proposal/validators/proposals.js +6 -8
- package/dist/commands/read/curate.js +78 -73
- package/dist/commands/read/knowledge.js +510 -13
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +84 -15
- package/dist/commands/read/search-cli.js +203 -96
- package/dist/commands/read/search.js +126 -94
- package/dist/commands/read/show.js +226 -250
- package/dist/commands/registry-cli.js +34 -60
- package/dist/commands/remember.js +18 -57
- package/dist/commands/sources/add-cli.js +104 -49
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +63 -0
- package/dist/commands/sources/info.js +27 -15
- package/dist/commands/sources/init.js +30 -40
- package/dist/commands/sources/installed-stashes.js +469 -172
- package/dist/commands/sources/schema-repair.js +10 -9
- package/dist/commands/sources/self-update.js +182 -121
- package/dist/commands/sources/source-add.js +169 -178
- package/dist/commands/sources/source-clone.js +144 -41
- package/dist/commands/sources/source-manage.js +94 -59
- package/dist/commands/sources/sources-cli.js +64 -205
- package/dist/commands/sources/stash-cli.js +91 -54
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +106 -104
- package/dist/commands/tasks/tasks.js +445 -262
- package/dist/commands/workflow-cli.js +75 -228
- 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 +528 -0
- package/dist/core/adapter/adapters/akm-lint.js +392 -0
- package/dist/core/adapter/adapters/akm-metadata.js +387 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -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 +119 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
- package/dist/core/adapter/adapters/okf-adapter.js +391 -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 +217 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +44 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/akm-markdown.js +30 -0
- package/dist/core/asset/asset-placement.js +243 -0
- package/dist/core/asset/asset-ref.js +110 -79
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +28 -12
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +274 -0
- package/dist/core/asset/stash-meta.js +2 -2
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +281 -86
- package/dist/core/config/config-io.js +42 -128
- package/dist/core/config/config-schema.js +233 -855
- package/dist/core/config/config-sources.js +162 -39
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +126 -37
- package/dist/core/config/config.js +154 -331
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +28 -0
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/experimental.js +47 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +389 -0
- package/dist/core/config/schema/improve.js +94 -0
- package/dist/core/config/schema/index-config.js +176 -0
- package/dist/core/config/schema/output.js +18 -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 +18 -0
- package/dist/core/config/schema/sources-bundles.js +169 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +155 -20
- package/dist/core/errors.js +17 -15
- package/dist/core/events-types.js +4 -0
- package/dist/core/events.js +46 -128
- package/dist/core/extra-params.js +62 -0
- package/dist/core/file-change.js +17 -0
- package/dist/core/file-lock.js +202 -57
- package/dist/core/fs-txn.js +392 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +167 -0
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +135 -0
- package/dist/core/migration-operation.js +44 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/paths.js +22 -25
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +128 -0
- package/dist/core/redaction.js +392 -0
- package/dist/core/standards/resolve-standards-context.js +36 -65
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +5 -5
- package/dist/core/state/migrations.js +242 -11
- package/dist/core/state-db.js +98 -10
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +303 -0
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +834 -118
- package/dist/indexer/bundle-identity-guard.js +92 -0
- package/dist/indexer/db/graph-db.js +1 -25
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +30 -9
- package/dist/indexer/graph/graph-boost.js +9 -30
- package/dist/indexer/graph/graph-extraction.js +41 -27
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-writer-lock.js +93 -49
- package/dist/indexer/index-written-assets.js +100 -53
- package/dist/indexer/indexer.js +746 -329
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +142 -0
- package/dist/indexer/passes/dir-staleness.js +18 -10
- package/dist/indexer/passes/memory-inference.js +25 -15
- package/dist/indexer/passes/metadata.js +412 -243
- package/dist/indexer/scan/doc-to-entry.js +160 -0
- package/dist/indexer/scan/drain-dir.js +134 -0
- package/dist/indexer/search/db-search.js +292 -108
- package/dist/indexer/search/fts-query.js +64 -0
- package/dist/indexer/search/ranking-contributors.js +145 -25
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +28 -71
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-fields.js +18 -3
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +157 -111
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/usage-events.js +10 -30
- package/dist/indexer/walk/file-context.js +3 -45
- package/dist/indexer/walk/matchers.js +42 -73
- package/dist/indexer/walk/path-resolver.js +11 -5
- package/dist/indexer/walk/walker.js +42 -14
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -58
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +231 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +8 -3
- package/dist/integrations/agent/profiles.js +6 -99
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +78 -13
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +48 -279
- package/dist/integrations/harnesses/aider/agent-builder.js +9 -8
- package/dist/integrations/harnesses/aider/index.js +2 -12
- package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -16
- package/dist/integrations/harnesses/amazonq/index.js +3 -17
- package/dist/integrations/harnesses/claude/agent-builder.js +2 -3
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +1 -14
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +8 -7
- package/dist/integrations/harnesses/codex/index.js +2 -13
- package/dist/integrations/harnesses/copilot/agent-builder.js +9 -9
- package/dist/integrations/harnesses/copilot/index.js +1 -13
- package/dist/integrations/harnesses/gemini/agent-builder.js +8 -9
- package/dist/integrations/harnesses/gemini/index.js +1 -13
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +31 -33
- package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +1 -18
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +3 -17
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +274 -191
- package/dist/integrations/harnesses/openhands/agent-builder.js +12 -10
- package/dist/integrations/harnesses/openhands/index.js +2 -12
- package/dist/integrations/harnesses/pi/agent-builder.js +11 -18
- package/dist/integrations/harnesses/pi/index.js +3 -16
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +38 -34
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +24 -40
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +182 -110
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +21 -9
- package/dist/llm/feature-gate.js +17 -57
- package/dist/llm/graph-extract.js +12 -13
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +45 -30
- package/dist/llm/structured-call.js +16 -8
- package/dist/llm/usage-persist.js +30 -5
- package/dist/llm/usage-telemetry.js +59 -6
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/command-registry.js +27 -0
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +251 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +15 -281
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +58 -84
- package/dist/output/shapes/passthrough.js +8 -40
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/shapes.js +0 -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 +562 -0
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/helpers.js +15 -1375
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +202 -0
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +117 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +332 -0
- package/dist/output/text/workflow.js +1 -2
- package/dist/output/text.js +10 -19
- 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 +15 -25
- package/dist/registry/resolve.js +43 -94
- package/dist/registry/semver.js +43 -0
- package/dist/runtime.js +81 -12
- package/dist/scripts/akm-migrate.js +35529 -0
- package/dist/setup/detect.js +5 -7
- package/dist/setup/detected-engines.js +136 -0
- package/dist/setup/engine-config.js +100 -0
- package/dist/setup/registry-stash-loader.js +3 -3
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +444 -208
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +108 -305
- package/dist/setup/steps/platforms.js +13 -12
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +21 -15
- package/dist/setup/steps/stashdir.js +6 -4
- package/dist/setup/steps/tasks.js +236 -119
- package/dist/setup/steps.js +3 -2
- package/dist/sources/freshness.js +39 -0
- 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 +54 -56
- package/dist/sources/providers/git-stash.js +420 -91
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +47 -22
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +11 -10
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
- package/dist/storage/database.js +60 -4
- package/dist/storage/engines/sqlite-migrations.js +156 -5
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +51 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -32
- package/dist/storage/repositories/index-connection.js +79 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +863 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +167 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
- package/dist/storage/repositories/index-meta-repository.js +49 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +356 -0
- package/dist/storage/repositories/index-vec-repository.js +250 -0
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +317 -75
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +110 -3
- package/dist/storage/repositories/workflow-runs-repository.js +68 -35
- package/dist/tasks/backends/cron.js +169 -46
- package/dist/tasks/backends/exec-utils.js +76 -3
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +292 -55
- package/dist/tasks/backends/schtasks.js +557 -70
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/command-executable.js +93 -0
- package/dist/tasks/embedded.js +56 -38
- package/dist/tasks/parser.js +156 -64
- package/dist/tasks/resolve-akm-bin.js +144 -51
- package/dist/tasks/runner.js +377 -209
- package/dist/tasks/schedule.js +108 -19
- package/dist/tasks/scheduler-invocation.js +296 -0
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/task-id.js +35 -0
- package/dist/tasks/validator.js +30 -16
- package/dist/workflows/authoring/authoring.js +96 -148
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -20
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +25 -59
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +157 -94
- package/dist/workflows/exec/report.js +365 -200
- package/dist/workflows/exec/run-workflow.js +46 -40
- package/dist/workflows/exec/scheduler.js +12 -41
- package/dist/workflows/exec/step-work.js +239 -205
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/ir/compile.js +141 -283
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/plan-hash.js +40 -5
- package/dist/workflows/ir/schema.js +537 -1
- package/dist/workflows/parser.js +878 -306
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +7 -10
- package/dist/workflows/renderer.js +99 -121
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +200 -113
- 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 +235 -97
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +4 -26
- package/dist/workflows/validator.js +52 -30
- package/docs/README.md +42 -78
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +9 -8
- package/docs/migration/release-notes/0.9.0.md +158 -14
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +844 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/data-and-telemetry.md +333 -0
- package/package.json +21 -17
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +4636 -0
- package/schemas/akm-task.json +87 -0
- package/{dist/schemas → schemas}/akm-workflow.json +127 -82
- package/dist/akm-migrate-storage +0 -38
- 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/profiles/frequent.json +0 -13
- package/dist/assets/profiles/recombine-only.json +0 -21
- package/dist/assets/profiles/reflect-distill.json +0 -30
- package/dist/assets/profiles/synthesize.json +0 -15
- 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/tasks/core/backup.yml +0 -4
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- 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/cli/config-migrate.js +0 -150
- package/dist/cli/config-validate.js +0 -39
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -487
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -276
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/commands/improve/procedural.js +0 -398
- package/dist/commands/improve/recombine.js +0 -818
- 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/sources/history.js +0 -196
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/commands/wiki-cli.js +0 -292
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -316
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- 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 -1414
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
- package/dist/llm/call-ai.js +0 -62
- package/dist/llm/memory-infer-impl.js +0 -138
- 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/output/text/wiki.js +0 -16
- package/dist/registry/build-index.js +0 -386
- package/dist/schemas/akm-config.json +0 -14225
- package/dist/scripts/migrate-storage.js +0 -13169
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -10169
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/setup/legacy-config.js +0 -106
- 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 -1012
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/db.js +0 -350
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -760
- package/dist/workflows/program/project.js +0 -105
- package/docs/data-and-telemetry.md +0 -227
- 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
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import fs from "node:fs";
|
|
12
12
|
import { parse as yamlParse, stringify as yamlStringify } from "yaml";
|
|
13
|
-
import { assembleAsset } from "./asset-serialize.js";
|
|
13
|
+
import { assembleAsset, serializeFrontmatter } from "./asset-serialize.js";
|
|
14
14
|
/**
|
|
15
15
|
* Parse YAML frontmatter from a Markdown (or similar) string.
|
|
16
16
|
*
|
|
@@ -51,15 +51,11 @@ export function parseFrontmatter(raw) {
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
|
-
* Normalize YAML
|
|
54
|
+
* Normalize YAML dates to match expected AKM frontmatter types.
|
|
55
55
|
*
|
|
56
|
-
*
|
|
57
|
-
* 1. `Date` → YYYY-MM-DD string: the yaml "core" schema parses bare date
|
|
56
|
+
* `Date` → YYYY-MM-DD string: the yaml "core" schema parses bare date
|
|
58
57
|
* scalars like `2026-06-18` as JS Date instances. AKM frontmatter treats
|
|
59
58
|
* `updated:` and similar fields as plain strings.
|
|
60
|
-
* 2. `null` → `""`: the yaml library parses empty-value keys (`key:` with no
|
|
61
|
-
* value) as `null`, but AKM callers historically received `""` from the
|
|
62
|
-
* hand-rolled parser. Convert to preserve backward compatibility.
|
|
63
59
|
*/
|
|
64
60
|
function normalizeYamlValues(value) {
|
|
65
61
|
if (value instanceof Date) {
|
|
@@ -68,11 +64,9 @@ function normalizeYamlValues(value) {
|
|
|
68
64
|
const d = String(value.getUTCDate()).padStart(2, "0");
|
|
69
65
|
return `${y}-${m}-${d}`;
|
|
70
66
|
}
|
|
71
|
-
if (value === null)
|
|
72
|
-
return "";
|
|
73
67
|
if (Array.isArray(value))
|
|
74
68
|
return value.map(normalizeYamlValues);
|
|
75
|
-
if (typeof value === "object") {
|
|
69
|
+
if (value !== null && typeof value === "object") {
|
|
76
70
|
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, normalizeYamlValues(v)]));
|
|
77
71
|
}
|
|
78
72
|
return value;
|
|
@@ -118,15 +112,37 @@ function parseFrontmatterLenient(frontmatter) {
|
|
|
118
112
|
* or `null` to skip the write entirely (e.g. for idempotent no-ops). The body
|
|
119
113
|
* content is preserved from the parse.
|
|
120
114
|
*
|
|
115
|
+
* A frontmatter mutation is a METADATA edit, not a content edit: when the file
|
|
116
|
+
* already has a frontmatter block, only that block is replaced and the body
|
|
117
|
+
* bytes are kept verbatim (routing through `assembleAsset` would strip the
|
|
118
|
+
* body's leading blank lines and force a trailing newline, silently reshaping
|
|
119
|
+
* assets whose writer used a different separator style). A file gaining its
|
|
120
|
+
* FIRST frontmatter block goes through the canonical `assembleAsset` shape.
|
|
121
|
+
*
|
|
121
122
|
* @returns `true` if a write occurred, `false` if the mutator returned `null`.
|
|
122
123
|
*/
|
|
123
124
|
export function mutateFrontmatter(filePath, mutator) {
|
|
124
125
|
const raw = fs.readFileSync(filePath, "utf8");
|
|
125
126
|
const parsed = parseFrontmatter(raw);
|
|
127
|
+
if (parsed.frontmatter?.trim()) {
|
|
128
|
+
let strict;
|
|
129
|
+
try {
|
|
130
|
+
strict = yamlParse(parsed.frontmatter);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
throw new Error(`Cannot mutate malformed YAML frontmatter in ${filePath}.`);
|
|
134
|
+
}
|
|
135
|
+
if (strict === null || typeof strict !== "object" || Array.isArray(strict)) {
|
|
136
|
+
throw new Error(`Cannot mutate non-mapping YAML frontmatter in ${filePath}.`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
126
139
|
const nextFrontmatter = mutator(parsed);
|
|
127
140
|
if (nextFrontmatter === null)
|
|
128
141
|
return false;
|
|
129
|
-
|
|
142
|
+
const next = parsed.frontmatter !== null
|
|
143
|
+
? `---\n${serializeFrontmatter(nextFrontmatter)}\n---\n${parsed.content}`
|
|
144
|
+
: assembleAsset(nextFrontmatter, parsed.content);
|
|
145
|
+
fs.writeFileSync(filePath, next, "utf8");
|
|
130
146
|
return true;
|
|
131
147
|
}
|
|
132
148
|
export function parseFrontmatterBlock(raw) {
|
|
@@ -141,7 +157,7 @@ export function parseFrontmatterBlock(raw) {
|
|
|
141
157
|
return {
|
|
142
158
|
frontmatter,
|
|
143
159
|
content,
|
|
144
|
-
bodyStartLine: countLines(raw.slice(0, match[0].length -
|
|
160
|
+
bodyStartLine: countLines(raw.slice(0, match[0].length - content.length)) + 1,
|
|
145
161
|
};
|
|
146
162
|
}
|
|
147
163
|
// Empty frontmatter (---\n---): the content-bearing regex above requires at
|
|
@@ -2,6 +2,34 @@
|
|
|
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
4
|
import { parseFrontmatter } from "./frontmatter.js";
|
|
5
|
+
/** Stable GitHub-style selector for a Markdown heading. */
|
|
6
|
+
export function markdownHeadingSlug(heading) {
|
|
7
|
+
return heading
|
|
8
|
+
.trim()
|
|
9
|
+
.toLowerCase()
|
|
10
|
+
.replace(/<[^>]*>/g, "")
|
|
11
|
+
.replace(/[^\p{L}\p{N}\s_-]+/gu, "-")
|
|
12
|
+
.replace(/[\s_]+/g, "-")
|
|
13
|
+
.replace(/-+/g, "-")
|
|
14
|
+
.replace(/^-|-$/g, "");
|
|
15
|
+
}
|
|
16
|
+
export function markdownFragmentSlugs(content) {
|
|
17
|
+
return uniqueHeadingSlugs(parseMarkdownToc(content).headings).filter(Boolean);
|
|
18
|
+
}
|
|
19
|
+
function uniqueHeadingSlugs(headings) {
|
|
20
|
+
const used = new Set();
|
|
21
|
+
return headings.map((heading) => {
|
|
22
|
+
const base = markdownHeadingSlug(heading.text);
|
|
23
|
+
if (!base)
|
|
24
|
+
return "";
|
|
25
|
+
let slug = base;
|
|
26
|
+
let suffix = 0;
|
|
27
|
+
while (used.has(slug))
|
|
28
|
+
slug = `${base}-${++suffix}`;
|
|
29
|
+
used.add(slug);
|
|
30
|
+
return slug;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
5
33
|
// ── Parsing ─────────────────────────────────────────────────────────────────
|
|
6
34
|
export function parseMarkdownToc(content) {
|
|
7
35
|
const lines = content.split(/\r?\n/);
|
|
@@ -31,61 +59,22 @@ export function parseMarkdownToc(content) {
|
|
|
31
59
|
// ── Extraction ──────────────────────────────────────────────────────────────
|
|
32
60
|
export function extractSection(content, heading) {
|
|
33
61
|
const lines = content.split(/\r?\n/);
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
continue;
|
|
41
|
-
const text = match[2].replace(/\s+#+\s*$/, "").trim();
|
|
42
|
-
if (text.toLowerCase() === target && startIdx === -1) {
|
|
43
|
-
startIdx = i;
|
|
44
|
-
startLevel = match[1].length;
|
|
45
|
-
}
|
|
46
|
-
else if (startIdx !== -1 && match[1].length <= startLevel) {
|
|
47
|
-
return {
|
|
48
|
-
content: lines.slice(startIdx, i).join("\n"),
|
|
49
|
-
startLine: startIdx + 1,
|
|
50
|
-
endLine: i,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (startIdx === -1)
|
|
62
|
+
const headings = parseMarkdownToc(content).headings;
|
|
63
|
+
const fragment = heading.trim();
|
|
64
|
+
const slugIndex = uniqueHeadingSlugs(headings).indexOf(fragment);
|
|
65
|
+
const exact = slugIndex < 0 ? headings.find((candidate) => candidate.text.toLowerCase() === fragment.toLowerCase()) : undefined;
|
|
66
|
+
const selected = slugIndex >= 0 ? headings[slugIndex] : exact;
|
|
67
|
+
if (!selected)
|
|
55
68
|
return null;
|
|
69
|
+
const next = headings.find((candidate) => candidate.line > selected.line && candidate.level <= selected.level);
|
|
70
|
+
const startIdx = selected.line - 1;
|
|
71
|
+
const endIdx = next ? next.line - 1 : lines.length;
|
|
56
72
|
return {
|
|
57
|
-
content: lines.slice(startIdx).join("\n"),
|
|
58
|
-
startLine:
|
|
59
|
-
endLine:
|
|
73
|
+
content: lines.slice(startIdx, endIdx).join("\n"),
|
|
74
|
+
startLine: selected.line,
|
|
75
|
+
endLine: endIdx,
|
|
60
76
|
};
|
|
61
77
|
}
|
|
62
|
-
export function extractLineRange(content, start, end) {
|
|
63
|
-
const lines = content.split(/\r?\n/);
|
|
64
|
-
if (end < start)
|
|
65
|
-
return "";
|
|
66
|
-
const s = Math.max(1, Math.min(start, lines.length));
|
|
67
|
-
const e = Math.min(end, lines.length);
|
|
68
|
-
return lines.slice(s - 1, e).join("\n");
|
|
69
|
-
}
|
|
70
|
-
export function extractFrontmatterOnly(content) {
|
|
71
|
-
const parsed = parseFrontmatter(content);
|
|
72
|
-
return parsed.frontmatter;
|
|
73
|
-
}
|
|
74
|
-
// ── Formatting ──────────────────────────────────────────────────────────────
|
|
75
|
-
export function formatToc(toc) {
|
|
76
|
-
if (toc.headings.length === 0) {
|
|
77
|
-
return `(no headings found — ${toc.totalLines} lines total)`;
|
|
78
|
-
}
|
|
79
|
-
const lineWidth = String(toc.totalLines).length;
|
|
80
|
-
const parts = toc.headings.map((h) => {
|
|
81
|
-
const lineNum = `L${String(h.line).padStart(lineWidth)}`;
|
|
82
|
-
const indent = " ".repeat(h.level - 1);
|
|
83
|
-
const prefix = "#".repeat(h.level);
|
|
84
|
-
return `${lineNum} ${indent}${prefix} ${h.text}`;
|
|
85
|
-
});
|
|
86
|
-
parts.push(`\n${toc.totalLines} lines total`);
|
|
87
|
-
return parts.join("\n");
|
|
88
|
-
}
|
|
89
78
|
// ── Fence stripping ──────────────────────────────────────────────────────────
|
|
90
79
|
/**
|
|
91
80
|
* Best-effort fence stripping. Strips `<think>` reasoning blocks emitted by
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Ref RESOLUTION layer — akm 0.9.0 Chunk-5 flip, stage F1 (ref-grammar decision
|
|
6
|
+
* D-R1 / D-R4).
|
|
7
|
+
*
|
|
8
|
+
* The 0.9.0 ref abstraction is `parse → resolve → serialize`:
|
|
9
|
+
* - parse — `parseBundleRef` (`asset-ref.ts`), pure syntax, no I/O.
|
|
10
|
+
* - resolve — {@link resolveRef} (this module): turn a maybe-short
|
|
11
|
+
* {@link BundleRef} into a fully-qualified {@link ResolvedRef}
|
|
12
|
+
* against an injected {@link RefContext}. This is the "the short
|
|
13
|
+
* form is input sugar" rule (§11.1) made structural: only a
|
|
14
|
+
* `ResolvedRef` ever crosses a storage boundary.
|
|
15
|
+
* - serialize — `bundleRefToString` (`asset-ref.ts`); serializing a
|
|
16
|
+
* `ResolvedRef` always emits the fully-qualified form.
|
|
17
|
+
*
|
|
18
|
+
* ── Cycle-safety (HARD constraint) ──
|
|
19
|
+
*
|
|
20
|
+
* This is a PURE LEAF. It imports only sibling leaves (`asset-ref`,
|
|
21
|
+
* `asset-placement`) and the `core/errors` sink — nothing from the indexer-db
|
|
22
|
+
* SCC and no `Database`/config handle. The resolution surface is INJECTED via
|
|
23
|
+
* {@link RefContext}; callers build the context from their own db handle /
|
|
24
|
+
* installation list and hand it in. Keeping the resolver free of I/O is what
|
|
25
|
+
* lets it stay out of every import cycle.
|
|
26
|
+
*
|
|
27
|
+
* ── Input-boundary parser (new-grammar only) ──
|
|
28
|
+
*
|
|
29
|
+
* {@link parseRefInput} parses a RAW user/CLI/API ref in the 0.9.0
|
|
30
|
+
* `[bundle//]conceptId` grammar and returns an {@link AssetRef} value object via
|
|
31
|
+
* the permanent D-R2 reverse table {@link typeNameFromConceptId}. Post-Chunk-8
|
|
32
|
+
* every durable ref reaching a reader is already the new grammar, so this is the
|
|
33
|
+
* ONE ref parser outside the frozen migrator — there is no stored-ref dual
|
|
34
|
+
* grammar to bridge any more.
|
|
35
|
+
*/
|
|
36
|
+
import { NotFoundError, UsageError } from "../errors.js";
|
|
37
|
+
import { placementSpecFor, stashDirFor, typeForStashDir } from "./asset-placement.js";
|
|
38
|
+
import { isBundleSlug, parseBundleRef } from "./asset-ref.js";
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a maybe-short input ref to a fully-qualified {@link ResolvedRef}
|
|
41
|
+
* against `ctx`, implementing D-R4 exactly:
|
|
42
|
+
*
|
|
43
|
+
* 1. Already-qualified input (`bundle//…`) → that bundle (passthrough). When
|
|
44
|
+
* `ctx.only` is set and disagrees, that is a not-found (the ref names a
|
|
45
|
+
* bundle the caller scoped out).
|
|
46
|
+
* 2. Short input, `only` set → resolve to `only` iff it contains the concept.
|
|
47
|
+
* 3. Short input, no `only` → `defaultBundle` if it contains the concept,
|
|
48
|
+
* otherwise the FIRST bundle (priority order) that contains it.
|
|
49
|
+
* 4. No match → {@link NotFoundError} naming the forms tried.
|
|
50
|
+
*
|
|
51
|
+
* The `#fragment` is carried through untouched.
|
|
52
|
+
*/
|
|
53
|
+
export function resolveRef(input, ctx) {
|
|
54
|
+
const ref = typeof input === "string" ? parseBundleRef(input) : input;
|
|
55
|
+
const { conceptId, fragment } = ref;
|
|
56
|
+
// 1. Qualified passthrough — an explicit bundle prefix wins.
|
|
57
|
+
if (ref.bundle !== undefined) {
|
|
58
|
+
if (ctx.only !== undefined && ref.bundle !== ctx.only) {
|
|
59
|
+
throw notFound(conceptId, [`${ref.bundle}//${conceptId}`], ctx);
|
|
60
|
+
}
|
|
61
|
+
return { bundle: ref.bundle, conceptId, fragment };
|
|
62
|
+
}
|
|
63
|
+
// `only` scoping restricts the candidate set to a single bundle.
|
|
64
|
+
const candidates = ctx.only !== undefined ? ctx.bundles.filter((b) => b.id === ctx.only) : ctx.bundles;
|
|
65
|
+
// 2/3. defaultBundle wins over priority order for a short ref (but only when
|
|
66
|
+
// not `only`-scoped; an `only` request never falls back to the default).
|
|
67
|
+
if (ctx.only === undefined && ctx.defaultBundle !== undefined) {
|
|
68
|
+
const def = ctx.bundles.find((b) => b.id === ctx.defaultBundle);
|
|
69
|
+
if (def?.hasConcept(conceptId))
|
|
70
|
+
return { bundle: def.id, conceptId, fragment };
|
|
71
|
+
}
|
|
72
|
+
// First candidate (priority order) that contains the concept.
|
|
73
|
+
for (const b of candidates) {
|
|
74
|
+
if (b.hasConcept(conceptId))
|
|
75
|
+
return { bundle: b.id, conceptId, fragment };
|
|
76
|
+
}
|
|
77
|
+
throw notFound(conceptId, [conceptId], ctx);
|
|
78
|
+
}
|
|
79
|
+
function notFound(conceptId, triedForms, ctx) {
|
|
80
|
+
const scope = ctx.only !== undefined ? ` in bundle "${ctx.only}"` : "";
|
|
81
|
+
const forms = triedForms.map((f) => `"${f}"`).join(", ");
|
|
82
|
+
return new NotFoundError(`No bundle contains concept "${conceptId}"${scope} (tried ${forms}).`, "ASSET_NOT_FOUND");
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* D-R2 conceptId derivation from an asset `type`/`name` pair
|
|
86
|
+
* (`stashDirFor(type)/name`; bare name for a foreign type with no placement
|
|
87
|
+
* stash-subdir). Kept self-contained so {@link displayRef} — a PERMANENT display
|
|
88
|
+
* rule remains independent of input parsing.
|
|
89
|
+
*
|
|
90
|
+
* Exported (Chunk-8 WI-8.5c) as the ONE conceptId derivation the improve
|
|
91
|
+
* correlation sites (`eligibility.ts` candidate refs, `salience.ts`
|
|
92
|
+
* last-use lookup, `collapse-detector.ts` canary mint/score) share with the
|
|
93
|
+
* display rule — the permanent successor to the retired transient
|
|
94
|
+
* `legacyConceptId`.
|
|
95
|
+
*/
|
|
96
|
+
export function conceptIdFromTypeName(type, name) {
|
|
97
|
+
const stashDir = stashDirFor(type);
|
|
98
|
+
return stashDir !== undefined ? `${stashDir}/${name}` : name;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Build the USER-FACING / envelope ref string for an indexed item, applying the
|
|
102
|
+
* Chunk-5 flip F4b output-spelling rule (orchestrator decision; ref-grammar
|
|
103
|
+
* decision D-R2 / D-R3). This is the ONE place the rule lives — every emission
|
|
104
|
+
* site calls it instead of hand-building a ref from an entry.
|
|
105
|
+
*
|
|
106
|
+
* The rule mirrors TODAY'S origin-qualification UX, transposed to the 0.9.0
|
|
107
|
+
* grammar:
|
|
108
|
+
*
|
|
109
|
+
* - An item in the **default/primary bundle** (`bundleId` undefined, or equal
|
|
110
|
+
* to `defaultBundleId`) emits the SHORT conceptId (`knowledge/http-caching`)
|
|
111
|
+
* — exactly where the pre-0.9.0 output emitted an un-qualified `type:name`.
|
|
112
|
+
* - Any other **non-default bundle** emits the fully-qualified
|
|
113
|
+
* `bundle//conceptId`. Post-Chunk-8 every bundle id is a legal slug (the
|
|
114
|
+
* config migration assigned each source its D-R5 slug bundle key), so this
|
|
115
|
+
* is always the new grammar — a non-slug registryId now displays under its
|
|
116
|
+
* derived slug bundle id, never the retired `origin//type:name` spelling.
|
|
117
|
+
*/
|
|
118
|
+
export function displayRef(item, defaultBundleId) {
|
|
119
|
+
const conceptId = item.conceptId ?? conceptIdFromTypeName(item.type, item.name);
|
|
120
|
+
const { bundleId } = item;
|
|
121
|
+
// Default/primary bundle → SHORT conceptId (the flip).
|
|
122
|
+
if (bundleId === undefined || bundleId === defaultBundleId)
|
|
123
|
+
return conceptId;
|
|
124
|
+
// Non-default bundle → the new fully-qualified `bundle//conceptId` grammar.
|
|
125
|
+
return `${bundleId}//${conceptId}`;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Split a qualified conceptId (`<stash-subdir>/<name>`) into its asset
|
|
129
|
+
* `type`/`name`, or `undefined` when the leading segment is not a known stash
|
|
130
|
+
* subdir (a bare-name conceptId from a foreign type — no legacy predicate
|
|
131
|
+
* applies). The PERMANENT D-R2 reverse table: the input boundary uses it to map
|
|
132
|
+
* a new-grammar conceptId onto today's {@link AssetRef} shape. (The migrate home
|
|
133
|
+
* keeps a private transient copy for stored-ref parsing.)
|
|
134
|
+
*/
|
|
135
|
+
export function typeNameFromConceptId(conceptId) {
|
|
136
|
+
const slash = conceptId.indexOf("/");
|
|
137
|
+
if (slash <= 0)
|
|
138
|
+
return undefined;
|
|
139
|
+
const type = typeForStashDir(conceptId.slice(0, slash));
|
|
140
|
+
if (type === undefined)
|
|
141
|
+
return undefined;
|
|
142
|
+
return { type, name: conceptId.slice(slash + 1) };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* D11 — the opaque-adapter-conceptId fallback. `typeNameFromConceptId` only
|
|
146
|
+
* ever answers for the PLACEMENT_SPECS stash-resident subset (D-R2); a
|
|
147
|
+
* conceptId whose leading segment is NOT a registered placement stashDir is
|
|
148
|
+
* still perfectly legal DATA per D11 — an OKF item (`tables/customers`), a
|
|
149
|
+
* website page, a wiki pageKind, an adapter `instruction` doc, … — and the
|
|
150
|
+
* ref-consuming commands must accept it rather than treat "not an AKM
|
|
151
|
+
* placement dir" as "malformed ref". This function draws the line: it accepts
|
|
152
|
+
* any well-formed `<segment>/<rest>` conceptId (so the shape is still
|
|
153
|
+
* anchored — a bare no-slash name stays the caller's job to pre-qualify with a
|
|
154
|
+
* default type, the existing env/secret/`akm mv` "bare name" convenience), and
|
|
155
|
+
* REJECTS anything shaped like the retired `type:name` colon grammar (Q-02):
|
|
156
|
+
* a `:` in the leading segment is that grammar smuggled through a conceptId
|
|
157
|
+
* string (e.g. `script:db/migrate/run.sh`, `workflow:release/train`), not a
|
|
158
|
+
* real adapter directory name, so it is refused rather than silently
|
|
159
|
+
* reinterpreted as opaque data.
|
|
160
|
+
*
|
|
161
|
+
* `name` deliberately carries the FULL original conceptId, not just the tail.
|
|
162
|
+
* This is what makes the pair round-trip through the UNCHANGED
|
|
163
|
+
* {@link conceptIdFromTypeName} (`stashDirFor(type)/name`, bare `name` when
|
|
164
|
+
* `type` has no placement stashDir): since an opaque `type` never owns a
|
|
165
|
+
* placement stashDir, `conceptIdFromTypeName(type, name)` falls to its bare-
|
|
166
|
+
* `name` branch and returns `name` verbatim — the original conceptId,
|
|
167
|
+
* unchanged — instead of losing the leading segment. `type` itself carries
|
|
168
|
+
* the leading segment (informational/behavioral use: `.type === "lesson"`
|
|
169
|
+
* checks correctly miss for opaque data) UNLESS that segment happens to
|
|
170
|
+
* collide with a real PLACEMENT_SPECS type key that merely uses a different
|
|
171
|
+
* stashDir spelling (e.g. a foreign top-level dir literally named "skill",
|
|
172
|
+
* singular) — that pathological case would make `stashDirFor` succeed on the
|
|
173
|
+
* "type" and corrupt the round-trip, so it falls back to the full conceptId as
|
|
174
|
+
* `type` too (never a placement key, since a placement key never contains
|
|
175
|
+
* `/`).
|
|
176
|
+
*
|
|
177
|
+
* This intentionally does NOT collapse the KNOWN_TYPES/PLACEMENT_SPECS split:
|
|
178
|
+
* `typeNameFromConceptId` (PLACEMENT_SPECS only) is untouched, and an opaque
|
|
179
|
+
* `type` returned here is never a {@link KnownType} — it is a passthrough
|
|
180
|
+
* label, not a claim that AKM recognizes or owns the concept.
|
|
181
|
+
*/
|
|
182
|
+
function opaqueRefParts(conceptId, allowRoot = false) {
|
|
183
|
+
const slash = conceptId.indexOf("/");
|
|
184
|
+
if (slash <= 0)
|
|
185
|
+
return allowRoot && !conceptId.includes(":") ? { type: conceptId, name: conceptId } : undefined;
|
|
186
|
+
const segment = conceptId.slice(0, slash);
|
|
187
|
+
if (segment.includes(":"))
|
|
188
|
+
return undefined; // retired `type:name` grammar, not opaque data (Q-02).
|
|
189
|
+
const type = placementSpecFor(segment) === undefined ? segment : conceptId;
|
|
190
|
+
return { type, name: conceptId };
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Parse a RAW user / CLI / API ref string in the 0.9.0 `[bundle//]conceptId`
|
|
194
|
+
* grammar, returning it in today's {@link AssetRef} value-object shape
|
|
195
|
+
* (ref-grammar decision D-R1 / D-R4). All boundaries are NEW-GRAMMAR ONLY: a
|
|
196
|
+
* legacy `type:name` input now fails as an unknown-conceptId not-found. Post-
|
|
197
|
+
* Chunk-8 every durable ref is already the new grammar, so this parser also
|
|
198
|
+
* serves the (formerly dual-grammar) stored-ref readers.
|
|
199
|
+
*
|
|
200
|
+
* Mapping (new grammar → {@link AssetRef}):
|
|
201
|
+
* - `conceptId` → `type`/`name` via {@link typeNameFromConceptId} (the D-R2
|
|
202
|
+
* static stash-subdir table) when the leading segment is a known AKM
|
|
203
|
+
* placement stashDir, else via {@link opaqueRefParts} (D11 — the ref-parser
|
|
204
|
+
* seam accepts opaque adapter conceptIds, e.g. OKF items, website pages,
|
|
205
|
+
* wiki pageKinds, adapter `instruction` docs) when it is merely a well-
|
|
206
|
+
* formed but foreign `<segment>/<rest>` shape. A conceptId that is neither
|
|
207
|
+
* — no slash at all, or a retired colon-grammar shape smuggled through —
|
|
208
|
+
* has no type predicate: the same not-found outcome a genuine typo
|
|
209
|
+
* produces today.
|
|
210
|
+
* - `bundle` → `origin`. A new-grammar bundle slug is a registryId-shaped
|
|
211
|
+
* id by construction, so it flows straight into the legacy origin channel
|
|
212
|
+
* that `resolveSourcesForOrigin` matches on `registryId`. The SHORT form (no
|
|
213
|
+
* bundle) leaves `origin` undefined = search-all-sources.
|
|
214
|
+
* - `#fragment` → rejected. No input boundary consumes an export fragment.
|
|
215
|
+
*/
|
|
216
|
+
export function parseRefInput(raw) {
|
|
217
|
+
const ref = parseBundleRef(raw);
|
|
218
|
+
if (ref.fragment !== undefined) {
|
|
219
|
+
throw new UsageError(`Export fragment "#${ref.fragment}" is not accepted here — drop it from "${raw.trim()}".`, "INVALID_FLAG_VALUE");
|
|
220
|
+
}
|
|
221
|
+
const parts = typeNameFromConceptId(ref.conceptId) ?? opaqueRefParts(ref.conceptId, ref.bundle !== undefined);
|
|
222
|
+
if (parts === undefined) {
|
|
223
|
+
throw new NotFoundError(`Unrecognized asset ref "${raw.trim()}": conceptId "${ref.conceptId}" has no known asset-type prefix.`, "ASSET_NOT_FOUND");
|
|
224
|
+
}
|
|
225
|
+
return { type: parts.type, name: parts.name, origin: ref.bundle };
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Parse a CLI/API ref that MAY be qualified by a NON-slug origin — a registry
|
|
229
|
+
* ref (`github:owner/repo`, `npm:@scope/pkg`, `git:host/path`), a bare path, or
|
|
230
|
+
* a URL — as its `origin//conceptId` prefix. Such an origin carries `:`/`.`/`/`
|
|
231
|
+
* so it is not a legal bundle slug and the strict {@link parseRefInput} rejects
|
|
232
|
+
* it; but it is still a valid SOURCE origin that `resolveSourcesForOrigin`
|
|
233
|
+
* matches by registry-id / path and the remote-fetch fallback can install. The
|
|
234
|
+
* conceptId body is parsed under the strict new grammar; the raw origin is kept
|
|
235
|
+
* as-is — the symmetric input side of {@link displayRef}, which likewise keeps
|
|
236
|
+
* `origin//…` for exactly these non-slug origins (ref-grammar decision D-R5).
|
|
237
|
+
*
|
|
238
|
+
* A short ref (no origin) or a slug-origin ref is delegated verbatim to
|
|
239
|
+
* {@link parseRefInput}, so this is a safe superset for origin-accepting
|
|
240
|
+
* commands (`show`, `clone`, `graph`, `history`).
|
|
241
|
+
*/
|
|
242
|
+
export function parseQualifiedRefInput(raw) {
|
|
243
|
+
const trimmed = raw.trim();
|
|
244
|
+
const boundary = trimmed.indexOf("//");
|
|
245
|
+
if (boundary > 0) {
|
|
246
|
+
const origin = trimmed.slice(0, boundary);
|
|
247
|
+
if (!isBundleSlug(origin)) {
|
|
248
|
+
return { ...parseRefInput(trimmed.slice(boundary + 2)), origin };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return parseRefInput(trimmed);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Does `raw` already read as a COMPLETE new-grammar asset ref, as opposed to a
|
|
255
|
+
* bare asset name that a boundary would prefix with a default type (the
|
|
256
|
+
* `env`/`secret`/`akm mv` "bare name" convenience)?
|
|
257
|
+
*
|
|
258
|
+
* True when `raw` is a `[bundle//]conceptId` whose conceptId leads with a KNOWN
|
|
259
|
+
* stash subdir ({@link typeNameFromConceptId} resolves it). A bare name like
|
|
260
|
+
* `prod` or `projectA/new-note` is neither — its leading segment maps to no
|
|
261
|
+
* type — so it stays a bare name for the caller to qualify.
|
|
262
|
+
*/
|
|
263
|
+
export function isFullRefInput(raw) {
|
|
264
|
+
const trimmed = raw.trim();
|
|
265
|
+
if (!trimmed)
|
|
266
|
+
return false;
|
|
267
|
+
try {
|
|
268
|
+
const parsed = parseBundleRef(trimmed);
|
|
269
|
+
return parsed.bundle !== undefined || typeNameFromConceptId(parsed.conceptId) !== undefined;
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* A stash may carry an optional, human-authored `.meta/` directory at its
|
|
8
8
|
* root holding orientation docs for the stash as a whole: purpose, key
|
|
9
9
|
* assets, conventions, maintainer info. Because `.meta/` is a dot-directory,
|
|
10
|
-
* the indexer's walker already skips it (see `src/indexer/walker.ts`), so
|
|
10
|
+
* the indexer's walker already skips it (see `src/indexer/walk/walker.ts`), so
|
|
11
11
|
* these files never pollute the search corpus. They are surfaced on demand
|
|
12
12
|
* via `akm show [<origin>//]meta[:<name>]`, which direct-reads the file
|
|
13
13
|
* rather than going through the index.
|
|
@@ -54,7 +54,7 @@ export function parseMetaRef(ref) {
|
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
56
|
* Reject meta names that would escape the `.meta/` directory. Mirrors the
|
|
57
|
-
* traversal guards in
|
|
57
|
+
* traversal guards in the ref parser's `validateName`.
|
|
58
58
|
*/
|
|
59
59
|
function assertSafeMetaName(name) {
|
|
60
60
|
if (name.includes("\0")) {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import crypto from "node:crypto";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { isBundleSlug } from "./asset/asset-ref.js";
|
|
7
|
+
/** Deterministic, filesystem-safe bundle slug from a source path. */
|
|
8
|
+
export function slugForPath(sourcePath) {
|
|
9
|
+
const resolved = path.resolve(sourcePath);
|
|
10
|
+
const base = path
|
|
11
|
+
.basename(resolved)
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
14
|
+
.replace(/^-+|-+$/g, "");
|
|
15
|
+
if (base.length > 0)
|
|
16
|
+
return base;
|
|
17
|
+
return `bundle-${shortHash(resolved)}`;
|
|
18
|
+
}
|
|
19
|
+
/** Derive one batch-unique bundle id. */
|
|
20
|
+
export function deriveBundleId(registryId, sourcePath, usedIds) {
|
|
21
|
+
const preferred = registryId && registryId.length > 0 && isBundleSlug(registryId) ? registryId : slugForPath(sourcePath);
|
|
22
|
+
const id = ensureUniqueId(preferred, sourcePath, usedIds);
|
|
23
|
+
usedIds.add(id);
|
|
24
|
+
return id;
|
|
25
|
+
}
|
|
26
|
+
/** Derive an ordered batch while reserving every explicit configured bundle id. */
|
|
27
|
+
export function deriveBundleIds(sources) {
|
|
28
|
+
const usedIds = new Set();
|
|
29
|
+
const reservedIds = new Set(sources.flatMap((source) => (source.registryId && isBundleSlug(source.registryId) ? [source.registryId] : [])));
|
|
30
|
+
return sources.map((source) => {
|
|
31
|
+
const id = source.registryId && isBundleSlug(source.registryId)
|
|
32
|
+
? deriveBundleId(source.registryId, source.path, usedIds)
|
|
33
|
+
: deriveBundleId(undefined, source.path, new Set([...usedIds, ...reservedIds]));
|
|
34
|
+
usedIds.add(id);
|
|
35
|
+
return id;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function ensureUniqueId(preferred, sourcePath, used) {
|
|
39
|
+
if (!used.has(preferred))
|
|
40
|
+
return preferred;
|
|
41
|
+
const suffixed = `${preferred}-${shortHash(path.resolve(sourcePath))}`;
|
|
42
|
+
if (!used.has(suffixed))
|
|
43
|
+
return suffixed;
|
|
44
|
+
let n = 2;
|
|
45
|
+
while (used.has(`${suffixed}-${n}`))
|
|
46
|
+
n++;
|
|
47
|
+
return `${suffixed}-${n}`;
|
|
48
|
+
}
|
|
49
|
+
function shortHash(input) {
|
|
50
|
+
return crypto.createHash("sha256").update(input).digest("hex").slice(0, 8);
|
|
51
|
+
}
|