akm-cli 0.9.0-rc.0 → 0.9.0-rc.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1283 -22
- package/README.md +62 -37
- package/SECURITY.md +46 -31
- package/dist/akm +162 -38
- package/dist/akm-migrate +44 -0
- package/dist/assets/backends/schtasks-template.xml +2 -1
- package/dist/assets/hints/cli-hints-full.md +268 -118
- package/dist/assets/hints/cli-hints-short.md +87 -24
- package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
- package/dist/assets/improve-strategies/frequent.json +15 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
- package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
- package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
- package/dist/assets/improve-strategies/reflect-distill.json +30 -0
- package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +5 -5
- package/dist/assets/prompts/extract-session.md +2 -6
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
- package/dist/assets/prompts/reflect-output-repair.md +3 -0
- package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
- package/dist/assets/stash-skeleton/README.md +38 -10
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
- package/dist/assets/tasks/core/extract.yml +3 -2
- package/dist/assets/tasks/core/improve.yml +2 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +2 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +5 -4
- package/dist/assets/workflows/workflow-template.md +31 -15
- package/dist/cli/invocation.js +279 -0
- package/dist/cli/parse-args.js +5 -90
- package/dist/cli/retired-commands.js +78 -0
- package/dist/cli/shared.js +158 -48
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +747 -293
- package/dist/commands/agent/agent-dispatch.js +19 -18
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +43 -97
- package/dist/commands/completions.js +80 -23
- package/dist/commands/config-cli.js +44 -281
- package/dist/commands/env/env-binding.js +99 -0
- package/dist/commands/env/env-cli.js +84 -224
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +45 -61
- package/dist/commands/env/secret.js +32 -62
- package/dist/commands/feedback-cli.js +179 -85
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +7 -8
- package/dist/commands/health/checks.js +279 -94
- package/dist/commands/health/html-report.js +197 -578
- package/dist/commands/health/improve-metrics.js +277 -246
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +16 -7
- package/dist/commands/health/metrics.js +67 -32
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +508 -0
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +16 -56
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
- package/dist/commands/health/types-improve.js +29 -0
- package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
- package/dist/commands/health/types-result.js +7 -0
- package/dist/commands/health/types-runs.js +4 -0
- package/dist/commands/health/types-session-log.js +4 -0
- package/dist/commands/health/types-windows.js +4 -0
- package/dist/commands/health/types.js +26 -21
- package/dist/commands/health/windows.js +2 -3
- package/dist/commands/health.js +296 -167
- package/dist/commands/improve/anti-collapse.js +5 -5
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +65 -52
- package/dist/commands/improve/consolidate/chunking.js +9 -7
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +454 -1354
- package/dist/commands/improve/content-hash.js +39 -0
- package/dist/commands/improve/distill/content-repair.js +4 -10
- package/dist/commands/improve/distill/promote-memory.js +89 -64
- package/dist/commands/improve/distill/quality-gate.js +118 -42
- package/dist/commands/improve/distill-guards.js +1 -1
- package/dist/commands/improve/distill-promotion-policy.js +33 -888
- package/dist/commands/improve/distill.js +607 -363
- package/dist/commands/improve/eligibility.js +165 -79
- package/dist/commands/improve/extract-cli.js +35 -126
- package/dist/commands/improve/extract-prompt.js +6 -35
- package/dist/commands/improve/extract.js +640 -391
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +134 -135
- package/dist/commands/improve/improve-result-file.js +30 -50
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +135 -0
- package/dist/commands/improve/improve.js +904 -701
- package/dist/commands/improve/locks.js +64 -111
- package/dist/commands/improve/loop-stages.js +1110 -923
- package/dist/commands/improve/memory/derived-ref.js +124 -0
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
- package/dist/commands/improve/memory/memory-improve.js +25 -37
- package/dist/commands/improve/outcome-loop.js +25 -88
- package/dist/commands/improve/preparation.js +1034 -813
- package/dist/commands/improve/proactive-maintenance.js +34 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +983 -794
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +24 -127
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -34
- package/dist/commands/improve/source-identity.js +28 -0
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +340 -313
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +185 -30
- package/dist/commands/{events.js → log.js} +28 -38
- package/dist/commands/migrate-cli.js +54 -0
- package/dist/commands/migration-tool.js +55 -0
- package/dist/commands/observability-cli.js +70 -208
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +91 -40
- package/dist/commands/proposal/proposal-cli.js +134 -132
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +83 -65
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +105 -88
- package/dist/commands/proposal/repository.js +1303 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
- package/dist/commands/proposal/validators/proposal-validators.js +61 -12
- package/dist/commands/proposal/validators/proposals.js +6 -8
- package/dist/commands/read/curate.js +78 -73
- package/dist/commands/read/knowledge.js +510 -13
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +84 -15
- package/dist/commands/read/search-cli.js +203 -96
- package/dist/commands/read/search.js +126 -94
- package/dist/commands/read/show.js +226 -250
- package/dist/commands/registry-cli.js +34 -60
- package/dist/commands/remember.js +18 -57
- package/dist/commands/sources/add-cli.js +104 -49
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +63 -0
- package/dist/commands/sources/info.js +27 -15
- package/dist/commands/sources/init.js +30 -40
- package/dist/commands/sources/installed-stashes.js +469 -172
- package/dist/commands/sources/migration-help.js +7 -4
- package/dist/commands/sources/schema-repair.js +10 -9
- package/dist/commands/sources/self-update.js +182 -121
- package/dist/commands/sources/source-add.js +169 -178
- package/dist/commands/sources/source-clone.js +144 -41
- package/dist/commands/sources/source-manage.js +94 -59
- package/dist/commands/sources/sources-cli.js +64 -205
- package/dist/commands/sources/stash-cli.js +91 -54
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +106 -104
- package/dist/commands/tasks/tasks.js +445 -262
- package/dist/commands/workflow-cli.js +232 -121
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/activation-policy.js +49 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
- package/dist/core/adapter/adapters/akm-adapter.js +528 -0
- package/dist/core/adapter/adapters/akm-lint.js +392 -0
- package/dist/core/adapter/adapters/akm-metadata.js +387 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
- package/dist/core/adapter/adapters/claude-adapter.js +61 -0
- package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
- package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
- package/dist/core/adapter/adapters/okf-adapter.js +391 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
- package/dist/core/adapter/adapters/shared.js +286 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +44 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/akm-markdown.js +30 -0
- package/dist/core/asset/asset-placement.js +243 -0
- package/dist/core/asset/asset-ref.js +110 -79
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +28 -12
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +274 -0
- package/dist/core/asset/stash-meta.js +2 -2
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +281 -86
- package/dist/core/config/config-io.js +42 -128
- package/dist/core/config/config-schema.js +233 -834
- package/dist/core/config/config-sources.js +162 -39
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +126 -37
- package/dist/core/config/config.js +154 -331
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +28 -0
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/experimental.js +47 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +389 -0
- package/dist/core/config/schema/improve.js +94 -0
- package/dist/core/config/schema/index-config.js +176 -0
- package/dist/core/config/schema/output.js +18 -0
- package/dist/core/config/schema/primitives.js +94 -0
- package/dist/core/config/schema/search.js +30 -0
- package/dist/core/config/schema/setup.js +18 -0
- package/dist/core/config/schema/sources-bundles.js +169 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +155 -20
- package/dist/core/errors.js +17 -15
- package/dist/core/events-types.js +4 -0
- package/dist/core/events.js +46 -128
- package/dist/core/extra-params.js +62 -0
- package/dist/core/file-change.js +17 -0
- package/dist/core/file-lock.js +202 -57
- package/dist/core/fs-txn.js +392 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +167 -0
- package/dist/core/json-schema.js +142 -0
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +135 -0
- package/dist/core/migration-operation.js +44 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/paths.js +22 -25
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +128 -0
- package/dist/core/redaction.js +392 -0
- package/dist/core/standards/resolve-standards-context.js +36 -65
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +5 -5
- package/dist/core/state/migrations.js +242 -11
- package/dist/core/state-db.js +98 -10
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +303 -0
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +834 -118
- package/dist/indexer/bundle-identity-guard.js +92 -0
- package/dist/indexer/db/graph-db.js +1 -25
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +30 -9
- package/dist/indexer/graph/graph-boost.js +9 -30
- package/dist/indexer/graph/graph-extraction.js +41 -27
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-writer-lock.js +93 -49
- package/dist/indexer/index-written-assets.js +100 -53
- package/dist/indexer/indexer.js +746 -329
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +142 -0
- package/dist/indexer/passes/dir-staleness.js +18 -10
- package/dist/indexer/passes/memory-inference.js +25 -15
- package/dist/indexer/passes/metadata.js +412 -243
- package/dist/indexer/scan/doc-to-entry.js +160 -0
- package/dist/indexer/scan/drain-dir.js +134 -0
- package/dist/indexer/search/db-search.js +292 -108
- package/dist/indexer/search/fts-query.js +64 -0
- package/dist/indexer/search/ranking-contributors.js +145 -25
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +28 -71
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-fields.js +18 -3
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +157 -111
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/usage-events.js +10 -30
- package/dist/indexer/walk/file-context.js +3 -45
- package/dist/indexer/walk/matchers.js +42 -34
- package/dist/indexer/walk/path-resolver.js +11 -5
- package/dist/indexer/walk/walker.js +42 -14
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -56
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +231 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +16 -2
- package/dist/integrations/agent/profiles.js +36 -62
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +93 -4
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +88 -196
- package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
- package/dist/integrations/harnesses/aider/index.js +48 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
- package/dist/integrations/harnesses/amazonq/index.js +45 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +24 -35
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
- package/dist/integrations/harnesses/codex/index.js +52 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
- package/dist/integrations/harnesses/copilot/index.js +48 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
- package/dist/integrations/harnesses/gemini/index.js +48 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +54 -34
- package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +14 -32
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
- package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
- package/dist/integrations/harnesses/openhands/index.js +48 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
- package/dist/integrations/harnesses/pi/index.js +45 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +43 -32
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +36 -39
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +182 -110
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +21 -9
- package/dist/llm/feature-gate.js +17 -57
- package/dist/llm/graph-extract.js +12 -13
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +45 -30
- package/dist/llm/structured-call.js +16 -8
- package/dist/llm/usage-persist.js +30 -5
- package/dist/llm/usage-telemetry.js +59 -6
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/command-registry.js +27 -0
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +251 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -279
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +58 -84
- package/dist/output/shapes/passthrough.js +11 -39
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/shapes.js +0 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +562 -0
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/helpers.js +15 -1164
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +202 -0
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +117 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +332 -0
- package/dist/output/text/workflow.js +3 -2
- package/dist/output/text.js +10 -19
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +15 -25
- package/dist/registry/resolve.js +43 -94
- package/dist/registry/semver.js +43 -0
- package/dist/runtime.js +81 -12
- package/dist/scripts/akm-migrate.js +35529 -0
- package/dist/setup/detect.js +5 -7
- package/dist/setup/detected-engines.js +136 -0
- package/dist/setup/engine-config.js +100 -0
- package/dist/setup/registry-stash-loader.js +3 -3
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +444 -208
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +108 -305
- package/dist/setup/steps/platforms.js +13 -12
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +21 -15
- package/dist/setup/steps/stashdir.js +6 -4
- package/dist/setup/steps/tasks.js +236 -119
- package/dist/setup/steps.js +3 -2
- package/dist/sources/freshness.js +39 -0
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +54 -56
- package/dist/sources/providers/git-stash.js +420 -91
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +47 -22
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +11 -10
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
- package/dist/storage/database.js +60 -4
- package/dist/storage/engines/sqlite-migrations.js +156 -5
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +51 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -32
- package/dist/storage/repositories/index-connection.js +79 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +863 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +167 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
- package/dist/storage/repositories/index-meta-repository.js +49 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +356 -0
- package/dist/storage/repositories/index-vec-repository.js +250 -0
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +317 -75
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +110 -3
- package/dist/storage/repositories/workflow-runs-repository.js +240 -19
- package/dist/tasks/backends/cron.js +169 -46
- package/dist/tasks/backends/exec-utils.js +76 -3
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +292 -55
- package/dist/tasks/backends/schtasks.js +557 -70
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/command-executable.js +93 -0
- package/dist/tasks/embedded.js +56 -38
- package/dist/tasks/parser.js +156 -64
- package/dist/tasks/resolve-akm-bin.js +144 -51
- package/dist/tasks/runner.js +377 -209
- package/dist/tasks/schedule.js +108 -19
- package/dist/tasks/scheduler-invocation.js +296 -0
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/task-id.js +35 -0
- package/dist/tasks/validator.js +30 -16
- package/dist/text-import-hook.mjs +1 -1
- package/dist/workflows/authoring/authoring.js +104 -43
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -16
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +450 -0
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +1038 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1460 -0
- package/dist/workflows/exec/run-workflow.js +602 -0
- package/dist/workflows/exec/scheduler.js +71 -0
- package/dist/workflows/exec/step-work.js +1190 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +246 -0
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +68 -0
- package/dist/workflows/ir/schema.js +540 -0
- package/dist/workflows/parser.js +878 -304
- package/dist/workflows/program/expressions.js +181 -0
- package/dist/workflows/program/schema.js +51 -0
- package/dist/workflows/renderer.js +100 -45
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +376 -119
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +2 -3
- package/dist/workflows/validator.js +52 -30
- package/docs/README.md +42 -78
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +9 -8
- package/docs/migration/release-notes/0.9.0.md +158 -14
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +844 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/data-and-telemetry.md +333 -0
- package/package.json +21 -17
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +4636 -0
- package/schemas/akm-task.json +87 -0
- package/schemas/akm-workflow.json +373 -0
- package/dist/akm-migrate-storage +0 -38
- package/dist/assets/help/help-accept.md +0 -12
- package/dist/assets/help/help-improve.md +0 -84
- package/dist/assets/help/help-proposals.md +0 -17
- package/dist/assets/help/help-propose.md +0 -17
- package/dist/assets/help/help-reject.md +0 -11
- package/dist/assets/profiles/frequent.json +0 -13
- package/dist/assets/profiles/recombine-only.json +0 -21
- package/dist/assets/profiles/reflect-distill.json +0 -30
- package/dist/assets/profiles/synthesize.json +0 -15
- package/dist/assets/prompts/procedural-system.md +0 -44
- package/dist/assets/prompts/recombine-system.md +0 -40
- package/dist/assets/prompts/staleness-detect-system.md +0 -6
- package/dist/assets/tasks/core/backup.yml +0 -4
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/assets/templates/html/default.html +0 -78
- package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
- package/dist/assets/wiki/index-template.md +0 -12
- package/dist/assets/wiki/ingest-workflow-template.md +0 -83
- package/dist/assets/wiki/log-template.md +0 -8
- package/dist/assets/wiki/schema-template.md +0 -61
- package/dist/cli/config-migrate.js +0 -150
- package/dist/cli/config-validate.js +0 -39
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -487
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -276
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/commands/improve/procedural.js +0 -398
- package/dist/commands/improve/recombine.js +0 -818
- package/dist/commands/improve/schema-similarity-gate.js +0 -168
- package/dist/commands/lint/agent-linter.js +0 -44
- package/dist/commands/lint/command-linter.js +0 -44
- package/dist/commands/lint/default-linter.js +0 -16
- package/dist/commands/lint/fact-linter.js +0 -39
- package/dist/commands/lint/knowledge-linter.js +0 -16
- package/dist/commands/lint/memory-linter.js +0 -61
- package/dist/commands/lint/registry.js +0 -41
- package/dist/commands/lint/skill-linter.js +0 -45
- package/dist/commands/lint/task-linter.js +0 -50
- package/dist/commands/lint/workflow-linter.js +0 -81
- package/dist/commands/proposal/legacy-import.js +0 -115
- package/dist/commands/sources/history.js +0 -196
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/commands/wiki-cli.js +0 -292
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -259
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/core/eval/rank-metrics.js +0 -113
- package/dist/core/ripgrep/install.js +0 -163
- package/dist/core/ripgrep/resolve.js +0 -81
- package/dist/indexer/db/db.js +0 -1413
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
- package/dist/llm/call-ai.js +0 -62
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/output/text/wiki.js +0 -16
- package/dist/registry/build-index.js +0 -386
- package/dist/scripts/migrate-storage.js +0 -19108
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/setup/legacy-config.js +0 -106
- package/dist/storage/repositories/consolidation-repository.js +0 -38
- package/dist/storage/repositories/recombine-repository.js +0 -213
- package/dist/wiki/wiki-templates.js +0 -15
- package/dist/wiki/wiki.js +0 -1012
- package/dist/workflows/db.js +0 -215
- package/docs/data-and-telemetry.md +0 -226
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
|
@@ -2,32 +2,32 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Environment security lint rules — flags known-dangerous variable names.
|
|
6
6
|
*
|
|
7
|
-
* These env var names, when present
|
|
7
|
+
* These env var names, when present in an environment file, indicate the file can be
|
|
8
8
|
* used to hijack process execution via loader injection, path override, or
|
|
9
9
|
* shell/runtime startup hooks. The lint pass emits a warning-level finding;
|
|
10
|
-
* it does NOT block
|
|
10
|
+
* it does NOT block local environment edits.
|
|
11
11
|
*
|
|
12
12
|
* Enforcement scope:
|
|
13
|
-
* - `akm lint` reports findings as `dangerous-
|
|
14
|
-
* - `akm add` BLOCKS install unless `--allow-insecure` is set (or, on TTY,
|
|
13
|
+
* - `akm lint` reports findings as `dangerous-env-key` (non-blocking warn).
|
|
14
|
+
* - `akm bundle add` BLOCKS install unless `--allow-insecure` is set (or, on TTY,
|
|
15
15
|
* the user explicitly confirms at the prompt).
|
|
16
|
-
* -
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* - Local env writes do NOT consult this list — by design, the operator may
|
|
17
|
+
* legitimately store any key locally. The gate exists only for third-party
|
|
18
|
+
* stash installation.
|
|
19
19
|
*
|
|
20
20
|
* False-positive tradeoff:
|
|
21
21
|
* A handful of keys (EDITOR, VISUAL, PAGER) are included because they are
|
|
22
22
|
* invoked by many interactive tools and are a documented RCE vector when
|
|
23
|
-
* sourced from untrusted
|
|
23
|
+
* sourced from untrusted environments. They will also flag on benign files
|
|
24
24
|
* where the operator legitimately wants to set their editor — accept the
|
|
25
25
|
* FP and bypass with `--allow-insecure` after review.
|
|
26
26
|
*/
|
|
27
27
|
import fs from "node:fs";
|
|
28
28
|
import { listKeys } from "../env/env.js";
|
|
29
29
|
// ── Dangerous key set ─────────────────────────────────────────────────────────
|
|
30
|
-
export const
|
|
30
|
+
export const DANGEROUS_ENV_KEYS = new Set([
|
|
31
31
|
// Dynamic linker hijacking (Linux glibc ld.so)
|
|
32
32
|
"LD_PRELOAD", // forces shared library injection
|
|
33
33
|
"LD_LIBRARY_PATH", // overrides library search path
|
|
@@ -89,7 +89,7 @@ export const DANGEROUS_VAULT_KEYS = new Set([
|
|
|
89
89
|
* prefixed with `BASH_FUNC_`. Listing every concrete name is impossible; we
|
|
90
90
|
* test against this pattern set in addition to the literal `Set`.
|
|
91
91
|
*/
|
|
92
|
-
export const
|
|
92
|
+
export const DANGEROUS_ENV_KEY_PATTERNS = [
|
|
93
93
|
{
|
|
94
94
|
// CVE-2014-6271 (Shellshock) — bash imports exported functions named
|
|
95
95
|
// `BASH_FUNC_<name>%%` and parses their bodies, enabling RCE.
|
|
@@ -103,13 +103,13 @@ export const DANGEROUS_VAULT_KEY_PATTERNS = [
|
|
|
103
103
|
];
|
|
104
104
|
/**
|
|
105
105
|
* Returns `true` if the given key name is dangerous — either by literal match
|
|
106
|
-
* against `
|
|
107
|
-
* `
|
|
106
|
+
* against `DANGEROUS_ENV_KEYS` or by matching any entry in
|
|
107
|
+
* `DANGEROUS_ENV_KEY_PATTERNS`.
|
|
108
108
|
*/
|
|
109
|
-
export function
|
|
110
|
-
if (
|
|
109
|
+
export function isDangerousEnvKey(key) {
|
|
110
|
+
if (DANGEROUS_ENV_KEYS.has(key))
|
|
111
111
|
return true;
|
|
112
|
-
for (const { pattern } of
|
|
112
|
+
for (const { pattern } of DANGEROUS_ENV_KEY_PATTERNS) {
|
|
113
113
|
if (pattern.test(key))
|
|
114
114
|
return true;
|
|
115
115
|
}
|
|
@@ -117,27 +117,26 @@ export function isDangerousVaultKey(key) {
|
|
|
117
117
|
}
|
|
118
118
|
// ── Checker ───────────────────────────────────────────────────────────────────
|
|
119
119
|
/**
|
|
120
|
-
* Inspect
|
|
121
|
-
*
|
|
122
|
-
* `DANGEROUS_VAULT_KEY_PATTERNS`.
|
|
120
|
+
* Inspect an `.env` file and return a lint finding for every key whose name
|
|
121
|
+
* appears in `DANGEROUS_ENV_KEYS` or matches `DANGEROUS_ENV_KEY_PATTERNS`.
|
|
123
122
|
*
|
|
124
|
-
* @param
|
|
123
|
+
* @param envPath Absolute path to the `.env` file.
|
|
125
124
|
* @param relPath Stash-relative path used as the `file` field in findings
|
|
126
|
-
* (e.g. `"
|
|
127
|
-
* @param
|
|
125
|
+
* (e.g. `"env/prod.env"`).
|
|
126
|
+
* @param envRef Human-readable env ref (e.g. `"env/prod"`) shown in
|
|
128
127
|
* the finding message.
|
|
129
128
|
*/
|
|
130
129
|
/** Suppression comment token checked case-insensitively on the preceding non-empty line. */
|
|
131
|
-
const SUPPRESSION_COMMENT = "# akm-lint-ok: dangerous-
|
|
130
|
+
const SUPPRESSION_COMMENT = "# akm-lint-ok: dangerous-env-key";
|
|
132
131
|
/**
|
|
133
|
-
* Returns the set of keys suppressed by an inline `# akm-lint-ok: dangerous-
|
|
132
|
+
* Returns the set of keys suppressed by an inline `# akm-lint-ok: dangerous-env-key`
|
|
134
133
|
* comment on the line immediately preceding the key assignment in the `.env` file.
|
|
135
134
|
*/
|
|
136
|
-
function collectSuppressedKeys(
|
|
135
|
+
function collectSuppressedKeys(envPath) {
|
|
137
136
|
const suppressed = new Set();
|
|
138
137
|
let raw;
|
|
139
138
|
try {
|
|
140
|
-
raw = fs.readFileSync(
|
|
139
|
+
raw = fs.readFileSync(envPath, "utf8");
|
|
141
140
|
}
|
|
142
141
|
catch {
|
|
143
142
|
return suppressed;
|
|
@@ -156,36 +155,21 @@ function collectSuppressedKeys(vaultPath) {
|
|
|
156
155
|
}
|
|
157
156
|
return suppressed;
|
|
158
157
|
}
|
|
159
|
-
export function
|
|
160
|
-
const { keys } = listKeys(
|
|
161
|
-
const suppressed = collectSuppressedKeys(
|
|
158
|
+
export function checkEnvForDangerousKeys(envPath, relPath, envRef) {
|
|
159
|
+
const { keys } = listKeys(envPath);
|
|
160
|
+
const suppressed = collectSuppressedKeys(envPath);
|
|
162
161
|
const issues = [];
|
|
163
162
|
for (const key of keys) {
|
|
164
|
-
if (!
|
|
163
|
+
if (!isDangerousEnvKey(key))
|
|
165
164
|
continue;
|
|
166
165
|
if (suppressed.has(key))
|
|
167
166
|
continue;
|
|
168
167
|
issues.push({
|
|
169
168
|
file: relPath,
|
|
170
|
-
issue: "dangerous-
|
|
171
|
-
detail: `Env key \`${key}\` can be used to hijack process execution when injected via \`akm env run\`. Ref: ${
|
|
169
|
+
issue: "dangerous-env-key",
|
|
170
|
+
detail: `Env key \`${key}\` can be used to hijack process execution when injected via \`akm env run\`. Ref: ${envRef}. Review this file before running \`akm env run\` commands against untrusted stashes. (suppress with: ${SUPPRESSION_COMMENT} on previous line)`,
|
|
172
171
|
fixed: false,
|
|
173
172
|
});
|
|
174
173
|
}
|
|
175
174
|
return issues;
|
|
176
175
|
}
|
|
177
|
-
// ── Env-neutral aliases ───────────────────────────────────────────────────────
|
|
178
|
-
//
|
|
179
|
-
// These primitives guard *environment variable injection*, which is shared by
|
|
180
|
-
// the `env` asset type, whole-file `secret` injection, and the `akm add`
|
|
181
|
-
// supply-chain gate. The original `*Vault*` names are retained above for
|
|
182
|
-
// backward compatibility (and stable lint output) through the 0.8.x
|
|
183
|
-
// deprecation window; new call sites should prefer the env-neutral names.
|
|
184
|
-
/** Env-neutral alias of {@link DANGEROUS_VAULT_KEYS}. */
|
|
185
|
-
export const DANGEROUS_ENV_KEYS = DANGEROUS_VAULT_KEYS;
|
|
186
|
-
/** Env-neutral alias of {@link DANGEROUS_VAULT_KEY_PATTERNS}. */
|
|
187
|
-
export const DANGEROUS_ENV_KEY_PATTERNS = DANGEROUS_VAULT_KEY_PATTERNS;
|
|
188
|
-
/** Env-neutral alias of {@link isDangerousVaultKey}. */
|
|
189
|
-
export const isDangerousEnvKey = isDangerousVaultKey;
|
|
190
|
-
/** Env-neutral alias of {@link checkVaultForDangerousKeys}. */
|
|
191
|
-
export const checkEnvForDangerousKeys = checkVaultForDangerousKeys;
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { parse as parseYaml } from "yaml";
|
|
7
|
-
import {
|
|
7
|
+
import { factDiagnostics, matchWorkflowPlaceholder, memoryOrphanStubApplies, nameOrTypeDiagnostics, ORPHANED_STUB_DETAIL, taskDiagnostics, workflowStructureDiagnostics, } from "../../core/adapter/adapters/akm-lint.js";
|
|
8
|
+
import { detectAdapterId } from "../../core/adapter/detect-adapter.js";
|
|
9
|
+
import { parseFrontmatter, parseFrontmatterBlock } from "../../core/asset/frontmatter.js";
|
|
8
10
|
import { resolveStashDir } from "../../core/common.js";
|
|
9
|
-
import { loadConfig } from "../../core/config/config.js";
|
|
11
|
+
import { loadConfig, primaryBundlePath } from "../../core/config/config.js";
|
|
10
12
|
import { resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
13
|
+
import { runBaseChecks } from "./base-linter.js";
|
|
11
14
|
import { checkEnvForDangerousKeys } from "./env-key-rules.js";
|
|
12
|
-
import { getLinterForType } from "./registry.js";
|
|
13
15
|
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
14
16
|
const STASH_SUBDIRS = [
|
|
15
17
|
"agents",
|
|
@@ -38,21 +40,57 @@ function collectYamlFiles(dir) {
|
|
|
38
40
|
}
|
|
39
41
|
return results;
|
|
40
42
|
}
|
|
41
|
-
function collectMarkdownFiles(dir) {
|
|
43
|
+
function collectMarkdownFiles(dir, caseInsensitive = false) {
|
|
42
44
|
if (!fs.existsSync(dir))
|
|
43
45
|
return [];
|
|
44
46
|
const results = [];
|
|
45
47
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
48
|
+
if (entry.name === ".git" || entry.isSymbolicLink())
|
|
49
|
+
continue;
|
|
46
50
|
const full = path.join(dir, entry.name);
|
|
47
51
|
if (entry.isDirectory()) {
|
|
48
|
-
results.push(...collectMarkdownFiles(full));
|
|
52
|
+
results.push(...collectMarkdownFiles(full, caseInsensitive));
|
|
49
53
|
}
|
|
50
|
-
else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
54
|
+
else if (entry.isFile() && (caseInsensitive ? entry.name.toLowerCase() : entry.name).endsWith(".md")) {
|
|
51
55
|
results.push(full);
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
return results;
|
|
55
59
|
}
|
|
60
|
+
function lintOkfBundle(stashRoot) {
|
|
61
|
+
const flagged = [];
|
|
62
|
+
for (const filePath of collectMarkdownFiles(stashRoot, true)) {
|
|
63
|
+
const basename = path.basename(filePath).toLowerCase();
|
|
64
|
+
if (basename === "index.md" || basename === "log.md")
|
|
65
|
+
continue;
|
|
66
|
+
const relPath = path.relative(stashRoot, filePath);
|
|
67
|
+
let validMappingWithType = false;
|
|
68
|
+
try {
|
|
69
|
+
const block = parseFrontmatterBlock(fs.readFileSync(filePath, "utf8"));
|
|
70
|
+
if (block) {
|
|
71
|
+
const data = parseYaml(block.frontmatter);
|
|
72
|
+
validMappingWithType =
|
|
73
|
+
typeof data === "object" &&
|
|
74
|
+
data !== null &&
|
|
75
|
+
!Array.isArray(data) &&
|
|
76
|
+
typeof data.type === "string" &&
|
|
77
|
+
data.type.trim().length > 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
validMappingWithType = false;
|
|
82
|
+
}
|
|
83
|
+
if (!validMappingWithType) {
|
|
84
|
+
flagged.push({
|
|
85
|
+
file: relPath,
|
|
86
|
+
issue: "missing-type",
|
|
87
|
+
detail: "OKF concepts require parseable mapping frontmatter with a non-empty type.",
|
|
88
|
+
fixed: false,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { ok: true, fixed: [], flagged, summary: { fixed: 0, flagged: flagged.length } };
|
|
93
|
+
}
|
|
56
94
|
function collectEnvFiles(dir) {
|
|
57
95
|
const results = [];
|
|
58
96
|
try {
|
|
@@ -73,45 +111,162 @@ function collectEnvFiles(dir) {
|
|
|
73
111
|
function isFileDeletion(issue) {
|
|
74
112
|
return issue.fixed === true && (issue.issue === "orphaned-stub" || issue.issue === "placeholder-stub");
|
|
75
113
|
}
|
|
114
|
+
// ── Per-file lint dispatch (was registry.ts + the 9 per-type linter classes) ──
|
|
115
|
+
//
|
|
116
|
+
// akm 0.9.0 chunk-3 (plan §12): the 9 `BaseLinter` subclasses + `LINTER_MAP`/
|
|
117
|
+
// `getLinterForType` are gone. The format-generic checks are the shared
|
|
118
|
+
// `runBaseChecks` (`./base-linter`); the per-`type` RULES are the `akm`
|
|
119
|
+
// adapter's `validate` surface (`core/adapter/adapters/akm-lint.ts`), imported
|
|
120
|
+
// here so both the read-only adapter and this fix-capable CLI sweep share ONE
|
|
121
|
+
// definition of each finding. The adapter never writes; the delete-fix for the
|
|
122
|
+
// two stub types is applied HERE (a core/CLI concern), reproducing the old
|
|
123
|
+
// MemoryLinter/WorkflowLinter `--fix` behavior byte-for-byte.
|
|
124
|
+
/**
|
|
125
|
+
* Reproduce `SkillLinter.lintDirectory`: a skill subdirectory with no
|
|
126
|
+
* `SKILL.md` is flagged `missing-skill-md` (never auto-fixable). Exported for
|
|
127
|
+
* the lint-parity golden (`tests/integration/goldens-lint-output.test.ts`).
|
|
128
|
+
*/
|
|
129
|
+
export function lintSkillDirectory(subdirPath, stashRoot) {
|
|
130
|
+
if (fs.existsSync(path.join(subdirPath, "SKILL.md")))
|
|
131
|
+
return [];
|
|
132
|
+
const relDir = path.relative(stashRoot, subdirPath);
|
|
133
|
+
return [{ file: relDir, issue: "missing-skill-md", detail: `no SKILL.md in ${relDir}/`, fixed: false }];
|
|
134
|
+
}
|
|
135
|
+
/** MemoryLinter's `orphaned-stub` check WITH its `--fix` delete (memory-linter.ts:19-65). */
|
|
136
|
+
function appendMemoryStubIssue(ctx, issues) {
|
|
137
|
+
if (!memoryOrphanStubApplies(ctx.data, ctx.body))
|
|
138
|
+
return;
|
|
139
|
+
const derivedPath = `${ctx.filePath.replace(/\.md$/i, "")}.derived.md`;
|
|
140
|
+
if (fs.existsSync(derivedPath))
|
|
141
|
+
return;
|
|
142
|
+
if (ctx.fix) {
|
|
143
|
+
try {
|
|
144
|
+
fs.unlinkSync(ctx.filePath);
|
|
145
|
+
issues.push({ file: ctx.relPath, issue: "orphaned-stub", detail: "deleted orphaned stub", fixed: true });
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
issues.push({
|
|
149
|
+
file: ctx.relPath,
|
|
150
|
+
issue: "orphaned-stub",
|
|
151
|
+
detail: `could not delete: ${e instanceof Error ? e.message : String(e)}`,
|
|
152
|
+
fixed: "failed",
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
issues.push({ file: ctx.relPath, issue: "orphaned-stub", detail: ORPHANED_STUB_DETAIL, fixed: false });
|
|
158
|
+
}
|
|
159
|
+
/** WorkflowLinter's `placeholder-stub` (WITH `--fix` delete) + `invalid-workflow-structure` (workflow-linter.ts:22-79). */
|
|
160
|
+
function appendWorkflowIssues(ctx, issues) {
|
|
161
|
+
const placeholder = matchWorkflowPlaceholder(ctx.body);
|
|
162
|
+
if (placeholder) {
|
|
163
|
+
if (ctx.fix) {
|
|
164
|
+
try {
|
|
165
|
+
fs.unlinkSync(ctx.filePath);
|
|
166
|
+
issues.push({
|
|
167
|
+
file: ctx.relPath,
|
|
168
|
+
issue: "placeholder-stub",
|
|
169
|
+
detail: `deleted: found "${placeholder}"`,
|
|
170
|
+
fixed: true,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
issues.push({
|
|
175
|
+
file: ctx.relPath,
|
|
176
|
+
issue: "placeholder-stub",
|
|
177
|
+
detail: `could not delete: ${e instanceof Error ? e.message : String(e)}`,
|
|
178
|
+
fixed: "failed",
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return; // WorkflowLinter returns before the structure check once a stub is fixed.
|
|
182
|
+
}
|
|
183
|
+
issues.push({
|
|
184
|
+
file: ctx.relPath,
|
|
185
|
+
issue: "placeholder-stub",
|
|
186
|
+
detail: `placeholder text: "${placeholder}"`,
|
|
187
|
+
fixed: false,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
// NB: the CLI passes the ABSOLUTE filePath to parseWorkflow (matching the old
|
|
191
|
+
// WorkflowLinter), whereas the adapter passes the change relPath.
|
|
192
|
+
issues.push(...workflowStructureDiagnostics(ctx.relPath, ctx.raw, ctx.filePath));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Lint ONE asset file: the shared base checks, then the winning stash subdir's
|
|
196
|
+
* per-`type` extra rules. Replaces `getLinterForType(subdir).lint(ctx)`.
|
|
197
|
+
* `--fix` mutations (frontmatter rewrites inside `runBaseChecks`; stub deletes
|
|
198
|
+
* here) are applied when `ctx.fix` is set.
|
|
199
|
+
*/
|
|
200
|
+
export function lintAssetFile(ctx, subdir) {
|
|
201
|
+
const issues = runBaseChecks(ctx);
|
|
202
|
+
switch (subdir) {
|
|
203
|
+
case "agents":
|
|
204
|
+
issues.push(...nameOrTypeDiagnostics(ctx.relPath, ctx.data, ctx.frontmatter, ["agent"]));
|
|
205
|
+
break;
|
|
206
|
+
case "commands":
|
|
207
|
+
issues.push(...nameOrTypeDiagnostics(ctx.relPath, ctx.data, ctx.frontmatter, ["command"]));
|
|
208
|
+
break;
|
|
209
|
+
case "facts":
|
|
210
|
+
issues.push(...factDiagnostics(ctx.relPath, ctx.data));
|
|
211
|
+
break;
|
|
212
|
+
case "tasks":
|
|
213
|
+
issues.push(...taskDiagnostics(ctx.relPath, ctx.data));
|
|
214
|
+
break;
|
|
215
|
+
case "memories":
|
|
216
|
+
appendMemoryStubIssue(ctx, issues);
|
|
217
|
+
break;
|
|
218
|
+
case "workflows":
|
|
219
|
+
appendWorkflowIssues(ctx, issues);
|
|
220
|
+
break;
|
|
221
|
+
// knowledge / lessons / skills: base checks only (skill directory-level
|
|
222
|
+
// `missing-skill-md` runs separately, per-subdir, in the sweep loop).
|
|
223
|
+
}
|
|
224
|
+
return issues;
|
|
225
|
+
}
|
|
76
226
|
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
77
227
|
export function akmLint(options = {}) {
|
|
78
|
-
const stashRoot = options.dir ?? options.config?.stashDir ?? resolveStashDir();
|
|
79
228
|
// Collect secondary stash roots from configured filesystem sources so that
|
|
80
229
|
// cross-stash refs (e.g. referencing assets in dimm-city/agent-stash) are
|
|
81
230
|
// not falsely flagged as missing-ref.
|
|
82
231
|
const cfg = options.config ?? loadConfig();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
232
|
+
// 0.9.0 (spec §10.1): the primary stash is the defaultBundle's path.
|
|
233
|
+
const stashRoot = options.dir ?? primaryBundlePath(cfg) ?? resolveStashDir();
|
|
234
|
+
const sources = resolveSourceEntries(stashRoot, cfg);
|
|
235
|
+
const configuredAdapter = sources.find((source) => path.resolve(source.path) === path.resolve(stashRoot))?.adapterId;
|
|
236
|
+
const adapterId = configuredAdapter ?? detectAdapterId(stashRoot);
|
|
237
|
+
if (adapterId === "okf")
|
|
238
|
+
return lintOkfBundle(stashRoot);
|
|
239
|
+
const extraStashRoots = sources.map((s) => s.path).filter((p) => p !== stashRoot && fs.existsSync(p));
|
|
240
|
+
const fix = adapterId === "akm" && options.fix === true;
|
|
87
241
|
const fixed = [];
|
|
88
242
|
const flagged = [];
|
|
89
243
|
const dirsToScan = options.typeFilter ? STASH_SUBDIRS.filter((d) => d === options.typeFilter) : STASH_SUBDIRS;
|
|
90
244
|
for (const subdir of dirsToScan) {
|
|
91
245
|
const dirPath = path.join(stashRoot, subdir);
|
|
92
|
-
// Tasks are .yml files; everything else
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
//
|
|
97
|
-
|
|
246
|
+
// Tasks are .yml files; everything else (including workflows, one
|
|
247
|
+
// markdown format now) is .md
|
|
248
|
+
const files = subdir === "tasks" ? collectYamlFiles(dirPath) : collectMarkdownFiles(dirPath, true);
|
|
249
|
+
const assetFiles = subdir === "workflows" ? files.filter((file) => path.basename(file).toLowerCase() !== "readme.md") : files;
|
|
250
|
+
// Directory-level check: skills require a SKILL.md entry point (was
|
|
251
|
+
// SkillLinter.lintDirectory). Run once per direct subdirectory before the
|
|
252
|
+
// per-file loop.
|
|
253
|
+
if (subdir === "skills" && fs.existsSync(dirPath)) {
|
|
98
254
|
for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
|
|
99
|
-
if (entry.isDirectory())
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
255
|
+
if (!entry.isDirectory())
|
|
256
|
+
continue;
|
|
257
|
+
for (const issue of lintSkillDirectory(path.join(dirPath, entry.name), stashRoot)) {
|
|
258
|
+
// Tristate-safe: only `true` counts as fixed; `false` and "failed"
|
|
259
|
+
// are both flagged.
|
|
260
|
+
if (issue.fixed === true) {
|
|
261
|
+
fixed.push(issue);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
flagged.push(issue);
|
|
110
265
|
}
|
|
111
266
|
}
|
|
112
267
|
}
|
|
113
268
|
}
|
|
114
|
-
for (const filePath of
|
|
269
|
+
for (const filePath of assetFiles) {
|
|
115
270
|
// Skip registry-cached read-only files — --fix must not mutate them.
|
|
116
271
|
if (filePath.includes("/.cache/") || filePath.includes("/registry/"))
|
|
117
272
|
continue;
|
|
@@ -142,7 +297,7 @@ export function akmLint(options = {}) {
|
|
|
142
297
|
else {
|
|
143
298
|
({ data, content: body, frontmatter } = parseFrontmatter(raw));
|
|
144
299
|
}
|
|
145
|
-
const issues =
|
|
300
|
+
const issues = lintAssetFile({ filePath, relPath, raw, data, body, frontmatter, fix, stashRoot, extraStashRoots }, subdir);
|
|
146
301
|
let fileDeleted = false;
|
|
147
302
|
for (const issue of issues) {
|
|
148
303
|
if (isFileDeletion(issue)) {
|
|
@@ -2,21 +2,26 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Programmatic event listing behind `akm log` (#204).
|
|
6
6
|
*
|
|
7
|
-
* Programmatic surface — the CLI dispatcher in `src/cli.ts` registers
|
|
8
|
-
*
|
|
7
|
+
* Programmatic surface — the CLI dispatcher in `src/cli.ts` registers the
|
|
8
|
+
* `log` leaf command that delegates here. Returns a JSON envelope shaped by
|
|
9
9
|
* `src/output/shapes.ts` so the output flows through the same shape and
|
|
10
10
|
* text-renderer pipeline as the rest of the CLI (no silent
|
|
11
11
|
* `JSON.stringify` fallback).
|
|
12
|
+
*
|
|
13
|
+
* 0.9.0 CLI overhaul (S3): `akmEventsTail` (and the `log tail` command it
|
|
14
|
+
* backed) was dropped — a foreground polling daemon in a one-shot CLI. The
|
|
15
|
+
* lower-level `tailEvents` poller it wrapped (src/core/events.ts) had no
|
|
16
|
+
* other caller and was removed with it.
|
|
12
17
|
*/
|
|
13
|
-
import {
|
|
18
|
+
import { makeBundleRef, parseBundleRef } from "../core/asset/asset-ref.js";
|
|
14
19
|
import { UsageError } from "../core/errors.js";
|
|
15
|
-
import { readEvents
|
|
20
|
+
import { readEvents } from "../core/events.js";
|
|
16
21
|
import { parseSinceToIso } from "../core/time.js";
|
|
17
22
|
/**
|
|
18
|
-
* Parse `--since` accepting either
|
|
19
|
-
* cross-process resumption, or a timestamp / epoch-ms
|
|
23
|
+
* Parse `--since` accepting either an opaque row cursor (`@offset:<int>`) for
|
|
24
|
+
* cross-process resumption, or a timestamp / epoch-ms.
|
|
20
25
|
* Returns one of `{ sinceOffset }` or `{ since }`.
|
|
21
26
|
*/
|
|
22
27
|
function parseSinceFlag(since) {
|
|
@@ -30,7 +35,7 @@ function parseSinceFlag(since) {
|
|
|
30
35
|
const raw = trimmed.slice("@offset:".length);
|
|
31
36
|
const value = Number.parseInt(raw, 10);
|
|
32
37
|
if (Number.isNaN(value) || value < 0) {
|
|
33
|
-
throw new UsageError(`Invalid --since
|
|
38
|
+
throw new UsageError(`Invalid --since offset: "${since}". Expected @offset:<non-negative integer>.`, "INVALID_FLAG_VALUE");
|
|
34
39
|
}
|
|
35
40
|
return { sinceOffset: value };
|
|
36
41
|
}
|
|
@@ -43,19 +48,31 @@ function validateRef(ref) {
|
|
|
43
48
|
if (!trimmed) {
|
|
44
49
|
throw new UsageError("--ref cannot be empty.", "INVALID_FLAG_VALUE");
|
|
45
50
|
}
|
|
46
|
-
|
|
51
|
+
const parsed = parseBundleRef(trimmed);
|
|
52
|
+
return makeBundleRef(parsed.bundle, parsed.conceptId);
|
|
53
|
+
}
|
|
54
|
+
function validateRunId(run) {
|
|
55
|
+
if (run === undefined)
|
|
56
|
+
return undefined;
|
|
57
|
+
const trimmed = run.trim();
|
|
58
|
+
if (!trimmed) {
|
|
59
|
+
throw new UsageError("--run cannot be empty.", "INVALID_FLAG_VALUE");
|
|
60
|
+
}
|
|
47
61
|
return trimmed;
|
|
48
62
|
}
|
|
49
63
|
export function akmEventsList(options = {}) {
|
|
50
64
|
const ref = validateRef(options.ref);
|
|
65
|
+
const run = validateRunId(options.run);
|
|
51
66
|
const parsed = parseSinceFlag(options.since);
|
|
52
67
|
const result = readEvents({
|
|
53
68
|
since: parsed.since,
|
|
54
69
|
sinceOffset: parsed.sinceOffset,
|
|
55
70
|
type: options.type,
|
|
56
71
|
ref,
|
|
72
|
+
runId: run,
|
|
57
73
|
excludeTags: options.excludeTags,
|
|
58
74
|
includeTags: options.includeTags,
|
|
75
|
+
limit: options.limit,
|
|
59
76
|
}, options.ctx);
|
|
60
77
|
return {
|
|
61
78
|
schemaVersion: 1,
|
|
@@ -64,36 +81,9 @@ export function akmEventsList(options = {}) {
|
|
|
64
81
|
...(options.type !== undefined ? { type: options.type } : {}),
|
|
65
82
|
...(parsed.since !== undefined ? { since: parsed.since } : {}),
|
|
66
83
|
...(parsed.sinceOffset !== undefined ? { sinceOffset: parsed.sinceOffset } : {}),
|
|
84
|
+
...(options.limit !== undefined ? { limit: options.limit } : {}),
|
|
85
|
+
...(run !== undefined ? { run } : {}),
|
|
67
86
|
nextOffset: result.nextOffset,
|
|
68
87
|
events: result.events,
|
|
69
88
|
};
|
|
70
89
|
}
|
|
71
|
-
export async function akmEventsTail(options = {}) {
|
|
72
|
-
const ref = validateRef(options.ref);
|
|
73
|
-
const parsed = parseSinceFlag(options.since);
|
|
74
|
-
const tailOptions = {
|
|
75
|
-
since: parsed.since,
|
|
76
|
-
sinceOffset: parsed.sinceOffset,
|
|
77
|
-
type: options.type,
|
|
78
|
-
ref,
|
|
79
|
-
intervalMs: options.intervalMs,
|
|
80
|
-
maxDurationMs: options.maxDurationMs,
|
|
81
|
-
maxEvents: options.maxEvents,
|
|
82
|
-
signal: options.signal,
|
|
83
|
-
onEvent: options.onEvent,
|
|
84
|
-
excludeTags: options.excludeTags,
|
|
85
|
-
includeTags: options.includeTags,
|
|
86
|
-
};
|
|
87
|
-
const result = await tailEvents(tailOptions, options.ctx);
|
|
88
|
-
return {
|
|
89
|
-
schemaVersion: 1,
|
|
90
|
-
totalCount: result.events.length,
|
|
91
|
-
...(ref !== undefined ? { ref } : {}),
|
|
92
|
-
...(options.type !== undefined ? { type: options.type } : {}),
|
|
93
|
-
...(parsed.since !== undefined ? { since: parsed.since } : {}),
|
|
94
|
-
...(parsed.sinceOffset !== undefined ? { sinceOffset: parsed.sinceOffset } : {}),
|
|
95
|
-
nextOffset: result.nextOffset,
|
|
96
|
-
events: result.events,
|
|
97
|
-
reason: result.reason,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
@@ -0,0 +1,54 @@
|
|
|
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 { defineGroupCommand, defineJsonCommand } from "../cli/shared.js";
|
|
5
|
+
import { runMigrationTool } from "./migration-tool.js";
|
|
6
|
+
const configArg = {
|
|
7
|
+
type: "string",
|
|
8
|
+
description: "Complete operator-prepared current config; optional when the active config is current",
|
|
9
|
+
};
|
|
10
|
+
export const migrateCommand = defineGroupCommand({
|
|
11
|
+
// Hidden from `--help` and the completions walker (S11): this is the
|
|
12
|
+
// self-update contract's internal command, not a surface end users
|
|
13
|
+
// discover by browsing help. `akm migrate status`/`apply` still execute
|
|
14
|
+
// normally — `hidden` only affects listing.
|
|
15
|
+
meta: { name: "migrate", hidden: true, description: "Inspect or apply config and durable database migrations" },
|
|
16
|
+
subCommands: {
|
|
17
|
+
status: defineJsonCommand({
|
|
18
|
+
meta: { name: "status", description: "Read-only cross-artifact migration eligibility check" },
|
|
19
|
+
args: { config: configArg },
|
|
20
|
+
run({ args }) {
|
|
21
|
+
return runMigrationTool(["status", ...(args.config ? ["--config", args.config] : [])]);
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
apply: defineJsonCommand({
|
|
25
|
+
meta: { name: "apply", description: "Create a verified backup and atomically apply pending migrations" },
|
|
26
|
+
args: {
|
|
27
|
+
config: configArg,
|
|
28
|
+
// R-062: canonical spelling is kebab-case, matching every other
|
|
29
|
+
// multi-word flag in the CLI. `--dryRun` (the pre-rename spelling)
|
|
30
|
+
// is kept as an explicit, documented alias — citty registers BOTH
|
|
31
|
+
// the camelCase and kebab-case spelling of any declared flag name
|
|
32
|
+
// automatically, so this is a rename, not a breaking change: both
|
|
33
|
+
// spellings already worked, and both keep working.
|
|
34
|
+
"dry-run": {
|
|
35
|
+
type: "boolean",
|
|
36
|
+
alias: "dryRun",
|
|
37
|
+
default: false,
|
|
38
|
+
description: "Run the same eligibility checks without mutation. Alias: --dryRun.",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
run({ args }) {
|
|
42
|
+
return runMigrationTool([
|
|
43
|
+
"apply",
|
|
44
|
+
...(args.config ? ["--config", args.config] : []),
|
|
45
|
+
...(args.dryRun ? ["--dry-run"] : []),
|
|
46
|
+
]);
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
},
|
|
50
|
+
// No `defaultRun`: bare `akm migrate` is a usage error (exit 2). This group
|
|
51
|
+
// already threw its own hand-rolled UsageError; it now shares the canonical
|
|
52
|
+
// one from `defineGroupCommand` so the message and hint match every other
|
|
53
|
+
// group — owner ruling 12.
|
|
54
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
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 { spawnSync } from "node:child_process";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { NotFoundError } from "../core/errors.js";
|
|
8
|
+
function migrationEntryPoint() {
|
|
9
|
+
const candidates = [
|
|
10
|
+
fileURLToPath(new URL("../../scripts/akm-migrate.ts", import.meta.url)),
|
|
11
|
+
fileURLToPath(new URL("../scripts/akm-migrate.js", import.meta.url)),
|
|
12
|
+
];
|
|
13
|
+
return candidates.find((candidate) => fs.existsSync(candidate));
|
|
14
|
+
}
|
|
15
|
+
export async function runMigrationTool(args) {
|
|
16
|
+
const entry = migrationEntryPoint();
|
|
17
|
+
if (!entry && process.env.AKM_MIGRATE_ENTRY === "1") {
|
|
18
|
+
// Re-exec loop guard: we ARE the marked child, yet no migrator entry
|
|
19
|
+
// resolved and the standalone wrapper did not intercept the marker — this
|
|
20
|
+
// binary was compiled without `scripts/akm-standalone.ts`.
|
|
21
|
+
throw new NotFoundError("This binary was built without the embedded akm-migrate tool.", "FILE_NOT_FOUND", "Rebuild from scripts/akm-standalone.ts, or run akm-migrate from a source/npm install.");
|
|
22
|
+
}
|
|
23
|
+
// Compiled standalone: no scripts/ tree exists on disk (`import.meta.url`
|
|
24
|
+
// resolves inside the binary's virtual filesystem), so the documented
|
|
25
|
+
// `./akm-<ver> migrate status/apply` path used to dead-end with
|
|
26
|
+
// FILE_NOT_FOUND. Release binaries are compiled from
|
|
27
|
+
// `scripts/akm-standalone.ts`, which embeds the migrator and dispatches to
|
|
28
|
+
// it when `AKM_MIGRATE_ENTRY=1` — so re-exec ourselves with the marker.
|
|
29
|
+
// (src must not import scripts/: the dist build's tsc has `rootDir: src`.)
|
|
30
|
+
const runtime = process.versions.bun ? process.execPath : "bun";
|
|
31
|
+
const result = spawnSync(runtime, entry ? [entry, ...args] : [...args], {
|
|
32
|
+
encoding: "utf8",
|
|
33
|
+
env: entry ? process.env : { ...process.env, AKM_MIGRATE_ENTRY: "1" },
|
|
34
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
35
|
+
});
|
|
36
|
+
if (result.error) {
|
|
37
|
+
throw new NotFoundError(`Cannot start the standalone akm-migrate tool: ${result.error.message}`, "FILE_NOT_FOUND", "Install Bun, then run akm-migrate directly.");
|
|
38
|
+
}
|
|
39
|
+
if (result.stdout)
|
|
40
|
+
process.stdout.write(result.stdout);
|
|
41
|
+
if (result.stderr)
|
|
42
|
+
process.stderr.write(result.stderr);
|
|
43
|
+
// R-067: was `process.exit(result.status ?? 1)` on the failure branch,
|
|
44
|
+
// which terminates the process synchronously and skips the `finally {
|
|
45
|
+
// await disposeDispatchResources(); }` cleanup in src/cli.ts's
|
|
46
|
+
// `runCommand`. The success path (status === 0) was already fine — it
|
|
47
|
+
// just returns and the process exits 0 naturally. Setting
|
|
48
|
+
// `process.exitCode` and returning still propagates the child's exact
|
|
49
|
+
// non-zero status once the event loop drains, but lets cleanup run first —
|
|
50
|
+
// same pattern `emitJsonError` (src/cli/shared.ts) already established.
|
|
51
|
+
if (result.status !== 0) {
|
|
52
|
+
process.exitCode = result.status ?? 1;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
}
|