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
|
@@ -14,7 +14,7 @@ function readGithubTokenFromEnv() {
|
|
|
14
14
|
return undefined;
|
|
15
15
|
}
|
|
16
16
|
function readGithubTokenFromGhCli() {
|
|
17
|
-
const result = childProcess.spawnSync("gh", ["auth", "token"], {
|
|
17
|
+
const result = childProcess.spawnSync("gh", ["auth", "token", "--hostname", "github.com"], {
|
|
18
18
|
encoding: "utf8",
|
|
19
19
|
timeout: 5_000,
|
|
20
20
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -60,10 +60,12 @@
|
|
|
60
60
|
* - **effort** — stays unconsumed (reserved; the shared request contract's
|
|
61
61
|
* "no builder consumes it yet" note stays true).
|
|
62
62
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* `
|
|
66
|
-
*
|
|
63
|
+
* Registered: `aiderBuilder` is `AiderHarness.agentBuilder` (`./index.ts`),
|
|
64
|
+
* one of the ten harnesses `HARNESS_REGISTRY` constructs
|
|
65
|
+
* (`harnesses/index.ts`); `agent/builders.ts` derives `BUILTIN_BUILDERS` from
|
|
66
|
+
* that registry, so this builder is reachable under the `"aider"` platform
|
|
67
|
+
* name without any further wiring. The registry entry also declares
|
|
68
|
+
* `structuredOutput: "none"` alongside it (`./index.ts`).
|
|
67
69
|
*/
|
|
68
70
|
import { assertNotFlag, resolveDispatchModel, } from "../../agent/builder-shared.js";
|
|
69
71
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
@@ -54,10 +54,13 @@
|
|
|
54
54
|
* - **effort** — stays unconsumed (reserved; the shared request contract's
|
|
55
55
|
* "no builder consumes it yet" note stays true).
|
|
56
56
|
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* that
|
|
57
|
+
* Registered: `amazonqBuilder` is `AmazonqHarness.agentBuilder`
|
|
58
|
+
* (`./index.ts`), one of the ten harnesses `HARNESS_REGISTRY` constructs
|
|
59
|
+
* (`harnesses/index.ts`); `agent/builders.ts` derives `BUILTIN_BUILDERS` from
|
|
60
|
+
* that registry, so this builder is reachable under the `"amazonq"` platform
|
|
61
|
+
* name without any further wiring. The registry-side capability entry —
|
|
62
|
+
* pattern `local-runner`, structuredOutput `none` — is declared alongside it
|
|
63
|
+
* (`./index.ts`).
|
|
61
64
|
*/
|
|
62
65
|
import { assertNotFlag, resolveDispatchModel, } from "../../agent/builder-shared.js";
|
|
63
66
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
@@ -108,16 +108,6 @@ export class ClaudeCodeProvider extends AbstractSessionLogProvider {
|
|
|
108
108
|
availabilityRoot() {
|
|
109
109
|
return claudeProjectsDir();
|
|
110
110
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Directory holding Claude Code's per-project session JSONL files
|
|
113
|
-
* (`~/.claude/projects`, honoring `AKM_CLAUDE_PROJECTS_DIR`). Returns `[]`
|
|
114
|
-
* when the directory does not exist on this machine. See {@link
|
|
115
|
-
* SessionLogHarness.watchRoots}.
|
|
116
|
-
*/
|
|
117
|
-
watchRoots() {
|
|
118
|
-
const dir = claudeProjectsDir();
|
|
119
|
-
return fs.existsSync(dir) ? [dir] : [];
|
|
120
|
-
}
|
|
121
111
|
*readEvents(input) {
|
|
122
112
|
try {
|
|
123
113
|
for (const jsonlPath of this.#walkJsonl(claudeProjectsDir())) {
|
|
@@ -46,8 +46,11 @@
|
|
|
46
46
|
* `-c model_reasoning_effort=<v>` — left to the integration task so the
|
|
47
47
|
* shared request contract's "no builder consumes it yet" note stays true).
|
|
48
48
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
49
|
+
* Registered: `codexBuilder` is `CodexHarness.agentBuilder` (`./index.ts`),
|
|
50
|
+
* one of the ten harnesses `HARNESS_REGISTRY` constructs
|
|
51
|
+
* (`harnesses/index.ts`); `agent/builders.ts` derives `BUILTIN_BUILDERS` from
|
|
52
|
+
* that registry, so this builder is reachable under the `"codex"` platform
|
|
53
|
+
* name without any further wiring.
|
|
51
54
|
*/
|
|
52
55
|
import { mkdtempSync, writeFileSync } from "node:fs";
|
|
53
56
|
import { tmpdir } from "node:os";
|
|
@@ -39,9 +39,11 @@
|
|
|
39
39
|
* programmatic mode Copilot then denies unapproved tool calls, which is the
|
|
40
40
|
* conservative failure mode.
|
|
41
41
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
42
|
+
* Registered: `copilotBuilder` is `CopilotHarness.agentBuilder`
|
|
43
|
+
* (`./index.ts`), one of the ten harnesses `HARNESS_REGISTRY` constructs
|
|
44
|
+
* (`harnesses/index.ts`); `agent/builders.ts` derives `BUILTIN_BUILDERS` from
|
|
45
|
+
* that registry, so this builder is reachable under the `"copilot"` platform
|
|
46
|
+
* name without any further wiring.
|
|
45
47
|
*/
|
|
46
48
|
import { assertNotFlag, resolveDispatchModel, } from "../../agent/builder-shared.js";
|
|
47
49
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
@@ -43,9 +43,11 @@
|
|
|
43
43
|
* `gemini -p "<p>"`; autonomy flags (`--yolo`, `--approval-mode`) belong in
|
|
44
44
|
* `profile.args` where the operator opts in explicitly.
|
|
45
45
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
46
|
+
* Registered: `geminiBuilder` is `GeminiHarness.agentBuilder` (`./index.ts`),
|
|
47
|
+
* one of the ten harnesses `HARNESS_REGISTRY` constructs
|
|
48
|
+
* (`harnesses/index.ts`); `agent/builders.ts` derives `BUILTIN_BUILDERS` from
|
|
49
|
+
* that registry, so this builder is reachable under the `"gemini"` platform
|
|
50
|
+
* name without any further wiring.
|
|
49
51
|
*/
|
|
50
52
|
import { assertNotFlag, resolveDispatchModel, } from "../../agent/builder-shared.js";
|
|
51
53
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
@@ -12,10 +12,6 @@
|
|
|
12
12
|
* This module is a dependency-graph LEAF: it imports nothing from
|
|
13
13
|
* `core/config`. `core/config/config-types.ts` derives `VALID_HARNESS_IDS`
|
|
14
14
|
* from here, which keeps the import direction acyclic (config ← harnesses).
|
|
15
|
-
*
|
|
16
|
-
* Implementations (session-log readers, agent profiles) are migrated under each
|
|
17
|
-
* harness in #563/#564; this step only owns ids + capability membership and
|
|
18
|
-
* wires the existing call sites to consult it (behaviour-preserving).
|
|
19
15
|
*/
|
|
20
16
|
import { AiderHarness } from "./aider/index.js";
|
|
21
17
|
import { AmazonqHarness } from "./amazonq/index.js";
|
|
@@ -51,9 +47,9 @@ export { isSessionLogHarness } from "./types.js";
|
|
|
51
47
|
// Order is significant: VALID_HARNESS_IDS derives from this array and feeds the
|
|
52
48
|
// committed JSON-schema enum order. The original [opencode, claude,
|
|
53
49
|
// opencode-sdk] prefix is preserved so the pre-unification portion of the
|
|
54
|
-
// generated schema enum does not reorder
|
|
55
|
-
//
|
|
56
|
-
//
|
|
50
|
+
// generated schema enum does not reorder; the seven P2 harness adapters are
|
|
51
|
+
// appended after it, which extends the enum additively (schemas/akm-config.json
|
|
52
|
+
// is regenerated in lockstep).
|
|
57
53
|
export const HARNESS_REGISTRY = Object.freeze([
|
|
58
54
|
new OpencodeHarness(),
|
|
59
55
|
new ClaudeHarness(),
|
|
@@ -27,13 +27,32 @@ export const opencodeBuilder = {
|
|
|
27
27
|
build(profile, req) {
|
|
28
28
|
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
29
29
|
assertNotFlag(req.model, "model");
|
|
30
|
-
|
|
30
|
+
let configuredModel;
|
|
31
|
+
const args = req.model ? [] : [...profile.args];
|
|
32
|
+
if (req.model) {
|
|
33
|
+
for (let index = 0; index < profile.args.length; index += 1) {
|
|
34
|
+
const arg = profile.args[index];
|
|
35
|
+
if (arg === undefined)
|
|
36
|
+
continue;
|
|
37
|
+
if (arg === "--model") {
|
|
38
|
+
configuredModel = profile.args[index + 1];
|
|
39
|
+
index += 1;
|
|
40
|
+
}
|
|
41
|
+
else if (arg.startsWith("--model=")) {
|
|
42
|
+
configuredModel = arg.slice("--model=".length);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
args.push(arg);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
31
49
|
if (req.systemPrompt) {
|
|
32
50
|
args.push("--system-prompt", req.systemPrompt);
|
|
33
51
|
}
|
|
34
52
|
if (req.model) {
|
|
35
53
|
const resolved = resolveDispatchModel(req, profile, "opencode");
|
|
36
|
-
|
|
54
|
+
const provider = configuredModel?.split("/", 1)[0];
|
|
55
|
+
args.push("--model", provider && !resolved.includes("/") ? `${provider}/${resolved}` : resolved);
|
|
37
56
|
}
|
|
38
57
|
args.push("--");
|
|
39
58
|
args.push(req.prompt);
|
|
@@ -42,21 +42,6 @@ export class OpenCodeProvider extends AbstractSessionLogProvider {
|
|
|
42
42
|
#dbPath(base) {
|
|
43
43
|
return path.join(base, OPENCODE_DB_FILENAME);
|
|
44
44
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Directories/files opencode writes session data under. Returns the base dir
|
|
47
|
-
* when the SQLite store (`opencode.db`) exists, the legacy JSON session root
|
|
48
|
-
* (`<base>/storage/session`) when present, or both during a migration overlap.
|
|
49
|
-
* Empty when neither exists. See {@link SessionLogHarness.watchRoots}.
|
|
50
|
-
*/
|
|
51
|
-
watchRoots() {
|
|
52
|
-
const roots = [];
|
|
53
|
-
if (fs.existsSync(this.#dbPath(this.#baseDir)))
|
|
54
|
-
roots.push(this.#baseDir);
|
|
55
|
-
const sessionRoot = path.join(this.#baseDir, "storage", "session");
|
|
56
|
-
if (fs.existsSync(sessionRoot))
|
|
57
|
-
roots.push(sessionRoot);
|
|
58
|
-
return roots;
|
|
59
|
-
}
|
|
60
45
|
*readEvents(input) {
|
|
61
46
|
// Legacy behavior: stream raw log lines from the top-level dir and `log/`
|
|
62
47
|
// subdirectory. Kept to keep `getExecutionLogCandidates` working without
|
|
@@ -4,9 +4,13 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* OpenCode SDK agent runner (migrated from `agent/sdk-runner.ts`, #564).
|
|
6
6
|
*
|
|
7
|
-
* Uses the embedded `@opencode-ai/sdk` instead of `Bun.spawn
|
|
8
|
-
* agent CLI
|
|
9
|
-
*
|
|
7
|
+
* Uses the embedded `@opencode-ai/sdk` instead of `Bun.spawn` for dispatch, so
|
|
8
|
+
* no agent CLI argv is ever constructed — but the SDK is not self-contained:
|
|
9
|
+
* {@link createManagedOpencode} spawns `opencode serve` and talks HTTP to it,
|
|
10
|
+
* so the `opencode` binary must be on PATH (which is why setup's
|
|
11
|
+
* `detectHarness` gates this harness on that probe). The user provides an
|
|
12
|
+
* OpenAI-compatible endpoint (or inherits from the selected fallback LLM
|
|
13
|
+
* engine) for the SDK.
|
|
10
14
|
*
|
|
11
15
|
* This is the runtime surface of the {@link OpencodeSdkHarness} (`id =
|
|
12
16
|
* 'opencode-sdk'`). It is the dispatch path for SDK runner specs; it exposes
|
|
@@ -70,7 +74,12 @@
|
|
|
70
74
|
* until the child ACTUALLY exits — and a real `opencode serve` (a live HTTP
|
|
71
75
|
* server with provider children) can outlive SIGTERM long enough to hang the
|
|
72
76
|
* caller indefinitely. {@link createManagedOpencode} therefore owns the spawn
|
|
73
|
-
* (the SDK package is used only for `createOpencodeClient`)
|
|
77
|
+
* (the SDK package is used only for `createOpencodeClient`).
|
|
78
|
+
*
|
|
79
|
+
* Owning the spawn changes the LIFECYCLE, not the REQUIREMENT: the SDK's
|
|
80
|
+
* `createOpencodeServer` is itself a `spawn("opencode", ["serve", ...])`, and
|
|
81
|
+
* the package declares `"dependencies": {}`, so `opencode` must be on PATH
|
|
82
|
+
* either way. akm's version differs only in how it supervises the child:
|
|
74
83
|
*
|
|
75
84
|
* - after the URL handshake, the child and its stdio are `unref()`ed /
|
|
76
85
|
* destroyed, so the handle can never hold akm open;
|
|
@@ -63,10 +63,13 @@
|
|
|
63
63
|
* - **effort** — stays unconsumed (reserved; the shared request contract's
|
|
64
64
|
* "no builder consumes it yet" note stays true).
|
|
65
65
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* `
|
|
69
|
-
*
|
|
66
|
+
* Registered: `openhandsBuilder` is `OpenhandsHarness.agentBuilder`
|
|
67
|
+
* (`./index.ts`), one of the ten harnesses `HARNESS_REGISTRY` constructs
|
|
68
|
+
* (`harnesses/index.ts`); `agent/builders.ts` derives `BUILTIN_BUILDERS` from
|
|
69
|
+
* that registry, so this builder is reachable under the `"openhands"`
|
|
70
|
+
* platform name without any further wiring. The registry entry also declares
|
|
71
|
+
* `pattern: "local-runner"`, `structuredOutput: "native-json"` alongside it
|
|
72
|
+
* (`./index.ts`).
|
|
70
73
|
*/
|
|
71
74
|
import { assertNotFlag, resolveDispatchModel, } from "../../agent/builder-shared.js";
|
|
72
75
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
@@ -74,8 +77,8 @@ export const OPENHANDS_PLATFORM = "openhands";
|
|
|
74
77
|
/**
|
|
75
78
|
* Env var OpenHands reads its LLM model from — the platform's documented
|
|
76
79
|
* model-selection channel for headless runs (there is no headless model
|
|
77
|
-
* flag). Exported
|
|
78
|
-
* constant.
|
|
80
|
+
* flag). Exported (re-exported from `./index.ts`) so this harness's tests
|
|
81
|
+
* share the one constant.
|
|
79
82
|
*/
|
|
80
83
|
export const OPENHANDS_MODEL_ENV = "LLM_MODEL";
|
|
81
84
|
/**
|
|
@@ -43,10 +43,12 @@
|
|
|
43
43
|
* - **effort** — stays unconsumed (reserved; the shared request contract's
|
|
44
44
|
* "no builder consumes it yet" note stays true).
|
|
45
45
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
46
|
+
* Registered: `piBuilder` is `PiHarness.agentBuilder` (`./index.ts`), one of
|
|
47
|
+
* the ten harnesses `HARNESS_REGISTRY` constructs (`harnesses/index.ts`);
|
|
48
|
+
* `agent/builders.ts` derives `BUILTIN_BUILDERS` from that registry, so this
|
|
49
|
+
* builder is reachable under the `"pi"` platform name without any further
|
|
50
|
+
* wiring. The `PI_SESSION_ID` identity-env marker is declared alongside it
|
|
51
|
+
* (`./index.ts`).
|
|
50
52
|
*/
|
|
51
53
|
import { assertNotFlag, resolveDispatchModel, } from "../../agent/builder-shared.js";
|
|
52
54
|
/** Canonical harness/platform id used for model-alias resolution. */
|
|
@@ -54,6 +54,48 @@ export function readLockfile() {
|
|
|
54
54
|
return [];
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Like {@link readLockfile}, but THROWS instead of silently degrading to `[]`
|
|
59
|
+
* when the on-disk lockfile exists yet is not parseable JSON or not a JSON
|
|
60
|
+
* array (R-012).
|
|
61
|
+
*
|
|
62
|
+
* `readLockfile`'s fail-open contract is intentional for READ paths — a
|
|
63
|
+
* corrupt lock degrades a managed bundle to "unmanaged" rather than erroring
|
|
64
|
+
* every read-only command (`list`, `installed-stashes`, …). But
|
|
65
|
+
* {@link upsertLockEntry} and {@link removeLockEntry} read the current
|
|
66
|
+
* entries and then WRITE `[...entries, change]` back out; if that read
|
|
67
|
+
* silently returned `[]` for a corrupt file, the write would silently
|
|
68
|
+
* replace the corrupt file with one containing only the single new/changed
|
|
69
|
+
* entry — permanently destroying every other surviving lock record. Write
|
|
70
|
+
* paths use this strict variant so a corrupt lockfile fails the operation
|
|
71
|
+
* loudly (matching the guard `mergeLockEntriesSync` already applies) instead
|
|
72
|
+
* of quietly deleting user state. A missing file is NOT corruption — there
|
|
73
|
+
* is nothing to preserve, so that case still returns `[]`. Entries that fail
|
|
74
|
+
* per-entry validation are still tolerated (filtered out), matching
|
|
75
|
+
* `readLockfile`'s existing shape-tolerant behavior.
|
|
76
|
+
*/
|
|
77
|
+
function readLockfileOrThrow() {
|
|
78
|
+
const lockfilePath = getLockfilePath();
|
|
79
|
+
let raw;
|
|
80
|
+
try {
|
|
81
|
+
raw = fs.readFileSync(lockfilePath, "utf8");
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
rethrowIfTestIsolationError(err);
|
|
85
|
+
return []; // File does not exist (or is otherwise unreadable) — nothing to preserve.
|
|
86
|
+
}
|
|
87
|
+
let parsed;
|
|
88
|
+
try {
|
|
89
|
+
parsed = JSON.parse(raw);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
throw new ConfigError(`Refusing to modify lockfile ${lockfilePath}: existing content is not valid JSON (${error instanceof Error ? error.message : String(error)}). Fix or remove the file by hand before retrying — every existing lock entry would otherwise be lost.`, "INVALID_CONFIG_FILE");
|
|
93
|
+
}
|
|
94
|
+
if (!Array.isArray(parsed)) {
|
|
95
|
+
throw new ConfigError(`Refusing to modify lockfile ${lockfilePath}: existing content is not a JSON array. Fix or remove the file by hand before retrying — every existing lock entry would otherwise be lost.`, "INVALID_CONFIG_FILE");
|
|
96
|
+
}
|
|
97
|
+
return parsed.filter(isValidLockfileEntry);
|
|
98
|
+
}
|
|
57
99
|
/**
|
|
58
100
|
* The materialized content root recorded in the lock for a managed (git/npm)
|
|
59
101
|
* bundle — spec §10.2 desired/resolved split, where the desired config carries
|
|
@@ -93,10 +135,27 @@ export async function writeLockfile(entries) {
|
|
|
93
135
|
release();
|
|
94
136
|
}
|
|
95
137
|
}
|
|
138
|
+
/** Replace one exact parsed lock generation while the lockfile sentinel is held. */
|
|
139
|
+
export async function compareAndSwapLockfile(expected, desired) {
|
|
140
|
+
const release = await acquireLockSentinel();
|
|
141
|
+
try {
|
|
142
|
+
const current = readLockfileOrThrow();
|
|
143
|
+
if (JSON.stringify(current) !== JSON.stringify(expected))
|
|
144
|
+
return false;
|
|
145
|
+
writeLockfileUnlocked(desired);
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
release();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
96
152
|
export async function upsertLockEntry(entry) {
|
|
97
153
|
const release = await acquireLockSentinel();
|
|
98
154
|
try {
|
|
99
|
-
|
|
155
|
+
// R-012: readLockfileOrThrow (not readLockfile) — a corrupt/malformed
|
|
156
|
+
// lockfile must abort the upsert loudly rather than read as `[]` and get
|
|
157
|
+
// silently overwritten with just this one entry.
|
|
158
|
+
const entries = readLockfileOrThrow();
|
|
100
159
|
const withoutExisting = entries.filter((e) => e.id !== entry.id);
|
|
101
160
|
writeLockfileUnlocked([...withoutExisting, entry]);
|
|
102
161
|
}
|
|
@@ -110,19 +169,55 @@ export async function upsertLockEntry(entry) {
|
|
|
110
169
|
* migrate-apply's config lock + maintenance barrier) whose synchronous body
|
|
111
170
|
* cannot await the sentinel's retry loop. No-op for an empty list.
|
|
112
171
|
*/
|
|
172
|
+
function readLockEntriesForMigration() {
|
|
173
|
+
let existing = [];
|
|
174
|
+
const lockfilePath = getLockfilePath();
|
|
175
|
+
if (fs.existsSync(lockfilePath)) {
|
|
176
|
+
let raw;
|
|
177
|
+
try {
|
|
178
|
+
raw = JSON.parse(fs.readFileSync(lockfilePath, "utf8"));
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
throw new ConfigError(`Cannot merge migration lock entries into unreadable lockfile ${lockfilePath}: ${error instanceof Error ? error.message : String(error)}.`, "INVALID_CONFIG_FILE");
|
|
182
|
+
}
|
|
183
|
+
if (!Array.isArray(raw) || !raw.every(isValidLockfileEntry)) {
|
|
184
|
+
throw new ConfigError(`Cannot merge migration lock entries into malformed lockfile ${lockfilePath}.`, "INVALID_CONFIG_FILE");
|
|
185
|
+
}
|
|
186
|
+
existing = raw;
|
|
187
|
+
}
|
|
188
|
+
return existing;
|
|
189
|
+
}
|
|
190
|
+
/** Validate the current lockfile before migrate-apply creates its backup or sentinel. */
|
|
191
|
+
export function assertMigrationLockfileReadable() {
|
|
192
|
+
readLockEntriesForMigration();
|
|
193
|
+
}
|
|
113
194
|
export function mergeLockEntriesSync(entries) {
|
|
195
|
+
const existing = readLockEntriesForMigration();
|
|
114
196
|
if (entries.length === 0)
|
|
115
197
|
return;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
198
|
+
// MERGE per id, never replace: the migrator's entries are sparse (id/source/
|
|
199
|
+
// ref/localRoot), while an existing row may carry `resolvedVersion`,
|
|
200
|
+
// `resolvedRevision`, `integrity`, `installedAt`, … from a real install.
|
|
201
|
+
// Replacing the whole row discarded the user's recorded resolution/pin and
|
|
202
|
+
// left later update reporting comparing against an unknown prior version.
|
|
203
|
+
// Incoming DEFINED fields win; existing fields absent from the incoming
|
|
204
|
+
// entry are preserved.
|
|
205
|
+
const byId = new Map(existing.map((e) => [e.id, e]));
|
|
206
|
+
const merged = entries.map((incoming) => {
|
|
207
|
+
const prior = byId.get(incoming.id);
|
|
208
|
+
return prior ? { ...prior, ...incoming } : incoming;
|
|
209
|
+
});
|
|
210
|
+
const incomingIds = new Set(entries.map((e) => e.id));
|
|
211
|
+
writeLockfileUnlocked([...existing.filter((e) => !incomingIds.has(e.id)), ...merged]);
|
|
119
212
|
}
|
|
120
213
|
export async function removeLockEntry(id) {
|
|
121
214
|
if (!fs.existsSync(getDataDir()))
|
|
122
215
|
return;
|
|
123
216
|
const release = await acquireLockSentinel();
|
|
124
217
|
try {
|
|
125
|
-
|
|
218
|
+
// R-012: see upsertLockEntry — same destructive-overwrite risk on a
|
|
219
|
+
// corrupt lockfile, so the same strict reader is used here.
|
|
220
|
+
const entries = readLockfileOrThrow();
|
|
126
221
|
writeLockfileUnlocked(entries.filter((e) => e.id !== id));
|
|
127
222
|
}
|
|
128
223
|
finally {
|
|
@@ -130,7 +225,7 @@ export async function removeLockEntry(id) {
|
|
|
130
225
|
}
|
|
131
226
|
}
|
|
132
227
|
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
133
|
-
function isValidLockfileEntry(value) {
|
|
228
|
+
export function isValidLockfileEntry(value) {
|
|
134
229
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
135
230
|
return false;
|
|
136
231
|
const obj = value;
|
|
@@ -50,22 +50,6 @@ const ERROR_PATTERNS = /error|failed|exception|cannot|undefined|null pointer|ENO
|
|
|
50
50
|
export function getAvailableHarnesses() {
|
|
51
51
|
return HARNESSES.filter((harness) => harness.isAvailable());
|
|
52
52
|
}
|
|
53
|
-
/**
|
|
54
|
-
* Map each available harness to its `{ harnessName, roots }` watch target,
|
|
55
|
-
* skipping harnesses that expose no roots (absent `watchRoots()` or an empty
|
|
56
|
-
* result). This is the one stable entry point the watcher uses so it never
|
|
57
|
-
* reaches into providers directly.
|
|
58
|
-
*/
|
|
59
|
-
export function getWatchTargets() {
|
|
60
|
-
const targets = [];
|
|
61
|
-
for (const harness of getAvailableHarnesses()) {
|
|
62
|
-
const roots = harness.watchRoots?.() ?? [];
|
|
63
|
-
if (roots.length === 0)
|
|
64
|
-
continue;
|
|
65
|
-
targets.push({ harnessName: harness.name, roots });
|
|
66
|
-
}
|
|
67
|
-
return targets;
|
|
68
|
-
}
|
|
69
53
|
export function normalizeSessionTopic(text) {
|
|
70
54
|
const normalized = text.replace(/\s+/g, " ").trim().toLowerCase();
|
|
71
55
|
if (normalized.length < 10)
|
|
@@ -107,16 +91,13 @@ export function aggregateSessionEvents(events) {
|
|
|
107
91
|
* Collect normalized session events from a set of harnesses for the health
|
|
108
92
|
* candidate scan (#568).
|
|
109
93
|
*
|
|
110
|
-
* Pipeline selection per harness
|
|
111
|
-
* -
|
|
112
|
-
* richer `listSessions()` + `readSession()` pipeline. `readSession` flattens
|
|
94
|
+
* Pipeline selection per harness:
|
|
95
|
+
* - Drive the richer `listSessions()` + `readSession()` pipeline. `readSession` flattens
|
|
113
96
|
* structured content — tool calls, assistant content blocks, thinking,
|
|
114
97
|
* tool_result — into event text (e.g. ClaudeCodeProvider's `parseClaudeEvent`
|
|
115
98
|
* surfaces `[tool:*]` / `[tool_result]` blocks that the legacy flat
|
|
116
99
|
* `readEvents` scan drops entirely). This is what lets health advisories see
|
|
117
100
|
* repeated tool failures / long runs that the flat scan hid.
|
|
118
|
-
* - legacy-only harness (`supportsReadSession === false`): fall back to the
|
|
119
|
-
* legacy flat `readEvents()` scan (behaviour-preserving).
|
|
120
101
|
*
|
|
121
102
|
* Extracted as a pure function (harnesses injected) so it is unit-testable
|
|
122
103
|
* without touching the real on-disk session-log locations.
|
|
@@ -129,19 +110,13 @@ export function aggregateSessionEvents(events) {
|
|
|
129
110
|
* health command (`akm health`, which calls this synchronously) blow past its
|
|
130
111
|
* latency budget. `listSessions()` returns summaries sorted newest-first, so
|
|
131
112
|
* capping to the most-recent N sessions per harness keeps the richer signal
|
|
132
|
-
* for what actually matters (recent activity) while bounding cost.
|
|
133
|
-
* flat-scan path is naturally cheaper and is left uncapped.
|
|
113
|
+
* for what actually matters (recent activity) while bounding cost.
|
|
134
114
|
*/
|
|
135
115
|
const DEFAULT_MAX_SESSIONS_PER_HARNESS = 50;
|
|
136
116
|
export function collectSessionEvents(harnesses, sinceMs, maxSessionsPerHarness = DEFAULT_MAX_SESSIONS_PER_HARNESS) {
|
|
137
117
|
const events = [];
|
|
138
118
|
for (const harness of harnesses) {
|
|
139
119
|
try {
|
|
140
|
-
if (harness.supportsReadSession === false) {
|
|
141
|
-
// Legacy-only harness: only the flat event scan is available.
|
|
142
|
-
events.push(...harness.readEvents({ sinceMs }));
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
120
|
// Rich path: enumerate sessions cheaply, then read each one's full
|
|
146
121
|
// structured event stream. Falls back to readEvents if listSessions
|
|
147
122
|
// surfaces nothing (e.g. a harness that wired readSession but whose
|