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
|
@@ -23,6 +23,9 @@ import { purgeOldCycleMetrics } from "../../storage/repositories/canaries-reposi
|
|
|
23
23
|
import { purgeOldEvents } from "../../storage/repositories/events-repository.js";
|
|
24
24
|
import { purgeOldImproveRuns } from "../../storage/repositories/improve-runs-repository.js";
|
|
25
25
|
import { closeDatabase, openIndexDatabase } from "../../storage/repositories/index-connection.js";
|
|
26
|
+
import { getEntryByRef } from "../../storage/repositories/index-entries-repository.js";
|
|
27
|
+
import { clearAssetOutcomeMissing, countAssetOutcomeMissing, deleteAssetOutcomeMissingBefore, listAssetOutcomeMissingState, stampAssetOutcomeMissing, } from "../../storage/repositories/outcome-repository.js";
|
|
28
|
+
import { clearAssetSalienceMissing, countAssetSalienceMissing, deleteAssetSalienceMissingBefore, listAssetSalienceMissingState, stampAssetSalienceMissing, } from "../../storage/repositories/salience-repository.js";
|
|
26
29
|
import { expireStaleProposals, listProposals, purgeOrphanProposals } from "../proposal/repository.js";
|
|
27
30
|
import { checkDeadUrls } from "../url-checker.js";
|
|
28
31
|
import { DEFAULT_RETENTION_DAYS as CYCLE_METRICS_RETENTION_DAYS, runCollapseDetector } from "./collapse-detector.js";
|
|
@@ -34,7 +37,7 @@ import { writeEvalCase } from "./eval-cases.js";
|
|
|
34
37
|
import { shouldSkipRef } from "./improve-strategies.js";
|
|
35
38
|
import { recordNoOp, resetConsecutiveNoOps } from "./salience.js";
|
|
36
39
|
import { errMessage, refSlug } from "./shared.js";
|
|
37
|
-
import { durableImproveRef } from "./source-identity.js";
|
|
40
|
+
import { bareImproveRef, durableImproveRef } from "./source-identity.js";
|
|
38
41
|
// ── improve loop / post-loop / maintenance stages ───────────────────
|
|
39
42
|
// The cycle stages run by akmImprove, extracted from improve.ts.
|
|
40
43
|
/** O-5 / #378: rolling per-originator error-window cap. */
|
|
@@ -180,17 +183,17 @@ async function runLoopReflectPass(planned, isDistillOnly, env, tally) {
|
|
|
180
183
|
const reflectProfileRunner = resolvedPlan.processes.reflect.runner;
|
|
181
184
|
const reflectCallArgs = {
|
|
182
185
|
ref: planned.ref,
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
// Chunk-5 flip F5f — carry the resolved item_ref so reflect keys its
|
|
186
|
-
// reflect_invoked event + source/distill_invoked reads on it (dormant
|
|
187
|
-
// until item_ref populates through the improve path).
|
|
186
|
+
// Carry the resolved item_ref so reflect uses the same durable key for
|
|
187
|
+
// events and state reads.
|
|
188
188
|
...(planned.itemRef ? { itemRef: planned.itemRef } : {}),
|
|
189
189
|
task: options.task,
|
|
190
190
|
// Active strategy supplies non-engine process tuning.
|
|
191
191
|
...(improveProfile ? { improveProfile } : {}),
|
|
192
192
|
config: options.config,
|
|
193
193
|
...(primaryStashDir ? { stashDir: primaryStashDir } : {}),
|
|
194
|
+
...(options.sourceName && primaryStashDir
|
|
195
|
+
? { target: { source: options.sourceName, root: primaryStashDir } }
|
|
196
|
+
: {}),
|
|
194
197
|
...(reflectErrors.length > 0 ? { avoidPatterns: [...reflectErrors] } : {}),
|
|
195
198
|
eventSource: "improve",
|
|
196
199
|
// #639 — resolve the low-value filter from the ACTIVE improve profile
|
|
@@ -271,11 +274,8 @@ async function runLoopReflectPass(planned, isDistillOnly, env, tally) {
|
|
|
271
274
|
// A no_change reflect means the LLM was invoked but found nothing to
|
|
272
275
|
// improve — the asset is stable. Track it. A successful reflect means
|
|
273
276
|
// the asset changed; reset the counter so the dampener lifts.
|
|
274
|
-
//
|
|
275
|
-
|
|
276
|
-
// item_ref when the planner resolved one, else the source-qualified
|
|
277
|
-
// `type:name`. A split key would strand consecutive_no_ops on a second row.
|
|
278
|
-
const plasticityKey = planned.itemRef ?? durableImproveRef(planned.ref, options.sourceName);
|
|
277
|
+
// Use the same item_ref-or-conceptId salience key as preparation/distill.
|
|
278
|
+
const plasticityKey = planned.itemRef ?? durableImproveRef(planned.ref);
|
|
279
279
|
if (isNoChange && eventsCtx?.db) {
|
|
280
280
|
try {
|
|
281
281
|
recordNoOp(eventsCtx.db, plasticityKey);
|
|
@@ -430,11 +430,8 @@ async function invokeDistillAndRecord(planned, parsedPlannedRef, env, tally) {
|
|
|
430
430
|
const { options, primaryStashDir, distillFn, eventsCtx, improveProfile, resolvedPlan, budgetSignal } = env;
|
|
431
431
|
const distillResult = await withLlmStage("distill", () => distillFn({
|
|
432
432
|
ref: planned.ref,
|
|
433
|
-
//
|
|
434
|
-
// write by it (matching preparation), when the planner supplied one.
|
|
433
|
+
// Carry the resolved item_ref so distill matches preparation's state key.
|
|
435
434
|
...(planned.itemRef ? { itemRef: planned.itemRef } : {}),
|
|
436
|
-
...(options.sourceName ? { sourceName: options.sourceName } : {}),
|
|
437
|
-
...(options.legacyBareState ? { legacyBareState: true } : {}),
|
|
438
435
|
...(parsedPlannedRef.type === "memory" ? { proposalKind: "auto" } : {}),
|
|
439
436
|
...(primaryStashDir ? { stashDir: primaryStashDir } : {}),
|
|
440
437
|
// Active profile so distill's per-process reads honor `--profile`.
|
|
@@ -461,9 +458,8 @@ async function invokeDistillAndRecord(planned, parsedPlannedRef, env, tally) {
|
|
|
461
458
|
// quality gate — the asset is not yielding useful distill output.
|
|
462
459
|
// queued: a proposal was produced; reset the no-op counter.
|
|
463
460
|
if (eventsCtx?.db) {
|
|
464
|
-
//
|
|
465
|
-
|
|
466
|
-
const plasticityKey = planned.itemRef ?? durableImproveRef(planned.ref, options.sourceName);
|
|
461
|
+
// Use the same item_ref-or-conceptId key as the distill/preparation writers.
|
|
462
|
+
const plasticityKey = planned.itemRef ?? durableImproveRef(planned.ref);
|
|
467
463
|
try {
|
|
468
464
|
if (distillResult.outcome === "quality_rejected" || distillResult.outcome === "skipped") {
|
|
469
465
|
recordNoOp(eventsCtx.db, plasticityKey);
|
|
@@ -624,7 +620,6 @@ export async function runImprovePostLoopStage(args) {
|
|
|
624
620
|
runId: options.runId ?? "improve-adhoc",
|
|
625
621
|
...(improveProfile ? { improveProfile } : {}),
|
|
626
622
|
pass: "consolidate",
|
|
627
|
-
acceptedActions: args.acceptedActions ?? 0,
|
|
628
623
|
mergeFloorViolations: args.consolidationMergeFloorViolations ?? 0,
|
|
629
624
|
config: options.config ?? loadConfig(),
|
|
630
625
|
...(eventsCtx ? { eventsCtx } : {}),
|
|
@@ -744,6 +739,12 @@ async function runMaintenancePassesUnderLease(ctx, dbCell, args) {
|
|
|
744
739
|
allWarnings.push(...graph.warnings);
|
|
745
740
|
const orphan = runOrphanProposalPurgePass(ctx);
|
|
746
741
|
allWarnings.push(...orphan.warnings);
|
|
742
|
+
// #733: orphan-state GC — stamps/clears/(optionally) collects
|
|
743
|
+
// asset_salience/asset_outcome rows whose ref no longer resolves in
|
|
744
|
+
// index.db. Needs the SAME already-open index.db handle (dbCell.current)
|
|
745
|
+
// the passes above share.
|
|
746
|
+
const stateGc = runOrphanStateGcPass(ctx, dbCell);
|
|
747
|
+
allWarnings.push(...stateGc.warnings);
|
|
747
748
|
const expiration = runProposalExpirationPass(ctx);
|
|
748
749
|
allWarnings.push(...expiration.warnings);
|
|
749
750
|
allWarnings.push(...runRetentionPurgePass(ctx).warnings);
|
|
@@ -764,7 +765,7 @@ async function runMaintenancePassesUnderLease(ctx, dbCell, args) {
|
|
|
764
765
|
}
|
|
765
766
|
/**
|
|
766
767
|
* Memory inference candidate-discovery (post-Item 9 fix from
|
|
767
|
-
*
|
|
768
|
+
* memories/akm-improve-critical-review-2026-05-20). Previously this pass
|
|
768
769
|
* was gated on memoryRefsForInference.size > 0 AND passed those refs as a
|
|
769
770
|
* candidateRefs filter. But memoryRefsForInference is populated from refs
|
|
770
771
|
* distilled THIS RUN — by the time that happens, those parents are
|
|
@@ -1123,3 +1124,164 @@ export function runRetentionPurgePass(ctx) {
|
|
|
1123
1124
|
}
|
|
1124
1125
|
return { warnings };
|
|
1125
1126
|
}
|
|
1127
|
+
// ── #733 — orphan-state GC pass (Workstream C) ──────────────────────────────
|
|
1128
|
+
//
|
|
1129
|
+
// Deliberately lean: one maintenance pass, one additive migration (021), one
|
|
1130
|
+
// event type (asset_state_gc), one config gate (improve.stateGc.collect,
|
|
1131
|
+
// default false). See docs/architecture/specs/0.9.0-close-out-plan.md
|
|
1132
|
+
// Workstream C for the full design rationale. No quarantine archive, no
|
|
1133
|
+
// circuit breaker, no health-advisory plumbing, no new tables.
|
|
1134
|
+
/**
|
|
1135
|
+
* Grace window (ms) before an unresolved `asset_salience` / `asset_outcome`
|
|
1136
|
+
* row becomes delete-eligible — only when `improve.stateGc.collect` is true.
|
|
1137
|
+
* A named constant, not a config knob (owner ruling — see the close-out
|
|
1138
|
+
* plan's Workstream C). Mirrors `TXN_SWEEP_GRACE_MS` (src/core/fs-txn.ts:298).
|
|
1139
|
+
*/
|
|
1140
|
+
export const STATE_GC_GRACE_MS = daysToMs(7);
|
|
1141
|
+
/**
|
|
1142
|
+
* Resolve one state-table's stored `asset_ref` against the live index.
|
|
1143
|
+
*
|
|
1144
|
+
* "ref not present in entries.item_ref" is the authoritative-deletion
|
|
1145
|
+
* predicate (see the pass doc comment below), so this is a thin wrapper
|
|
1146
|
+
* around the same single-ref probe the rest of improve uses
|
|
1147
|
+
* (`getEntryByRef`, index-entries-repository.ts) — which already resolves
|
|
1148
|
+
* both storage spellings a write can produce (`salienceWriteKey`/
|
|
1149
|
+
* `outcomeWriteKey` = `itemRef ?? ref`): an exact bundle-qualified item_ref,
|
|
1150
|
+
* or a bare conceptId matched by suffix across all bundles.
|
|
1151
|
+
*
|
|
1152
|
+
* On top of that, falls back to the BARE conceptId form (`bareImproveRef` —
|
|
1153
|
+
* the same primitive `preparation.ts`'s `normalizeStoredKey` map is built
|
|
1154
|
+
* from via `improveStateReadRefs`) when the stored ref carries a bundle
|
|
1155
|
+
* prefix that no longer matches exactly. This is the legacy-spelling
|
|
1156
|
+
* normalization trap: a naive `asset_ref NOT IN (SELECT item_ref FROM
|
|
1157
|
+
* entries)` would treat a live asset whose row predates bundle-qualification
|
|
1158
|
+
* (or whose bundle prefix is stale) as an orphan and delete it. Preferring
|
|
1159
|
+
* "never delete a live row" over "never miss a genuinely dead one" mirrors
|
|
1160
|
+
* `getEntryByRef`'s own bare-conceptId suffix-match trade-off.
|
|
1161
|
+
*/
|
|
1162
|
+
function isStateRefLive(indexDb, storedRef) {
|
|
1163
|
+
if (getEntryByRef(indexDb, storedRef) !== null)
|
|
1164
|
+
return true;
|
|
1165
|
+
const bare = bareImproveRef(storedRef);
|
|
1166
|
+
return bare !== storedRef && getEntryByRef(indexDb, bare) !== null;
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Sweep ONE state table: stamp refs that just went unresolved, clear refs
|
|
1170
|
+
* that resolved again, and — only when `collect` is true — delete rows whose
|
|
1171
|
+
* `missing_since` is older than {@link STATE_GC_GRACE_MS}. `pending` is a
|
|
1172
|
+
* point-in-time snapshot taken AFTER stamp/clear/delete (re-queried, not
|
|
1173
|
+
* accumulated), so it reflects the current backlog rather than this run's
|
|
1174
|
+
* delta — "every run emits the counts either way, so live data accumulates
|
|
1175
|
+
* proof" (close-out plan, Workstream C).
|
|
1176
|
+
*/
|
|
1177
|
+
function gcOneStateTable(args) {
|
|
1178
|
+
const { refRows, indexDb, now, collect, stamp, clear, deleteOlderThan, countPending } = args;
|
|
1179
|
+
const toStamp = [];
|
|
1180
|
+
const toClear = [];
|
|
1181
|
+
for (const row of refRows) {
|
|
1182
|
+
const live = isStateRefLive(indexDb, row.asset_ref);
|
|
1183
|
+
if (!live && row.missing_since == null)
|
|
1184
|
+
toStamp.push(row.asset_ref);
|
|
1185
|
+
else if (live && row.missing_since != null)
|
|
1186
|
+
toClear.push(row.asset_ref);
|
|
1187
|
+
}
|
|
1188
|
+
if (toStamp.length > 0)
|
|
1189
|
+
stamp(toStamp, now);
|
|
1190
|
+
if (toClear.length > 0)
|
|
1191
|
+
clear(toClear);
|
|
1192
|
+
const collected = collect ? deleteOlderThan(now - STATE_GC_GRACE_MS) : 0;
|
|
1193
|
+
const pending = countPending();
|
|
1194
|
+
return { pending, collected };
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Orphan-state GC — #733 (Workstream C). For each of the two per-asset state
|
|
1198
|
+
* tables (`asset_salience`, `asset_outcome`), stamps `missing_since` on refs
|
|
1199
|
+
* that no longer resolve against `entries.item_ref` in index.db, clears the
|
|
1200
|
+
* stamp on refs that resolve again, and — only when `improve.stateGc.collect`
|
|
1201
|
+
* is true — deletes rows whose stamp is older than {@link STATE_GC_GRACE_MS}.
|
|
1202
|
+
*
|
|
1203
|
+
* "ref not present in entries.item_ref" IS the authoritative-deletion
|
|
1204
|
+
* predicate: "absent ≠ deleted" is inherited from the indexer, not
|
|
1205
|
+
* re-implemented here — an incomplete or failed source scan preserves that
|
|
1206
|
+
* source's last-known-good `entries` rows (indexer.ts ~1195-1199), and
|
|
1207
|
+
* mass-wipe is already gated upstream (`preserveExistingIndex` +
|
|
1208
|
+
* `fullDelete && scanComplete`). A temporarily unreachable source therefore
|
|
1209
|
+
* never surfaces candidates; no separate scan-status tracking is needed.
|
|
1210
|
+
*
|
|
1211
|
+
* Runs under the SAME index-writer lease / borrowed-state.db-connection
|
|
1212
|
+
* discipline as the neighboring maintenance passes: `dbCell.current` supplies
|
|
1213
|
+
* the already-open index.db handle (#584), and state.db access goes through
|
|
1214
|
+
* `withStateDb(..., { borrowed: eventsCtx?.db })` so this never opens a
|
|
1215
|
+
* second live writer alongside a long-lived `eventsCtx.db` connection — see
|
|
1216
|
+
* the #585 comment on {@link runRetentionPurgePass}'s events-purge call for
|
|
1217
|
+
* why that matters ("database is locked").
|
|
1218
|
+
*
|
|
1219
|
+
* Exported for direct test coverage (tests/integration/commands/improve/
|
|
1220
|
+
* state-gc.test.ts), mirroring the `runMemoryInferenceMaintenancePass` /
|
|
1221
|
+
* `runGraphExtractionMaintenancePass` / `runRetentionPurgePass` precedent;
|
|
1222
|
+
* production callers reach it only through `runMaintenancePassesUnderLease`.
|
|
1223
|
+
*/
|
|
1224
|
+
export function runOrphanStateGcPass(ctx, dbCell) {
|
|
1225
|
+
const { eventsCtx, config } = ctx;
|
|
1226
|
+
const warnings = [];
|
|
1227
|
+
const indexDb = dbCell.current;
|
|
1228
|
+
if (!indexDb) {
|
|
1229
|
+
warnings.push("orphan state GC skipped: no index.db handle available");
|
|
1230
|
+
return { pending: 0, collected: 0, warnings };
|
|
1231
|
+
}
|
|
1232
|
+
const collect = config.improve?.stateGc?.collect === true;
|
|
1233
|
+
const now = Date.now();
|
|
1234
|
+
let pending = 0;
|
|
1235
|
+
let collected = 0;
|
|
1236
|
+
try {
|
|
1237
|
+
withStateDb((stateDb) => {
|
|
1238
|
+
const salienceResult = gcOneStateTable({
|
|
1239
|
+
refRows: listAssetSalienceMissingState(stateDb),
|
|
1240
|
+
indexDb,
|
|
1241
|
+
now,
|
|
1242
|
+
collect,
|
|
1243
|
+
stamp: (refs, ts) => stampAssetSalienceMissing(stateDb, refs, ts),
|
|
1244
|
+
clear: (refs) => clearAssetSalienceMissing(stateDb, refs),
|
|
1245
|
+
deleteOlderThan: (cutoffMs) => deleteAssetSalienceMissingBefore(stateDb, cutoffMs),
|
|
1246
|
+
countPending: () => countAssetSalienceMissing(stateDb),
|
|
1247
|
+
});
|
|
1248
|
+
const outcomeResult = gcOneStateTable({
|
|
1249
|
+
refRows: listAssetOutcomeMissingState(stateDb),
|
|
1250
|
+
indexDb,
|
|
1251
|
+
now,
|
|
1252
|
+
collect,
|
|
1253
|
+
stamp: (refs, ts) => stampAssetOutcomeMissing(stateDb, refs, ts),
|
|
1254
|
+
clear: (refs) => clearAssetOutcomeMissing(stateDb, refs),
|
|
1255
|
+
deleteOlderThan: (cutoffMs) => deleteAssetOutcomeMissingBefore(stateDb, cutoffMs),
|
|
1256
|
+
countPending: () => countAssetOutcomeMissing(stateDb),
|
|
1257
|
+
});
|
|
1258
|
+
// Table-name-shaped keys ("salience"/"outcome", not the guarded
|
|
1259
|
+
// "asset_salience"/"asset_outcome" table names) — this file sits
|
|
1260
|
+
// outside src/storage/repositories/**, where the state-table-sql
|
|
1261
|
+
// lint rule (#672) forbids naming those tables even in a log string
|
|
1262
|
+
// or an object key, not just in raw SQL.
|
|
1263
|
+
const byTable = { salience: salienceResult, outcome: outcomeResult };
|
|
1264
|
+
pending = salienceResult.pending + outcomeResult.pending;
|
|
1265
|
+
collected = salienceResult.collected + outcomeResult.collected;
|
|
1266
|
+
if (pending > 0 || collected > 0) {
|
|
1267
|
+
info(`[improve] orphan state GC: ${pending} pending, ${collected} collected ` +
|
|
1268
|
+
`(salience ${salienceResult.pending}/${salienceResult.collected}, ` +
|
|
1269
|
+
`outcome ${outcomeResult.pending}/${outcomeResult.collected})`);
|
|
1270
|
+
// #733 — asset_state_gc reports the current per-table backlog
|
|
1271
|
+
// snapshot (`pending`) plus this run's deletions (`collected`);
|
|
1272
|
+
// emitted only when there is something to report (mirrors the
|
|
1273
|
+
// rekey script's no-op-stays-silent precedent) so a perpetually
|
|
1274
|
+
// clean stash never accumulates events.
|
|
1275
|
+
appendEvent({
|
|
1276
|
+
eventType: "asset_state_gc",
|
|
1277
|
+
ref: "asset_state/_gc",
|
|
1278
|
+
metadata: { pending, collected, byTable },
|
|
1279
|
+
}, eventsCtx);
|
|
1280
|
+
}
|
|
1281
|
+
}, { path: eventsCtx?.dbPath, borrowed: eventsCtx?.db });
|
|
1282
|
+
}
|
|
1283
|
+
catch (err) {
|
|
1284
|
+
warnings.push(`orphan state GC failed: ${errMessage(err)}`);
|
|
1285
|
+
}
|
|
1286
|
+
return { pending, collected, warnings };
|
|
1287
|
+
}
|
|
@@ -9,10 +9,9 @@
|
|
|
9
9
|
* (`memory-improve.ts`, keyed on the memory name) and the PRODUCER
|
|
10
10
|
* (`memory-contradiction-detect.ts`, keyed on the file path). The producer's
|
|
11
11
|
* copy was strictly narrower: it ignored `derivedFrom` entirely and matched
|
|
12
|
-
* `source:`
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* plan §6 calls out ("producer/consumer cannot disagree").
|
|
12
|
+
* `source:` through a separate parser. That let the producer and consumer
|
|
13
|
+
* disagree on a memory's parent — the exact defect plan §6 calls out
|
|
14
|
+
* ("producer/consumer cannot disagree").
|
|
16
15
|
*
|
|
17
16
|
* Both sides now share this one impl, keyed on the memory NAME (the stash-
|
|
18
17
|
* relative path without the `.md` extension, e.g. `nested/foo.derived`). The
|
|
@@ -21,9 +20,8 @@
|
|
|
21
20
|
* `tests/commands/improve/derived-ref.test.ts`:
|
|
22
21
|
* - `derivedFrom`-keyed families now resolve a parent (and so participate in
|
|
23
22
|
* contradiction detection); and
|
|
24
|
-
* - `source:` is
|
|
25
|
-
*
|
|
26
|
-
* silently degrading to the filename.
|
|
23
|
+
* - `source:` is parsed through `parseRefInput` so current bundle-qualified
|
|
24
|
+
* refs resolve consistently.
|
|
27
25
|
*
|
|
28
26
|
* Resolution order (source → derivedFrom → `.derived` suffix) matches the
|
|
29
27
|
* consumer's prior behaviour exactly, so the consumer side is a pure move.
|
|
@@ -32,62 +30,66 @@ import { conceptIdFromTypeName, parseRefInput } from "../../../core/asset/resolv
|
|
|
32
30
|
import { asNonEmptyString } from "../../../core/common.js";
|
|
33
31
|
import { DERIVED_SUFFIX } from "../../../core/recognition-util.js";
|
|
34
32
|
/**
|
|
35
|
-
* Parse
|
|
36
|
-
*
|
|
37
|
-
* Trims whitespace and drops any origin/bundle prefix.
|
|
33
|
+
* Parse a belief edge (`supersededBy` / `contradictedBy` / `currentBeliefRefs`)
|
|
34
|
+
* to the bare memory name the identity channel keys on.
|
|
38
35
|
*
|
|
39
|
-
*
|
|
40
|
-
* `
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
36
|
+
* Accepts BOTH spellings, because both reach this function:
|
|
37
|
+
* - `memory:<name>` — the internal identity spelling, and what belief edges
|
|
38
|
+
* written before 0.9.0 carry on disk;
|
|
39
|
+
* - `memories/<name>` / `<bundle>//memories/<name>` — the conceptId grammar
|
|
40
|
+
* the current writers emit (`akm remember --supersedes` and `akm import
|
|
41
|
+
* --supersedes` go through `writeSupersededEdge` with the write result's
|
|
42
|
+
* `ref`, which is fully qualified).
|
|
43
|
+
*
|
|
44
|
+
* Accepting only the first spelling silently reduced every edge written by the
|
|
45
|
+
* current code path to nothing, so a superseded memory read back as active.
|
|
46
|
+
* Both normalize to the bare name; the caller re-mints the internal
|
|
47
|
+
* `memory:<name>` form via {@link memoryIdentityRef}, so there is still exactly
|
|
48
|
+
* one identity spelling downstream.
|
|
48
49
|
*/
|
|
49
50
|
export function parseMemoryName(value) {
|
|
50
51
|
if (!value)
|
|
51
52
|
return undefined;
|
|
52
53
|
const trimmed = value.trim();
|
|
54
|
+
const MEMORY_PREFIX = "memory:";
|
|
55
|
+
if (trimmed.startsWith(MEMORY_PREFIX)) {
|
|
56
|
+
const name = trimmed.slice(MEMORY_PREFIX.length);
|
|
57
|
+
return name.length > 0 ? name : undefined;
|
|
58
|
+
}
|
|
53
59
|
try {
|
|
54
60
|
const parsed = parseRefInput(trimmed);
|
|
55
|
-
return parsed.type === "memory" ? parsed.name : undefined;
|
|
61
|
+
return parsed.type === "memory" && parsed.name.length > 0 ? parsed.name : undefined;
|
|
56
62
|
}
|
|
57
63
|
catch {
|
|
58
|
-
|
|
59
|
-
const boundary = trimmed.indexOf("//");
|
|
60
|
-
const body = boundary >= 0 ? trimmed.slice(boundary + 2) : trimmed;
|
|
61
|
-
const MEMORY_PREFIX = "memory:";
|
|
62
|
-
return body.startsWith(MEMORY_PREFIX) ? body.slice(MEMORY_PREFIX.length) : undefined;
|
|
64
|
+
return undefined;
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* (Group-C item 2 flip). Tolerant of BOTH grammars on input (see
|
|
69
|
-
* {@link parseMemoryName}), but the NORMALISED OUTPUT is always the conceptId —
|
|
70
|
-
* so every consumer that compares against the `derived_from` channel (the
|
|
71
|
-
* parentRef filter, inference dedup, eligibility) speaks one grammar. The
|
|
72
|
-
* content-migration folds the on-disk legacy spelling forward; this reader keeps
|
|
73
|
-
* tolerating it until the 0.10.0 grammar removal.
|
|
68
|
+
* Parse a current `source:` backref and return its canonical memory conceptId,
|
|
69
|
+
* or `undefined` when it is empty, invalid, or not a memory ref.
|
|
74
70
|
*/
|
|
75
71
|
export function parseMemoryRef(value) {
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
if (!value)
|
|
73
|
+
return undefined;
|
|
74
|
+
try {
|
|
75
|
+
const parsed = parseRefInput(value.trim());
|
|
76
|
+
return parsed.type === "memory" ? conceptIdFromTypeName("memory", parsed.name) : undefined;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
78
81
|
}
|
|
79
82
|
/**
|
|
80
83
|
* Format a bare memory name into the belief-edge IDENTITY channel ref
|
|
81
84
|
* `memory:<name>` — the ONE implementation of that spelling.
|
|
82
85
|
*
|
|
83
|
-
*
|
|
86
|
+
* Belief-edge / identity
|
|
84
87
|
* channel (`contradictedBy` / `supersededBy` / `currentBeliefRefs`, and a derived
|
|
85
|
-
* memory's own `record.ref`)
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* `memories/<name>`. Both `memory-improve.ts` (`refArray`) and
|
|
88
|
+
* memory's own `record.ref`) uses `memory:<name>` and is compared against a
|
|
89
|
+
* derived memory's identity ref. This channel is separate from `source:` asset
|
|
90
|
+
* refs, which use `memories/<name>`. Both `memory-improve.ts` (`refArray`) and
|
|
89
91
|
* `memory-contradiction-detect.ts` (`toMemoryRef`) emit through here so the
|
|
90
|
-
*
|
|
92
|
+
* identity spelling has one implementation.
|
|
91
93
|
*/
|
|
92
94
|
export function memoryIdentityRef(name) {
|
|
93
95
|
return `memory:${name}`;
|
|
@@ -101,8 +103,8 @@ export function isDerivedMemory(name, frontmatter) {
|
|
|
101
103
|
return frontmatter.inferred === true || name.endsWith(DERIVED_SUFFIX);
|
|
102
104
|
}
|
|
103
105
|
/**
|
|
104
|
-
* Resolve the parent (source) memory ref for a derived memory as
|
|
105
|
-
* `memories/<name>` conceptId
|
|
106
|
+
* Resolve the parent (source) memory ref for a derived memory as a canonical
|
|
107
|
+
* `memories/<name>` conceptId, or `undefined` when none
|
|
106
108
|
* can be determined. Precedence:
|
|
107
109
|
* 1. `frontmatter.source` (normalised through {@link parseMemoryRef});
|
|
108
110
|
* 2. `frontmatter.derivedFrom` (a bare memory name → `memories/<name>`);
|
|
@@ -63,7 +63,7 @@ function readEdgeList(value) {
|
|
|
63
63
|
* present WITHOUT the demotion (e.g. a hand-written `contradictedBy:` line,
|
|
64
64
|
* or a beliefState lost to a partial edit) is repaired, not skipped — an
|
|
65
65
|
* edge-only guard would make such a file a permanent no-op while
|
|
66
|
-
*
|
|
66
|
+
* contradiction writers report the contradiction as applied.
|
|
67
67
|
*
|
|
68
68
|
* Never weakens a stronger demotion: `archived` ranks BELOW `contradicted`
|
|
69
69
|
* (see `BELIEF_STATE_SCORE_CEILINGS` in
|
|
@@ -37,9 +37,10 @@ import fs from "node:fs";
|
|
|
37
37
|
import path from "node:path";
|
|
38
38
|
import contradictionJudgeTemplate from "../../../assets/prompts/contradiction-judge.md" with { type: "text" };
|
|
39
39
|
import { mutateFrontmatter, parseFrontmatter } from "../../../core/asset/frontmatter.js";
|
|
40
|
+
import { parseEmbeddedJsonResponse } from "../../../core/parse.js";
|
|
40
41
|
import { getDefaultLlmConfig } from "../../../integrations/agent/engine-resolution.js";
|
|
41
42
|
import { materializeLlmRunnerConnection, resolveImproveProcessRunner } from "../../../integrations/agent/runner.js";
|
|
42
|
-
import { chatCompletion
|
|
43
|
+
import { chatCompletion } from "../../../llm/client.js";
|
|
43
44
|
import { callStructured } from "../../../llm/structured-call.js";
|
|
44
45
|
import { isDerivedMemory, memoryIdentityRef, resolveParentRef } from "./derived-ref.js";
|
|
45
46
|
// ── Constants ────────────────────────────────────────────────────────────────
|
|
@@ -56,8 +57,7 @@ const MAX_PAIRS_PER_RUN = 20;
|
|
|
56
57
|
/**
|
|
57
58
|
* Minimum confidence required to write a contradiction edge. Below this
|
|
58
59
|
* threshold the LLM may be flagging topic-overlap rather than genuine logical
|
|
59
|
-
* exclusivity (investigation 2026-06-18).
|
|
60
|
-
* 1.0 for backward compatibility with older judge responses.
|
|
60
|
+
* exclusivity (investigation 2026-06-18).
|
|
61
61
|
*/
|
|
62
62
|
const CONTRADICT_CONFIDENCE_THRESHOLD = 0.92;
|
|
63
63
|
/**
|
|
@@ -230,11 +230,6 @@ export async function detectAndWriteContradictions(stashDir, config, chat = chat
|
|
|
230
230
|
// edge already exists (no new information; avoids re-judging resolved
|
|
231
231
|
// pairs across runs).
|
|
232
232
|
//
|
|
233
|
-
// Legacy mutual A↔B edges written by the pre-fix pass self-heal: the
|
|
234
|
-
// skip fires this run, but the SCC resolver treats the 2-cycle as a sink
|
|
235
|
-
// and refreshes both to active — DELETING both `contradictedBy` arrays
|
|
236
|
-
// (memory-improve.ts persistBeliefStateTransition). The next detection
|
|
237
|
-
// run then sees no edge, re-judges, and writes the single canonical edge.
|
|
238
233
|
const aParsed = parseFrontmatter(fs.readFileSync(a.filePath, "utf8"));
|
|
239
234
|
const bParsed = parseFrontmatter(fs.readFileSync(b.filePath, "utf8"));
|
|
240
235
|
const { loser, winnerRef } = pickContradictionLoser(a, b);
|
|
@@ -274,10 +269,7 @@ export async function detectAndWriteContradictions(stashDir, config, chat = chat
|
|
|
274
269
|
}
|
|
275
270
|
if (!parsed?.contradicts)
|
|
276
271
|
continue;
|
|
277
|
-
|
|
278
|
-
// pre-confidence responses). Do NOT default to 0 — that would silently
|
|
279
|
-
// disable all detection during the rollout period.
|
|
280
|
-
const confidence = typeof parsed.confidence === "number" ? parsed.confidence : 1.0;
|
|
272
|
+
const confidence = typeof parsed.confidence === "number" ? parsed.confidence : 0;
|
|
281
273
|
if (confidence < CONTRADICT_CONFIDENCE_THRESHOLD) {
|
|
282
274
|
result.warnings.push(`Pair ${a.ref} / ${b.ref}: confidence ${confidence.toFixed(2)} below ${CONTRADICT_CONFIDENCE_THRESHOLD} threshold — skipped.`);
|
|
283
275
|
continue;
|
|
@@ -657,11 +657,12 @@ function resolveBeliefState(frontmatter) {
|
|
|
657
657
|
// Belief-edge refs (contradictedBy / supersededBy / currentBeliefRefs) are the
|
|
658
658
|
// IDENTITY channel: they are compared against a derived memory's own
|
|
659
659
|
// `memory:<name>` ref (resolveFamilyContradictions' familyRefSet,
|
|
660
|
-
// firstExistingRef's byRef map), so they
|
|
661
|
-
//
|
|
662
|
-
//
|
|
663
|
-
//
|
|
664
|
-
//
|
|
660
|
+
// firstExistingRef's byRef map), so they are NORMALIZED to `memory:<name>` here.
|
|
661
|
+
// On disk they arrive in either spelling — `memory:<name>` from pre-0.9.0
|
|
662
|
+
// writes, or the `[<bundle>//]memories/<name>` conceptId that
|
|
663
|
+
// `writeSupersededEdge`/`writeContradictEdge` persist today — and
|
|
664
|
+
// `parseMemoryName` accepts both. Reading only the first spelling silently
|
|
665
|
+
// dropped every edge the current write path produces.
|
|
665
666
|
function refArray(value) {
|
|
666
667
|
if (typeof value === "string") {
|
|
667
668
|
const name = parseMemoryName(value);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { getAllAssetOutcomes, getAssetOutcome, getOutcomeScoresByRef, upsertAssetOutcome, } from "../../storage/repositories/outcome-repository.js";
|
|
4
5
|
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
5
6
|
/**
|
|
6
7
|
* EMA decay factor for the expected-retrieval rolling mean (α).
|
|
@@ -94,76 +95,32 @@ export function updateAssetOutcome(db, inputs) {
|
|
|
94
95
|
const newScore = OUTCOME_EMA_ALPHA * rawUpdate + (1 - OUTCOME_EMA_ALPHA) * existing.outcome_score;
|
|
95
96
|
// Clip to [OUTCOME_SCORE_MIN, OUTCOME_SCORE_MAX] — the ceiling is the RPE
|
|
96
97
|
// saturation analog (G2): without it, long-lived popular assets accumulate
|
|
97
|
-
// unbounded positive mass
|
|
98
|
-
//
|
|
99
|
-
// ceiling converge back under it on their next differential update.
|
|
98
|
+
// unbounded positive mass and would dominate rank_score when outcome weight
|
|
99
|
+
// is enabled.
|
|
100
100
|
outcomeScore = Math.min(OUTCOME_SCORE_MAX, Math.max(OUTCOME_SCORE_MIN, newScore));
|
|
101
101
|
}
|
|
102
|
-
// Upsert the row. `
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
negative_feedback_count= excluded.negative_feedback_count,
|
|
117
|
-
accepted_change_count = excluded.accepted_change_count,
|
|
118
|
-
outcome_score = excluded.outcome_score,
|
|
119
|
-
updated_at = excluded.updated_at`).run(inputs.ref, inputs.lastRetrievedAt, inputs.currentRetrievalCount, expectedRetrievalRate, inputs.negativeFeedbackCount, inputs.acceptedChangeCount, outcomeScore, now);
|
|
102
|
+
// Upsert the row. See `upsertAssetOutcome` in
|
|
103
|
+
// storage/repositories/outcome-repository.ts (#672 part 2) for the SQL text
|
|
104
|
+
// and the `review_pressure` omission rationale — this call site is
|
|
105
|
+
// unchanged in intent, just no longer inline.
|
|
106
|
+
upsertAssetOutcome(db, {
|
|
107
|
+
ref: inputs.ref,
|
|
108
|
+
lastRetrievedAt: inputs.lastRetrievedAt,
|
|
109
|
+
retrievalCount: inputs.currentRetrievalCount,
|
|
110
|
+
expectedRetrievalRate,
|
|
111
|
+
negativeFeedbackCount: inputs.negativeFeedbackCount,
|
|
112
|
+
acceptedChangeCount: inputs.acceptedChangeCount,
|
|
113
|
+
outcomeScore,
|
|
114
|
+
updatedAt: now,
|
|
115
|
+
});
|
|
120
116
|
return { outcomeScore, isNewRow };
|
|
121
117
|
}
|
|
122
118
|
// ── Reader ────────────────────────────────────────────────────────────────────
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
.prepare(`SELECT asset_ref, last_retrieved_at, retrieval_count, expected_retrieval_rate,
|
|
129
|
-
negative_feedback_count, accepted_change_count,
|
|
130
|
-
outcome_score, updated_at
|
|
131
|
-
FROM asset_outcome WHERE asset_ref = ?`)
|
|
132
|
-
.get(ref);
|
|
133
|
-
return row == null ? undefined : row;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Load ALL asset_outcome rows. Used for the proxy-adequacy tripwire computation.
|
|
137
|
-
*/
|
|
138
|
-
export function getAllAssetOutcomes(db) {
|
|
139
|
-
return db
|
|
140
|
-
.prepare(`SELECT asset_ref, last_retrieved_at, retrieval_count, expected_retrieval_rate,
|
|
141
|
-
negative_feedback_count, accepted_change_count,
|
|
142
|
-
outcome_score, updated_at
|
|
143
|
-
FROM asset_outcome ORDER BY asset_ref`)
|
|
144
|
-
.all();
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Build a Map<ref, outcome_score> for a set of refs in one query.
|
|
148
|
-
* Used by `salience.ts` to populate `outcomeSalience`.
|
|
149
|
-
*/
|
|
150
|
-
export function getOutcomeScoresByRef(db, refs) {
|
|
151
|
-
const result = new Map();
|
|
152
|
-
if (refs.length === 0)
|
|
153
|
-
return result;
|
|
154
|
-
const CHUNK = 500;
|
|
155
|
-
for (let i = 0; i < refs.length; i += CHUNK) {
|
|
156
|
-
const chunk = refs.slice(i, i + CHUNK);
|
|
157
|
-
const placeholders = chunk.map(() => "?").join(",");
|
|
158
|
-
const rows = db
|
|
159
|
-
.prepare(`SELECT asset_ref, outcome_score FROM asset_outcome WHERE asset_ref IN (${placeholders})`)
|
|
160
|
-
.all(...chunk);
|
|
161
|
-
for (const row of rows) {
|
|
162
|
-
result.set(row.asset_ref, row.outcome_score);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return result;
|
|
166
|
-
}
|
|
119
|
+
//
|
|
120
|
+
// getAssetOutcome / getAllAssetOutcomes / getOutcomeScoresByRef moved verbatim
|
|
121
|
+
// to storage/repositories/outcome-repository.ts (#672 part 2) — re-exported
|
|
122
|
+
// here so existing importers of this module resolve unchanged.
|
|
123
|
+
export { getAllAssetOutcomes, getAssetOutcome, getOutcomeScoresByRef };
|
|
167
124
|
// ── outcomeSalience projection ────────────────────────────────────────────────
|
|
168
125
|
/**
|
|
169
126
|
* Convert a raw `outcome_score` (differential, may be negative) to a
|