akm-cli 0.9.0-rc.8 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1063 -44
- package/README.md +51 -25
- package/SECURITY.md +14 -1
- package/STABILITY.md +497 -0
- package/dist/akm +148 -35
- package/dist/{akm-migrate-storage → akm-migrate} +6 -9
- package/dist/assets/hints/cli-hints-full.md +223 -95
- package/dist/assets/hints/cli-hints-short.md +85 -22
- package/dist/assets/improve-strategies/default.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/stash-skeleton/README.md +6 -5
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
- package/dist/assets/tasks/core/extract.yml +1 -1
- package/dist/assets/tasks/core/version-check.yml +1 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +1 -3
- package/dist/assets/workflows/workflow-template.md +32 -15
- package/dist/cli/invocation.js +40 -15
- package/dist/cli/parse-args.js +0 -22
- package/dist/cli/retired-commands.js +121 -0
- package/dist/cli/shared.js +154 -22
- package/dist/cli/unknown-flags.js +236 -0
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +696 -258
- package/dist/commands/agent/agent-dispatch.js +14 -3
- package/dist/commands/agent/contribute-cli.js +73 -88
- package/dist/commands/completions.js +79 -22
- package/dist/commands/config-cli.js +17 -150
- package/dist/commands/env/env-cli.js +59 -143
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +36 -66
- package/dist/commands/env/secret.js +24 -57
- package/dist/commands/feedback-cli.js +141 -87
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +3 -4
- package/dist/commands/health/checks.js +85 -23
- package/dist/commands/health/html-report.js +7 -10
- package/dist/commands/health/improve-metrics.js +25 -83
- package/dist/commands/health/md-report.js +5 -9
- package/dist/commands/health/metrics.js +62 -20
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +4 -5
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +3 -48
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/commands/health/types-improve.js +7 -0
- package/dist/commands/health.js +99 -28
- package/dist/commands/improve/anti-collapse.js +2 -2
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +41 -40
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +140 -1000
- package/dist/commands/improve/distill/promote-memory.js +12 -12
- package/dist/commands/improve/distill/quality-gate.js +6 -6
- package/dist/commands/improve/distill.js +58 -69
- package/dist/commands/improve/eligibility.js +105 -57
- package/dist/commands/improve/extract-cli.js +14 -133
- package/dist/commands/improve/improve-cli.js +98 -114
- package/dist/commands/improve/improve-result-file.js +1 -28
- package/dist/commands/improve/improve-strategies.js +8 -5
- package/dist/commands/improve/improve.js +128 -91
- package/dist/commands/improve/loop-stages.js +182 -20
- package/dist/commands/improve/memory/derived-ref.js +45 -43
- package/dist/commands/improve/memory/memory-belief.js +1 -1
- package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
- package/dist/commands/improve/memory/memory-improve.js +6 -5
- package/dist/commands/improve/outcome-loop.js +22 -65
- package/dist/commands/improve/preparation.js +114 -123
- package/dist/commands/improve/proactive-maintenance.js +2 -5
- package/dist/commands/improve/reflect.js +56 -160
- package/dist/commands/improve/salience.js +11 -122
- package/dist/commands/improve/source-identity.js +10 -38
- package/dist/commands/lint/base-linter.js +20 -124
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +249 -43
- package/dist/commands/{events.js → log.js} +33 -38
- package/dist/commands/migrate-cli.js +92 -12
- package/dist/commands/migration-tool.js +46 -0
- package/dist/commands/observability-cli.js +70 -209
- package/dist/commands/proposal/drain.js +101 -29
- package/dist/commands/proposal/proposal-cli.js +76 -48
- package/dist/commands/proposal/proposal.js +54 -18
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +23 -15
- package/dist/commands/proposal/repository.js +701 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
- package/dist/commands/proposal/validators/proposal-validators.js +55 -7
- package/dist/commands/proposal/validators/proposals.js +4 -7
- package/dist/commands/read/curate.js +34 -53
- package/dist/commands/read/knowledge.js +150 -95
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +42 -15
- package/dist/commands/read/search-cli.js +180 -78
- package/dist/commands/read/search.js +58 -43
- package/dist/commands/read/show.js +197 -141
- package/dist/commands/registry-cli.js +12 -51
- package/dist/commands/remember.js +14 -57
- package/dist/commands/sources/add-cli.js +100 -31
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +7 -2
- package/dist/commands/sources/info.js +18 -5
- package/dist/commands/sources/init.js +12 -12
- package/dist/commands/sources/installed-stashes.js +382 -98
- package/dist/commands/sources/schema-repair.js +3 -2
- package/dist/commands/sources/self-update.js +131 -38
- package/dist/commands/sources/source-add.js +72 -17
- package/dist/commands/sources/source-clone.js +129 -45
- package/dist/commands/sources/source-manage.js +43 -23
- package/dist/commands/sources/sources-cli.js +57 -208
- package/dist/commands/sources/stash-cli.js +46 -53
- package/dist/commands/tasks/tasks-cli.js +91 -97
- package/dist/commands/tasks/tasks.js +276 -421
- package/dist/commands/workflow-cli.js +175 -450
- package/dist/core/adapter/adapters/akm-adapter.js +47 -28
- package/dist/core/adapter/adapters/akm-lint.js +42 -27
- package/dist/core/adapter/adapters/akm-metadata.js +15 -44
- package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
- package/dist/core/adapter/adapters/index.js +6 -6
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
- package/dist/core/adapter/adapters/okf-adapter.js +187 -19
- package/dist/core/adapter/adapters/shared.js +3 -19
- package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +6 -4
- package/dist/core/adapter/validate-context.js +214 -0
- package/dist/core/asset/akm-markdown.js +63 -0
- package/dist/core/asset/asset-placement.js +20 -6
- package/dist/core/asset/asset-ref.js +11 -9
- package/dist/core/asset/frontmatter-lint.js +30 -0
- package/dist/core/asset/frontmatter.js +37 -9
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +89 -18
- package/dist/core/asset/stash-meta.js +1 -1
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +152 -38
- package/dist/core/config/config-io.js +12 -1
- package/dist/core/config/config-schema.js +35 -8
- package/dist/core/config/config-sources.js +55 -11
- package/dist/core/config/config-walker.js +25 -9
- package/dist/core/config/config.js +9 -48
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +5 -1
- package/dist/core/config/schema/experimental.js +30 -0
- package/dist/core/config/schema/improve-processes.js +0 -6
- package/dist/core/config/schema/improve.js +21 -3
- package/dist/core/config/schema/index-config.js +8 -15
- package/dist/core/config/schema/output.js +4 -1
- package/dist/core/config/schema/setup.js +9 -18
- package/dist/core/config/schema/sources-bundles.js +49 -33
- package/dist/core/config/schema/workflow.js +3 -3
- package/dist/core/env-secret-ref.js +76 -46
- package/dist/core/errors.js +18 -12
- package/dist/core/events.js +46 -128
- package/dist/core/file-change.js +6 -5
- package/dist/core/fs-txn.js +83 -7
- package/dist/core/git-message.js +2 -2
- package/dist/core/improve-result.js +1 -100
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +2 -1
- package/dist/core/migration-operation.js +16 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/parse.js +4 -1
- package/dist/core/paths.js +17 -20
- package/dist/core/recognition-util.js +12 -14
- package/dist/core/redaction.js +34 -0
- package/dist/core/standards/resolve-standards-context.js +2 -14
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +2 -2
- package/dist/core/state/migrations.js +41 -18
- package/dist/core/state-db.js +5 -14
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +6 -4
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/type-presentation.js +3 -3
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +771 -95
- package/dist/indexer/bundle-identity-guard.js +3 -2
- package/dist/indexer/db/graph-db.js +0 -24
- package/dist/indexer/ensure-index.js +1 -0
- package/dist/indexer/graph/graph-boost.js +9 -34
- package/dist/indexer/graph/graph-extraction.js +8 -5
- package/dist/indexer/index-writer-lock.js +53 -17
- package/dist/indexer/index-written-assets.js +16 -22
- package/dist/indexer/indexer.js +497 -239
- package/dist/indexer/installations.js +14 -96
- package/dist/indexer/passes/dir-staleness.js +16 -9
- package/dist/indexer/passes/memory-inference.js +11 -9
- package/dist/indexer/passes/metadata.js +113 -47
- package/dist/indexer/scan/doc-to-entry.js +38 -1
- package/dist/indexer/scan/drain-dir.js +13 -23
- package/dist/indexer/search/db-search.js +99 -54
- package/dist/indexer/search/fts-query.js +47 -24
- package/dist/indexer/search/ranking-contributors.js +42 -20
- package/dist/indexer/search/ranking.js +18 -99
- package/dist/indexer/search/search-fields.js +7 -2
- package/dist/indexer/search/search-source.js +82 -93
- package/dist/indexer/usage/usage-events.js +0 -89
- package/dist/indexer/walk/file-context.js +2 -1
- package/dist/indexer/walk/matchers.js +30 -43
- package/dist/indexer/walk/path-resolver.js +7 -2
- package/dist/indexer/walk/walker.js +38 -12
- package/dist/integrations/agent/builders.js +0 -6
- package/dist/integrations/agent/config.js +2 -2
- package/dist/integrations/agent/detect.js +49 -19
- package/dist/integrations/agent/engine-fallback.js +76 -0
- package/dist/integrations/agent/profiles.js +14 -0
- package/dist/integrations/agent/prompts.js +12 -8
- package/dist/integrations/agent/runner-dispatch.js +4 -2
- package/dist/integrations/agent/runner.js +0 -1
- package/dist/integrations/agent/spawn.js +5 -6
- package/dist/integrations/github.js +1 -1
- package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
- package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
- package/dist/integrations/harnesses/claude/session-log.js +0 -10
- package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
- package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
- package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
- package/dist/integrations/harnesses/index.js +3 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
- package/dist/integrations/harnesses/opencode/session-log.js +0 -15
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
- package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
- package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
- package/dist/integrations/lockfile.js +101 -6
- package/dist/integrations/session-logs/index.js +3 -28
- package/dist/llm/client.js +136 -100
- package/dist/llm/embedders/remote.js +13 -5
- package/dist/llm/feature-gate.js +4 -12
- package/dist/llm/graph-extract.js +5 -11
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +5 -7
- package/dist/llm/structured-call.js +1 -1
- package/dist/llm/usage-persist.js +26 -5
- package/dist/llm/usage-telemetry.js +25 -2
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +259 -0
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -36
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +56 -83
- package/dist/output/shapes/migrate.js +8 -0
- package/dist/output/shapes/passthrough.js +7 -41
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes.js +2 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +164 -96
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/health-format.js +103 -0
- package/dist/output/text/health.js +7 -0
- package/dist/output/text/helpers.js +10 -8
- package/dist/output/text/lint-format.js +43 -0
- package/dist/output/text/{save.js → lint.js} +2 -2
- package/dist/output/text/migrate.js +88 -0
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +44 -72
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +15 -7
- package/dist/output/text/status-list.js +32 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +24 -203
- package/dist/output/text/workflow.js +1 -7
- package/dist/output/text.js +16 -17
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +13 -23
- package/dist/registry/resolve.js +42 -7
- package/dist/registry/semver.js +34 -84
- package/dist/runtime.js +2 -23
- package/dist/scripts/akm-migrate-node.js +60290 -0
- package/dist/scripts/akm-migrate.js +59628 -0
- package/dist/setup/detect.js +42 -15
- package/dist/setup/registry-stash-loader.js +2 -2
- package/dist/setup/setup.js +236 -136
- package/dist/setup/steps/connection.js +7 -9
- package/dist/setup/steps/platforms.js +9 -9
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +12 -13
- package/dist/setup/steps/stashdir.js +2 -3
- package/dist/setup/steps/tasks.js +237 -120
- package/dist/sources/freshness.js +1 -1
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +25 -23
- package/dist/sources/providers/git-stash.js +395 -106
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +7 -4
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +6 -1
- package/dist/sources/resolve.js +6 -5
- package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
- package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
- package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
- package/dist/sources/snapshot-fetchers/github.js +100 -0
- package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
- package/dist/sources/snapshot-fetchers/registry.js +17 -1
- package/dist/sources/snapshot-fetchers/robots.js +348 -0
- package/dist/sources/snapshot-fetchers/rss.js +282 -0
- package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
- package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
- package/dist/sources/snapshot-fetchers/x.js +910 -0
- package/dist/storage/database.js +7 -0
- package/dist/storage/engines/sqlite-migrations.js +23 -111
- package/dist/storage/managed-db.js +2 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +27 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -12
- package/dist/storage/repositories/index-connection.js +17 -6
- package/dist/storage/repositories/index-entries-repository.js +151 -240
- package/dist/storage/repositories/index-entry-mapper.js +15 -11
- package/dist/storage/repositories/index-fts-repository.js +5 -2
- package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
- package/dist/storage/repositories/index-meta-repository.js +2 -3
- package/dist/storage/repositories/index-schema.js +10 -25
- package/dist/storage/repositories/index-utility-repository.js +15 -28
- package/dist/storage/repositories/index-vec-repository.js +6 -1
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +296 -59
- package/dist/storage/repositories/registry-cache.js +19 -0
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +15 -13
- package/dist/storage/repositories/workflow-runs-repository.js +52 -40
- package/dist/tasks/backends/cron.js +105 -15
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +85 -38
- package/dist/tasks/backends/schtasks.js +135 -15
- package/dist/tasks/embedded.js +56 -40
- package/dist/tasks/parser.js +7 -157
- package/dist/tasks/resolve-akm-bin.js +137 -59
- package/dist/tasks/runner.js +79 -42
- package/dist/tasks/scheduler-invocation.js +220 -10
- package/dist/tasks/schema.js +24 -1
- package/dist/tasks/task-id.js +1 -3
- package/dist/tasks/validator.js +20 -6
- package/dist/workflows/authoring/authoring.js +94 -143
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/exec/frozen-judge.js +28 -2
- package/dist/workflows/exec/native-executor.js +77 -57
- package/dist/workflows/exec/param-secrets.js +9 -9
- package/dist/workflows/exec/run-workflow.js +133 -79
- package/dist/workflows/exec/step-work.js +219 -346
- package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
- package/dist/workflows/ir/compile.js +141 -270
- package/dist/workflows/ir/freeze.js +40 -30
- package/dist/workflows/ir/params.js +135 -11
- package/dist/workflows/ir/plan-hash.js +1 -1
- package/dist/workflows/ir/schema.js +25 -26
- package/dist/workflows/parser.js +872 -307
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +7 -10
- package/dist/workflows/renderer.js +95 -68
- package/dist/workflows/resource-limits.js +2 -0
- package/dist/workflows/runtime/checkin.js +3 -3
- package/dist/workflows/runtime/plan-classifier.js +16 -75
- package/dist/workflows/runtime/runs.js +186 -127
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +2 -2
- package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +30 -36
- package/dist/workflows/validator.js +21 -62
- package/docs/README.md +68 -0
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.7.0.md +11 -11
- package/docs/migration/release-notes/0.9.0.md +208 -27
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +564 -208
- package/docs/migration/v0.9.0-troubleshooting.md +561 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/cli.md +2253 -0
- package/docs/reference/configuration.md +358 -0
- package/docs/reference/data-and-telemetry.md +105 -42
- package/docs/reference/workflows.md +647 -0
- package/package.json +22 -11
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +81 -128
- package/schemas/akm-workflow.json +74 -73
- package/dist/assets/tasks/core/backup.yml +0 -5
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/cli/config-migrate.js +0 -1806
- package/dist/cli/config-validate.js +0 -41
- package/dist/commands/backup-cli.js +0 -56
- package/dist/commands/bundle/bundle-cli.js +0 -68
- package/dist/commands/bundle/bundle.js +0 -219
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -489
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/mv-cli.js +0 -1221
- package/dist/commands/sources/history.js +0 -201
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/core/migration-backup.js +0 -1234
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/migrate/legacy/config-source-migration.js +0 -223
- package/dist/migrate/legacy/content-migration.js +0 -305
- package/dist/migrate/legacy/legacy-layout.js +0 -779
- package/dist/migrate/legacy/legacy-paths.js +0 -25
- package/dist/migrate/legacy/legacy-stash-json.js +0 -72
- package/dist/migrate/legacy/proposal-fs-import.js +0 -168
- package/dist/migrate/legacy/task-target-ref-migration.js +0 -272
- package/dist/migrate/legacy/three-db-cutover.js +0 -841
- package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
- package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
- package/dist/migrate/legacy-ref-grammar.js +0 -214
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/registry/build-index.js +0 -382
- package/dist/schemas/akm-config.json +0 -4704
- package/dist/schemas/akm-task.json +0 -87
- package/dist/schemas/akm-workflow.json +0 -372
- package/dist/scripts/migrate-storage.js +0 -3816
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/cli.js +0 -53
- package/dist/workflows/exec/brief.js +0 -481
- package/dist/workflows/exec/report.js +0 -1460
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -813
- package/dist/workflows/program/project.js +0 -104
|
@@ -10,9 +10,6 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { SCRIPT_EXTENSIONS } from "../../core/recognition-util.js";
|
|
12
12
|
import { presentationFor } from "../../core/type-presentation.js";
|
|
13
|
-
import { looksLikeWorkflow } from "../../workflows/parser.js";
|
|
14
|
-
import { looksLikeWorkflowProgram } from "../../workflows/program/parser.js";
|
|
15
|
-
import { WORKFLOW_PROGRAM_RENDERER_NAME } from "../../workflows/program/project.js";
|
|
16
13
|
// ---------------------------------------------------------------------------
|
|
17
14
|
// Private data
|
|
18
15
|
// ---------------------------------------------------------------------------
|
|
@@ -37,6 +34,18 @@ const DIR_TYPE_MAP = [
|
|
|
37
34
|
type: "knowledge",
|
|
38
35
|
test: (ext) => ext === ".md",
|
|
39
36
|
},
|
|
37
|
+
{
|
|
38
|
+
// R-045 / Q-18 second half (owner ruling 11) — stash-resident `instruction`
|
|
39
|
+
// assets live under `instructions/`, mirroring the `knowledge` rule. This
|
|
40
|
+
// is a walker discovery rule for FILES ON DISK under a stash's
|
|
41
|
+
// `instructions/` dir; it is unrelated to the adapter-emitted root
|
|
42
|
+
// CLAUDE.md/AGENTS.md instruction docs (`tool-dir-shared.ts`), which are
|
|
43
|
+
// synthesized by format-family adapters, carry `ownsPresentation: true`,
|
|
44
|
+
// and never pass through this matcher at all.
|
|
45
|
+
dir: "instructions",
|
|
46
|
+
type: "instruction",
|
|
47
|
+
test: (ext) => ext === ".md",
|
|
48
|
+
},
|
|
40
49
|
{
|
|
41
50
|
dir: "workflows",
|
|
42
51
|
type: "workflow",
|
|
@@ -102,6 +111,9 @@ const TYPED_DIR_DOC_FILES = new Set(["readme.md"]);
|
|
|
102
111
|
function isTypedDirDocFile(fileName) {
|
|
103
112
|
return TYPED_DIR_DOC_FILES.has(fileName.toLowerCase());
|
|
104
113
|
}
|
|
114
|
+
function isNestedSkillResource(ctx) {
|
|
115
|
+
return ctx.ancestorDirs[0] === "skills" && ctx.ancestorDirs.length > 1 && ctx.fileName !== "SKILL.md";
|
|
116
|
+
}
|
|
105
117
|
// ---------------------------------------------------------------------------
|
|
106
118
|
// Private helpers
|
|
107
119
|
// ---------------------------------------------------------------------------
|
|
@@ -132,6 +144,8 @@ function classifyByExtension(ctx) {
|
|
|
132
144
|
return null;
|
|
133
145
|
}
|
|
134
146
|
function classifyByDirectory(ctx) {
|
|
147
|
+
if (isNestedSkillResource(ctx))
|
|
148
|
+
return null;
|
|
135
149
|
for (const dir of ctx.ancestorDirs) {
|
|
136
150
|
const result = matchDirectoryHint(dir, ctx, 10);
|
|
137
151
|
if (result)
|
|
@@ -141,6 +155,8 @@ function classifyByDirectory(ctx) {
|
|
|
141
155
|
}
|
|
142
156
|
function classifyByParentDirHint(ctx) {
|
|
143
157
|
const { parentDir, ext, fileName } = ctx;
|
|
158
|
+
if (isNestedSkillResource(ctx))
|
|
159
|
+
return null;
|
|
144
160
|
if (parentDir === "skills" && (fileName === "SKILL.md" || ext === ".md")) {
|
|
145
161
|
return { type: "skill", specificity: 15 };
|
|
146
162
|
}
|
|
@@ -162,12 +178,19 @@ function classifyBySmartMd(ctx) {
|
|
|
162
178
|
return { type: "knowledge", specificity: 5 };
|
|
163
179
|
}
|
|
164
180
|
const body = ctx.content();
|
|
165
|
-
|
|
181
|
+
const fm = ctx.frontmatter();
|
|
182
|
+
// Recognition is frontmatter `type: workflow` or residence under `workflows/`
|
|
183
|
+
// (workflow-format-unification, spec §2.5) — no content sniffing. The
|
|
184
|
+
// directory rule is `classifyByDirectory`/`classifyByParentDirHint`'s job;
|
|
185
|
+
// this only catches a workflow living OUTSIDE `workflows/` that still
|
|
186
|
+
// declares its type explicitly.
|
|
187
|
+
if (fm && fm.type === "workflow") {
|
|
166
188
|
return { type: "workflow", specificity: 19 };
|
|
167
189
|
}
|
|
168
|
-
const fm = ctx.frontmatter();
|
|
169
190
|
if (fm) {
|
|
170
|
-
|
|
191
|
+
// `tools` is the one authoring key for an agent's tool grant. Recognition
|
|
192
|
+
// covers only the key the renderer honors.
|
|
193
|
+
if ("tools" in fm) {
|
|
171
194
|
return { type: "agent", specificity: 20 };
|
|
172
195
|
}
|
|
173
196
|
if ("agent" in fm) {
|
|
@@ -182,35 +205,6 @@ function classifyBySmartMd(ctx) {
|
|
|
182
205
|
}
|
|
183
206
|
return { type: "knowledge", specificity: 5 };
|
|
184
207
|
}
|
|
185
|
-
/** YAML workflow *programs* (redesign addendum, R1): `.yaml`/`.yml` files. */
|
|
186
|
-
const WORKFLOW_PROGRAM_EXTENSIONS = new Set([".yaml", ".yml"]);
|
|
187
|
-
/**
|
|
188
|
-
* Classify YAML workflow programs. Two claims, mirroring the markdown rules:
|
|
189
|
-
*
|
|
190
|
-
* - any `.yaml`/`.yml` under a `workflows/` dir (the directory rule —
|
|
191
|
-
* specificity 15 when `workflows` is the immediate parent, 10 for a
|
|
192
|
-
* deeper ancestor, same ladder as `matchDirectoryHint`);
|
|
193
|
-
* - anywhere else, a content probe via `looksLikeWorkflowProgram`
|
|
194
|
-
* (`version: 1` + `steps:` at column 0) at specificity 19, the same
|
|
195
|
-
* level as `classifyBySmartMd`'s `looksLikeWorkflow` claim.
|
|
196
|
-
*
|
|
197
|
-
* The fact does NOT go through `toMatchResult` — the workflow TYPE maps to
|
|
198
|
-
* the markdown renderer by default, so this classifier names the
|
|
199
|
-
* `workflow-program-yaml` renderer on its result directly.
|
|
200
|
-
*/
|
|
201
|
-
function classifyByWorkflowProgram(ctx) {
|
|
202
|
-
if (!WORKFLOW_PROGRAM_EXTENSIONS.has(ctx.ext))
|
|
203
|
-
return null;
|
|
204
|
-
if (isTypedDirDocFile(ctx.fileName))
|
|
205
|
-
return null;
|
|
206
|
-
if (ctx.parentDir === "workflows")
|
|
207
|
-
return { type: "workflow", specificity: 15 };
|
|
208
|
-
if (ctx.ancestorDirs.includes("workflows"))
|
|
209
|
-
return { type: "workflow", specificity: 10 };
|
|
210
|
-
if (looksLikeWorkflowProgram(ctx.content()))
|
|
211
|
-
return { type: "workflow", specificity: 19 };
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
214
208
|
// ---------------------------------------------------------------------------
|
|
215
209
|
// Adapter: MatchFact → MatchResult
|
|
216
210
|
// ---------------------------------------------------------------------------
|
|
@@ -246,14 +240,7 @@ export function parentDirHintMatcher(ctx) {
|
|
|
246
240
|
export function smartMdMatcher(ctx) {
|
|
247
241
|
return toMatchResult(ctx, classifyBySmartMd);
|
|
248
242
|
}
|
|
249
|
-
|
|
250
|
-
const fact = classifyByWorkflowProgram(ctx);
|
|
251
|
-
if (!fact)
|
|
252
|
-
return null;
|
|
253
|
-
// Named directly (not via rendererNameFor) — see classifyByWorkflowProgram.
|
|
254
|
-
return { type: fact.type, specificity: fact.specificity, renderer: WORKFLOW_PROGRAM_RENDERER_NAME };
|
|
255
|
-
}
|
|
256
|
-
// The five matcher functions above are consumed directly by the akm adapter's
|
|
243
|
+
// The four matcher functions above are consumed directly by the akm adapter's
|
|
257
244
|
// synchronous `recognizeMatch()` (`core/adapter/adapters/akm-adapter.ts`, which
|
|
258
245
|
// holds the same registration-order array for tie-breaking). The chunk-3 cutover
|
|
259
246
|
// removed the file-context matcher registry, so there is no `registerBuiltinMatchers`
|
|
@@ -10,11 +10,16 @@ import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
|
|
|
10
10
|
import { lookup } from "../indexer.js";
|
|
11
11
|
import { resolveSourceEntries } from "../search/search-source.js";
|
|
12
12
|
function normalizeRef(ref) {
|
|
13
|
-
//
|
|
13
|
+
// String inputs use the current `[bundle//]conceptId` grammar.
|
|
14
14
|
return typeof ref === "string" ? parseRefInput(ref) : ref;
|
|
15
15
|
}
|
|
16
16
|
function buildDiskCandidates(sourcePath, ref, preserveDirectNameFallback) {
|
|
17
|
-
const
|
|
17
|
+
const placementStashDir = stashDirFor(ref.type);
|
|
18
|
+
// Opaque adapter conceptIds are index-resolved. Core cannot infer their
|
|
19
|
+
// adapter-owned serialization or path extension before indexing.
|
|
20
|
+
if (placementStashDir === undefined)
|
|
21
|
+
return [];
|
|
22
|
+
const typeDir = path.join(sourcePath, placementStashDir);
|
|
18
23
|
const candidates = [
|
|
19
24
|
assetPathForName(ref.type, typeDir, ref.name),
|
|
20
25
|
path.join(sourcePath, ref.type, `${ref.name}.md`),
|
|
@@ -13,7 +13,8 @@ import path from "node:path";
|
|
|
13
13
|
import { isRelevantAssetFile } from "../../core/asset/asset-placement.js";
|
|
14
14
|
import { spawnSync } from "../../runtime.js";
|
|
15
15
|
import { buildFileContext } from "./file-context.js";
|
|
16
|
-
const
|
|
16
|
+
const ALWAYS_SKIP_DIRS = new Set([".git"]);
|
|
17
|
+
const AKM_SKIP_DIRS = new Set(["node_modules", "bin", ".cache"]);
|
|
17
18
|
/**
|
|
18
19
|
* Walk a type root directory and return files grouped by their parent directory.
|
|
19
20
|
*
|
|
@@ -62,21 +63,24 @@ export function walkStash(typeRoot, assetType) {
|
|
|
62
63
|
* Otherwise falls back to a manual walk that skips .git, node_modules, bin,
|
|
63
64
|
* .cache, dot-directories, and the legacy metadata sidecar.
|
|
64
65
|
*/
|
|
65
|
-
export function walkStashFlat(stashRoot) {
|
|
66
|
+
export function walkStashFlat(stashRoot, options = {}) {
|
|
67
|
+
return walkStashFlatWithStatus(stashRoot, options).files;
|
|
68
|
+
}
|
|
69
|
+
export function walkStashFlatWithStatus(stashRoot, options = {}) {
|
|
66
70
|
if (!fs.existsSync(stashRoot))
|
|
67
|
-
return [];
|
|
71
|
+
return { files: [], complete: false };
|
|
68
72
|
// Try git-based walk first (respects .gitignore)
|
|
69
|
-
const gitResult = walkStashGit(stashRoot);
|
|
73
|
+
const gitResult = walkStashGit(stashRoot, options);
|
|
70
74
|
if (gitResult)
|
|
71
75
|
return gitResult;
|
|
72
76
|
// Fallback: manual walk
|
|
73
|
-
return walkStashManual(stashRoot);
|
|
77
|
+
return walkStashManual(stashRoot, options);
|
|
74
78
|
}
|
|
75
79
|
/**
|
|
76
80
|
* Walk using `git ls-files` to respect .gitignore.
|
|
77
81
|
* Returns null if the directory is not a git repo or git fails.
|
|
78
82
|
*/
|
|
79
|
-
function walkStashGit(stashRoot) {
|
|
83
|
+
function walkStashGit(stashRoot, options) {
|
|
80
84
|
// Quick check: is this a git repo? Look for .git in this dir or parents.
|
|
81
85
|
if (!isInsideGitRepo(stashRoot))
|
|
82
86
|
return null;
|
|
@@ -87,6 +91,15 @@ function walkStashGit(stashRoot) {
|
|
|
87
91
|
// result.success is false if the process exited non-zero OR git was not found
|
|
88
92
|
if (!result.success)
|
|
89
93
|
return null;
|
|
94
|
+
// `--cached` includes tracked files deleted from the worktree. They are not
|
|
95
|
+
// scan failures and must not make an otherwise complete snapshot look stale.
|
|
96
|
+
const deletedResult = spawnSync(["git", "ls-files", "--deleted", "-z", "--", "."], { cwd: stashRoot });
|
|
97
|
+
if (!deletedResult.success)
|
|
98
|
+
return null;
|
|
99
|
+
const deletedStdout = Buffer.isBuffer(deletedResult.stdout)
|
|
100
|
+
? deletedResult.stdout.toString("utf8")
|
|
101
|
+
: String(deletedResult.stdout ?? "");
|
|
102
|
+
const deletedFiles = new Set(deletedStdout.split("\0").filter(Boolean));
|
|
90
103
|
// Data-hygiene filename skips: the legacy metadata sidecar (never indexed as
|
|
91
104
|
// content — Chunk-8 folds it into the bundle format) plus git dot-files.
|
|
92
105
|
const SKIP_FILES = new Set([".stash.json", ".gitignore", ".gitattributes"]);
|
|
@@ -94,16 +107,19 @@ function walkStashGit(stashRoot) {
|
|
|
94
107
|
const files = stdout
|
|
95
108
|
.split("\0")
|
|
96
109
|
.filter((f) => f.length > 0)
|
|
110
|
+
.filter((f) => !deletedFiles.has(f))
|
|
97
111
|
.filter((f) => !f.startsWith("..") && !path.isAbsolute(f))
|
|
98
112
|
.filter((f) => {
|
|
99
113
|
const dirParts = path
|
|
100
114
|
.dirname(f)
|
|
101
115
|
.split(/[\\/]+/)
|
|
102
116
|
.filter(Boolean);
|
|
103
|
-
return !dirParts.some((part) =>
|
|
117
|
+
return !dirParts.some((part) => ALWAYS_SKIP_DIRS.has(part) ||
|
|
118
|
+
(!options.includeAllDirectories && (AKM_SKIP_DIRS.has(part) || part.startsWith("."))));
|
|
104
119
|
})
|
|
105
120
|
.filter((f) => !SKIP_FILES.has(path.basename(f)));
|
|
106
121
|
const results = [];
|
|
122
|
+
let complete = true;
|
|
107
123
|
for (const relFile of files) {
|
|
108
124
|
const absPath = path.join(stashRoot, relFile);
|
|
109
125
|
try {
|
|
@@ -113,9 +129,10 @@ function walkStashGit(stashRoot) {
|
|
|
113
129
|
}
|
|
114
130
|
catch {
|
|
115
131
|
// File may have been deleted since git ls-files ran
|
|
132
|
+
complete = false;
|
|
116
133
|
}
|
|
117
134
|
}
|
|
118
|
-
return results;
|
|
135
|
+
return { files: results, complete };
|
|
119
136
|
}
|
|
120
137
|
/**
|
|
121
138
|
* Check if a directory is inside a git repository by walking up to find .git.
|
|
@@ -176,14 +193,22 @@ export function* walkMarkdownFiles(root) {
|
|
|
176
193
|
}
|
|
177
194
|
}
|
|
178
195
|
/** Manual walk for non-git directories. */
|
|
179
|
-
function walkStashManual(stashRoot) {
|
|
196
|
+
function walkStashManual(stashRoot, options) {
|
|
180
197
|
const results = [];
|
|
198
|
+
let complete = true;
|
|
181
199
|
const stack = [stashRoot];
|
|
182
200
|
while (stack.length > 0) {
|
|
183
201
|
const current = stack.pop();
|
|
184
202
|
if (!current)
|
|
185
203
|
continue;
|
|
186
|
-
|
|
204
|
+
let entries;
|
|
205
|
+
try {
|
|
206
|
+
entries = fs.readdirSync(current, { withFileTypes: true });
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
complete = false;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
187
212
|
for (const entry of entries) {
|
|
188
213
|
if (entry.name === ".stash.json")
|
|
189
214
|
continue;
|
|
@@ -193,7 +218,8 @@ function walkStashManual(stashRoot) {
|
|
|
193
218
|
continue;
|
|
194
219
|
}
|
|
195
220
|
if (entry.isDirectory()) {
|
|
196
|
-
if (
|
|
221
|
+
if (ALWAYS_SKIP_DIRS.has(entry.name) ||
|
|
222
|
+
(!options.includeAllDirectories && (AKM_SKIP_DIRS.has(entry.name) || entry.name.startsWith("."))))
|
|
197
223
|
continue;
|
|
198
224
|
stack.push(fullPath);
|
|
199
225
|
}
|
|
@@ -202,5 +228,5 @@ function walkStashManual(stashRoot) {
|
|
|
202
228
|
}
|
|
203
229
|
}
|
|
204
230
|
}
|
|
205
|
-
return results;
|
|
231
|
+
return { files: results, complete };
|
|
206
232
|
}
|
|
@@ -14,12 +14,6 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { ConfigError } from "../../core/errors.js";
|
|
16
16
|
import { HARNESS_REGISTRY } from "../harnesses/index.js";
|
|
17
|
-
export { assertNotFlag, normalizeTools } from "./builder-shared.js";
|
|
18
|
-
// ── Platform builders ─────────────────────────────────────────────────────────
|
|
19
|
-
// The OpenCode builder was migrated to its harness directory in #564
|
|
20
|
-
// (`harnesses/opencode/agent-builder.ts`) and the Claude Code builder in #563
|
|
21
|
-
// (`harnesses/claude/agent-builder.ts`). Both are imported back into
|
|
22
|
-
// BUILTIN_BUILDERS below so platform routing is unchanged.
|
|
23
17
|
// ── Registry ──────────────────────────────────────────────────────────────────
|
|
24
18
|
/**
|
|
25
19
|
* DERIVED from `HARNESS_REGISTRY` (P0.5 registry-drift fix): each harness that
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/** Default
|
|
5
|
-
export const DEFAULT_AGENT_TIMEOUT_MS =
|
|
4
|
+
/** Default agent CLI timeout; null means agents run until they finish. */
|
|
5
|
+
export const DEFAULT_AGENT_TIMEOUT_MS = null;
|
|
6
6
|
/** Default hard timeout for direct LLM calls when no engine/use override exists. */
|
|
7
7
|
export const DEFAULT_LLM_TIMEOUT_MS = 600_000;
|
|
@@ -15,26 +15,34 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import fs from "node:fs";
|
|
17
17
|
import path from "node:path";
|
|
18
|
-
import { getBuiltinAgentProfile, listBuiltinAgentProfiles } from "./profiles.js";
|
|
18
|
+
import { getBuiltinAgentProfile, listBuiltinAgentProfiles, OPENCODE_SDK_SERVER_BIN, } from "./profiles.js";
|
|
19
19
|
/**
|
|
20
20
|
* Default PATH lookup. Walks `process.env.PATH` and returns the first
|
|
21
21
|
* existing executable file. Returns `undefined` when the bin is not on
|
|
22
22
|
* PATH or the env is empty.
|
|
23
23
|
*
|
|
24
|
-
* `process.env.PATH` is split on the platform-correct delimiter
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* match
|
|
24
|
+
* `process.env.PATH` is split on the platform-correct delimiter. On Windows
|
|
25
|
+
* agent CLIs install as extension-bearing shims (`claude.cmd`, `q.exe`), so
|
|
26
|
+
* each PATH entry is probed for the bare name AND for `<bin><ext>` over
|
|
27
|
+
* PATHEXT — an exact-match-only probe reports every agent CLI as missing
|
|
28
|
+
* there, which silently hides the "installed CLI agent" option during setup.
|
|
28
29
|
*/
|
|
29
30
|
export function defaultWhich(bin, envSource = process.env) {
|
|
31
|
+
// Computed once per call — not per PATH entry — since it never varies.
|
|
32
|
+
const suffixes = executableSuffixes(envSource);
|
|
30
33
|
if (!bin || bin.includes("/") || bin.includes("\\")) {
|
|
31
34
|
// Absolute / relative paths: caller already specified location.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
for (const suffix of suffixes) {
|
|
36
|
+
const candidate = bin + suffix;
|
|
37
|
+
try {
|
|
38
|
+
if (fs.statSync(candidate).isFile())
|
|
39
|
+
return candidate;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
/* try the next extension */
|
|
43
|
+
}
|
|
37
44
|
}
|
|
45
|
+
return undefined;
|
|
38
46
|
}
|
|
39
47
|
const pathVar = envSource.PATH ?? envSource.Path ?? envSource.path ?? "";
|
|
40
48
|
if (!pathVar)
|
|
@@ -43,18 +51,40 @@ export function defaultWhich(bin, envSource = process.env) {
|
|
|
43
51
|
for (const dir of pathVar.split(sep)) {
|
|
44
52
|
if (!dir)
|
|
45
53
|
continue;
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
const base = path.join(dir, bin);
|
|
55
|
+
for (const suffix of suffixes) {
|
|
56
|
+
const candidate = base + suffix;
|
|
57
|
+
try {
|
|
58
|
+
const st = fs.statSync(candidate);
|
|
59
|
+
if (st.isFile())
|
|
60
|
+
return candidate;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
/* keep walking */
|
|
64
|
+
}
|
|
54
65
|
}
|
|
55
66
|
}
|
|
56
67
|
return undefined;
|
|
57
68
|
}
|
|
69
|
+
/** Windows PATHEXT default, used when the env carries no explicit list. */
|
|
70
|
+
const DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
|
|
71
|
+
/**
|
|
72
|
+
* Executable suffixes to try for each candidate path, bare name (`""`) first
|
|
73
|
+
* so POSIX resolution is byte-for-byte unchanged. Extensions are appended only
|
|
74
|
+
* on win32 or when the env supplies PATHEXT (which is also the seam tests use
|
|
75
|
+
* to cover Windows resolution from a POSIX runner).
|
|
76
|
+
*/
|
|
77
|
+
function executableSuffixes(envSource) {
|
|
78
|
+
const pathext = envSource.PATHEXT ?? envSource.Pathext ?? envSource.pathext;
|
|
79
|
+
if (process.platform !== "win32" && !pathext)
|
|
80
|
+
return [""];
|
|
81
|
+
const exts = (pathext ?? DEFAULT_PATHEXT)
|
|
82
|
+
.split(";")
|
|
83
|
+
.map((ext) => ext.trim())
|
|
84
|
+
.filter(Boolean)
|
|
85
|
+
.map((ext) => (ext.startsWith(".") ? ext : `.${ext}`));
|
|
86
|
+
return ["", ...exts];
|
|
87
|
+
}
|
|
58
88
|
let detectOverrides;
|
|
59
89
|
/** TEST-ONLY. Swap the detection implementations; pass undefined to restore. */
|
|
60
90
|
export function _setAgentDetectForTests(fakes) {
|
|
@@ -79,7 +109,7 @@ export function detectAgentCliProfiles(agent, whichFn = defaultWhich) {
|
|
|
79
109
|
profilesByName.set(name, {
|
|
80
110
|
name,
|
|
81
111
|
platform: engine.platform,
|
|
82
|
-
bin: engine.bin ?? builtin?.bin ?? (engine.platform === "opencode-sdk" ?
|
|
112
|
+
bin: engine.bin ?? builtin?.bin ?? (engine.platform === "opencode-sdk" ? OPENCODE_SDK_SERVER_BIN : engine.platform),
|
|
83
113
|
args: engine.args ?? builtin?.args ?? [],
|
|
84
114
|
stdio: "captured",
|
|
85
115
|
envPassthrough: builtin?.envPassthrough ?? [],
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { defaultWhich } from "./detect.js";
|
|
5
|
+
import { OPENCODE_SDK_SERVER_BIN } from "./profiles.js";
|
|
6
|
+
/**
|
|
7
|
+
* Engine name used for the synthesized entry. Matches the platform id so it
|
|
8
|
+
* reads correctly in `akm workflow status`, frozen plans, and error messages.
|
|
9
|
+
* A user-configured engine of the same name is preferred over synthesizing.
|
|
10
|
+
*/
|
|
11
|
+
export const FALLBACK_ENGINE_NAME = "opencode-sdk";
|
|
12
|
+
/** Announcement text, surfaced once per run/dispatch. */
|
|
13
|
+
export const FALLBACK_ANNOUNCEMENT = `No engine is configured; falling back to \`${FALLBACK_ENGINE_NAME}\` via the ` +
|
|
14
|
+
`\`${OPENCODE_SDK_SERVER_BIN}\` binary on PATH — provider, model, and auth come ` +
|
|
15
|
+
"from opencode's own configuration. " +
|
|
16
|
+
"Run `akm setup`, or set `defaults.engine`, to choose explicitly.";
|
|
17
|
+
/**
|
|
18
|
+
* Failure suffix for every surface that needs an engine and found none.
|
|
19
|
+
* Owned HERE, beside the probe whose outcome it describes: the probe follows a
|
|
20
|
+
* configured `bin` when one is pinned, so a consumer restating "not on PATH"
|
|
21
|
+
* would misdescribe a missing absolute path.
|
|
22
|
+
*/
|
|
23
|
+
export const NO_ENGINE_MESSAGE_SUFFIX = `has no selected engine, and no usable \`${OPENCODE_SDK_SERVER_BIN}\` binary was found to fall back to.`;
|
|
24
|
+
/**
|
|
25
|
+
* Guidance used when the fallback itself is unavailable.
|
|
26
|
+
*
|
|
27
|
+
* The opencode route names a BINARY install, not `npm i @opencode-ai/sdk`:
|
|
28
|
+
* that package is an HTTP client with no dependencies and cannot serve
|
|
29
|
+
* anything on its own (see the module doc).
|
|
30
|
+
*/
|
|
31
|
+
export const NO_ENGINE_REMEDY = "Run `akm setup` to detect an installed agent, or set one explicitly: " +
|
|
32
|
+
'`akm config set engines.claude \'{"kind":"agent","platform":"claude"}\'` ' +
|
|
33
|
+
"then `akm config set defaults.engine claude`. " +
|
|
34
|
+
`Installing the \`${OPENCODE_SDK_SERVER_BIN}\` binary also works ` +
|
|
35
|
+
"(`npm i -g opencode-ai`) — akm falls back to it automatically.";
|
|
36
|
+
/**
|
|
37
|
+
* Return a config whose `defaults.engine` resolves, applying the implicit
|
|
38
|
+
* `opencode-sdk` fallback when it does not and an opencode binary is present.
|
|
39
|
+
*
|
|
40
|
+
* Pure with respect to the input: never mutates `config`. Returns the input
|
|
41
|
+
* object identity unchanged when no fallback is needed, so callers can cheaply
|
|
42
|
+
* detect the common case.
|
|
43
|
+
*/
|
|
44
|
+
export function withEngineFallback(config, whichFn = defaultWhich) {
|
|
45
|
+
if (config.defaults?.engine)
|
|
46
|
+
return { config };
|
|
47
|
+
// An operator-configured engine of this name wins over a synthesized one —
|
|
48
|
+
// theirs may carry a model, an llmEngine fallback, or a pinned bin. Probe
|
|
49
|
+
// THAT bin rather than the bare command: a configured absolute path outside
|
|
50
|
+
// PATH is still a usable engine, and reporting it as missing would contradict
|
|
51
|
+
// the operator-configured-wins rule.
|
|
52
|
+
const existing = config.engines?.[FALLBACK_ENGINE_NAME];
|
|
53
|
+
if (!whichFn(existing?.bin ?? OPENCODE_SDK_SERVER_BIN))
|
|
54
|
+
return { config };
|
|
55
|
+
const engines = existing
|
|
56
|
+
? config.engines
|
|
57
|
+
: { ...(config.engines ?? {}), [FALLBACK_ENGINE_NAME]: { kind: "agent", platform: "opencode-sdk" } };
|
|
58
|
+
return {
|
|
59
|
+
config: {
|
|
60
|
+
...config,
|
|
61
|
+
engines,
|
|
62
|
+
defaults: { ...(config.defaults ?? {}), engine: FALLBACK_ENGINE_NAME },
|
|
63
|
+
},
|
|
64
|
+
fallbackEngineName: FALLBACK_ENGINE_NAME,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The announcement, but only when the fallback candidate is the engine that
|
|
69
|
+
* actually won selection. Returns `undefined` otherwise, so an explicitly
|
|
70
|
+
* selected engine never triggers a claim that opencode supplied the model.
|
|
71
|
+
*/
|
|
72
|
+
export function fallbackAnnouncement(fallbackEngineName, selectedEngineName) {
|
|
73
|
+
if (!fallbackEngineName || selectedEngineName !== fallbackEngineName)
|
|
74
|
+
return undefined;
|
|
75
|
+
return FALLBACK_ANNOUNCEMENT;
|
|
76
|
+
}
|
|
@@ -91,6 +91,20 @@ const BUILTINS = {
|
|
|
91
91
|
parseOutput: "text",
|
|
92
92
|
},
|
|
93
93
|
};
|
|
94
|
+
/**
|
|
95
|
+
* Binary the `opencode-sdk` harness needs on PATH.
|
|
96
|
+
*
|
|
97
|
+
* The embedded SDK is not self-contained, and that is the SDK's own design
|
|
98
|
+
* rather than a consequence of how akm drives it: `@opencode-ai/sdk` ships
|
|
99
|
+
* with `"dependencies": {}` and its `createOpencodeServer` is itself a
|
|
100
|
+
* `spawn("opencode", ["serve", ...])`. akm's runner spawns the same binary
|
|
101
|
+
* directly and talks HTTP to it (see `harnesses/opencode-sdk/sdk-runner.ts`),
|
|
102
|
+
* so the `opencode` binary gates the SDK path exactly as it gates the CLI
|
|
103
|
+
* path — a host with the npm package but no binary can dispatch neither.
|
|
104
|
+
* `opencode-sdk` deliberately has no {@link BUILTINS} entry — it dispatches
|
|
105
|
+
* without argv construction — so this is the one place that pairing lives.
|
|
106
|
+
*/
|
|
107
|
+
export const OPENCODE_SDK_SERVER_BIN = "opencode";
|
|
94
108
|
/** Names of the canonical built-in harness descriptors. Stable, sorted. */
|
|
95
109
|
export const BUILTIN_AGENT_PROFILE_NAMES = Object.freeze(Object.keys(BUILTINS).sort());
|
|
96
110
|
/** Returns the built-in descriptor for a canonical harness id. */
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
* `src/integrations/agent/` rather than `src/llm/` is deliberate: these are
|
|
13
13
|
* shell-out prompts targeting an agent CLI, not in-tree LLM API calls.
|
|
14
14
|
*
|
|
15
|
-
* The
|
|
15
|
+
* The stdout output an agent must produce is a strict JSON object:
|
|
16
16
|
*
|
|
17
17
|
* ```json
|
|
18
18
|
* {
|
|
19
|
-
* "ref": "
|
|
19
|
+
* "ref": "lessons/my-lesson",
|
|
20
20
|
* "content": "---\ndescription: ...\nwhen_to_use: ...\n---\n\nbody",
|
|
21
21
|
* "frontmatter": { "description": "...", "when_to_use": "..." }
|
|
22
22
|
* }
|
|
@@ -29,6 +29,7 @@ import reflectLlmFramedContract from "../../assets/prompts/reflect-llm-framed-co
|
|
|
29
29
|
import reflectLlmSchemaContract from "../../assets/prompts/reflect-llm-schema-contract.md" with { type: "text" };
|
|
30
30
|
import reflectOutputRepair from "../../assets/prompts/reflect-output-repair.md" with { type: "text" };
|
|
31
31
|
import { placementTypes } from "../../core/asset/asset-placement.js";
|
|
32
|
+
import { parseRefInput } from "../../core/asset/resolve-ref.js";
|
|
32
33
|
import { authoringRulesForType, DESCRIPTION_MAX_CHARS, DESCRIPTION_MIN_CHARS, requiresDescription, } from "../../core/authoring-rules.js";
|
|
33
34
|
import { parseEmbeddedJsonResponse, stripCodeFences, stripThinkBlocks } from "../../core/parse.js";
|
|
34
35
|
/**
|
|
@@ -45,7 +46,7 @@ const TYPE_HINTS = {
|
|
|
45
46
|
memory: "memory assets are short factual notes the user wants persisted across sessions. Frontmatter usually includes `description`.",
|
|
46
47
|
workflow: "workflow assets are markdown describing a multi-step process. Include `# <Title>` and ordered `## Step N` sections.",
|
|
47
48
|
script: "script assets are executable text files. Include a shebang and minimal usage comment.",
|
|
48
|
-
env: "env assets are `.env` files holding a group of related CONFIGURATION for an app/service (KEY=VALUE pairs, `#` comments) — URLs, flags, and any credentials it needs. Values may or may not be sensitive; all are protected (key names discoverable, values stay on disk). Inject with `akm env run env
|
|
49
|
+
env: "env assets are `.env` files holding a group of related CONFIGURATION for an app/service (KEY=VALUE pairs, `#` comments) — URLs, flags, and any credentials it needs. Values may or may not be sensitive; all are protected (key names discoverable, values stay on disk). Inject with `akm env run env/<name> -- <cmd>`; prefer `--clean` in agent contexts so the child starts from a minimal inherited environment. AKM itself does not print values, but the child command can print its environment, so do not run `env`, `printenv`, shell tracing, or similar diagnostics when secrets are in scope. For a single sensitive value used on its own for authentication (token, key, cert) use a `secret` instead. Never echo values back to the user.",
|
|
49
50
|
wiki: "wiki assets are markdown reference pages with `# Title` and structured headings.",
|
|
50
51
|
fact: "fact assets are durable stash-level facts (personal/team/project details, coding conventions, stash-meta). Frontmatter SHOULD include `description` and a `category` (personal|team|project|convention|meta); set `pinned: true` only for the small always-injected core. Keep each fact short, high-signal, and self-contained — it is durable context, not an episodic note.",
|
|
51
52
|
};
|
|
@@ -63,7 +64,10 @@ function knownTypeList() {
|
|
|
63
64
|
*/
|
|
64
65
|
const RESPONSE_CONTRACT_JSON = [
|
|
65
66
|
"Respond ONLY with a single JSON object. No prose before or after.",
|
|
66
|
-
|
|
67
|
+
// Slash conceptId, not the retired `<type>:<name>` colon grammar (Q-02/Q-08).
|
|
68
|
+
// This contract is the schema an agent copies from, so a stale spelling here
|
|
69
|
+
// teaches every proposal to use a ref form the CLI now rejects outright.
|
|
70
|
+
'Shape: {"ref": "<type>/<name>", "content": "<full file contents>", "frontmatter": {...}, "confidence": <number 0..1>}',
|
|
67
71
|
"`content` is the full file body that will be written if accepted.",
|
|
68
72
|
"`frontmatter` is optional — include it if `content` starts with `---` so reviewers can sanity-check the keys.",
|
|
69
73
|
"`confidence` is REQUIRED. Self-rate this proposal on [0, 1] by how certain you are it materially improves the source asset. Calibrate honestly:",
|
|
@@ -174,7 +178,7 @@ export function buildReflectPrompt(input) {
|
|
|
174
178
|
const goalSentence = isLesson
|
|
175
179
|
? `Your task is to distill what usage signals reveal about this ${input.type} asset — when to reach for it, what goes wrong without it, and what real use has revealed that the asset itself does not say. Do not reproduce the source content; your proposal must add information the source does not contain.`
|
|
176
180
|
: isSkill
|
|
177
|
-
? "Your task is to review this skill asset, identify what the feedback and related distilled lessons show is broken, missing, unclear, or durable enough to promote into long-term documentation, and produce a single improved proposal. If the strongest evidence points to companion reference material rather than the main SKILL.md, you may instead propose a skill-adjacent knowledge doc such as `knowledge
|
|
181
|
+
? "Your task is to review this skill asset, identify what the feedback and related distilled lessons show is broken, missing, unclear, or durable enough to promote into long-term documentation, and produce a single improved proposal. If the strongest evidence points to companion reference material rather than the main SKILL.md, you may instead propose a skill-adjacent knowledge doc such as `knowledge/skills/<skill>/references/<topic>`."
|
|
178
182
|
: `Your task is to review this ${input.type} asset, identify what the feedback signals as broken, missing, or unclear, and produce an improved version. Do not reproduce the source content unchanged; your proposal must correct or add something the source lacks.`;
|
|
179
183
|
sections.push(goalSentence);
|
|
180
184
|
sections.push(`Target ref: ${input.ref}`);
|
|
@@ -210,7 +214,7 @@ export function buildReflectPrompt(input) {
|
|
|
210
214
|
sections.push(input.standardsContext.trim());
|
|
211
215
|
}
|
|
212
216
|
{
|
|
213
|
-
const resolvedType = input.type ?? (input.ref
|
|
217
|
+
const resolvedType = input.type ?? (input.ref ? parseRefInput(input.ref).type : "");
|
|
214
218
|
const authoringRules = resolvedType ? authoringRulesForType(resolvedType) : "";
|
|
215
219
|
if (authoringRules) {
|
|
216
220
|
sections.push(authoringRules);
|
|
@@ -268,7 +272,7 @@ export function buildReflectPrompt(input) {
|
|
|
268
272
|
}
|
|
269
273
|
sections.push("Evaluate whether these lessons contain strong evidence of factual, repeatable guidance that should be promoted into long-term skill documentation.");
|
|
270
274
|
sections.push("Promote only guidance that is durable, generally applicable, and supported by repeated evidence. Do not copy anecdotal details, one-off incidents, or duplicate wording verbatim.");
|
|
271
|
-
sections.push("If the guidance belongs in the main skill instructions, update the skill proposal. If it belongs in a companion reference document, return a `knowledge
|
|
275
|
+
sections.push("If the guidance belongs in the main skill instructions, update the skill proposal. If it belongs in a companion reference document, return a `knowledge/skills/<skill>/references/<topic>` proposal instead.");
|
|
272
276
|
}
|
|
273
277
|
if (input.rejectedProposals && input.rejectedProposals.length > 0) {
|
|
274
278
|
const lines = ["## Previously Rejected Proposals"];
|
|
@@ -423,7 +427,7 @@ export function buildSchemaRepairPrompt(input) {
|
|
|
423
427
|
* can map to {@link AgentFailureReason} `parse_error`.
|
|
424
428
|
*
|
|
425
429
|
* Resilient to two common local-LLM failure modes:
|
|
426
|
-
* 1. `<think>…</think>` blocks emitted before the JSON (stripped
|
|
430
|
+
* 1. `<think>…</think>` blocks emitted before the JSON (stripped before parsing).
|
|
427
431
|
* 2. Prose preamble / postamble around the JSON object (handled by `extractEmbeddedJson`).
|
|
428
432
|
*/
|
|
429
433
|
export function parseAgentProposalPayload(stdout) {
|
|
@@ -76,8 +76,10 @@ export function collectDispatchSensitiveValues(spec, opts, envSource = opts.envS
|
|
|
76
76
|
add(value);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
for (const value of Object.
|
|
80
|
-
|
|
79
|
+
for (const [name, value] of Object.entries(opts.env ?? {})) {
|
|
80
|
+
if (!isEnvPassthroughValueSafeToExpose(name, value))
|
|
81
|
+
add(value);
|
|
82
|
+
}
|
|
81
83
|
return collectSensitiveValues(values);
|
|
82
84
|
}
|
|
83
85
|
function redactResult(result, sensitiveValues) {
|
|
@@ -21,7 +21,6 @@ import { parseEmbeddedJsonResponse } from "../../core/parse.js";
|
|
|
21
21
|
import { runManagedSubprocess, } from "../../core/subprocess.js";
|
|
22
22
|
import { getCommandBuilder } from "./builders.js";
|
|
23
23
|
import { DEFAULT_AGENT_TIMEOUT_MS } from "./config.js";
|
|
24
|
-
const DEFAULT_TIMEOUT_MS = DEFAULT_AGENT_TIMEOUT_MS;
|
|
25
24
|
/**
|
|
26
25
|
* Supplement `existingPath` with well-known user binary directories when
|
|
27
26
|
* running in a scheduler context (cron/launchd) where PATH is stripped.
|
|
@@ -144,7 +143,7 @@ function streamFailureMessage(profileName, stdout, stderr) {
|
|
|
144
143
|
export async function runAgent(profile, prompt, options = {}) {
|
|
145
144
|
const stdioMode = options.stdio ?? profile.stdio;
|
|
146
145
|
// null = explicitly disabled (no kill timer). undefined = runtime default.
|
|
147
|
-
const timeoutMs = options.timeoutMs !== undefined ? options.timeoutMs :
|
|
146
|
+
const timeoutMs = options.timeoutMs !== undefined ? options.timeoutMs : DEFAULT_AGENT_TIMEOUT_MS;
|
|
148
147
|
const parseOutput = options.parseOutput ?? profile.parseOutput;
|
|
149
148
|
const setTimeoutImpl = options.setTimeoutFn ?? setTimeout;
|
|
150
149
|
const clearTimeoutImpl = options.clearTimeoutFn ?? clearTimeout;
|
|
@@ -160,7 +159,7 @@ export async function runAgent(profile, prompt, options = {}) {
|
|
|
160
159
|
}
|
|
161
160
|
};
|
|
162
161
|
// Build argv via the platform-specific builder when dispatch params are
|
|
163
|
-
// provided;
|
|
162
|
+
// provided; otherwise use the direct positional-prompt form.
|
|
164
163
|
let builtArgv;
|
|
165
164
|
let builtEnv;
|
|
166
165
|
if (options.dispatch !== undefined) {
|
|
@@ -170,10 +169,10 @@ export async function runAgent(profile, prompt, options = {}) {
|
|
|
170
169
|
builtEnv = built.env;
|
|
171
170
|
}
|
|
172
171
|
else {
|
|
173
|
-
const
|
|
172
|
+
const positionalArgs = [...profile.args, ...(options.args ?? [])];
|
|
174
173
|
if (prompt !== undefined)
|
|
175
|
-
|
|
176
|
-
builtArgv = [profile.bin, ...
|
|
174
|
+
positionalArgs.push(prompt);
|
|
175
|
+
builtArgv = [profile.bin, ...positionalArgs];
|
|
177
176
|
}
|
|
178
177
|
// Extra args (e.g. forwarded CLI positionals) are appended after the builder output.
|
|
179
178
|
const finalArgv = [...builtArgv, ...(options.dispatch ? (options.args ?? []) : [])];
|