akm-cli 0.9.0-rc.9 → 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 +95 -55
- 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 +25 -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 +88 -7
- 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 -1878
- 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 -1231
- 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 -257
- package/dist/migrate/legacy/content-migration.js +0 -350
- 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 -80
- package/dist/migrate/legacy/proposal-fs-import.js +0 -168
- package/dist/migrate/legacy/task-target-ref-migration.js +0 -278
- package/dist/migrate/legacy/three-db-cutover.js +0 -845
- 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
|
@@ -4,9 +4,12 @@
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { parseFrontmatter } from "../../core/asset/frontmatter.js";
|
|
7
|
-
import { conceptIdFromTypeName, parseRefInput } from "../../core/asset/resolve-ref.js";
|
|
7
|
+
import { conceptIdFromTypeName, parseRefInput, resolveRef } from "../../core/asset/resolve-ref.js";
|
|
8
|
+
import { loadConfig } from "../../core/config/config.js";
|
|
8
9
|
import { NotFoundError, rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
|
|
9
10
|
import { readEvents } from "../../core/events.js";
|
|
11
|
+
import { getDbPath } from "../../core/paths.js";
|
|
12
|
+
import { deriveInstallations } from "../../indexer/installations.js";
|
|
10
13
|
import { getWritableStashDirs, resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
11
14
|
import { resolveAssetPath } from "../../indexer/walk/path-resolver.js";
|
|
12
15
|
import { closeDatabase, openExistingDatabase, openReadonlyExistingDatabase, } from "../../storage/repositories/index-connection.js";
|
|
@@ -19,6 +22,17 @@ import { improveStateReadRefs } from "./source-identity.js";
|
|
|
19
22
|
// Eligibility / candidate-selection predicates for improve. Free functions
|
|
20
23
|
// (no akmImprove closure state) extracted from improve.ts to shrink the
|
|
21
24
|
// orchestrator and make candidate selection independently testable.
|
|
25
|
+
/**
|
|
26
|
+
* Open the index for eligibility queries, or `undefined` when no index exists
|
|
27
|
+
* yet. `openExistingDatabase` refuses to create a missing `index.db` (see
|
|
28
|
+
* index-connection.ts) — for eligibility, "no index" simply means nothing is
|
|
29
|
+
* eligible, exactly like the readOnly arm's `undefined`.
|
|
30
|
+
*/
|
|
31
|
+
function openEligibilityDb(readOnly) {
|
|
32
|
+
if (readOnly)
|
|
33
|
+
return openReadonlyExistingDatabase();
|
|
34
|
+
return fs.existsSync(getDbPath()) ? openExistingDatabase() : undefined;
|
|
35
|
+
}
|
|
22
36
|
export function resolveImproveScope(scope) {
|
|
23
37
|
const trimmed = scope?.trim();
|
|
24
38
|
if (!trimmed)
|
|
@@ -28,9 +42,8 @@ export function resolveImproveScope(scope) {
|
|
|
28
42
|
return { mode: "ref", value: trimmed };
|
|
29
43
|
}
|
|
30
44
|
catch (err) {
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
// such word is now accepted, including foreign/unknown type strings,
|
|
45
|
+
// A bare word with no ref separator is a `--scope <type>` filter attempt,
|
|
46
|
+
// not a ref. Any such word is accepted, including foreign/unknown type strings,
|
|
34
47
|
// which simply match zero entries downstream (a read-only query filter,
|
|
35
48
|
// not a data-acceptance gate, so no deny-list is needed here: an
|
|
36
49
|
// unrecognized type just matches nothing, since nothing is ever indexed
|
|
@@ -42,7 +55,7 @@ export function resolveImproveScope(scope) {
|
|
|
42
55
|
// deliberately-removed type like tool/vault, D1.5-6) — that must still
|
|
43
56
|
// surface as a real error, not be silently absorbed into a type filter
|
|
44
57
|
// that will never match anything.
|
|
45
|
-
if (
|
|
58
|
+
if (!/[/:#]/.test(trimmed)) {
|
|
46
59
|
return { mode: "type", value: trimmed };
|
|
47
60
|
}
|
|
48
61
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -50,7 +63,8 @@ export function resolveImproveScope(scope) {
|
|
|
50
63
|
}
|
|
51
64
|
}
|
|
52
65
|
/**
|
|
53
|
-
* Dedupe
|
|
66
|
+
* Dedupe eligible refs by their durable item ref when available, preserving
|
|
67
|
+
* the first candidate and its display ref. Used to
|
|
54
68
|
* merge the eligibility sources (feedback-signal, Layer-2 proactive-maintenance,
|
|
55
69
|
* high-salience) without admitting a ref into the loop twice.
|
|
56
70
|
*/
|
|
@@ -58,44 +72,76 @@ export function dedupeRefs(refs) {
|
|
|
58
72
|
const seen = new Set();
|
|
59
73
|
const out = [];
|
|
60
74
|
for (const r of refs) {
|
|
61
|
-
|
|
75
|
+
const key = r.itemRef ?? r.ref;
|
|
76
|
+
if (seen.has(key))
|
|
62
77
|
continue;
|
|
63
|
-
seen.add(
|
|
78
|
+
seen.add(key);
|
|
64
79
|
out.push(r);
|
|
65
80
|
}
|
|
66
81
|
return out;
|
|
67
82
|
}
|
|
68
|
-
export async function collectEligibleRefs(scope, stashDir, improveProfile) {
|
|
69
|
-
return collectEligibleRefsFromIndex(scope, stashDir, improveProfile, false);
|
|
83
|
+
export async function collectEligibleRefs(scope, stashDir, improveProfile, config) {
|
|
84
|
+
return collectEligibleRefsFromIndex(scope, stashDir, improveProfile, false, config);
|
|
70
85
|
}
|
|
71
86
|
/** Dry-run planner path: query an existing index without creating or mutating it. */
|
|
72
|
-
export async function collectEligibleRefsReadOnly(scope, stashDir, improveProfile) {
|
|
73
|
-
return collectEligibleRefsFromIndex(scope, stashDir, improveProfile, true);
|
|
87
|
+
export async function collectEligibleRefsReadOnly(scope, stashDir, improveProfile, config) {
|
|
88
|
+
return collectEligibleRefsFromIndex(scope, stashDir, improveProfile, true, config);
|
|
74
89
|
}
|
|
75
|
-
async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, readOnly) {
|
|
90
|
+
async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, readOnly, configOverride) {
|
|
91
|
+
const config = configOverride ?? loadConfig();
|
|
76
92
|
if (scope.mode === "ref" && scope.value) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
93
|
+
const writableDirs = new Set(getWritableStashDirs(stashDir, config).map((dir) => path.resolve(dir)));
|
|
94
|
+
let db;
|
|
95
|
+
try {
|
|
96
|
+
db = openEligibilityDb(readOnly);
|
|
97
|
+
if (!db) {
|
|
98
|
+
return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
|
|
99
|
+
}
|
|
100
|
+
const entries = getAllEntries(db);
|
|
101
|
+
const entriesByItemRef = new Map(entries.flatMap((entry) => entry.bundleId && entry.conceptId ? [[`${entry.bundleId}//${entry.conceptId}`, entry]] : []));
|
|
102
|
+
const installations = deriveInstallations(resolveSourceEntries(stashDir, config));
|
|
103
|
+
const resolved = resolveRef(scope.value, {
|
|
104
|
+
defaultBundle: config.defaultBundle,
|
|
105
|
+
bundles: installations.map((installation) => ({
|
|
106
|
+
id: installation.id,
|
|
107
|
+
hasConcept: (conceptId) => entriesByItemRef.has(`${installation.id}//${conceptId}`),
|
|
108
|
+
})),
|
|
109
|
+
});
|
|
110
|
+
const indexed = entriesByItemRef.get(`${resolved.bundle}//${resolved.conceptId}`);
|
|
111
|
+
if (!indexed?.bundleId || !indexed.conceptId || !fs.existsSync(indexed.filePath)) {
|
|
112
|
+
if (await findAssetFilePath(scope.value, stashDir)) {
|
|
113
|
+
return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
|
|
114
|
+
}
|
|
115
|
+
throw new NotFoundError(`Asset not found in the selected writable source: ${scope.value}`, "ASSET_NOT_FOUND");
|
|
116
|
+
}
|
|
117
|
+
if (!isEntryInScope(indexed.stashDir, indexed.filePath, stashDir) ||
|
|
118
|
+
!isEntryInWritableSource(indexed.stashDir, indexed.filePath, writableDirs)) {
|
|
119
|
+
return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
|
|
120
|
+
}
|
|
121
|
+
const itemRef = `${indexed.bundleId}//${indexed.conceptId}`;
|
|
81
122
|
return {
|
|
82
|
-
plannedRefs: [],
|
|
83
|
-
memorySummary: {
|
|
123
|
+
plannedRefs: [{ ref: indexed.conceptId, itemRef, reason: "scope-ref", filePath: indexed.filePath }],
|
|
124
|
+
memorySummary: {
|
|
125
|
+
eligible: indexed.entry.type === "memory" ? 1 : 0,
|
|
126
|
+
derived: indexed.entry.type === "memory" && indexed.entry.name.endsWith(".derived") ? 1 : 0,
|
|
127
|
+
},
|
|
84
128
|
strategyFilteredRefs: [],
|
|
85
129
|
};
|
|
86
130
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
131
|
+
catch (error) {
|
|
132
|
+
if (error instanceof Error && /no such table:\s*entries/i.test(error.message)) {
|
|
133
|
+
return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
|
|
134
|
+
}
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
if (db)
|
|
139
|
+
closeDatabase(db);
|
|
140
|
+
}
|
|
95
141
|
}
|
|
96
142
|
let sources;
|
|
97
143
|
try {
|
|
98
|
-
sources = resolveSourceEntries(stashDir);
|
|
144
|
+
sources = resolveSourceEntries(stashDir, config);
|
|
99
145
|
}
|
|
100
146
|
catch {
|
|
101
147
|
return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
|
|
@@ -107,7 +153,7 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
|
|
|
107
153
|
// or remote stashes that the user did not mark writable.
|
|
108
154
|
let writableDirs;
|
|
109
155
|
try {
|
|
110
|
-
writableDirs = getWritableStashDirs(stashDir);
|
|
156
|
+
writableDirs = getWritableStashDirs(stashDir, config);
|
|
111
157
|
}
|
|
112
158
|
catch {
|
|
113
159
|
writableDirs = sources.slice(0, 1).map((s) => s.path); // fallback: primary only
|
|
@@ -115,7 +161,7 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
|
|
|
115
161
|
const writableDirSet = new Set(writableDirs.map((d) => path.resolve(d)));
|
|
116
162
|
let db;
|
|
117
163
|
try {
|
|
118
|
-
db = readOnly
|
|
164
|
+
db = openEligibilityDb(readOnly);
|
|
119
165
|
if (!db) {
|
|
120
166
|
return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
|
|
121
167
|
}
|
|
@@ -127,7 +173,7 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
|
|
|
127
173
|
return isEntryInWritableSource(indexed.stashDir, indexed.filePath, writableDirSet);
|
|
128
174
|
});
|
|
129
175
|
const planned = new Map();
|
|
130
|
-
const
|
|
176
|
+
const strategyFiltered = new Map();
|
|
131
177
|
let memoryEligible = 0;
|
|
132
178
|
let memoryDerived = 0;
|
|
133
179
|
for (const indexed of entries) {
|
|
@@ -144,11 +190,8 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
|
|
|
144
190
|
continue;
|
|
145
191
|
throw error;
|
|
146
192
|
}
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
// queries (D-R3 — derived from the resolved index entry, never raw input).
|
|
150
|
-
// `undefined` for a NULL-provenance (pre-flip / write-back) row; the durable
|
|
151
|
-
// writers then fall back to the legacy `type:name` key.
|
|
193
|
+
// Derive the durable item_ref from indexed provenance without another query.
|
|
194
|
+
// A provenance-free row uses the short conceptId ref for improve state.
|
|
152
195
|
const itemRef = indexed.bundleId && indexed.conceptId ? `${indexed.bundleId}//${indexed.conceptId}` : undefined;
|
|
153
196
|
const isDerived = indexed.entry.name.endsWith(".derived");
|
|
154
197
|
// `.derived` memories are LLM-inferred and intentionally skip reflect
|
|
@@ -158,16 +201,16 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
|
|
|
158
201
|
// 2026-05-21: 11 derived refs re-planned every hour during idle periods.
|
|
159
202
|
// The cleanup phase (analyzeMemoryCleanup) inspects derived memories
|
|
160
203
|
// independently of `plannedRefs`, so dropping them here loses nothing.
|
|
161
|
-
if (!isDerived && !planned.has(ref) && !
|
|
162
|
-
// 2026-05-27: extend the .derived precedent to
|
|
204
|
+
if (!isDerived && !planned.has(ref) && !strategyFiltered.has(ref)) {
|
|
205
|
+
// 2026-05-27: extend the .derived precedent to strategy-incompatible
|
|
163
206
|
// refs. If every per-ref pass (reflect + distill) on the active
|
|
164
|
-
//
|
|
207
|
+
// strategy would refuse this ref, drop it from `plannedRefs`. The
|
|
165
208
|
// caller emits `improve_skipped { reason: strategy_filtered_all_passes }`
|
|
166
209
|
// once `eventsCtx` is available so the audit trail is preserved in a
|
|
167
210
|
// single event per ref instead of 2× synthetic actions per run.
|
|
168
211
|
// Background: see /tmp/akm-health-investigations/planner-profile-metrics-deep-analysis.md
|
|
169
212
|
if (improveProfile && isStrategyFilteredForAllPasses(ref, improveProfile)) {
|
|
170
|
-
|
|
213
|
+
strategyFiltered.set(ref, {
|
|
171
214
|
ref,
|
|
172
215
|
reason: "strategy_filtered_all_passes",
|
|
173
216
|
filePath: indexed.filePath,
|
|
@@ -192,7 +235,7 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
|
|
|
192
235
|
return {
|
|
193
236
|
plannedRefs: [...planned.values()],
|
|
194
237
|
memorySummary: { eligible: memoryEligible, derived: memoryDerived },
|
|
195
|
-
strategyFilteredRefs: [...
|
|
238
|
+
strategyFilteredRefs: [...strategyFiltered.values()],
|
|
196
239
|
};
|
|
197
240
|
}
|
|
198
241
|
catch (error) {
|
|
@@ -255,9 +298,8 @@ export function memoryCleanupParentRef(scope, stashDir) {
|
|
|
255
298
|
continue;
|
|
256
299
|
const raw = fs.readFileSync(candidate, "utf8");
|
|
257
300
|
const fm = parseFrontmatter(raw).data;
|
|
258
|
-
// The `source:` backref
|
|
259
|
-
//
|
|
260
|
-
// `memories/<name>` conceptId (Group-C item 2). That is exactly what
|
|
301
|
+
// The `source:` backref is normalized to the `memories/<name>` conceptId.
|
|
302
|
+
// That is exactly what
|
|
261
303
|
// analyzeMemoryCleanup's parentRef filter compares against — resolveParentRef
|
|
262
304
|
// emits the same conceptId — so the two sites stay in lockstep.
|
|
263
305
|
const parent = parseMemoryRef(typeof fm.source === "string" ? fm.source : undefined);
|
|
@@ -290,7 +332,7 @@ export function isLessonCandidate(ref) {
|
|
|
290
332
|
* which was true *only* for `lesson:*` refs — exactly the set distill refuses.
|
|
291
333
|
* The result: every hourly run re-queued the same lesson refs, the same skip
|
|
292
334
|
* message returned, and no work was ever done. See
|
|
293
|
-
* `tests/commands/improve-distill-planner-skip-lessons.test.ts`.
|
|
335
|
+
* `tests/integration/commands/improve-distill-planner-skip-lessons.test.ts`.
|
|
294
336
|
*/
|
|
295
337
|
export function isDistillCandidateRef(ref, stashDir) {
|
|
296
338
|
const parsed = parseRefInput(ref);
|
|
@@ -333,13 +375,12 @@ export function shouldDistillMemoryRef(ref, stashDir) {
|
|
|
333
375
|
* metadata events are ignored so a stray `akm feedback <ref>` invocation
|
|
334
376
|
* without a flag doesn't trigger downstream re-processing.
|
|
335
377
|
*/
|
|
336
|
-
export function buildLatestFeedbackTsMap(refs, sinceIso,
|
|
378
|
+
export function buildLatestFeedbackTsMap(refs, sinceIso, itemRefByRef) {
|
|
337
379
|
const out = new Map();
|
|
338
380
|
if (refs.length === 0)
|
|
339
381
|
return out;
|
|
340
|
-
//
|
|
341
|
-
|
|
342
|
-
const refByDurableKey = new Map(refs.flatMap((ref) => improveStateReadRefs(ref, sourceName, includeLegacyBare, itemRefByRef?.get(ref)).map((key) => [key, ref])));
|
|
382
|
+
// Correlate item_ref-keyed events and conceptId-keyed direct invocations.
|
|
383
|
+
const refByDurableKey = new Map(refs.flatMap((ref) => improveStateReadRefs(ref, itemRefByRef?.get(ref)).map((key) => [key, ref])));
|
|
343
384
|
const { events } = readEvents({ type: "feedback", since: sinceIso });
|
|
344
385
|
for (const e of events) {
|
|
345
386
|
const ref = e.ref ? refByDurableKey.get(e.ref) : undefined;
|
|
@@ -359,18 +400,17 @@ export function buildLatestFeedbackTsMap(refs, sinceIso, sourceName, includeLega
|
|
|
359
400
|
* Latest proposal timestamp per input-ref, filtered by source ('reflect' or
|
|
360
401
|
* 'distill'). Reads the corresponding `*_invoked` events from state.db —
|
|
361
402
|
* these events are emitted at proposal creation time and carry the *input*
|
|
362
|
-
* asset ref (
|
|
403
|
+
* asset ref (`memories/foo`, `skills/bar`, etc.) directly. We use them rather than
|
|
363
404
|
* `listProposals` because distill proposals are keyed by the derived
|
|
364
405
|
* lesson/knowledge ref, not the source memory — joining back through the
|
|
365
406
|
* payload would be fragile.
|
|
366
407
|
*/
|
|
367
|
-
export function buildLatestProposalTsMap(refs, source,
|
|
408
|
+
export function buildLatestProposalTsMap(refs, source, itemRefByRef) {
|
|
368
409
|
const out = new Map();
|
|
369
410
|
if (refs.length === 0)
|
|
370
411
|
return out;
|
|
371
|
-
//
|
|
372
|
-
|
|
373
|
-
const refByDurableKey = new Map(refs.flatMap((ref) => improveStateReadRefs(ref, sourceName, includeLegacyBare, itemRefByRef?.get(ref)).map((key) => [key, ref])));
|
|
412
|
+
// Correlate item_ref-keyed events and conceptId-keyed direct invocations.
|
|
413
|
+
const refByDurableKey = new Map(refs.flatMap((ref) => improveStateReadRefs(ref, itemRefByRef?.get(ref)).map((key) => [key, ref])));
|
|
374
414
|
const eventType = source === "reflect" ? "reflect_invoked" : "distill_invoked";
|
|
375
415
|
const { events } = readEvents({ type: eventType });
|
|
376
416
|
for (const e of events) {
|
|
@@ -487,6 +527,6 @@ export async function findAssetFilePath(ref, stashDir, writableDirSet) {
|
|
|
487
527
|
writableDirSet,
|
|
488
528
|
directoryIndexNames: ["SKILL.md"],
|
|
489
529
|
preserveDirectNameFallback: true,
|
|
490
|
-
honorOrigin:
|
|
530
|
+
honorOrigin: true,
|
|
491
531
|
});
|
|
492
532
|
}
|
|
@@ -2,31 +2,30 @@
|
|
|
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
|
-
* CLI surface for `akm extract
|
|
5
|
+
* CLI surface for `akm proposal extract` (formerly the top-level `akm
|
|
6
|
+
* extract`, moved under the `proposal` group in the 0.9 CLI overhaul, S8 —
|
|
7
|
+
* see src/commands/proposal/proposal-cli.ts for its registration).
|
|
6
8
|
*
|
|
7
9
|
* Examples:
|
|
8
|
-
* akm extract --type claude-code --session-id <id>
|
|
9
|
-
* akm extract --type claude-code --since 24h
|
|
10
|
-
* akm extract --type opencode --since 7d --dry-run
|
|
11
|
-
* akm extract --auto # iterate all available harnesses
|
|
12
|
-
* akm extract --type claude-code --location /custom/path --session-id <id>
|
|
10
|
+
* akm proposal extract --type claude-code --session-id <id>
|
|
11
|
+
* akm proposal extract --type claude-code --since 24h
|
|
12
|
+
* akm proposal extract --type opencode --since 7d --dry-run
|
|
13
|
+
* akm proposal extract --auto # iterate all available harnesses
|
|
14
|
+
* akm proposal extract --type claude-code --location /custom/path --session-id <id>
|
|
13
15
|
*
|
|
14
16
|
* Output is the AkmExtractResult JSON envelope (or an aggregated one when
|
|
15
17
|
* `--auto` runs multiple harnesses).
|
|
16
18
|
*/
|
|
17
|
-
import fs from "node:fs";
|
|
18
|
-
import path from "node:path";
|
|
19
19
|
import { getStringArg } from "../../cli/parse-args.js";
|
|
20
20
|
import { defineJsonCommand, EXIT_CODES, output } from "../../cli/shared.js";
|
|
21
21
|
import { loadConfig } from "../../core/config/config.js";
|
|
22
22
|
import { UsageError } from "../../core/errors.js";
|
|
23
|
-
import { getAvailableHarnesses
|
|
24
|
-
import { akmExtract, resolveStandaloneExtractPlan
|
|
25
|
-
import { akmExtractWatch } from "./extract-watch.js";
|
|
23
|
+
import { getAvailableHarnesses } from "../../integrations/session-logs/index.js";
|
|
24
|
+
import { akmExtract, resolveStandaloneExtractPlan } from "./extract.js";
|
|
26
25
|
export const extractCommand = defineJsonCommand({
|
|
27
26
|
meta: {
|
|
28
27
|
name: "extract",
|
|
29
|
-
description: "Extract durable insights from native session files (claude-code, opencode) and queue them as proposals.
|
|
28
|
+
description: "Extract durable insights from native session files (claude-code, opencode) and queue them as proposals.",
|
|
30
29
|
},
|
|
31
30
|
args: {
|
|
32
31
|
type: {
|
|
@@ -72,15 +71,6 @@ export const extractCommand = defineJsonCommand({
|
|
|
72
71
|
type: "string",
|
|
73
72
|
description: "Improve strategy supplying extract behavior and engine. Mutually exclusive with --engine.",
|
|
74
73
|
},
|
|
75
|
-
watch: {
|
|
76
|
-
type: "boolean",
|
|
77
|
-
description: "Watch harness session-log directories and run extract on change (debounced). Stays alive until SIGINT/SIGTERM.",
|
|
78
|
-
default: false,
|
|
79
|
-
},
|
|
80
|
-
"debounce-ms": {
|
|
81
|
-
type: "string",
|
|
82
|
-
description: "Debounce window in ms for --watch (default 2000).",
|
|
83
|
-
},
|
|
84
74
|
},
|
|
85
75
|
async run({ args }) {
|
|
86
76
|
const type = getStringArg(args, "type") ?? "";
|
|
@@ -101,17 +91,10 @@ export const extractCommand = defineJsonCommand({
|
|
|
101
91
|
if (engine && strategy) {
|
|
102
92
|
throw new UsageError("--engine and --strategy are mutually exclusive. Pick one.", "INVALID_FLAG_VALUE");
|
|
103
93
|
}
|
|
104
|
-
|
|
105
|
-
const debounceMs = typeof args["debounce-ms"] === "string" && args["debounce-ms"] !== ""
|
|
106
|
-
? Number.parseInt(args["debounce-ms"], 10)
|
|
107
|
-
: 2000;
|
|
108
|
-
if (watch && (!Number.isFinite(debounceMs) || debounceMs <= 0)) {
|
|
109
|
-
throw new UsageError(`--debounce-ms must be a positive integer (got "${args["debounce-ms"]}").`, "INVALID_FLAG_VALUE");
|
|
110
|
-
}
|
|
111
|
-
if (!watch && auto && type) {
|
|
94
|
+
if (auto && type) {
|
|
112
95
|
throw new UsageError("--auto and --type are mutually exclusive. Pick one.", "INVALID_FLAG_VALUE");
|
|
113
96
|
}
|
|
114
|
-
if (!
|
|
97
|
+
if (!auto && !type) {
|
|
115
98
|
throw new UsageError("--type is required (or pass --auto to try every available harness).", "MISSING_REQUIRED_ARGUMENT");
|
|
116
99
|
}
|
|
117
100
|
const config = loadConfig();
|
|
@@ -120,10 +103,6 @@ export const extractCommand = defineJsonCommand({
|
|
|
120
103
|
...(strategy ? { strategy } : {}),
|
|
121
104
|
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
122
105
|
});
|
|
123
|
-
if (watch) {
|
|
124
|
-
await runWatchMode({ debounceMs, dryRun, force, config, resolvedPlan, ...(since ? { since } : {}) });
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
106
|
const commonOptions = Object.freeze({
|
|
128
107
|
...(sessionId ? { sessionId } : {}),
|
|
129
108
|
...(location ? { location } : {}),
|
|
@@ -164,7 +143,7 @@ export const extractCommand = defineJsonCommand({
|
|
|
164
143
|
// Signal failure to callers/schedulers when every harness failed. output()
|
|
165
144
|
// only renders; without this a scheduled run exits 0 on a total failure
|
|
166
145
|
// and the breakage is invisible to exit-code monitoring. process.exitCode
|
|
167
|
-
// (not process.exit) lets stdout flush
|
|
146
|
+
// (not process.exit) lets stdout flush before the process exits.
|
|
168
147
|
if (!ok)
|
|
169
148
|
process.exitCode = EXIT_CODES.GENERAL;
|
|
170
149
|
return;
|
|
@@ -175,101 +154,3 @@ export const extractCommand = defineJsonCommand({
|
|
|
175
154
|
process.exitCode = EXIT_CODES.GENERAL;
|
|
176
155
|
},
|
|
177
156
|
});
|
|
178
|
-
/**
|
|
179
|
-
* A thin {@link WatchEventSource} over `fs.watch` for each configured root.
|
|
180
|
-
* This adapter is the ONLY place a real `fs.watch` is created (the core stays
|
|
181
|
-
* injectable + fully unit-tested); it is intentionally not unit-covered.
|
|
182
|
-
*
|
|
183
|
-
* `fs.watch(dir, { recursive: true })` is unreliable for recursive mode on some
|
|
184
|
-
* Node/Bun/Linux combinations. A root that cannot be watched is skipped while
|
|
185
|
-
* successfully-created watchers continue running.
|
|
186
|
-
*/
|
|
187
|
-
function createFsWatchEventSource(roots) {
|
|
188
|
-
return {
|
|
189
|
-
subscribe(listener) {
|
|
190
|
-
const watchers = [];
|
|
191
|
-
for (const root of roots) {
|
|
192
|
-
try {
|
|
193
|
-
const watcher = fs.watch(root, { recursive: true }, (_event, filename) => {
|
|
194
|
-
if (!filename)
|
|
195
|
-
return;
|
|
196
|
-
const filePath = path.isAbsolute(filename.toString())
|
|
197
|
-
? filename.toString()
|
|
198
|
-
: path.join(root, filename.toString());
|
|
199
|
-
listener({ path: filePath });
|
|
200
|
-
});
|
|
201
|
-
watchers.push(watcher);
|
|
202
|
-
}
|
|
203
|
-
catch {
|
|
204
|
-
// A root that can't be watched is skipped.
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return () => {
|
|
208
|
-
for (const w of watchers) {
|
|
209
|
-
try {
|
|
210
|
-
w.close();
|
|
211
|
-
}
|
|
212
|
-
catch {
|
|
213
|
-
// best-effort teardown
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
},
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
/** Snapshot the CLI-resolved watch options once and reuse them for every debounced trigger. */
|
|
221
|
-
export function createExtractWatchTrigger(options, extractFn = akmExtract) {
|
|
222
|
-
const snapshot = Object.freeze({ ...options });
|
|
223
|
-
return async (harnessName) => {
|
|
224
|
-
await extractFn({ type: harnessName, ...snapshot });
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Run `akm extract --watch`: watch every available harness's session-log
|
|
229
|
-
* roots and run extract (debounced, per-harness) on change. Stays alive until
|
|
230
|
-
* SIGINT/SIGTERM, then stops cleanly. PROCESS-HYGIENE: stop() removes every
|
|
231
|
-
* watcher + pending timer before the process exits.
|
|
232
|
-
*/
|
|
233
|
-
async function runWatchMode(opts) {
|
|
234
|
-
const targets = getWatchTargets();
|
|
235
|
-
if (targets.length === 0) {
|
|
236
|
-
output("extract", {
|
|
237
|
-
schemaVersion: 1,
|
|
238
|
-
ok: false,
|
|
239
|
-
shape: "extract-watch-started",
|
|
240
|
-
warnings: ["no watchable harness session-log directories found on this machine"],
|
|
241
|
-
watching: [],
|
|
242
|
-
});
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
const allRoots = targets.flatMap((t) => t.roots);
|
|
246
|
-
const eventSource = createFsWatchEventSource(allRoots);
|
|
247
|
-
const onTrigger = createExtractWatchTrigger({
|
|
248
|
-
dryRun: opts.dryRun,
|
|
249
|
-
force: opts.force,
|
|
250
|
-
config: opts.config,
|
|
251
|
-
resolvedPlan: opts.resolvedPlan,
|
|
252
|
-
...(opts.since ? { since: opts.since } : {}),
|
|
253
|
-
});
|
|
254
|
-
const handle = akmExtractWatch({
|
|
255
|
-
roots: targets,
|
|
256
|
-
eventSource,
|
|
257
|
-
debounceMs: opts.debounceMs,
|
|
258
|
-
onTrigger,
|
|
259
|
-
});
|
|
260
|
-
output("extract", {
|
|
261
|
-
schemaVersion: 1,
|
|
262
|
-
ok: true,
|
|
263
|
-
shape: "extract-watch-started",
|
|
264
|
-
debounceMs: opts.debounceMs,
|
|
265
|
-
watching: allRoots,
|
|
266
|
-
});
|
|
267
|
-
await new Promise((resolve) => {
|
|
268
|
-
const shutdown = () => {
|
|
269
|
-
handle.stop();
|
|
270
|
-
resolve();
|
|
271
|
-
};
|
|
272
|
-
process.once("SIGINT", shutdown);
|
|
273
|
-
process.once("SIGTERM", shutdown);
|
|
274
|
-
});
|
|
275
|
-
}
|