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
|
@@ -0,0 +1,509 @@
|
|
|
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
|
+
* The AKM workspace's own `akm` adapter — akm 0.9.0 chunk-2, WI-B.
|
|
6
|
+
*
|
|
7
|
+
* Implements `docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md` §5.1 (BINDING) +
|
|
8
|
+
* §6 + §7 (the `akm` row) EXACTLY: a BEHAVIOR-PRESERVING PORT that reproduces
|
|
9
|
+
* TODAY'S classification and placement VERBATIM by REUSING the existing matcher
|
|
10
|
+
* stack. It is NOT re-derived onto frontmatter `type` (that is the sibling
|
|
11
|
+
* `okf` adapter's job, §5), NOT split per-`type` (the 14 AKM formats are `type`
|
|
12
|
+
* VALUES the single `akm` adapter emits, §6/§0.2), and introduces NO new
|
|
13
|
+
* positional/directory heuristics of its own.
|
|
14
|
+
*
|
|
15
|
+
* ── recognize (§5.1): the sync `runMatchers` reproduction ──
|
|
16
|
+
*
|
|
17
|
+
* `file-context.ts#runMatchers` (`:242-265`) is async ONLY because of its lazy
|
|
18
|
+
* `ensureBuiltinsRegistered()` dynamic import; its ARBITRATION is pure and
|
|
19
|
+
* synchronous. We reproduce it here by importing the SAME five builtin matcher
|
|
20
|
+
* functions (`matchers.ts` `extensionMatcher` / `directoryMatcher` /
|
|
21
|
+
* `parentDirHintMatcher` / `smartMdMatcher` / `workflowProgramMatcher`) in the
|
|
22
|
+
* SAME order they are registered, collecting every non-null
|
|
23
|
+
* `MatchResult` and picking the winner by **specificity descending, ties broken
|
|
24
|
+
* by later-registered (higher index) winning** — byte-identical to
|
|
25
|
+
* `runMatchers`'s `b.specificity - a.specificity` then `b.index - a.index`.
|
|
26
|
+
* Because the matcher functions (which resolve renderer names via the static
|
|
27
|
+
* `TYPE_PRESENTATION` table in `type-presentation.ts`, all built-in types
|
|
28
|
+
* present at load) are the exact ones `runMatchers` uses, {@link recognizeMatch}
|
|
29
|
+
* agrees with the async `runMatchers` on `type` / `specificity` / `renderer` for
|
|
30
|
+
* every input. This is "use the existing matchers" literally — same functions,
|
|
31
|
+
* same arbitration.
|
|
32
|
+
*
|
|
33
|
+
* The winning `MatchResult.renderer` is carried on `documentJson.renderer` so
|
|
34
|
+
* WI-C can wire presentation via `TYPE_PRESENTATION` without a new
|
|
35
|
+
* `IndexDocument` field (WI-C owns presentation).
|
|
36
|
+
*
|
|
37
|
+
* ── conceptId (§5.1 + ref-grammar decision D-R2): the QUALIFIED spelling ──
|
|
38
|
+
*
|
|
39
|
+
* conceptId = `<stash-subdir>/<canonical-name>` — the placement stash-subdir
|
|
40
|
+
* (`stashDirFor(type)`) followed by the winning type's canonical name
|
|
41
|
+
* (`deriveCanonicalAssetNameFromStashRoot`: skill = its dir, script keeps its
|
|
42
|
+
* extension, markdown strips `.md`, env/task strip their ext, secret/session
|
|
43
|
+
* keep the natural path). For markdown types this IS the OKF concept ID
|
|
44
|
+
* (path − `.md`); it is the same spelling {@link placeNew} consumes, so
|
|
45
|
+
* recognize/place share one identity (D-R2 resolved the earlier split). The
|
|
46
|
+
* `type` is carried separately on `IndexDocument.type`, per §0.2 (type ≠
|
|
47
|
+
* identity), and `entry.name` keeps the BARE canonical name for FTS parity.
|
|
48
|
+
*
|
|
49
|
+
* ── placeNew / directoryList / looksLikeRoot: type-driven placement ──
|
|
50
|
+
*
|
|
51
|
+
* Placement is type-driven (`path-resolver.ts#buildDiskCandidates`: the primary
|
|
52
|
+
* candidate is `assetPathForName(ref.type, join(root, stashDirFor(ref.type)),
|
|
53
|
+
* ref.name)`). §5.1 removes `type` from the ref, so {@link placeNew} recovers
|
|
54
|
+
* it from the conceptId's LEADING path segment — the qualified `<stash-subdir>/
|
|
55
|
+
* <name>` form of §1.3 — reverse-mapping that segment against the placement
|
|
56
|
+
* stash-subdir map and then delegating to `assetPathForName`. See the method
|
|
57
|
+
* doc for the recognize/place conceptId-spelling note.
|
|
58
|
+
*
|
|
59
|
+
* ── validate: base checks only (WI-B) ──
|
|
60
|
+
*
|
|
61
|
+
* Base validate checks only for this WI (shared `validateChangesWithBaseChecks`
|
|
62
|
+
* — the ported unquoted-colon / missing-updated / stale-path / missing-ref).
|
|
63
|
+
* The per-type linters (SkillLinter/WorkflowLinter/TaskLinter/…) are WI-C.
|
|
64
|
+
*
|
|
65
|
+
* ── Cycle-safety (chunk-3 cutover, baseline 18) ──
|
|
66
|
+
*
|
|
67
|
+
* This module VALUE-imports `matchers.ts` (indexer/walk) for classification and
|
|
68
|
+
* `asset-placement.ts` (core/asset) for placement — delegating to the existing
|
|
69
|
+
* logic, not re-implementing it. Neither is a taxonomy import-cycle (SCC)
|
|
70
|
+
* participant: `matchers.ts` resolves renderers via `type-presentation.ts`, and
|
|
71
|
+
* `asset-placement.ts` is a pure leaf (only Node builtins + `recognition-util`).
|
|
72
|
+
* Nothing in `src/` imports this adapter back (only the test-only
|
|
73
|
+
* `adapters/index.ts` barrel does, and nothing in `src/` imports THAT), so the
|
|
74
|
+
* adapter is itself a leaf — verified: `bun scripts/lint-import-cycles.ts` stays
|
|
75
|
+
* within baseline and this module is NOT a participant.
|
|
76
|
+
*/
|
|
77
|
+
import fs from "node:fs";
|
|
78
|
+
import path from "node:path";
|
|
79
|
+
import { parse as parseYaml } from "yaml";
|
|
80
|
+
import { applyPostContributorFields, applyPreContributorFields, extractPackageMetadata, } from "../../../indexer/passes/metadata.js";
|
|
81
|
+
import { assetPathForName, deriveCanonicalAssetNameFromStashRoot, placementTypes, stashDirFor, stashDirNames, } from "../../asset/asset-placement.js";
|
|
82
|
+
import { parseFrontmatter } from "../../asset/frontmatter.js";
|
|
83
|
+
import { recognizeMatch } from "../recognize-match.js";
|
|
84
|
+
import { perTypeValidateChecks, skillDirectoryDiagnostics } from "./akm-lint.js";
|
|
85
|
+
import { applyFoldedMetadata, foldRecognizedMetadata } from "./akm-metadata.js";
|
|
86
|
+
import { hashContent, runBaseValidateChecks } from "./shared.js";
|
|
87
|
+
// `recognizeMatch` + the builtin matcher list moved to the cycle-free leaf
|
|
88
|
+
// `../recognize-match` (Chunk 5 M-b) so both this adapter AND the indexer
|
|
89
|
+
// metadata pass import it without closing a metadata ↔ adapter cycle. Re-exported
|
|
90
|
+
// here so existing `akm-adapter` importers (tests, sibling modules) are
|
|
91
|
+
// unaffected.
|
|
92
|
+
export { recognizeMatch } from "../recognize-match.js";
|
|
93
|
+
/**
|
|
94
|
+
* OKF reserved structural files (ref-grammar decision D-R6, spec §5.1 /
|
|
95
|
+
* adapter-spec §5.1/§6): `index.md` (directory listing) and `log.md` (update
|
|
96
|
+
* history) are bundle structure at EVERY depth — never a concept document. The
|
|
97
|
+
* `okf` / `llm-wiki` adapters already exclude them (`okf-adapter.ts`
|
|
98
|
+
* `RESERVED_FILES`); this brings the `akm` adapter into conformance so a
|
|
99
|
+
* `knowledge/index.md` never classifies as a `knowledge` item. Case-insensitive,
|
|
100
|
+
* matched on the bare filename so the exclusion holds at any depth.
|
|
101
|
+
*/
|
|
102
|
+
const RESERVED_FILES = new Set(["index.md", "log.md"]);
|
|
103
|
+
/** True when `name` (a bare file name) is an OKF reserved file, case-insensitively (D-R6). */
|
|
104
|
+
function isReservedFileName(name) {
|
|
105
|
+
return RESERVED_FILES.has(name.toLowerCase());
|
|
106
|
+
}
|
|
107
|
+
/** Wiki-directory infrastructure files excluded at a `wikis/<name>/` root (ported from the retired `shouldIndexStashFile`). */
|
|
108
|
+
const WIKI_INFRA_FILES = new Set(["schema.md", "index.md", "log.md"]);
|
|
109
|
+
/**
|
|
110
|
+
* AKM-stash indexing policy, moved here from the indexer's `shouldIndexStashFile`
|
|
111
|
+
* pre-filter (owner ruling 2026-07-21 — adapter-owned filtering). Each adapter
|
|
112
|
+
* abstains on its own bundle's files; the core walk keeps only universal hygiene.
|
|
113
|
+
*
|
|
114
|
+
* PATH/STAT-based ONLY — never reads `file.content()`, so the bytes-never-read
|
|
115
|
+
* invariant for sensitive env/secret files holds by construction. Returns `true`
|
|
116
|
+
* when the `akm` adapter must ABSTAIN (recognize → null):
|
|
117
|
+
* - an `env/…` `.env` file with a sibling `.sensitive` marker;
|
|
118
|
+
* - anything under the frozen legacy `vaults/` dir (the `vault` type is gone);
|
|
119
|
+
* - a `secrets/` `.sensitive`/`.lock` marker, or a secret with a sibling
|
|
120
|
+
* `<name>.sensitive` marker;
|
|
121
|
+
* - a `wikis/<name>/` root-level infra file (schema.md/index.md/log.md).
|
|
122
|
+
*/
|
|
123
|
+
function akmStashAbstains(root, absPath) {
|
|
124
|
+
const relPath = path.relative(root, absPath);
|
|
125
|
+
if (!relPath || relPath.startsWith("..") || path.isAbsolute(relPath))
|
|
126
|
+
return false;
|
|
127
|
+
const segments = relPath.split(/[\\/]+/).filter(Boolean);
|
|
128
|
+
if (segments.length === 0)
|
|
129
|
+
return false;
|
|
130
|
+
// Skip env `.env` files that have a sibling `.sensitive` marker file.
|
|
131
|
+
if (segments[0] === "env" && (absPath.endsWith(".env") || path.basename(absPath) === ".env")) {
|
|
132
|
+
if (fs.existsSync(absPath.replace(/\.env$/, ".sensitive")))
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
// The legacy `vaults/` directory (frozen copy left by the 0.8 migration) is
|
|
136
|
+
// never indexed — the `vault` asset type was removed in 0.9.0.
|
|
137
|
+
if (segments[0] === "vaults")
|
|
138
|
+
return true;
|
|
139
|
+
// Skip secret files that are themselves a `.sensitive` marker, or that have a
|
|
140
|
+
// sibling `<name>.sensitive` marker. Secrets are otherwise indexed by name
|
|
141
|
+
// only (their bytes are never read for classification here).
|
|
142
|
+
if (segments[0] === "secrets") {
|
|
143
|
+
if (absPath.endsWith(".sensitive") || absPath.endsWith(".lock"))
|
|
144
|
+
return true;
|
|
145
|
+
if (fs.existsSync(`${absPath}.sensitive`))
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
// Inside a `wikis/<name>/` directory, the root-level infrastructure files
|
|
149
|
+
// schema.md / index.md / log.md are excluded.
|
|
150
|
+
const wikisIdx = segments.indexOf("wikis");
|
|
151
|
+
if (wikisIdx < 0 || wikisIdx + 1 >= segments.length)
|
|
152
|
+
return false;
|
|
153
|
+
const wikiRelativeSegments = segments.slice(wikisIdx + 2);
|
|
154
|
+
return wikiRelativeSegments.length === 1 && WIKI_INFRA_FILES.has(wikiRelativeSegments[0]);
|
|
155
|
+
}
|
|
156
|
+
/** Reverse the placement map (stash subdir → akm type). Built per call so a runtime-registered custom type is honored (live-delegation, not a snapshot). */
|
|
157
|
+
function stashDirToType(stashDir) {
|
|
158
|
+
for (const type of placementTypes()) {
|
|
159
|
+
if (stashDirFor(type) === stashDir)
|
|
160
|
+
return type;
|
|
161
|
+
}
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The search-surface `IndexDocument` fields that have NO first-class `IndexDocument`
|
|
166
|
+
* home (spec §3) and therefore ride `documentJson` so the persist-time fold
|
|
167
|
+
* (`search-fields.ts:28-33`) can still reach them — the exact set
|
|
168
|
+
* `buildSearchFields` folds into the `hints`/`content` FTS columns beyond the
|
|
169
|
+
* first-class name/description/tags/aliases/searchHints, plus the provenance the
|
|
170
|
+
* WI-C tests read (renderer/source). Kept as a named list so the fold surface and
|
|
171
|
+
* the mapping stay in lockstep.
|
|
172
|
+
*/
|
|
173
|
+
const DOCUMENT_JSON_CARRIED_FIELDS = [
|
|
174
|
+
"examples",
|
|
175
|
+
"usage",
|
|
176
|
+
"intent",
|
|
177
|
+
"xrefs",
|
|
178
|
+
"pageKind",
|
|
179
|
+
"whenToUse",
|
|
180
|
+
"toc",
|
|
181
|
+
"parameters",
|
|
182
|
+
"bodyOpening",
|
|
183
|
+
"source",
|
|
184
|
+
"category",
|
|
185
|
+
"supersededBy",
|
|
186
|
+
"contradictedBy",
|
|
187
|
+
"run",
|
|
188
|
+
"setup",
|
|
189
|
+
"cwd",
|
|
190
|
+
"wikiRole",
|
|
191
|
+
"sources",
|
|
192
|
+
"generation",
|
|
193
|
+
"sourceRefs",
|
|
194
|
+
"evidenceSources",
|
|
195
|
+
];
|
|
196
|
+
/**
|
|
197
|
+
* Map the fully-assembled `IndexDocument` (produced by the shared metadata
|
|
198
|
+
* pipeline) onto an `IndexDocument` (spec §3). First-class ranking/embedding
|
|
199
|
+
* fields land on named IndexDocument fields; every other search-surface or
|
|
200
|
+
* signal field rides `documentJson` (opaque adapter extras) so nothing the
|
|
201
|
+
* ranking/embedding/filter inputs read is lost — the M-b shadow-parity gate.
|
|
202
|
+
* The winning renderer name is carried on `documentJson.renderer` (WI-C contract).
|
|
203
|
+
*/
|
|
204
|
+
function indexDocumentFromEntry(entry, base, rendererName) {
|
|
205
|
+
const extras = { renderer: rendererName };
|
|
206
|
+
for (const field of DOCUMENT_JSON_CARRIED_FIELDS) {
|
|
207
|
+
const value = entry[field];
|
|
208
|
+
if (value !== undefined)
|
|
209
|
+
extras[field] = value;
|
|
210
|
+
}
|
|
211
|
+
const doc = {
|
|
212
|
+
...base,
|
|
213
|
+
name: entry.name,
|
|
214
|
+
documentJson: extras,
|
|
215
|
+
};
|
|
216
|
+
// First-class search + signal fields (only when present).
|
|
217
|
+
if (entry.description !== undefined)
|
|
218
|
+
doc.description = entry.description;
|
|
219
|
+
if (entry.tags !== undefined)
|
|
220
|
+
doc.tags = entry.tags;
|
|
221
|
+
if (entry.aliases !== undefined)
|
|
222
|
+
doc.aliases = entry.aliases;
|
|
223
|
+
if (entry.searchHints !== undefined)
|
|
224
|
+
doc.searchHints = entry.searchHints;
|
|
225
|
+
if (entry.quality !== undefined)
|
|
226
|
+
doc.quality = entry.quality;
|
|
227
|
+
if (entry.confidence !== undefined)
|
|
228
|
+
doc.confidence = entry.confidence;
|
|
229
|
+
if (entry.beliefState !== undefined)
|
|
230
|
+
doc.beliefState = entry.beliefState;
|
|
231
|
+
if (entry.currentBeliefRefs !== undefined)
|
|
232
|
+
doc.currentBeliefRefs = entry.currentBeliefRefs;
|
|
233
|
+
if (entry.scope !== undefined)
|
|
234
|
+
doc.scope = entry.scope;
|
|
235
|
+
if (entry.captureMode !== undefined)
|
|
236
|
+
doc.captureMode = entry.captureMode;
|
|
237
|
+
if (entry.lessonStrength !== undefined)
|
|
238
|
+
doc.lessonStrength = entry.lessonStrength;
|
|
239
|
+
if (entry.derivedFrom !== undefined)
|
|
240
|
+
doc.derivedFrom = entry.derivedFrom;
|
|
241
|
+
return doc;
|
|
242
|
+
}
|
|
243
|
+
function recognize(c, file) {
|
|
244
|
+
// D-R6 (spec §5.1): `index.md` / `log.md` are OKF reserved structural files at
|
|
245
|
+
// every depth — never items. Excluded BEFORE classification so a directory
|
|
246
|
+
// listing or update log never becomes a `knowledge` (or other) concept.
|
|
247
|
+
if (isReservedFileName(file.fileName))
|
|
248
|
+
return null;
|
|
249
|
+
// Adapter-owned filtering (owner ruling 2026-07-21): AKM-stash policy that used
|
|
250
|
+
// to live in the indexer's `shouldIndexStashFile` pre-filter. Path/stat-based —
|
|
251
|
+
// `file.content()` is never read to reach this abstention.
|
|
252
|
+
if (akmStashAbstains(c.root, file.absPath))
|
|
253
|
+
return null;
|
|
254
|
+
const match = recognizeMatch(file);
|
|
255
|
+
if (match === null)
|
|
256
|
+
return null;
|
|
257
|
+
// canonical name = the winning type's per-type canonical name (§5.1:
|
|
258
|
+
// reproduce AssetSpec.toCanonicalName). Fall back to the BASENAME minus its
|
|
259
|
+
// extension only if the type's toCanonicalName abstains (e.g. a `skills/x.md`
|
|
260
|
+
// flat file, or a `SKILL.md` sitting directly at the skills/ root with no name
|
|
261
|
+
// dir). The basename fallback is byte-identical to the pre-0.9.0 flat-walk's
|
|
262
|
+
// `?? baseName` fallback (metadata.ts `generateMetadata`), so `entry.name`
|
|
263
|
+
// stays the BARE canonical name — never the stash-root-relative path, which
|
|
264
|
+
// would re-embed the `<stash-subdir>/` type prefix and double-prefix every
|
|
265
|
+
// downstream legacy `type:name` ref (e.g. `skill:skills/x`).
|
|
266
|
+
const derived = deriveCanonicalAssetNameFromStashRoot(match.type, c.root, file.absPath);
|
|
267
|
+
const canonicalName = derived ?? path.basename(file.absPath).replace(/\.[^./]+$/, "");
|
|
268
|
+
// conceptId = the QUALIFIED `<stash-subdir>/<canonical-name>` spelling
|
|
269
|
+
// (ref-grammar decision D-R2): the same form `placeNew` consumes, and for
|
|
270
|
+
// markdown types the OKF concept ID (path − .md). Both branches now feed a
|
|
271
|
+
// BARE canonicalName (the abstain fallback is the basename, above), so the
|
|
272
|
+
// stash-subdir is prefixed uniformly — a flat `skills/x.md` yields
|
|
273
|
+
// `skills/x`, never the un-prefixed `x` or the double-prefixed
|
|
274
|
+
// `skills/skills/x`. `entry.name` below keeps the BARE canonical name —
|
|
275
|
+
// identity ≠ search text.
|
|
276
|
+
const stashDir = stashDirFor(match.type);
|
|
277
|
+
const conceptId = stashDir !== undefined ? `${stashDir}/${canonicalName}` : canonicalName;
|
|
278
|
+
const dirPath = path.dirname(file.absPath);
|
|
279
|
+
// Chunk 5 M-b: recognize now carries the FULL index-time metadata surface
|
|
280
|
+
// (spec §2/§3), reproducing `buildEntryFromFile`'s flat-walk metadata
|
|
281
|
+
// output by SHARING its P1/P2/P4 assembly and substituting the synchronous
|
|
282
|
+
// `foldRecognizedMetadata` (+ `applyFoldedMetadata`, which replicates the
|
|
283
|
+
// in-place contributor precedence) for the async P3 renderer contributors.
|
|
284
|
+
// `entry.name` = the BARE canonical name (conceptId minus the D-R2 stash-subdir
|
|
285
|
+
// prefix) so the FTS `name` column
|
|
286
|
+
// matches the pre-0.9.0 indexer (search-behavior parity), NOT the frontmatter
|
|
287
|
+
// title. Parity is by construction — the two paths differ only in the P3 step,
|
|
288
|
+
// pinned equal by the akm-adapter fold-parity test.
|
|
289
|
+
const entry = {
|
|
290
|
+
name: canonicalName,
|
|
291
|
+
type: match.type,
|
|
292
|
+
quality: "generated",
|
|
293
|
+
confidence: 0.55,
|
|
294
|
+
source: "filename",
|
|
295
|
+
};
|
|
296
|
+
applyPreContributorFields(entry, file.absPath, file, extractPackageMetadata(dirPath));
|
|
297
|
+
applyFoldedMetadata(entry, foldRecognizedMetadata(match.renderer, file));
|
|
298
|
+
applyPostContributorFields(entry, file.absPath, canonicalName, dirPath);
|
|
299
|
+
return indexDocumentFromEntry(entry, {
|
|
300
|
+
ref: `${c.id}//${conceptId}`,
|
|
301
|
+
bundle: c.id,
|
|
302
|
+
component: c.id,
|
|
303
|
+
conceptId,
|
|
304
|
+
path: file.absPath,
|
|
305
|
+
// Hash over the full raw bytes (incrementality/fingerprints, `types.ts`
|
|
306
|
+
// hash doc comment) — an opaque digest, not indexed content.
|
|
307
|
+
hash: hashContent(file.content()),
|
|
308
|
+
adapterId: "akm",
|
|
309
|
+
type: match.type,
|
|
310
|
+
}, match.renderer);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* A read-only {@link FileContext} backed by an OVERLAY string (a pending
|
|
314
|
+
* change's content) instead of the live filesystem — the `validate` contract
|
|
315
|
+
* ({@link BundleAdapter.validate} doc comment / adapter-spec §12.1) forbids
|
|
316
|
+
* reading the live FS. It mirrors `buildFileContext`'s eager path-field
|
|
317
|
+
* derivation exactly (so the matchers classify identically) and serves the
|
|
318
|
+
* overlay bytes from `content()`/`frontmatter()`. `stat()` throws: no matcher
|
|
319
|
+
* calls it, and there is no snapshot mtime to serve.
|
|
320
|
+
*/
|
|
321
|
+
function buildOverlayContext(root, relPathInput, raw) {
|
|
322
|
+
const absPath = path.join(root, relPathInput);
|
|
323
|
+
const relPath = path.relative(root, absPath).replace(/\\/g, "/");
|
|
324
|
+
const ext = path.extname(absPath).toLowerCase();
|
|
325
|
+
const fileName = path.basename(absPath);
|
|
326
|
+
const parentDirAbs = path.dirname(absPath);
|
|
327
|
+
const parentDir = path.basename(parentDirAbs);
|
|
328
|
+
const relDir = path.dirname(relPath).replace(/\\/g, "/");
|
|
329
|
+
const ancestorDirs = relDir === "." ? [] : relDir.split("/").filter((seg) => seg.length > 0);
|
|
330
|
+
let cachedFrontmatter;
|
|
331
|
+
let frontmatterComputed = false;
|
|
332
|
+
return {
|
|
333
|
+
absPath,
|
|
334
|
+
relPath,
|
|
335
|
+
ext,
|
|
336
|
+
fileName,
|
|
337
|
+
parentDir,
|
|
338
|
+
parentDirAbs,
|
|
339
|
+
ancestorDirs,
|
|
340
|
+
stashRoot: root,
|
|
341
|
+
content: () => raw,
|
|
342
|
+
frontmatter: () => {
|
|
343
|
+
if (!frontmatterComputed) {
|
|
344
|
+
const parsed = parseFrontmatter(raw);
|
|
345
|
+
cachedFrontmatter = Object.keys(parsed.data).length > 0 ? parsed.data : null;
|
|
346
|
+
frontmatterComputed = true;
|
|
347
|
+
}
|
|
348
|
+
return cachedFrontmatter ?? null;
|
|
349
|
+
},
|
|
350
|
+
stat: () => {
|
|
351
|
+
throw new Error("stat() is unavailable in a validate overlay FileContext");
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* `validate` (spec §6) = shared base checks + the winning `type`'s per-type
|
|
357
|
+
* extra checks, reproducing today's `akmLint`/`getLinterForType` dispatch
|
|
358
|
+
* byte-for-byte (the FROZEN `lint/all-types.json` `perType` golden is the gate).
|
|
359
|
+
*
|
|
360
|
+
* Per change (non-delete, readable): the `type` is recovered by running the
|
|
361
|
+
* SAME sync matcher arbitration ({@link recognizeMatch}) over an OVERLAY
|
|
362
|
+
* FileContext ({@link buildOverlayContext}) — no live-FS read. `task` files are
|
|
363
|
+
* parsed as pure YAML (mirroring `lint/index.ts`'s `subdir === "tasks"` branch)
|
|
364
|
+
* so the TaskLinter's field checks see real data and `missing-updated` never
|
|
365
|
+
* fires (frontmatter is `null`); everything else parses via `parseFrontmatter`.
|
|
366
|
+
* Base checks (shared) then the per-type extra checks run; a `skills/` directory
|
|
367
|
+
* pass reproduces `SkillLinter.lintDirectory` across the change set.
|
|
368
|
+
*/
|
|
369
|
+
async function validate(c, changes, ctx) {
|
|
370
|
+
const diagnostics = [];
|
|
371
|
+
const seenSkillDirs = new Set();
|
|
372
|
+
for (const change of changes) {
|
|
373
|
+
if (change.op === "delete")
|
|
374
|
+
continue;
|
|
375
|
+
const raw = change.after ?? (await ctx.readFile(change.path));
|
|
376
|
+
if (typeof raw !== "string")
|
|
377
|
+
continue;
|
|
378
|
+
const overlay = buildOverlayContext(c.root, change.path, raw);
|
|
379
|
+
const match = recognizeMatch(overlay);
|
|
380
|
+
const type = match?.type;
|
|
381
|
+
// Parse strategy per `lint/index.ts`: `task` → pure YAML (frontmatter null),
|
|
382
|
+
// everything else → `parseFrontmatter`.
|
|
383
|
+
let parsed;
|
|
384
|
+
if (type === "task") {
|
|
385
|
+
let data = {};
|
|
386
|
+
try {
|
|
387
|
+
const doc = parseYaml(raw);
|
|
388
|
+
if (doc && typeof doc === "object" && !Array.isArray(doc))
|
|
389
|
+
data = doc;
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
data = {};
|
|
393
|
+
}
|
|
394
|
+
parsed = { data, content: raw, frontmatter: null };
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
const p = parseFrontmatter(raw);
|
|
398
|
+
parsed = { data: p.data, content: p.content, frontmatter: p.frontmatter };
|
|
399
|
+
}
|
|
400
|
+
diagnostics.push(...(await runBaseValidateChecks(change.path, parsed, c.root, ctx)));
|
|
401
|
+
diagnostics.push(...(await perTypeValidateChecks({
|
|
402
|
+
type,
|
|
403
|
+
relPath: change.path,
|
|
404
|
+
raw,
|
|
405
|
+
data: parsed.data,
|
|
406
|
+
frontmatter: parsed.frontmatter,
|
|
407
|
+
body: parsed.content,
|
|
408
|
+
ext: overlay.ext,
|
|
409
|
+
ctx,
|
|
410
|
+
})));
|
|
411
|
+
diagnostics.push(...(await skillDirectoryDiagnostics(change.path, seenSkillDirs, ctx)));
|
|
412
|
+
}
|
|
413
|
+
return diagnostics;
|
|
414
|
+
}
|
|
415
|
+
export const akmAdapter = {
|
|
416
|
+
id: "akm",
|
|
417
|
+
version: "0.9.0",
|
|
418
|
+
// Recognized-extension HINT, derived from what the matchers accept (§6):
|
|
419
|
+
// `.md` (markdown types + skill), `.yaml`/`.yml` (workflow programs,
|
|
420
|
+
// task YAML), `.env` (env files), and the 16 SCRIPT_EXTENSIONS. This is a
|
|
421
|
+
// NON-EXHAUSTIVE hint for the akm adapter: recognition is directory-driven
|
|
422
|
+
// via `recognize()` (e.g. a bare `secrets/<anything>` file with no extension
|
|
423
|
+
// is a `secret`), so `recognize()` — not this list — is the source of truth.
|
|
424
|
+
extensions: [
|
|
425
|
+
".md",
|
|
426
|
+
".yaml",
|
|
427
|
+
".yml",
|
|
428
|
+
".env",
|
|
429
|
+
".sh",
|
|
430
|
+
".ts",
|
|
431
|
+
".js",
|
|
432
|
+
".ps1",
|
|
433
|
+
".cmd",
|
|
434
|
+
".bat",
|
|
435
|
+
".py",
|
|
436
|
+
".rb",
|
|
437
|
+
".go",
|
|
438
|
+
".pl",
|
|
439
|
+
".php",
|
|
440
|
+
".lua",
|
|
441
|
+
".r",
|
|
442
|
+
".swift",
|
|
443
|
+
".kt",
|
|
444
|
+
".kts",
|
|
445
|
+
],
|
|
446
|
+
recognize,
|
|
447
|
+
validate,
|
|
448
|
+
/**
|
|
449
|
+
* Type-driven placement (§5.1), reproducing `path-resolver.ts#buildDiskCandidates`:
|
|
450
|
+
* the primary candidate is
|
|
451
|
+
* `assetPathForName(type, join(root, stashDirFor(type)), name)`.
|
|
452
|
+
*
|
|
453
|
+
* §5.1 removes `type` from the ref, so the winning type is recovered from the
|
|
454
|
+
* conceptId's LEADING path segment — the §1.3 qualified `<stash-subdir>/<name>`
|
|
455
|
+
* form (e.g. `knowledge/http-caching`, `workflows/release`, `skills/<dir>`).
|
|
456
|
+
* The leading segment is reverse-mapped against the placement stash-subdir map;
|
|
457
|
+
* the remainder is the per-type name handed to `assetPathForName`. An
|
|
458
|
+
* unqualified conceptId (no recognized leading stash-subdir) falls back to a
|
|
459
|
+
* direct `<root>/<conceptId>.md` — the same `${name}.md` fallback
|
|
460
|
+
* `buildDiskCandidates` carries (`preserveDirectNameFallback`).
|
|
461
|
+
*
|
|
462
|
+
* `recognize()` emits the SAME qualified spelling (ref-grammar decision
|
|
463
|
+
* D-R2), so recognize/place share one canonical identity — the earlier
|
|
464
|
+
* bare-vs-qualified split is resolved.
|
|
465
|
+
*/
|
|
466
|
+
placeNew(c, conceptId) {
|
|
467
|
+
const posix = conceptId.replace(/\\/g, "/");
|
|
468
|
+
const slash = posix.indexOf("/");
|
|
469
|
+
if (slash > 0) {
|
|
470
|
+
const head = posix.slice(0, slash);
|
|
471
|
+
const rest = posix.slice(slash + 1);
|
|
472
|
+
const type = stashDirToType(head);
|
|
473
|
+
if (type !== undefined && rest.length > 0) {
|
|
474
|
+
const typeDir = path.join(c.root, head);
|
|
475
|
+
return assetPathForName(type, typeDir, rest);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return path.join(c.root, `${posix}.md`);
|
|
479
|
+
},
|
|
480
|
+
/** The AKM workspace's owned stash subdirs (§7): the placement stash-subdir names, feeding git exact-path staging. */
|
|
481
|
+
directoryList(_c) {
|
|
482
|
+
return [...new Set(stashDirNames())];
|
|
483
|
+
},
|
|
484
|
+
/**
|
|
485
|
+
* Install-time probe (§1.2), reproducing today's stash-root detection
|
|
486
|
+
* (`provider-utils.ts#detectStashRoot`/`hasStashDirs`): a root is an AKM
|
|
487
|
+
* workspace root when it carries a `.stash` marker directory OR any immediate
|
|
488
|
+
* subdirectory named after a placement stash subdir. Pure stat/readdir; a
|
|
489
|
+
* missing/unreadable root is not a root.
|
|
490
|
+
*/
|
|
491
|
+
looksLikeRoot(root) {
|
|
492
|
+
try {
|
|
493
|
+
if (fs.statSync(path.join(root, ".stash")).isDirectory())
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
catch {
|
|
497
|
+
// no .stash marker — fall through to the type-dir probe
|
|
498
|
+
}
|
|
499
|
+
const ownedDirNames = new Set(stashDirNames());
|
|
500
|
+
let entries;
|
|
501
|
+
try {
|
|
502
|
+
entries = fs.readdirSync(root, { withFileTypes: true });
|
|
503
|
+
}
|
|
504
|
+
catch {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
return entries.some((entry) => entry.isDirectory() && ownedDirNames.has(entry.name));
|
|
508
|
+
},
|
|
509
|
+
};
|