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
|
@@ -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) {
|
|
@@ -136,11 +182,16 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
|
|
|
136
182
|
// xrefs, and `displayRef` output spelling. `.itemRef` below stays the
|
|
137
183
|
// fully-qualified durable key.
|
|
138
184
|
const ref = conceptIdFromTypeName(indexed.entry.type, indexed.entry.name);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
185
|
+
try {
|
|
186
|
+
parseRefInput(ref);
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
if (error instanceof UsageError || error instanceof NotFoundError)
|
|
190
|
+
continue;
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
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.
|
|
144
195
|
const itemRef = indexed.bundleId && indexed.conceptId ? `${indexed.bundleId}//${indexed.conceptId}` : undefined;
|
|
145
196
|
const isDerived = indexed.entry.name.endsWith(".derived");
|
|
146
197
|
// `.derived` memories are LLM-inferred and intentionally skip reflect
|
|
@@ -150,16 +201,16 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
|
|
|
150
201
|
// 2026-05-21: 11 derived refs re-planned every hour during idle periods.
|
|
151
202
|
// The cleanup phase (analyzeMemoryCleanup) inspects derived memories
|
|
152
203
|
// independently of `plannedRefs`, so dropping them here loses nothing.
|
|
153
|
-
if (!isDerived && !planned.has(ref) && !
|
|
154
|
-
// 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
|
|
155
206
|
// refs. If every per-ref pass (reflect + distill) on the active
|
|
156
|
-
//
|
|
207
|
+
// strategy would refuse this ref, drop it from `plannedRefs`. The
|
|
157
208
|
// caller emits `improve_skipped { reason: strategy_filtered_all_passes }`
|
|
158
209
|
// once `eventsCtx` is available so the audit trail is preserved in a
|
|
159
210
|
// single event per ref instead of 2× synthetic actions per run.
|
|
160
211
|
// Background: see /tmp/akm-health-investigations/planner-profile-metrics-deep-analysis.md
|
|
161
212
|
if (improveProfile && isStrategyFilteredForAllPasses(ref, improveProfile)) {
|
|
162
|
-
|
|
213
|
+
strategyFiltered.set(ref, {
|
|
163
214
|
ref,
|
|
164
215
|
reason: "strategy_filtered_all_passes",
|
|
165
216
|
filePath: indexed.filePath,
|
|
@@ -184,13 +235,13 @@ async function collectEligibleRefsFromIndex(scope, stashDir, improveProfile, rea
|
|
|
184
235
|
return {
|
|
185
236
|
plannedRefs: [...planned.values()],
|
|
186
237
|
memorySummary: { eligible: memoryEligible, derived: memoryDerived },
|
|
187
|
-
strategyFilteredRefs: [...
|
|
238
|
+
strategyFilteredRefs: [...strategyFiltered.values()],
|
|
188
239
|
};
|
|
189
240
|
}
|
|
190
241
|
catch (error) {
|
|
191
|
-
//
|
|
242
|
+
// Empty-stash setup paths can open index.db before its schema exists.
|
|
192
243
|
rethrowIfTestIsolationError(error);
|
|
193
|
-
if (error instanceof
|
|
244
|
+
if (error instanceof Error && /no such table:\s*entries/i.test(error.message)) {
|
|
194
245
|
return { plannedRefs: [], memorySummary: { eligible: 0, derived: 0 }, strategyFilteredRefs: [] };
|
|
195
246
|
}
|
|
196
247
|
throw error;
|
|
@@ -247,9 +298,8 @@ export function memoryCleanupParentRef(scope, stashDir) {
|
|
|
247
298
|
continue;
|
|
248
299
|
const raw = fs.readFileSync(candidate, "utf8");
|
|
249
300
|
const fm = parseFrontmatter(raw).data;
|
|
250
|
-
// The `source:` backref
|
|
251
|
-
//
|
|
252
|
-
// `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
|
|
253
303
|
// analyzeMemoryCleanup's parentRef filter compares against — resolveParentRef
|
|
254
304
|
// emits the same conceptId — so the two sites stay in lockstep.
|
|
255
305
|
const parent = parseMemoryRef(typeof fm.source === "string" ? fm.source : undefined);
|
|
@@ -282,7 +332,7 @@ export function isLessonCandidate(ref) {
|
|
|
282
332
|
* which was true *only* for `lesson:*` refs — exactly the set distill refuses.
|
|
283
333
|
* The result: every hourly run re-queued the same lesson refs, the same skip
|
|
284
334
|
* message returned, and no work was ever done. See
|
|
285
|
-
* `tests/commands/improve-distill-planner-skip-lessons.test.ts`.
|
|
335
|
+
* `tests/integration/commands/improve-distill-planner-skip-lessons.test.ts`.
|
|
286
336
|
*/
|
|
287
337
|
export function isDistillCandidateRef(ref, stashDir) {
|
|
288
338
|
const parsed = parseRefInput(ref);
|
|
@@ -325,13 +375,12 @@ export function shouldDistillMemoryRef(ref, stashDir) {
|
|
|
325
375
|
* metadata events are ignored so a stray `akm feedback <ref>` invocation
|
|
326
376
|
* without a flag doesn't trigger downstream re-processing.
|
|
327
377
|
*/
|
|
328
|
-
export function buildLatestFeedbackTsMap(refs, sinceIso,
|
|
378
|
+
export function buildLatestFeedbackTsMap(refs, sinceIso, itemRefByRef) {
|
|
329
379
|
const out = new Map();
|
|
330
380
|
if (refs.length === 0)
|
|
331
381
|
return out;
|
|
332
|
-
//
|
|
333
|
-
|
|
334
|
-
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])));
|
|
335
384
|
const { events } = readEvents({ type: "feedback", since: sinceIso });
|
|
336
385
|
for (const e of events) {
|
|
337
386
|
const ref = e.ref ? refByDurableKey.get(e.ref) : undefined;
|
|
@@ -351,18 +400,17 @@ export function buildLatestFeedbackTsMap(refs, sinceIso, sourceName, includeLega
|
|
|
351
400
|
* Latest proposal timestamp per input-ref, filtered by source ('reflect' or
|
|
352
401
|
* 'distill'). Reads the corresponding `*_invoked` events from state.db —
|
|
353
402
|
* these events are emitted at proposal creation time and carry the *input*
|
|
354
|
-
* asset ref (
|
|
403
|
+
* asset ref (`memories/foo`, `skills/bar`, etc.) directly. We use them rather than
|
|
355
404
|
* `listProposals` because distill proposals are keyed by the derived
|
|
356
405
|
* lesson/knowledge ref, not the source memory — joining back through the
|
|
357
406
|
* payload would be fragile.
|
|
358
407
|
*/
|
|
359
|
-
export function buildLatestProposalTsMap(refs, source,
|
|
408
|
+
export function buildLatestProposalTsMap(refs, source, itemRefByRef) {
|
|
360
409
|
const out = new Map();
|
|
361
410
|
if (refs.length === 0)
|
|
362
411
|
return out;
|
|
363
|
-
//
|
|
364
|
-
|
|
365
|
-
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])));
|
|
366
414
|
const eventType = source === "reflect" ? "reflect_invoked" : "distill_invoked";
|
|
367
415
|
const { events } = readEvents({ type: eventType });
|
|
368
416
|
for (const e of events) {
|
|
@@ -479,6 +527,6 @@ export async function findAssetFilePath(ref, stashDir, writableDirSet) {
|
|
|
479
527
|
writableDirSet,
|
|
480
528
|
directoryIndexNames: ["SKILL.md"],
|
|
481
529
|
preserveDirectNameFallback: true,
|
|
482
|
-
honorOrigin:
|
|
530
|
+
honorOrigin: true,
|
|
483
531
|
});
|
|
484
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
|
-
}
|