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
|
@@ -1,6 +1,17 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Repository for the state.db `proposals` table. Extracted verbatim from
|
|
6
|
+
* core/state-db.ts — queries and row-mapping unchanged, only relocated behind
|
|
7
|
+
* the repository boundary. Re-exported by core/state-db.ts so existing importers
|
|
8
|
+
* resolve.
|
|
9
|
+
*
|
|
10
|
+
* @module proposals-repository
|
|
11
|
+
*/
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import { stashDirFor } from "../../core/asset/asset-placement.js";
|
|
14
|
+
import { bundleRefToString, isBundleSlug, parseBundleRef } from "../../core/asset/asset-ref.js";
|
|
4
15
|
/** Serialize `Proposal.changes` for `metadata_json` (see {@link StoredFileChange}). */
|
|
5
16
|
function changesToStored(changes) {
|
|
6
17
|
return changes.map((c, i) => ({
|
|
@@ -11,42 +22,277 @@ function changesToStored(changes) {
|
|
|
11
22
|
}
|
|
12
23
|
/**
|
|
13
24
|
* Reconstruct `Proposal.changes` from `metadata_json.changes` + the `content`
|
|
14
|
-
* column.
|
|
15
|
-
* `update` entry with an empty `path` sentinel (resolve from the ref instead).
|
|
25
|
+
* column.
|
|
16
26
|
*/
|
|
17
27
|
function storedToChanges(stored, content) {
|
|
18
28
|
if (!Array.isArray(stored) || stored.length === 0) {
|
|
19
|
-
|
|
29
|
+
throw new Error("Proposal metadata is missing changes.");
|
|
30
|
+
}
|
|
31
|
+
return stored.map((value, i) => {
|
|
32
|
+
if (typeof value !== "object" || value === null)
|
|
33
|
+
throw new Error("Proposal metadata has invalid changes.");
|
|
34
|
+
const c = value;
|
|
35
|
+
if (typeof c.path !== "string" ||
|
|
36
|
+
(c.op !== "create" && c.op !== "update" && c.op !== "delete") ||
|
|
37
|
+
(c.after !== undefined && typeof c.after !== "string") ||
|
|
38
|
+
(c.op === "delete" && c.after !== undefined) ||
|
|
39
|
+
(i > 0 && c.op !== "delete" && typeof c.after !== "string")) {
|
|
40
|
+
throw new Error("Proposal metadata has invalid changes.");
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
path: c.path,
|
|
44
|
+
op: c.op,
|
|
45
|
+
...(i === 0 ? (c.op === "delete" ? {} : { after: content }) : c.after !== undefined ? { after: c.after } : {}),
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function currentProposalRef(ref, requireQualified = false) {
|
|
50
|
+
let parsed;
|
|
51
|
+
try {
|
|
52
|
+
parsed = parseBundleRef(ref);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw new Error(`Proposal row has an invalid current ref: ${ref}`, { cause: error });
|
|
56
|
+
}
|
|
57
|
+
const colon = parsed.conceptId.indexOf(":");
|
|
58
|
+
if (colon > 0 && stashDirFor(parsed.conceptId.slice(0, colon)) !== undefined) {
|
|
59
|
+
throw new Error(`Proposal row has an invalid current ref: ${ref}`);
|
|
60
|
+
}
|
|
61
|
+
if (parsed.fragment !== undefined)
|
|
62
|
+
throw new Error(`Proposal row ref contains a fragment: ${ref}`);
|
|
63
|
+
if (requireQualified && parsed.bundle === undefined)
|
|
64
|
+
throw new Error(`Proposal ref is not bundle-qualified: ${ref}`);
|
|
65
|
+
const canonical = bundleRefToString(parsed);
|
|
66
|
+
if (canonical !== ref)
|
|
67
|
+
throw new Error(`Proposal row ref is not canonical: ${ref}`);
|
|
68
|
+
return canonical;
|
|
69
|
+
}
|
|
70
|
+
function currentProposalTarget(value) {
|
|
71
|
+
if (typeof value !== "object" || value === null)
|
|
72
|
+
throw new Error("Proposal metadata is missing proposedTarget.");
|
|
73
|
+
const target = value;
|
|
74
|
+
if (typeof target.source !== "string" ||
|
|
75
|
+
!isBundleSlug(target.source) ||
|
|
76
|
+
typeof target.root !== "string" ||
|
|
77
|
+
!path.isAbsolute(target.root)) {
|
|
78
|
+
throw new Error("Proposal metadata has an invalid proposedTarget.");
|
|
79
|
+
}
|
|
80
|
+
return { source: target.source, root: path.resolve(target.root) };
|
|
81
|
+
}
|
|
82
|
+
function invalidPresentField(name) {
|
|
83
|
+
throw new Error(`Proposal metadata has an invalid ${name}.`);
|
|
84
|
+
}
|
|
85
|
+
const GATE_OUTCOMES = {
|
|
86
|
+
"auto-accepted": true,
|
|
87
|
+
deferred: true,
|
|
88
|
+
staged: true,
|
|
89
|
+
"auto-rejected": true,
|
|
90
|
+
};
|
|
91
|
+
function validatePresentMetadata(meta) {
|
|
92
|
+
const stringFields = ["sourceRun", "beforeHash", "backupContent"];
|
|
93
|
+
for (const field of stringFields) {
|
|
94
|
+
if (Object.hasOwn(meta, field) && typeof meta[field] !== "string")
|
|
95
|
+
invalidPresentField(field);
|
|
96
|
+
}
|
|
97
|
+
if (Object.hasOwn(meta, "confidence") &&
|
|
98
|
+
(typeof meta.confidence !== "number" ||
|
|
99
|
+
!Number.isFinite(meta.confidence) ||
|
|
100
|
+
meta.confidence < 0 ||
|
|
101
|
+
meta.confidence > 1)) {
|
|
102
|
+
invalidPresentField("confidence");
|
|
103
|
+
}
|
|
104
|
+
if (Object.hasOwn(meta, "review")) {
|
|
105
|
+
const review = meta.review;
|
|
106
|
+
if (typeof review !== "object" ||
|
|
107
|
+
review === null ||
|
|
108
|
+
(review.outcome !== "accepted" && review.outcome !== "rejected") ||
|
|
109
|
+
typeof review.decidedAt !== "string" ||
|
|
110
|
+
(review.reason !== undefined && typeof review.reason !== "string")) {
|
|
111
|
+
invalidPresentField("review");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (Object.hasOwn(meta, "gateDecision")) {
|
|
115
|
+
const gate = meta.gateDecision;
|
|
116
|
+
if (typeof gate !== "object" ||
|
|
117
|
+
gate === null ||
|
|
118
|
+
typeof gate.outcome !== "string" ||
|
|
119
|
+
!Object.hasOwn(GATE_OUTCOMES, gate.outcome) ||
|
|
120
|
+
typeof gate.reason !== "string" ||
|
|
121
|
+
typeof gate.decidedAt !== "string" ||
|
|
122
|
+
(gate.measured !== undefined && (typeof gate.measured !== "number" || !Number.isFinite(gate.measured))) ||
|
|
123
|
+
(gate.contentHash !== undefined && typeof gate.contentHash !== "string") ||
|
|
124
|
+
(gate.gate !== undefined && typeof gate.gate !== "string")) {
|
|
125
|
+
invalidPresentField("gateDecision");
|
|
126
|
+
}
|
|
127
|
+
if (gate.thresholds !== undefined) {
|
|
128
|
+
const thresholds = gate.thresholds;
|
|
129
|
+
if (typeof thresholds !== "object" ||
|
|
130
|
+
thresholds === null ||
|
|
131
|
+
[thresholds.maxDiffLines, thresholds.minContentLines].some((value) => value !== undefined && (typeof value !== "number" || !Number.isFinite(value)))) {
|
|
132
|
+
invalidPresentField("gateDecision");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (Object.hasOwn(meta, "acceptedTarget")) {
|
|
137
|
+
const target = meta.acceptedTarget;
|
|
138
|
+
if (typeof target !== "object" ||
|
|
139
|
+
target === null ||
|
|
140
|
+
typeof target.source !== "string" ||
|
|
141
|
+
!isBundleSlug(target.source) ||
|
|
142
|
+
typeof target.root !== "string" ||
|
|
143
|
+
!path.isAbsolute(target.root) ||
|
|
144
|
+
typeof target.path !== "string" ||
|
|
145
|
+
!path.isAbsolute(target.path) ||
|
|
146
|
+
typeof target.contentHash !== "string") {
|
|
147
|
+
invalidPresentField("acceptedTarget");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (Object.hasOwn(meta, "eligibilitySource") && typeof meta.eligibilitySource !== "string") {
|
|
151
|
+
invalidPresentField("eligibilitySource");
|
|
20
152
|
}
|
|
21
|
-
return stored.map((c, i) => ({
|
|
22
|
-
path: typeof c.path === "string" ? c.path : "",
|
|
23
|
-
op: c.op === "create" || c.op === "delete" ? c.op : "update",
|
|
24
|
-
...(i === 0 ? (c.op === "delete" ? {} : { after: content }) : c.after !== undefined ? { after: c.after } : {}),
|
|
25
|
-
}));
|
|
26
153
|
}
|
|
27
154
|
/**
|
|
28
155
|
* Convert a raw `ProposalRow` to the public `Proposal` shape.
|
|
29
156
|
*/
|
|
30
157
|
export function proposalRowToProposal(row) {
|
|
158
|
+
if (!["pending", "accepted", "rejected", "reverted"].includes(row.status)) {
|
|
159
|
+
throw new Error(`Proposal row has invalid status: ${row.status}`);
|
|
160
|
+
}
|
|
31
161
|
let frontmatter;
|
|
32
|
-
if (row.frontmatter_json) {
|
|
162
|
+
if (row.frontmatter_json !== null) {
|
|
33
163
|
try {
|
|
34
|
-
|
|
164
|
+
const parsed = JSON.parse(row.frontmatter_json);
|
|
165
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
166
|
+
throw new Error("Proposal frontmatter_json must contain an object.");
|
|
167
|
+
}
|
|
168
|
+
frontmatter = parsed;
|
|
35
169
|
}
|
|
36
|
-
catch {
|
|
37
|
-
|
|
170
|
+
catch (error) {
|
|
171
|
+
throw new Error("Proposal row has invalid frontmatter_json.", { cause: error });
|
|
38
172
|
}
|
|
39
173
|
}
|
|
40
174
|
let meta = {};
|
|
41
175
|
try {
|
|
42
|
-
|
|
176
|
+
const parsed = JSON.parse(row.metadata_json);
|
|
177
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
178
|
+
throw new Error("Proposal metadata_json must contain an object.");
|
|
179
|
+
}
|
|
180
|
+
meta = parsed;
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
throw new Error("Proposal row has invalid metadata_json.", { cause: error });
|
|
184
|
+
}
|
|
185
|
+
validatePresentMetadata(meta);
|
|
186
|
+
const changes = Object.hasOwn(meta, "changes")
|
|
187
|
+
? storedToChanges(meta.changes, row.content)
|
|
188
|
+
: [{ path: "", op: "update", after: row.content }];
|
|
189
|
+
const proposedTarget = Object.hasOwn(meta, "proposedTarget") ? currentProposalTarget(meta.proposedTarget) : undefined;
|
|
190
|
+
return {
|
|
191
|
+
id: row.id,
|
|
192
|
+
ref: currentProposalRef(row.ref),
|
|
193
|
+
status: row.status,
|
|
194
|
+
source: row.source,
|
|
195
|
+
...(typeof meta.sourceRun === "string" ? { sourceRun: meta.sourceRun } : {}),
|
|
196
|
+
createdAt: row.created_at,
|
|
197
|
+
updatedAt: row.updated_at,
|
|
198
|
+
payload: {
|
|
199
|
+
content: row.content,
|
|
200
|
+
...(frontmatter !== undefined ? { frontmatter } : {}),
|
|
201
|
+
},
|
|
202
|
+
changes,
|
|
203
|
+
...(proposedTarget !== undefined ? { proposedTarget } : {}),
|
|
204
|
+
...(typeof meta.beforeHash === "string" ? { beforeHash: meta.beforeHash } : {}),
|
|
205
|
+
...(meta.review !== undefined ? { review: meta.review } : {}),
|
|
206
|
+
...(typeof meta.confidence === "number" ? { confidence: meta.confidence } : {}),
|
|
207
|
+
...(meta.gateDecision !== undefined ? { gateDecision: meta.gateDecision } : {}),
|
|
208
|
+
...(typeof meta.backupContent === "string" ? { backupContent: meta.backupContent } : {}),
|
|
209
|
+
...(meta.acceptedTarget !== undefined ? { acceptedTarget: meta.acceptedTarget } : {}),
|
|
210
|
+
...(typeof meta.eligibilitySource === "string"
|
|
211
|
+
? { eligibilitySource: meta.eligibilitySource }
|
|
212
|
+
: {}),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Lenient counterpart to {@link proposalRowToProposal} for the terminal-status
|
|
217
|
+
* (reject/archive) read paths (repository.ts `archiveProposal` /
|
|
218
|
+
* `rejectProposalDurably`). Those paths must succeed even on legacy rows
|
|
219
|
+
* minted before a field was required — e.g. 0.8-era rows missing
|
|
220
|
+
* `proposedTarget` and/or carrying empty/missing `changes[].path` metadata —
|
|
221
|
+
* so an operator can reject them instead of resorting to manual SQL.
|
|
222
|
+
*
|
|
223
|
+
* Per-field decode failures are swallowed: the offending field degrades to a
|
|
224
|
+
* safe placeholder (matching the strict decoder's own "no changes recorded"
|
|
225
|
+
* fallback) and the failure is appended to `decodeWarnings` instead of
|
|
226
|
+
* throwing. `id` / `status` / timestamps / `source` are trusted verbatim (the
|
|
227
|
+
* schema guarantees they're non-null strings). The strict decoder remains the
|
|
228
|
+
* default everywhere else, including every other read of a `pending` or
|
|
229
|
+
* `accepted` proposal (accept/revert must keep failing exactly as today on a
|
|
230
|
+
* malformed row).
|
|
231
|
+
*/
|
|
232
|
+
export function proposalRowToProposalLenient(row) {
|
|
233
|
+
const warnings = [];
|
|
234
|
+
let meta = {};
|
|
235
|
+
try {
|
|
236
|
+
const parsed = JSON.parse(row.metadata_json);
|
|
237
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
238
|
+
throw new Error("metadata_json must contain an object.");
|
|
239
|
+
}
|
|
240
|
+
meta = parsed;
|
|
241
|
+
validatePresentMetadata(meta);
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
warnings.push(`metadata_json is invalid (${error instanceof Error ? error.message : String(error)}); optional fields dropped.`);
|
|
245
|
+
meta = {};
|
|
246
|
+
}
|
|
247
|
+
let frontmatter;
|
|
248
|
+
if (row.frontmatter_json !== null) {
|
|
249
|
+
try {
|
|
250
|
+
const parsed = JSON.parse(row.frontmatter_json);
|
|
251
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
252
|
+
throw new Error("frontmatter_json must contain an object.");
|
|
253
|
+
}
|
|
254
|
+
frontmatter = parsed;
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
warnings.push(`frontmatter_json is invalid (${error instanceof Error ? error.message : String(error)}); frontmatter dropped.`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
let ref;
|
|
261
|
+
try {
|
|
262
|
+
ref = currentProposalRef(row.ref);
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
warnings.push(`ref is invalid (${error instanceof Error ? error.message : String(error)}); keeping the raw stored value.`);
|
|
266
|
+
ref = row.ref;
|
|
267
|
+
}
|
|
268
|
+
let changes;
|
|
269
|
+
try {
|
|
270
|
+
changes = Object.hasOwn(meta, "changes")
|
|
271
|
+
? storedToChanges(meta.changes, row.content)
|
|
272
|
+
: [{ path: "", op: "update", after: row.content }];
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
warnings.push(`changes metadata is invalid (${error instanceof Error ? error.message : String(error)}); degraded to a single placeholder change.`);
|
|
276
|
+
changes = [{ path: "", op: "update", after: row.content }];
|
|
277
|
+
}
|
|
278
|
+
let proposedTarget;
|
|
279
|
+
if (Object.hasOwn(meta, "proposedTarget")) {
|
|
280
|
+
try {
|
|
281
|
+
proposedTarget = currentProposalTarget(meta.proposedTarget);
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
warnings.push(`proposedTarget is invalid (${error instanceof Error ? error.message : String(error)}); omitted.`);
|
|
285
|
+
}
|
|
43
286
|
}
|
|
44
|
-
|
|
45
|
-
|
|
287
|
+
else {
|
|
288
|
+
warnings.push("proposedTarget is missing (pre-WI-6.2 legacy row).");
|
|
289
|
+
}
|
|
290
|
+
if (!["pending", "accepted", "rejected", "reverted"].includes(row.status)) {
|
|
291
|
+
warnings.push(`status "${row.status}" is not a recognized value.`);
|
|
46
292
|
}
|
|
47
293
|
return {
|
|
48
294
|
id: row.id,
|
|
49
|
-
ref
|
|
295
|
+
ref,
|
|
50
296
|
status: row.status,
|
|
51
297
|
source: row.source,
|
|
52
298
|
...(typeof meta.sourceRun === "string" ? { sourceRun: meta.sourceRun } : {}),
|
|
@@ -56,19 +302,18 @@ export function proposalRowToProposal(row) {
|
|
|
56
302
|
content: row.content,
|
|
57
303
|
...(frontmatter !== undefined ? { frontmatter } : {}),
|
|
58
304
|
},
|
|
59
|
-
changes
|
|
305
|
+
changes,
|
|
306
|
+
...(proposedTarget !== undefined ? { proposedTarget } : {}),
|
|
60
307
|
...(typeof meta.beforeHash === "string" ? { beforeHash: meta.beforeHash } : {}),
|
|
61
308
|
...(meta.review !== undefined ? { review: meta.review } : {}),
|
|
62
309
|
...(typeof meta.confidence === "number" ? { confidence: meta.confidence } : {}),
|
|
63
310
|
...(meta.gateDecision !== undefined ? { gateDecision: meta.gateDecision } : {}),
|
|
64
311
|
...(typeof meta.backupContent === "string" ? { backupContent: meta.backupContent } : {}),
|
|
65
|
-
...(typeof meta.acceptedContentHash === "string" ? { acceptedContentHash: meta.acceptedContentHash } : {}),
|
|
66
312
|
...(meta.acceptedTarget !== undefined ? { acceptedTarget: meta.acceptedTarget } : {}),
|
|
67
|
-
...(meta.legacyAcceptedTargetDerived === true ? { legacyAcceptedTargetDerived: true } : {}),
|
|
68
|
-
...(meta.legacyAcceptedAssetWasAbsent === true ? { legacyAcceptedAssetWasAbsent: true } : {}),
|
|
69
313
|
...(typeof meta.eligibilitySource === "string"
|
|
70
314
|
? { eligibilitySource: meta.eligibilitySource }
|
|
71
315
|
: {}),
|
|
316
|
+
...(warnings.length > 0 ? { decodeWarnings: warnings } : {}),
|
|
72
317
|
};
|
|
73
318
|
}
|
|
74
319
|
/**
|
|
@@ -78,15 +323,17 @@ export function proposalRowToProposal(row) {
|
|
|
78
323
|
export function proposalToRowValues(proposal, stashDir) {
|
|
79
324
|
// Fields that have no dedicated column live in metadata_json.
|
|
80
325
|
const metaObj = {};
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
?
|
|
88
|
-
|
|
89
|
-
|
|
326
|
+
if (!Array.isArray(proposal.changes) || proposal.changes.length === 0) {
|
|
327
|
+
throw new Error(`Proposal ${proposal.id} has no file changes.`);
|
|
328
|
+
}
|
|
329
|
+
if (proposal.changes.some((change) => typeof change.path !== "string" ||
|
|
330
|
+
change.path.length === 0 ||
|
|
331
|
+
!["create", "update", "delete"].includes(change.op) ||
|
|
332
|
+
(change.op === "delete" ? change.after !== undefined : typeof change.after !== "string"))) {
|
|
333
|
+
throw new Error(`Proposal ${proposal.id} has invalid file changes.`);
|
|
334
|
+
}
|
|
335
|
+
metaObj.changes = changesToStored(proposal.changes);
|
|
336
|
+
metaObj.proposedTarget = currentProposalTarget(proposal.proposedTarget);
|
|
90
337
|
if (proposal.beforeHash !== undefined)
|
|
91
338
|
metaObj.beforeHash = proposal.beforeHash;
|
|
92
339
|
if (proposal.sourceRun !== undefined)
|
|
@@ -99,22 +346,15 @@ export function proposalToRowValues(proposal, stashDir) {
|
|
|
99
346
|
metaObj.gateDecision = proposal.gateDecision;
|
|
100
347
|
if (proposal.backupContent !== undefined)
|
|
101
348
|
metaObj.backupContent = proposal.backupContent;
|
|
102
|
-
if (proposal.acceptedContentHash !== undefined)
|
|
103
|
-
metaObj.acceptedContentHash = proposal.acceptedContentHash;
|
|
104
349
|
if (proposal.acceptedTarget !== undefined)
|
|
105
350
|
metaObj.acceptedTarget = proposal.acceptedTarget;
|
|
106
|
-
if (proposal.legacyAcceptedTargetDerived !== undefined) {
|
|
107
|
-
metaObj.legacyAcceptedTargetDerived = proposal.legacyAcceptedTargetDerived;
|
|
108
|
-
}
|
|
109
|
-
if (proposal.legacyAcceptedAssetWasAbsent !== undefined) {
|
|
110
|
-
metaObj.legacyAcceptedAssetWasAbsent = proposal.legacyAcceptedAssetWasAbsent;
|
|
111
|
-
}
|
|
112
351
|
if (proposal.eligibilitySource !== undefined)
|
|
113
352
|
metaObj.eligibilitySource = proposal.eligibilitySource;
|
|
353
|
+
validatePresentMetadata(metaObj);
|
|
114
354
|
return {
|
|
115
355
|
id: proposal.id,
|
|
116
356
|
stash_dir: stashDir,
|
|
117
|
-
ref: proposal.ref,
|
|
357
|
+
ref: currentProposalRef(proposal.ref, true),
|
|
118
358
|
status: proposal.status,
|
|
119
359
|
source: proposal.source,
|
|
120
360
|
created_at: proposal.createdAt,
|
|
@@ -173,7 +413,12 @@ export function listStateProposals(db, options = {}) {
|
|
|
173
413
|
content, frontmatter_json, metadata_json
|
|
174
414
|
FROM proposals ${where} ORDER BY created_at ASC, rowid ASC`)
|
|
175
415
|
.all(...params);
|
|
176
|
-
|
|
416
|
+
// Archived rows (accepted/rejected/reverted) decode leniently so a
|
|
417
|
+
// terminal-status row that was rejected via the lenient path (or predates
|
|
418
|
+
// a required field) remains listable — a strict throw here would defeat
|
|
419
|
+
// the point of tolerating it at reject/archive time. Pending rows keep the
|
|
420
|
+
// strict decoder; nothing about the live queue changes here.
|
|
421
|
+
return rows.map((row) => (row.status === "pending" ? proposalRowToProposal(row) : proposalRowToProposalLenient(row)));
|
|
177
422
|
}
|
|
178
423
|
/**
|
|
179
424
|
* Look up a single proposal by id, optionally scoped to one stash root.
|
|
@@ -186,6 +431,18 @@ export function getStateProposal(db, id, stashDir) {
|
|
|
186
431
|
const row = (stashDir ? db.prepare(sql).get(id, stashDir) : db.prepare(sql).get(id));
|
|
187
432
|
return row ? proposalRowToProposal(row) : undefined;
|
|
188
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* Lenient counterpart to {@link getStateProposal} — used ONLY by the
|
|
436
|
+
* terminal-status (reject/archive) read paths in repository.ts that must
|
|
437
|
+
* tolerate a malformed row (see {@link proposalRowToProposalLenient}).
|
|
438
|
+
*/
|
|
439
|
+
export function getStateProposalLenient(db, id, stashDir) {
|
|
440
|
+
const sql = `SELECT id, stash_dir, ref, status, source, created_at, updated_at,
|
|
441
|
+
content, frontmatter_json, metadata_json
|
|
442
|
+
FROM proposals WHERE id = ?${stashDir ? " AND stash_dir = ?" : ""}`;
|
|
443
|
+
const row = (stashDir ? db.prepare(sql).get(id, stashDir) : db.prepare(sql).get(id));
|
|
444
|
+
return row ? proposalRowToProposalLenient(row) : undefined;
|
|
445
|
+
}
|
|
189
446
|
/**
|
|
190
447
|
* Find PENDING proposal ids in one stash whose id starts with `idPrefix`.
|
|
191
448
|
* Backs the UUID-prefix form of `akm proposal show/accept/... <prefix>` —
|
|
@@ -203,23 +460,3 @@ export function listStateProposalIdsByPrefix(db, stashDir, idPrefix) {
|
|
|
203
460
|
.all(stashDir, `${escaped}%`);
|
|
204
461
|
return rows.map((r) => r.id);
|
|
205
462
|
}
|
|
206
|
-
/**
|
|
207
|
-
* Insert a proposal row ONLY when the id is not already present (used by the
|
|
208
|
-
* one-time legacy filesystem import in the migrator —
|
|
209
|
-
* `src/migrate/legacy/proposal-fs-import.ts` — so a re-run never clobbers rows
|
|
210
|
-
* that have since been mutated through the canonical store, and re-walking the
|
|
211
|
-
* still-on-disk legacy files is idempotent). Returns true when a row was
|
|
212
|
-
* inserted.
|
|
213
|
-
*/
|
|
214
|
-
export function insertProposalIfAbsent(db, proposal, stashDir) {
|
|
215
|
-
const v = proposalToRowValues(proposal, stashDir);
|
|
216
|
-
const result = db
|
|
217
|
-
.prepare(`
|
|
218
|
-
INSERT OR IGNORE INTO proposals
|
|
219
|
-
(id, stash_dir, ref, status, source, created_at, updated_at, content, frontmatter_json, metadata_json)
|
|
220
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
221
|
-
`)
|
|
222
|
-
.run(v.id, v.stash_dir, v.ref, v.status, v.source, v.created_at, v.updated_at, v.content, v.frontmatter_json, v.metadata_json);
|
|
223
|
-
const changes = result.changes ?? 0;
|
|
224
|
-
return Number(changes) > 0;
|
|
225
|
-
}
|
|
@@ -2,6 +2,7 @@
|
|
|
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
|
import { rethrowIfTestIsolationError } from "../../core/errors.js";
|
|
5
|
+
import { warn } from "../../core/warn.js";
|
|
5
6
|
import { closeDatabase, openIndexDatabase } from "./index-connection.js";
|
|
6
7
|
import { getRegistryIndexCache, upsertRegistryIndexCache } from "./registry-index-cache-repository.js";
|
|
7
8
|
/**
|
|
@@ -87,6 +88,24 @@ export async function fetchCachedJson(opts) {
|
|
|
87
88
|
if (stale !== undefined)
|
|
88
89
|
return stale;
|
|
89
90
|
}
|
|
91
|
+
// No in-TTL row — consult the cache PAST its TTL before giving up
|
|
92
|
+
// (§24.2 "Durability" gate): a briefly unreachable registry should
|
|
93
|
+
// degrade to the last-known index, loudly, not hard-fail the command.
|
|
94
|
+
try {
|
|
95
|
+
const expiredRow = db ? getRegistryIndexCache(db, cacheKey, Number.POSITIVE_INFINITY) : undefined;
|
|
96
|
+
if (expiredRow) {
|
|
97
|
+
const stale = parseCache(expiredRow.indexJson, { stale: true });
|
|
98
|
+
if (stale !== undefined) {
|
|
99
|
+
warn(`Registry fetch failed (${err instanceof Error ? err.message : String(err)}); ` +
|
|
100
|
+
"serving the last cached index, which is past its refresh interval.");
|
|
101
|
+
return stale;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (cacheErr) {
|
|
106
|
+
rethrowIfTestIsolationError(cacheErr);
|
|
107
|
+
// cache read failed — fall through to the original fetch error
|
|
108
|
+
}
|
|
90
109
|
throw err;
|
|
91
110
|
}
|
|
92
111
|
});
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Upsert salience scores for one asset into state.db.
|
|
6
|
+
*
|
|
7
|
+
* Idempotent: safe to call every run; updates the outcome / retrieval / rank
|
|
8
|
+
* columns on conflict.
|
|
9
|
+
*
|
|
10
|
+
* #644 — encoding provenance guard: the `encoding_salience` + `encoding_source`
|
|
11
|
+
* columns are NOT lowered from a real content-derived score to a type-weight
|
|
12
|
+
* stub. When the stored row is `encoding_source = 'content'` and the incoming
|
|
13
|
+
* vector is a `type-stub` fallback, the stored encoding score and its provenance
|
|
14
|
+
* are preserved (only the other sub-scores and `rank_score` advance). A `content`
|
|
15
|
+
* write always wins; a `type-stub` write only seeds a row that has no content
|
|
16
|
+
* score yet. This stops the improve loop's type-weight fallback re-asserting the
|
|
17
|
+
* stub over a distill-written score on every run.
|
|
18
|
+
*
|
|
19
|
+
* NOTE: when the guard preserves the stored encoding score, the incoming
|
|
20
|
+
* `vector.rankScore` (computed from the stub encoding) is still written. Callers
|
|
21
|
+
* that want the rank_score to reflect the preserved content score should pass the
|
|
22
|
+
* stored content score back in as `inputs.encodingSalience` to `computeSalience`
|
|
23
|
+
* — which the improve loop does. The guard here is the defensive backstop.
|
|
24
|
+
*/
|
|
25
|
+
export function upsertAssetSalience(db, ref, vector, now) {
|
|
26
|
+
const ts = now ?? Date.now();
|
|
27
|
+
db.prepare(`INSERT INTO asset_salience
|
|
28
|
+
(asset_ref, encoding_salience, outcome_salience, retrieval_salience, rank_score, consecutive_no_ops, updated_at, encoding_source)
|
|
29
|
+
VALUES (?, ?, ?, ?, ?, 0, ?, ?)
|
|
30
|
+
ON CONFLICT(asset_ref) DO UPDATE SET
|
|
31
|
+
-- #644: never lower a real content-derived score to a type-weight stub.
|
|
32
|
+
-- Keep the stored encoding score + provenance when the stored row is
|
|
33
|
+
-- 'content' and the incoming write is a 'type-stub' fallback.
|
|
34
|
+
encoding_salience = CASE
|
|
35
|
+
WHEN asset_salience.encoding_source = 'content' AND excluded.encoding_source = 'type-stub'
|
|
36
|
+
THEN asset_salience.encoding_salience
|
|
37
|
+
ELSE excluded.encoding_salience
|
|
38
|
+
END,
|
|
39
|
+
encoding_source = CASE
|
|
40
|
+
WHEN asset_salience.encoding_source = 'content' AND excluded.encoding_source = 'type-stub'
|
|
41
|
+
THEN asset_salience.encoding_source
|
|
42
|
+
ELSE excluded.encoding_source
|
|
43
|
+
END,
|
|
44
|
+
outcome_salience = excluded.outcome_salience,
|
|
45
|
+
retrieval_salience = excluded.retrieval_salience,
|
|
46
|
+
rank_score = excluded.rank_score,
|
|
47
|
+
updated_at = excluded.updated_at`).run(ref, vector.encoding, vector.outcome, vector.retrieval, vector.rankScore, ts, vector.encodingSource ?? "type-stub");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Load the salience row for one asset, or undefined if not yet computed.
|
|
51
|
+
*/
|
|
52
|
+
export function getAssetSalience(db, ref) {
|
|
53
|
+
const row = db
|
|
54
|
+
.prepare(`SELECT asset_ref, encoding_salience, outcome_salience, retrieval_salience,
|
|
55
|
+
rank_score, consecutive_no_ops, updated_at, encoding_source
|
|
56
|
+
FROM asset_salience WHERE asset_ref = ?`)
|
|
57
|
+
.get(ref);
|
|
58
|
+
// Bun SQLite returns null (not undefined) when no row found.
|
|
59
|
+
return row == null ? undefined : row;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Load ALL rank scores from the asset_salience table (full-stash query).
|
|
63
|
+
*
|
|
64
|
+
* Used by the forgetting-safety report (plan §WS-1 step 7) to compute stash-wide
|
|
65
|
+
* rank positions rather than pool-relative positions. Returns an empty Map when the
|
|
66
|
+
* table is empty (first WS-1 run = no pre-existing rows).
|
|
67
|
+
*
|
|
68
|
+
* Order is unspecified; callers must sort before assigning 1-indexed positions.
|
|
69
|
+
*/
|
|
70
|
+
export function getAllRankScores(db) {
|
|
71
|
+
const rows = db.prepare("SELECT asset_ref, rank_score FROM asset_salience").all();
|
|
72
|
+
const result = new Map();
|
|
73
|
+
for (const row of rows) {
|
|
74
|
+
result.set(row.asset_ref, row.rank_score);
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
// ── Plasticity helpers ────────────────────────────────────────────────────────
|
|
79
|
+
/**
|
|
80
|
+
* Increment `consecutive_no_ops` for an asset. Called after a no-op reflect/distill.
|
|
81
|
+
* Has NO effect on `rank_score` — the plasticity counter only dampens consolidation
|
|
82
|
+
* selection, not retrieval ranking. See plan §WS-1 step 8.
|
|
83
|
+
*
|
|
84
|
+
* Invariant: recordNoOp must never originate rank_score semantics. If the asset has
|
|
85
|
+
* no salience row yet (persistence's best-effort try/catch may have swallowed an
|
|
86
|
+
* error), we do nothing — a no-op counter is meaningless without a rank_score row,
|
|
87
|
+
* and a synthetic INSERT would fabricate a rank_score=0 entry that could produce
|
|
88
|
+
* false catastrophic-forgetting signals in buildRankChangeReport.
|
|
89
|
+
*/
|
|
90
|
+
export function recordNoOp(db, ref) {
|
|
91
|
+
db.prepare(`UPDATE asset_salience SET consecutive_no_ops = consecutive_no_ops + 1, updated_at = ? WHERE asset_ref = ?`).run(Date.now(), ref);
|
|
92
|
+
// If changes === 0 the asset has no salience row yet — leave the table unchanged.
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Reset `consecutive_no_ops` to 0 when an asset produces an accepted change.
|
|
96
|
+
* Call after a successful proposal acceptance or detected mutation.
|
|
97
|
+
*/
|
|
98
|
+
export function resetConsecutiveNoOps(db, ref) {
|
|
99
|
+
db.prepare(`UPDATE asset_salience SET consecutive_no_ops = 0, updated_at = ? WHERE asset_ref = ?`).run(Date.now(), ref);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Return the `consecutive_no_ops` count for one asset. 0 when unknown.
|
|
103
|
+
*/
|
|
104
|
+
export function getConsecutiveNoOps(db, ref) {
|
|
105
|
+
const row = db.prepare(`SELECT consecutive_no_ops FROM asset_salience WHERE asset_ref = ?`).get(ref);
|
|
106
|
+
return row?.consecutive_no_ops ?? 0;
|
|
107
|
+
}
|
|
108
|
+
// ── New in #672 part 2 ────────────────────────────────────────────────────────
|
|
109
|
+
/**
|
|
110
|
+
* Load the `retrieval_salience` column for the top `limit` assets ordered by
|
|
111
|
+
* `rank_score` descending.
|
|
112
|
+
*
|
|
113
|
+
* Absorbs the health read formerly inlined in `commands/health/metrics.ts`
|
|
114
|
+
* (`computeDegradationMetrics`'s corpus-diversity Gini calculation) — same
|
|
115
|
+
* query, now parameterised on `limit` instead of a hardcoded 100. This is new
|
|
116
|
+
* behavior (a named, parameterised repository entry point), not a verbatim
|
|
117
|
+
* move; callers that need fail-open behaviour on a missing table (pre-WS-1
|
|
118
|
+
* installs) must wrap the call in their own try/catch, matching the existing
|
|
119
|
+
* call site.
|
|
120
|
+
*/
|
|
121
|
+
export function getTopRetrievalSalience(db, limit) {
|
|
122
|
+
return db
|
|
123
|
+
.prepare(`SELECT retrieval_salience FROM asset_salience ORDER BY rank_score DESC LIMIT ?`)
|
|
124
|
+
.all(limit);
|
|
125
|
+
}
|
|
126
|
+
/** List every `asset_salience` ref with its current `missing_since` marker. */
|
|
127
|
+
export function listAssetSalienceMissingState(db) {
|
|
128
|
+
return db.prepare(`SELECT asset_ref, missing_since FROM asset_salience`).all();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Stamp `missing_since = now` for the given refs, but ONLY where it is
|
|
132
|
+
* currently NULL — a ref already stamped keeps its original timestamp so the
|
|
133
|
+
* grace window measures from first sighting, not last. Refs with no row at
|
|
134
|
+
* all are silently skipped (0 rows affected). Returns the number of rows
|
|
135
|
+
* actually stamped.
|
|
136
|
+
*/
|
|
137
|
+
export function stampAssetSalienceMissing(db, refs, now) {
|
|
138
|
+
if (refs.length === 0)
|
|
139
|
+
return 0;
|
|
140
|
+
const stmt = db.prepare(`UPDATE asset_salience SET missing_since = ? WHERE asset_ref = ? AND missing_since IS NULL`);
|
|
141
|
+
let changed = 0;
|
|
142
|
+
for (const ref of refs)
|
|
143
|
+
changed += Number(stmt.run(now, ref).changes);
|
|
144
|
+
return changed;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Clear `missing_since` for refs that resolved again. Returns the number of
|
|
148
|
+
* rows actually cleared.
|
|
149
|
+
*/
|
|
150
|
+
export function clearAssetSalienceMissing(db, refs) {
|
|
151
|
+
if (refs.length === 0)
|
|
152
|
+
return 0;
|
|
153
|
+
const stmt = db.prepare(`UPDATE asset_salience SET missing_since = NULL WHERE asset_ref = ? AND missing_since IS NOT NULL`);
|
|
154
|
+
let changed = 0;
|
|
155
|
+
for (const ref of refs)
|
|
156
|
+
changed += Number(stmt.run(ref).changes);
|
|
157
|
+
return changed;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Delete `asset_salience` rows whose `missing_since` is older than
|
|
161
|
+
* `cutoffMs`. A single DELETE — SQLite runs it as one implicit transaction.
|
|
162
|
+
* Returns the number of rows deleted.
|
|
163
|
+
*/
|
|
164
|
+
export function deleteAssetSalienceMissingBefore(db, cutoffMs) {
|
|
165
|
+
return Number(db.prepare(`DELETE FROM asset_salience WHERE missing_since IS NOT NULL AND missing_since < ?`).run(cutoffMs)
|
|
166
|
+
.changes);
|
|
167
|
+
}
|
|
168
|
+
/** Count `asset_salience` rows currently marked missing (the live backlog size). */
|
|
169
|
+
export function countAssetSalienceMissing(db) {
|
|
170
|
+
const row = db.prepare(`SELECT COUNT(*) AS n FROM asset_salience WHERE missing_since IS NOT NULL`).get();
|
|
171
|
+
return row.n;
|
|
172
|
+
}
|