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,416 @@
|
|
|
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
|
+
* Index-time metadata fold for the `akm` adapter's `recognize` — akm 0.9.0
|
|
6
|
+
* chunk-2, WI-C, implementing spec §2 ("the nine index-time metadata
|
|
7
|
+
* contributors move into recognize") + the 2 workflow contributors.
|
|
8
|
+
*
|
|
9
|
+
* This leaf reproduces the 11 `registerMetadataContributor` sites keyed on the
|
|
10
|
+
* winning RENDERER name (exactly how each contributor's `appliesTo({ rendererName })`
|
|
11
|
+
* selects):
|
|
12
|
+
*
|
|
13
|
+
* - `output/renderers.ts` (9): toc-metadata (knowledge-md),
|
|
14
|
+
* lesson-frontmatter-metadata, memory-frontmatter-metadata,
|
|
15
|
+
* script-comment-metadata, env-file-metadata, secret-file-metadata,
|
|
16
|
+
* task-yaml-metadata, session-md-metadata, fact-md-metadata;
|
|
17
|
+
* - `workflows/renderer.ts` (2): workflow-document-metadata (workflow-md),
|
|
18
|
+
* workflow-program-metadata (workflow-program-yaml).
|
|
19
|
+
*
|
|
20
|
+
* ── Cycle-safety (chunk-2 ratchet, baseline 18) ──
|
|
21
|
+
*
|
|
22
|
+
* Imported ONLY by `akm-adapter.ts` (itself imported by nothing in `src/` — see
|
|
23
|
+
* that file's header), so this leaf can never gain an inbound edge from a cycle
|
|
24
|
+
* participant and therefore can never JOIN a cycle. It VALUE-imports the pure
|
|
25
|
+
* parsers each contributor already uses so the fold cannot drift from them:
|
|
26
|
+
* `parseFrontmatter`, `parseMarkdownToc`, `parseWorkflow`, `parseWorkflowProgram`,
|
|
27
|
+
* `projectProgramParameters`/`programStepInstructions`, and `listKeys`
|
|
28
|
+
* (env key-names). `output/renderers.ts` / `workflows/renderer.ts` are the
|
|
29
|
+
* cycle-sensitive modules whose contributor bodies live in this port — their
|
|
30
|
+
* ONE non-importable helper (`metadata.ts#extractDescriptionFromComments`, a
|
|
31
|
+
* heavy cycle-participant module) is copied verbatim below as
|
|
32
|
+
* {@link extractDescriptionFromComments} rather than imported. Verified:
|
|
33
|
+
* `bun scripts/lint-import-cycles.ts` stays at 18.
|
|
34
|
+
*
|
|
35
|
+
* ── What is folded, and where it lands on the IndexDocument ──
|
|
36
|
+
*
|
|
37
|
+
* The contributors mutate a `IndexDocument`; {@link foldRecognizedMetadata} returns
|
|
38
|
+
* the same fields as a plain {@link FoldedMetadata}, which `recognize` maps onto
|
|
39
|
+
* `IndexDocument` first-class fields (`tags`/`searchHints`/`description`/
|
|
40
|
+
* `confidence`) and, for the fields without a first-class home
|
|
41
|
+
* (`toc`/`parameters`/`source`), onto `documentJson` (opaque adapter extras).
|
|
42
|
+
* The seed is a MINIMAL entry (name+type only): this isolates exactly what the
|
|
43
|
+
* contributors add, which is what the parity test compares against
|
|
44
|
+
* `applyMetadataContributors` run on the same minimal seed.
|
|
45
|
+
*
|
|
46
|
+
* ── Tolerance note ──
|
|
47
|
+
*
|
|
48
|
+
* Every contributor that reads/parses content is reproduced with the SAME
|
|
49
|
+
* try/catch tolerance it has today (toc/memory/session/fact/task swallow parse
|
|
50
|
+
* errors). The two workflow contributors throw-to-skip in today's pipeline (a
|
|
51
|
+
* broken workflow is dropped by the metadata drain); here the parse is wrapped
|
|
52
|
+
* so a broken workflow yields no folded metadata instead of throwing out of the
|
|
53
|
+
* synchronous `recognize` — the drop-the-entry behavior is an index-drain
|
|
54
|
+
* concern (Chunk 4/5), not recognition's. On the valid Chunk-0b fixture this
|
|
55
|
+
* distinction never triggers.
|
|
56
|
+
*/
|
|
57
|
+
import fs from "node:fs";
|
|
58
|
+
import { parse as parseYaml } from "yaml";
|
|
59
|
+
import { listKeys } from "../../../commands/env/env.js";
|
|
60
|
+
import { parseWorkflow } from "../../../workflows/parser.js";
|
|
61
|
+
import { parseWorkflowProgram } from "../../../workflows/program/parser.js";
|
|
62
|
+
import { programStepInstructions, projectProgramParameters } from "../../../workflows/program/project.js";
|
|
63
|
+
import { parseFrontmatter } from "../../asset/frontmatter.js";
|
|
64
|
+
import { parseMarkdownToc } from "../../asset/markdown.js";
|
|
65
|
+
import { nonEmptyString } from "./shared.js";
|
|
66
|
+
/**
|
|
67
|
+
* Verbatim copy of `indexer/passes/metadata.ts#extractDescriptionFromComments`
|
|
68
|
+
* (`:1510-1552`) — `metadata.ts` is a heavy cycle-participant module, so the
|
|
69
|
+
* one non-importable helper `applyScriptMetadata` needs is copied here (the
|
|
70
|
+
* others are imported). Reads a leading JSDoc block or hash-comment run from the
|
|
71
|
+
* script file; returns `null` on read/parse miss.
|
|
72
|
+
*/
|
|
73
|
+
function extractDescriptionFromComments(filePath) {
|
|
74
|
+
let content;
|
|
75
|
+
try {
|
|
76
|
+
content = fs.readFileSync(filePath, "utf8");
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
const lines = content.split(/\r?\n/).slice(0, 50);
|
|
82
|
+
const blockStart = lines.findIndex((l) => /^\s*\/\*\*/.test(l));
|
|
83
|
+
if (blockStart >= 0) {
|
|
84
|
+
const desc = [];
|
|
85
|
+
for (let i = blockStart; i < lines.length; i++) {
|
|
86
|
+
const line = lines[i];
|
|
87
|
+
if (i > blockStart && /\*\//.test(line))
|
|
88
|
+
break;
|
|
89
|
+
const cleaned = line
|
|
90
|
+
.replace(/^\s*\/?\*\*?\s?/, "")
|
|
91
|
+
.replace(/\*\/\s*$/, "")
|
|
92
|
+
.trim();
|
|
93
|
+
if (cleaned)
|
|
94
|
+
desc.push(cleaned);
|
|
95
|
+
}
|
|
96
|
+
if (desc.length > 0)
|
|
97
|
+
return desc.join(" ");
|
|
98
|
+
}
|
|
99
|
+
let start = 0;
|
|
100
|
+
if (lines[0]?.startsWith("#!"))
|
|
101
|
+
start = 1;
|
|
102
|
+
const hashLines = [];
|
|
103
|
+
for (let i = start; i < lines.length; i++) {
|
|
104
|
+
const line = lines[i].trim();
|
|
105
|
+
if (line.startsWith("#") && !line.startsWith("#!")) {
|
|
106
|
+
hashLines.push(line.replace(/^#+\s*/, "").trim());
|
|
107
|
+
}
|
|
108
|
+
else if (line === "") {
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (hashLines.length > 0)
|
|
115
|
+
return hashLines.join(" ");
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Reproduce `applyFrontmatterDescriptionAndTags` (`output/renderers.ts:668-684`):
|
|
120
|
+
* set description/source/confidence from frontmatter (only when not already set)
|
|
121
|
+
* and merge frontmatter `tags:` onto the folded tags. Returns nothing — mutates
|
|
122
|
+
* `out`.
|
|
123
|
+
*/
|
|
124
|
+
function applyFrontmatterDescriptionAndTags(fm, out) {
|
|
125
|
+
const desc = nonEmptyString(fm.description);
|
|
126
|
+
if (desc && !out.description) {
|
|
127
|
+
out.description = desc;
|
|
128
|
+
out.source = "frontmatter";
|
|
129
|
+
out.confidence = 0.9;
|
|
130
|
+
}
|
|
131
|
+
if (Array.isArray(fm.tags) && fm.tags.length > 0) {
|
|
132
|
+
const fmTags = fm.tags.filter((t) => typeof t === "string" && t.trim().length > 0);
|
|
133
|
+
if (fmTags.length > 0) {
|
|
134
|
+
out.tags = Array.from(new Set([...(out.tags ?? []), ...fmTags]));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/** Collect + finalize a searchHints set the way every contributor does (`Array.from(hints).filter(Boolean)`, assigned only when non-empty). */
|
|
139
|
+
function finalizeHints(out, hints) {
|
|
140
|
+
if (hints.size > 0)
|
|
141
|
+
out.searchHints = Array.from(hints).filter(Boolean);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The metadata fold, keyed on the winning renderer NAME. Returns the fields the
|
|
145
|
+
* 11 contributors would add to a MINIMAL (name+type) `IndexDocument`. `recognize`
|
|
146
|
+
* maps the result onto the `IndexDocument`. Reads the live file (index-time, so
|
|
147
|
+
* disk reads are legitimate — unlike `validate`).
|
|
148
|
+
*/
|
|
149
|
+
export function foldRecognizedMetadata(rendererName, file) {
|
|
150
|
+
const out = {};
|
|
151
|
+
switch (rendererName) {
|
|
152
|
+
// ── toc-metadata (knowledge-md) ──
|
|
153
|
+
case "knowledge-md": {
|
|
154
|
+
try {
|
|
155
|
+
const toc = parseMarkdownToc(file.content());
|
|
156
|
+
if (toc.headings.length > 0)
|
|
157
|
+
out.toc = toc.headings;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// Non-fatal: skip TOC if file can't be read
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
// ── lesson-frontmatter-metadata (lesson-md) ──
|
|
165
|
+
case "lesson-md": {
|
|
166
|
+
try {
|
|
167
|
+
const fm = parseFrontmatter(file.content()).data;
|
|
168
|
+
applyFrontmatterDescriptionAndTags(fm, out);
|
|
169
|
+
const whenToUse = nonEmptyString(fm.when_to_use);
|
|
170
|
+
if (whenToUse)
|
|
171
|
+
finalizeHints(out, new Set([`when_to_use:${whenToUse}`]));
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Non-fatal: skip metadata extraction on parse error
|
|
175
|
+
}
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
// ── memory-frontmatter-metadata (memory-md) ──
|
|
179
|
+
case "memory-md": {
|
|
180
|
+
try {
|
|
181
|
+
const fm = parseFrontmatter(file.content()).data;
|
|
182
|
+
applyFrontmatterDescriptionAndTags(fm, out);
|
|
183
|
+
const hints = new Set();
|
|
184
|
+
const source = nonEmptyString(fm.source);
|
|
185
|
+
if (source)
|
|
186
|
+
hints.add(source);
|
|
187
|
+
const fmObservedAt = nonEmptyString(fm.observed_at);
|
|
188
|
+
if (fmObservedAt) {
|
|
189
|
+
hints.add(`observed_at:${fmObservedAt}`);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
try {
|
|
193
|
+
const isoDate = file.stat().mtime.toISOString().slice(0, 10);
|
|
194
|
+
hints.add(`observed_at:${isoDate}`);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// Non-fatal: skip mtime fallback on stat error
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const expires = nonEmptyString(fm.expires);
|
|
201
|
+
if (expires)
|
|
202
|
+
hints.add(`expires:${expires}`);
|
|
203
|
+
if (fm.subjective === true)
|
|
204
|
+
hints.add("subjective");
|
|
205
|
+
finalizeHints(out, hints);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
// Non-fatal: skip metadata extraction on error
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
// ── script-comment-metadata (script-source) ──
|
|
213
|
+
case "script-source": {
|
|
214
|
+
if (file.ext === ".md")
|
|
215
|
+
return out;
|
|
216
|
+
const commentDesc = extractDescriptionFromComments(file.absPath);
|
|
217
|
+
if (commentDesc && !out.description) {
|
|
218
|
+
out.description = commentDesc;
|
|
219
|
+
out.source = "comments";
|
|
220
|
+
out.confidence = 0.7;
|
|
221
|
+
}
|
|
222
|
+
return out;
|
|
223
|
+
}
|
|
224
|
+
// ── env-file-metadata (env-file) ──
|
|
225
|
+
case "env-file": {
|
|
226
|
+
const { keys } = listKeys(file.absPath);
|
|
227
|
+
if (keys.length > 0)
|
|
228
|
+
out.searchHints = keys;
|
|
229
|
+
out.tags = Array.from(new Set([...(out.tags ?? []), "env", "secrets"]));
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
232
|
+
// ── secret-file-metadata (secret-file) — tags only, NEVER reads the body ──
|
|
233
|
+
case "secret-file": {
|
|
234
|
+
out.tags = Array.from(new Set([...(out.tags ?? []), "secret", "sensitive"]));
|
|
235
|
+
return out;
|
|
236
|
+
}
|
|
237
|
+
// ── task-yaml-metadata (task-yaml) ──
|
|
238
|
+
case "task-yaml": {
|
|
239
|
+
out.tags = Array.from(new Set([...(out.tags ?? []), "task", "scheduled"]));
|
|
240
|
+
try {
|
|
241
|
+
const doc = parseYaml(file.content());
|
|
242
|
+
const data = doc && typeof doc === "object" && !Array.isArray(doc) ? doc : {};
|
|
243
|
+
const hints = new Set();
|
|
244
|
+
const schedule = nonEmptyString(data.schedule);
|
|
245
|
+
if (schedule)
|
|
246
|
+
hints.add(`schedule:${schedule}`);
|
|
247
|
+
const workflow = nonEmptyString(data.workflow);
|
|
248
|
+
if (workflow)
|
|
249
|
+
hints.add(`workflow:${workflow}`);
|
|
250
|
+
const prompt = nonEmptyString(data.prompt);
|
|
251
|
+
if (prompt)
|
|
252
|
+
hints.add(`prompt:${prompt}`);
|
|
253
|
+
finalizeHints(out, hints);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
// Non-fatal: skip metadata extraction on parse error
|
|
257
|
+
}
|
|
258
|
+
return out;
|
|
259
|
+
}
|
|
260
|
+
// ── session-md-metadata (session-md) ──
|
|
261
|
+
case "session-md": {
|
|
262
|
+
try {
|
|
263
|
+
const fm = parseFrontmatter(file.content()).data;
|
|
264
|
+
applyFrontmatterDescriptionAndTags(fm, out);
|
|
265
|
+
out.tags = Array.from(new Set([...(out.tags ?? []), "session"]));
|
|
266
|
+
const hints = new Set();
|
|
267
|
+
const harness = nonEmptyString(fm.harness);
|
|
268
|
+
if (harness)
|
|
269
|
+
hints.add(`harness:${harness}`);
|
|
270
|
+
const project = nonEmptyString(fm.project);
|
|
271
|
+
if (project)
|
|
272
|
+
hints.add(`project:${project}`);
|
|
273
|
+
const logPath = nonEmptyString(fm.log_path);
|
|
274
|
+
if (logPath)
|
|
275
|
+
hints.add(`log_path:${logPath}`);
|
|
276
|
+
finalizeHints(out, hints);
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
// Non-fatal: skip metadata extraction on parse error
|
|
280
|
+
}
|
|
281
|
+
return out;
|
|
282
|
+
}
|
|
283
|
+
// ── fact-md-metadata (fact-md) ──
|
|
284
|
+
case "fact-md": {
|
|
285
|
+
try {
|
|
286
|
+
const fm = parseFrontmatter(file.content()).data;
|
|
287
|
+
applyFrontmatterDescriptionAndTags(fm, out);
|
|
288
|
+
const tags = new Set([...(out.tags ?? []), "fact"]);
|
|
289
|
+
const hints = new Set();
|
|
290
|
+
const category = nonEmptyString(fm.category);
|
|
291
|
+
if (category) {
|
|
292
|
+
tags.add(category);
|
|
293
|
+
hints.add(`category:${category}`);
|
|
294
|
+
}
|
|
295
|
+
if (fm.pinned === true) {
|
|
296
|
+
tags.add("pinned");
|
|
297
|
+
hints.add("pinned");
|
|
298
|
+
}
|
|
299
|
+
out.tags = Array.from(tags).filter(Boolean);
|
|
300
|
+
finalizeHints(out, hints);
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// Non-fatal: skip metadata extraction on parse error
|
|
304
|
+
}
|
|
305
|
+
return out;
|
|
306
|
+
}
|
|
307
|
+
// ── workflow-document-metadata (workflow-md) ──
|
|
308
|
+
case "workflow-md": {
|
|
309
|
+
try {
|
|
310
|
+
const result = parseWorkflow(file.content(), { path: file.relPath });
|
|
311
|
+
if (!result.ok)
|
|
312
|
+
return out;
|
|
313
|
+
const doc = result.document;
|
|
314
|
+
const hints = new Set();
|
|
315
|
+
hints.add(doc.title);
|
|
316
|
+
for (const step of doc.steps) {
|
|
317
|
+
hints.add(step.title);
|
|
318
|
+
hints.add(step.id);
|
|
319
|
+
hints.add(step.instructions.text);
|
|
320
|
+
for (const criterion of step.completionCriteria ?? [])
|
|
321
|
+
hints.add(criterion.text);
|
|
322
|
+
}
|
|
323
|
+
out.searchHints = Array.from(hints).filter(Boolean);
|
|
324
|
+
if (doc.parameters?.length) {
|
|
325
|
+
out.parameters = doc.parameters.map((p) => ({
|
|
326
|
+
name: p.name,
|
|
327
|
+
...(p.description ? { description: p.description } : {}),
|
|
328
|
+
}));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
// See file header: broken workflows drop at drain time, not here.
|
|
333
|
+
}
|
|
334
|
+
return out;
|
|
335
|
+
}
|
|
336
|
+
// ── workflow-program-metadata (workflow-program-yaml) ──
|
|
337
|
+
case "workflow-program-yaml": {
|
|
338
|
+
try {
|
|
339
|
+
const result = parseWorkflowProgram(file.content(), { path: file.relPath });
|
|
340
|
+
if (!result.ok)
|
|
341
|
+
return out;
|
|
342
|
+
const program = result.program;
|
|
343
|
+
const hints = new Set();
|
|
344
|
+
hints.add(program.name);
|
|
345
|
+
for (const step of program.steps) {
|
|
346
|
+
hints.add(step.id);
|
|
347
|
+
if (step.title)
|
|
348
|
+
hints.add(step.title);
|
|
349
|
+
hints.add(programStepInstructions(step));
|
|
350
|
+
for (const criterion of step.gate?.criteria ?? [])
|
|
351
|
+
hints.add(criterion);
|
|
352
|
+
}
|
|
353
|
+
out.searchHints = Array.from(hints).filter(Boolean);
|
|
354
|
+
if (!out.description && program.description)
|
|
355
|
+
out.description = program.description;
|
|
356
|
+
const parameters = projectProgramParameters(program);
|
|
357
|
+
if (parameters?.length)
|
|
358
|
+
out.parameters = parameters;
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
// See file header: broken programs drop at drain time, not here.
|
|
362
|
+
}
|
|
363
|
+
return out;
|
|
364
|
+
}
|
|
365
|
+
default:
|
|
366
|
+
// No contributor applies to this renderer (e.g. skill-md/command-md/
|
|
367
|
+
// agent-md — the static-only mappings carry no metadata contributor).
|
|
368
|
+
return out;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Apply {@link foldRecognizedMetadata}'s output onto a `IndexDocument` with the
|
|
373
|
+
* SAME precedence the live in-place renderer contributors use (Chunk 5 M-b), so
|
|
374
|
+
* `entry.applyPreContributorFields → applyFoldedMetadata → applyPostContributorFields`
|
|
375
|
+
* reproduces `buildEntryFromFile`'s `P1/P2 → contributors → P4` byte-for-byte.
|
|
376
|
+
*
|
|
377
|
+
* Precedence, verified against every case in {@link foldRecognizedMetadata}:
|
|
378
|
+
* - description/source/confidence travel together and only when the entry has
|
|
379
|
+
* no description yet (contributors gate on `!entry.description`); a
|
|
380
|
+
* contributor that sets description WITHOUT source/confidence
|
|
381
|
+
* (workflow-program-yaml) leaves those untouched — mirrored by the
|
|
382
|
+
* `folded.source`/`folded.confidence` guards below;
|
|
383
|
+
* - tags UNION into the existing set (order-preserving Set dedup), matching the
|
|
384
|
+
* contributors' `Array.from(new Set([...entry.tags, ...added]))`;
|
|
385
|
+
* - searchHints / toc / parameters are SET (overwrite), matching the
|
|
386
|
+
* contributors' direct assignment.
|
|
387
|
+
*
|
|
388
|
+
* The fold computes each field unconditionally from an empty seed; re-gating on
|
|
389
|
+
* `entry` state here is what recovers the in-place precedence (the fold ≡
|
|
390
|
+
* contributors-on-a-minimal-seed is pinned by the akm-adapter fold-parity test).
|
|
391
|
+
*/
|
|
392
|
+
export function applyFoldedMetadata(entry, folded) {
|
|
393
|
+
if (folded.description && !entry.description) {
|
|
394
|
+
entry.description = folded.description;
|
|
395
|
+
if (folded.source)
|
|
396
|
+
entry.source = folded.source;
|
|
397
|
+
if (folded.confidence !== undefined)
|
|
398
|
+
entry.confidence = folded.confidence;
|
|
399
|
+
}
|
|
400
|
+
if (folded.tags && folded.tags.length > 0) {
|
|
401
|
+
entry.tags = Array.from(new Set([...(entry.tags ?? []), ...folded.tags]));
|
|
402
|
+
}
|
|
403
|
+
// searchHints MERGE (not overwrite): every live contributor seeds its hints
|
|
404
|
+
// from `new Set(entry.searchHints ?? [])` before adding, so a frontmatter
|
|
405
|
+
// `searchHints:` set by P2 (applyCuratedFrontmatter) survives and the
|
|
406
|
+
// contributor's hints append to it. The fold computes only the contributor's
|
|
407
|
+
// additions (from an empty seed), so unioning them onto the existing set —
|
|
408
|
+
// existing first, deduped, truthy-filtered — reproduces the live merge exactly.
|
|
409
|
+
if (folded.searchHints) {
|
|
410
|
+
entry.searchHints = Array.from(new Set([...(entry.searchHints ?? []), ...folded.searchHints])).filter(Boolean);
|
|
411
|
+
}
|
|
412
|
+
if (folded.toc)
|
|
413
|
+
entry.toc = folded.toc;
|
|
414
|
+
if (folded.parameters)
|
|
415
|
+
entry.parameters = folded.parameters;
|
|
416
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
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-task` adapter — akm 0.9.0 format-family work item (#46).
|
|
6
|
+
*
|
|
7
|
+
* A native akm task-YAML bundle (spec §6/§7). A `.yml` file derives
|
|
8
|
+
* `type: task`; conceptId strips the `.yml` extension. Tasks are AKM-native
|
|
9
|
+
* YAML, NOT OKF markdown concepts. Recognition does NOT gate on validity — an
|
|
10
|
+
* invalid task (e.g. two targets) is still RECOGNIZED; the `invalid-task-yaml`
|
|
11
|
+
* violation surfaces only in `validate`.
|
|
12
|
+
*
|
|
13
|
+
* ── validate (spec §6 task validation column) ──
|
|
14
|
+
*
|
|
15
|
+
* A task must declare a `schedule`, an `enabled` boolean, and EXACTLY ONE
|
|
16
|
+
* target (`prompt` XOR `workflow` XOR `command`). The akm adapter's
|
|
17
|
+
* `TaskLinter` port checks "at least one" target; the native task family here is
|
|
18
|
+
* STRICTER — declaring two targets is `invalid-task-yaml`. So this adapter owns
|
|
19
|
+
* a purpose-built one-target check rather than reusing that port.
|
|
20
|
+
*
|
|
21
|
+
* Conformance oracle (authored, DO NOT modify): fixture
|
|
22
|
+
* `tests/fixtures/bundles/akm-task/` + goldens
|
|
23
|
+
* `tests/fixtures/format-family-goldens/akm-task/{recognition,placement,lint,renderer}.json`.
|
|
24
|
+
*/
|
|
25
|
+
import fs from "node:fs";
|
|
26
|
+
import path from "node:path";
|
|
27
|
+
import { parse as parseYaml } from "yaml";
|
|
28
|
+
import { hashContent } from "./shared.js";
|
|
29
|
+
/** A native task bundle is single-component; its one component is `main`. */
|
|
30
|
+
const COMPONENT_ID = "main";
|
|
31
|
+
/** The task YAML extension (spec §6 task row). */
|
|
32
|
+
const TASK_EXT = ".yml";
|
|
33
|
+
/** The mutually-exclusive task target keys (exactly one required). */
|
|
34
|
+
const TARGET_KEYS = ["prompt", "workflow", "command"];
|
|
35
|
+
/** Upper bound on the bounded `content` FTS field (mirrors okf-adapter). */
|
|
36
|
+
const MAX_CONTENT_CHARS = 100_000;
|
|
37
|
+
function toPosix(p) {
|
|
38
|
+
return p.replace(/\\/g, "/");
|
|
39
|
+
}
|
|
40
|
+
function recognize(c, file) {
|
|
41
|
+
if (file.ext !== TASK_EXT)
|
|
42
|
+
return null;
|
|
43
|
+
const conceptId = toPosix(file.relPath).replace(/\.yml$/i, "");
|
|
44
|
+
const name = conceptId.split("/").pop() ?? conceptId;
|
|
45
|
+
const raw = file.content();
|
|
46
|
+
return {
|
|
47
|
+
ref: `${c.id}//${conceptId}`,
|
|
48
|
+
bundle: c.id,
|
|
49
|
+
component: COMPONENT_ID,
|
|
50
|
+
conceptId,
|
|
51
|
+
path: file.absPath,
|
|
52
|
+
hash: hashContent(raw),
|
|
53
|
+
adapterId: "akm-task",
|
|
54
|
+
type: "task",
|
|
55
|
+
name,
|
|
56
|
+
content: raw.length > MAX_CONTENT_CHARS ? raw.slice(0, MAX_CONTENT_CHARS) : raw,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** Parse a task YAML into a plain record (tolerant: malformed / non-mapping → {}). */
|
|
60
|
+
function parseTaskYaml(raw) {
|
|
61
|
+
try {
|
|
62
|
+
const doc = parseYaml(raw);
|
|
63
|
+
if (doc && typeof doc === "object" && !Array.isArray(doc))
|
|
64
|
+
return doc;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// malformed YAML
|
|
68
|
+
}
|
|
69
|
+
return {};
|
|
70
|
+
}
|
|
71
|
+
/** The native `invalid-task-yaml` check: schedule + enabled(boolean) + EXACTLY ONE target. */
|
|
72
|
+
function taskDiagnostics(relPath, data) {
|
|
73
|
+
if (Object.keys(data).length === 0)
|
|
74
|
+
return [];
|
|
75
|
+
const problems = [];
|
|
76
|
+
if (typeof data.schedule !== "string" || data.schedule.trim() === "")
|
|
77
|
+
problems.push("schedule");
|
|
78
|
+
if (typeof data.enabled !== "boolean")
|
|
79
|
+
problems.push("enabled (must be a boolean)");
|
|
80
|
+
const targets = TARGET_KEYS.filter((k) => k in data && data[k] !== undefined && data[k] !== null);
|
|
81
|
+
if (targets.length === 0)
|
|
82
|
+
problems.push("exactly one target (prompt, workflow, or command)");
|
|
83
|
+
else if (targets.length > 1)
|
|
84
|
+
problems.push(`exactly one target — declares ${targets.length} (${targets.join(", ")})`);
|
|
85
|
+
if (problems.length === 0)
|
|
86
|
+
return [];
|
|
87
|
+
return [
|
|
88
|
+
{ file: relPath, issue: "invalid-task-yaml", detail: `task field errors: ${problems.join("; ")}`, fixed: false },
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
async function validate(_c, changes, ctx) {
|
|
92
|
+
const diagnostics = [];
|
|
93
|
+
for (const change of changes) {
|
|
94
|
+
if (change.op === "delete")
|
|
95
|
+
continue;
|
|
96
|
+
const raw = change.after ?? (await ctx.readFile(change.path));
|
|
97
|
+
if (typeof raw !== "string")
|
|
98
|
+
continue;
|
|
99
|
+
if (path.extname(change.path).toLowerCase() !== TASK_EXT)
|
|
100
|
+
continue;
|
|
101
|
+
diagnostics.push(...taskDiagnostics(toPosix(change.path), parseTaskYaml(raw)));
|
|
102
|
+
}
|
|
103
|
+
return diagnostics;
|
|
104
|
+
}
|
|
105
|
+
export const akmTaskAdapter = {
|
|
106
|
+
id: "akm-task",
|
|
107
|
+
version: "0.9.0",
|
|
108
|
+
extensions: [TASK_EXT],
|
|
109
|
+
recognize,
|
|
110
|
+
validate,
|
|
111
|
+
/** A task places to `<conceptId>.yml`; an already-suffixed conceptId is idempotent. */
|
|
112
|
+
placeNew(c, conceptId) {
|
|
113
|
+
const posix = toPosix(conceptId);
|
|
114
|
+
return path.join(c.root, /\.yml$/i.test(posix) ? posix : `${posix}.yml`);
|
|
115
|
+
},
|
|
116
|
+
/** Tasks live anywhere under the component root. */
|
|
117
|
+
directoryList() {
|
|
118
|
+
return ["."];
|
|
119
|
+
},
|
|
120
|
+
/**
|
|
121
|
+
* Install-time probe (§1.2): a root holding a top-level `.yml` file that
|
|
122
|
+
* parses as a task (a `schedule` key). The task-shape probe keeps it disjoint
|
|
123
|
+
* from the `akm-workflow` YAML program (`version` + `steps`, no `schedule`)
|
|
124
|
+
* and from any non-task YAML.
|
|
125
|
+
*/
|
|
126
|
+
looksLikeRoot(root) {
|
|
127
|
+
let entries;
|
|
128
|
+
try {
|
|
129
|
+
entries = fs.readdirSync(root, { withFileTypes: true });
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
for (const entry of entries) {
|
|
135
|
+
if (!entry.isFile() || path.extname(entry.name).toLowerCase() !== TASK_EXT)
|
|
136
|
+
continue;
|
|
137
|
+
let raw;
|
|
138
|
+
try {
|
|
139
|
+
raw = fs.readFileSync(path.join(root, entry.name), "utf8");
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const data = parseTaskYaml(raw);
|
|
145
|
+
if (typeof data.schedule === "string" && data.schedule.trim() !== "")
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
return false;
|
|
149
|
+
},
|
|
150
|
+
};
|