akm-cli 0.9.0-rc.0 → 0.9.0-rc.13
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 +1283 -22
- package/README.md +62 -37
- package/SECURITY.md +46 -31
- package/dist/akm +162 -38
- package/dist/akm-migrate +44 -0
- package/dist/assets/backends/schtasks-template.xml +2 -1
- package/dist/assets/hints/cli-hints-full.md +268 -118
- package/dist/assets/hints/cli-hints-short.md +87 -24
- package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
- package/dist/assets/improve-strategies/frequent.json +15 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
- package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
- package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
- package/dist/assets/improve-strategies/reflect-distill.json +30 -0
- package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +5 -5
- package/dist/assets/prompts/extract-session.md +2 -6
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
- package/dist/assets/prompts/reflect-output-repair.md +3 -0
- package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
- package/dist/assets/stash-skeleton/README.md +38 -10
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
- package/dist/assets/tasks/core/extract.yml +3 -2
- package/dist/assets/tasks/core/improve.yml +2 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +2 -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 +5 -4
- package/dist/assets/workflows/workflow-template.md +31 -15
- package/dist/cli/invocation.js +279 -0
- package/dist/cli/parse-args.js +5 -90
- package/dist/cli/retired-commands.js +78 -0
- package/dist/cli/shared.js +158 -48
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +747 -293
- package/dist/commands/agent/agent-dispatch.js +19 -18
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +43 -97
- package/dist/commands/completions.js +80 -23
- package/dist/commands/config-cli.js +44 -281
- package/dist/commands/env/env-binding.js +99 -0
- package/dist/commands/env/env-cli.js +84 -224
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +45 -61
- package/dist/commands/env/secret.js +32 -62
- package/dist/commands/feedback-cli.js +179 -85
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +7 -8
- package/dist/commands/health/checks.js +279 -94
- package/dist/commands/health/html-report.js +197 -578
- package/dist/commands/health/improve-metrics.js +277 -246
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +16 -7
- package/dist/commands/health/metrics.js +67 -32
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +508 -0
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +16 -56
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
- package/dist/commands/health/types-improve.js +29 -0
- package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
- package/dist/commands/health/types-result.js +7 -0
- package/dist/commands/health/types-runs.js +4 -0
- package/dist/commands/health/types-session-log.js +4 -0
- package/dist/commands/health/types-windows.js +4 -0
- package/dist/commands/health/types.js +26 -21
- package/dist/commands/health/windows.js +2 -3
- package/dist/commands/health.js +296 -167
- package/dist/commands/improve/anti-collapse.js +5 -5
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +65 -52
- package/dist/commands/improve/consolidate/chunking.js +9 -7
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +454 -1354
- package/dist/commands/improve/content-hash.js +39 -0
- package/dist/commands/improve/distill/content-repair.js +4 -10
- package/dist/commands/improve/distill/promote-memory.js +89 -64
- package/dist/commands/improve/distill/quality-gate.js +118 -42
- package/dist/commands/improve/distill-guards.js +1 -1
- package/dist/commands/improve/distill-promotion-policy.js +33 -888
- package/dist/commands/improve/distill.js +607 -363
- package/dist/commands/improve/eligibility.js +165 -79
- package/dist/commands/improve/extract-cli.js +35 -126
- package/dist/commands/improve/extract-prompt.js +6 -35
- package/dist/commands/improve/extract.js +640 -391
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +134 -135
- package/dist/commands/improve/improve-result-file.js +30 -50
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +135 -0
- package/dist/commands/improve/improve.js +904 -701
- package/dist/commands/improve/locks.js +64 -111
- package/dist/commands/improve/loop-stages.js +1110 -923
- package/dist/commands/improve/memory/derived-ref.js +124 -0
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
- package/dist/commands/improve/memory/memory-improve.js +25 -37
- package/dist/commands/improve/outcome-loop.js +25 -88
- package/dist/commands/improve/preparation.js +1034 -813
- package/dist/commands/improve/proactive-maintenance.js +34 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +983 -794
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +24 -127
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -34
- package/dist/commands/improve/source-identity.js +28 -0
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +340 -313
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +185 -30
- package/dist/commands/{events.js → log.js} +28 -38
- package/dist/commands/migrate-cli.js +54 -0
- package/dist/commands/migration-tool.js +55 -0
- package/dist/commands/observability-cli.js +70 -208
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +91 -40
- package/dist/commands/proposal/proposal-cli.js +134 -132
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +83 -65
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +105 -88
- package/dist/commands/proposal/repository.js +1303 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
- package/dist/commands/proposal/validators/proposal-validators.js +61 -12
- package/dist/commands/proposal/validators/proposals.js +6 -8
- package/dist/commands/read/curate.js +78 -73
- package/dist/commands/read/knowledge.js +510 -13
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +84 -15
- package/dist/commands/read/search-cli.js +203 -96
- package/dist/commands/read/search.js +126 -94
- package/dist/commands/read/show.js +226 -250
- package/dist/commands/registry-cli.js +34 -60
- package/dist/commands/remember.js +18 -57
- package/dist/commands/sources/add-cli.js +104 -49
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +63 -0
- package/dist/commands/sources/info.js +27 -15
- package/dist/commands/sources/init.js +30 -40
- package/dist/commands/sources/installed-stashes.js +469 -172
- package/dist/commands/sources/migration-help.js +7 -4
- package/dist/commands/sources/schema-repair.js +10 -9
- package/dist/commands/sources/self-update.js +182 -121
- package/dist/commands/sources/source-add.js +169 -178
- package/dist/commands/sources/source-clone.js +144 -41
- package/dist/commands/sources/source-manage.js +94 -59
- package/dist/commands/sources/sources-cli.js +64 -205
- package/dist/commands/sources/stash-cli.js +91 -54
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +106 -104
- package/dist/commands/tasks/tasks.js +445 -262
- package/dist/commands/workflow-cli.js +232 -121
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/activation-policy.js +49 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
- package/dist/core/adapter/adapters/akm-adapter.js +528 -0
- package/dist/core/adapter/adapters/akm-lint.js +392 -0
- package/dist/core/adapter/adapters/akm-metadata.js +387 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
- package/dist/core/adapter/adapters/claude-adapter.js +61 -0
- package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
- package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
- package/dist/core/adapter/adapters/okf-adapter.js +391 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
- package/dist/core/adapter/adapters/shared.js +286 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +44 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/akm-markdown.js +30 -0
- package/dist/core/asset/asset-placement.js +243 -0
- package/dist/core/asset/asset-ref.js +110 -79
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +28 -12
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +274 -0
- package/dist/core/asset/stash-meta.js +2 -2
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +281 -86
- package/dist/core/config/config-io.js +42 -128
- package/dist/core/config/config-schema.js +233 -834
- package/dist/core/config/config-sources.js +162 -39
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +126 -37
- package/dist/core/config/config.js +154 -331
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +28 -0
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/experimental.js +47 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +389 -0
- package/dist/core/config/schema/improve.js +94 -0
- package/dist/core/config/schema/index-config.js +176 -0
- package/dist/core/config/schema/output.js +18 -0
- package/dist/core/config/schema/primitives.js +94 -0
- package/dist/core/config/schema/search.js +30 -0
- package/dist/core/config/schema/setup.js +18 -0
- package/dist/core/config/schema/sources-bundles.js +169 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +155 -20
- package/dist/core/errors.js +17 -15
- package/dist/core/events-types.js +4 -0
- package/dist/core/events.js +46 -128
- package/dist/core/extra-params.js +62 -0
- package/dist/core/file-change.js +17 -0
- package/dist/core/file-lock.js +202 -57
- package/dist/core/fs-txn.js +392 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +167 -0
- package/dist/core/json-schema.js +142 -0
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +135 -0
- package/dist/core/migration-operation.js +44 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/paths.js +22 -25
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +128 -0
- package/dist/core/redaction.js +392 -0
- package/dist/core/standards/resolve-standards-context.js +36 -65
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +5 -5
- package/dist/core/state/migrations.js +242 -11
- package/dist/core/state-db.js +98 -10
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +303 -0
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +834 -118
- package/dist/indexer/bundle-identity-guard.js +92 -0
- package/dist/indexer/db/graph-db.js +1 -25
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +30 -9
- package/dist/indexer/graph/graph-boost.js +9 -30
- package/dist/indexer/graph/graph-extraction.js +41 -27
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-writer-lock.js +93 -49
- package/dist/indexer/index-written-assets.js +100 -53
- package/dist/indexer/indexer.js +746 -329
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +142 -0
- package/dist/indexer/passes/dir-staleness.js +18 -10
- package/dist/indexer/passes/memory-inference.js +25 -15
- package/dist/indexer/passes/metadata.js +412 -243
- package/dist/indexer/scan/doc-to-entry.js +160 -0
- package/dist/indexer/scan/drain-dir.js +134 -0
- package/dist/indexer/search/db-search.js +292 -108
- package/dist/indexer/search/fts-query.js +64 -0
- package/dist/indexer/search/ranking-contributors.js +145 -25
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +28 -71
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-fields.js +18 -3
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +157 -111
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/usage-events.js +10 -30
- package/dist/indexer/walk/file-context.js +3 -45
- package/dist/indexer/walk/matchers.js +42 -34
- package/dist/indexer/walk/path-resolver.js +11 -5
- package/dist/indexer/walk/walker.js +42 -14
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -56
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +231 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +16 -2
- package/dist/integrations/agent/profiles.js +36 -62
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +93 -4
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +88 -196
- package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
- package/dist/integrations/harnesses/aider/index.js +48 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
- package/dist/integrations/harnesses/amazonq/index.js +45 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +24 -35
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
- package/dist/integrations/harnesses/codex/index.js +52 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
- package/dist/integrations/harnesses/copilot/index.js +48 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
- package/dist/integrations/harnesses/gemini/index.js +48 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +54 -34
- package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +14 -32
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
- package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
- package/dist/integrations/harnesses/openhands/index.js +48 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
- package/dist/integrations/harnesses/pi/index.js +45 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +43 -32
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +36 -39
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +182 -110
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +21 -9
- package/dist/llm/feature-gate.js +17 -57
- package/dist/llm/graph-extract.js +12 -13
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +45 -30
- package/dist/llm/structured-call.js +16 -8
- package/dist/llm/usage-persist.js +30 -5
- package/dist/llm/usage-telemetry.js +59 -6
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/command-registry.js +27 -0
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +251 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -279
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +58 -84
- package/dist/output/shapes/passthrough.js +11 -39
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/shapes.js +0 -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 +562 -0
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/helpers.js +15 -1164
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +202 -0
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +117 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +332 -0
- package/dist/output/text/workflow.js +3 -2
- package/dist/output/text.js +10 -19
- 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 +15 -25
- package/dist/registry/resolve.js +43 -94
- package/dist/registry/semver.js +43 -0
- package/dist/runtime.js +81 -12
- package/dist/scripts/akm-migrate.js +35529 -0
- package/dist/setup/detect.js +5 -7
- package/dist/setup/detected-engines.js +136 -0
- package/dist/setup/engine-config.js +100 -0
- package/dist/setup/registry-stash-loader.js +3 -3
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +444 -208
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +108 -305
- package/dist/setup/steps/platforms.js +13 -12
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +21 -15
- package/dist/setup/steps/stashdir.js +6 -4
- package/dist/setup/steps/tasks.js +236 -119
- package/dist/setup/steps.js +3 -2
- package/dist/sources/freshness.js +39 -0
- 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 +54 -56
- package/dist/sources/providers/git-stash.js +420 -91
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +47 -22
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +11 -10
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
- package/dist/storage/database.js +60 -4
- package/dist/storage/engines/sqlite-migrations.js +156 -5
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +51 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -32
- package/dist/storage/repositories/index-connection.js +79 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +863 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +167 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
- package/dist/storage/repositories/index-meta-repository.js +49 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +356 -0
- package/dist/storage/repositories/index-vec-repository.js +250 -0
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +317 -75
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +110 -3
- package/dist/storage/repositories/workflow-runs-repository.js +240 -19
- package/dist/tasks/backends/cron.js +169 -46
- package/dist/tasks/backends/exec-utils.js +76 -3
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +292 -55
- package/dist/tasks/backends/schtasks.js +557 -70
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/command-executable.js +93 -0
- package/dist/tasks/embedded.js +56 -38
- package/dist/tasks/parser.js +156 -64
- package/dist/tasks/resolve-akm-bin.js +144 -51
- package/dist/tasks/runner.js +377 -209
- package/dist/tasks/schedule.js +108 -19
- package/dist/tasks/scheduler-invocation.js +296 -0
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/task-id.js +35 -0
- package/dist/tasks/validator.js +30 -16
- package/dist/text-import-hook.mjs +1 -1
- package/dist/workflows/authoring/authoring.js +104 -43
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -16
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +450 -0
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +1038 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1460 -0
- package/dist/workflows/exec/run-workflow.js +602 -0
- package/dist/workflows/exec/scheduler.js +71 -0
- package/dist/workflows/exec/step-work.js +1190 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +246 -0
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +68 -0
- package/dist/workflows/ir/schema.js +540 -0
- package/dist/workflows/parser.js +878 -304
- package/dist/workflows/program/expressions.js +181 -0
- package/dist/workflows/program/schema.js +51 -0
- package/dist/workflows/renderer.js +100 -45
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +376 -119
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +2 -3
- package/dist/workflows/validator.js +52 -30
- package/docs/README.md +42 -78
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +9 -8
- package/docs/migration/release-notes/0.9.0.md +158 -14
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +844 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/data-and-telemetry.md +333 -0
- package/package.json +21 -17
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +4636 -0
- package/schemas/akm-task.json +87 -0
- package/schemas/akm-workflow.json +373 -0
- package/dist/akm-migrate-storage +0 -38
- package/dist/assets/help/help-accept.md +0 -12
- package/dist/assets/help/help-improve.md +0 -84
- package/dist/assets/help/help-proposals.md +0 -17
- package/dist/assets/help/help-propose.md +0 -17
- package/dist/assets/help/help-reject.md +0 -11
- package/dist/assets/profiles/frequent.json +0 -13
- package/dist/assets/profiles/recombine-only.json +0 -21
- package/dist/assets/profiles/reflect-distill.json +0 -30
- package/dist/assets/profiles/synthesize.json +0 -15
- package/dist/assets/prompts/procedural-system.md +0 -44
- package/dist/assets/prompts/recombine-system.md +0 -40
- package/dist/assets/prompts/staleness-detect-system.md +0 -6
- package/dist/assets/tasks/core/backup.yml +0 -4
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/assets/templates/html/default.html +0 -78
- package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
- package/dist/assets/wiki/index-template.md +0 -12
- package/dist/assets/wiki/ingest-workflow-template.md +0 -83
- package/dist/assets/wiki/log-template.md +0 -8
- package/dist/assets/wiki/schema-template.md +0 -61
- package/dist/cli/config-migrate.js +0 -150
- package/dist/cli/config-validate.js +0 -39
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -487
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -276
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/commands/improve/procedural.js +0 -398
- package/dist/commands/improve/recombine.js +0 -818
- package/dist/commands/improve/schema-similarity-gate.js +0 -168
- package/dist/commands/lint/agent-linter.js +0 -44
- package/dist/commands/lint/command-linter.js +0 -44
- package/dist/commands/lint/default-linter.js +0 -16
- package/dist/commands/lint/fact-linter.js +0 -39
- package/dist/commands/lint/knowledge-linter.js +0 -16
- package/dist/commands/lint/memory-linter.js +0 -61
- package/dist/commands/lint/registry.js +0 -41
- package/dist/commands/lint/skill-linter.js +0 -45
- package/dist/commands/lint/task-linter.js +0 -50
- package/dist/commands/lint/workflow-linter.js +0 -81
- package/dist/commands/proposal/legacy-import.js +0 -115
- package/dist/commands/sources/history.js +0 -196
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/commands/wiki-cli.js +0 -292
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -259
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/core/eval/rank-metrics.js +0 -113
- package/dist/core/ripgrep/install.js +0 -163
- package/dist/core/ripgrep/resolve.js +0 -81
- package/dist/indexer/db/db.js +0 -1413
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
- package/dist/llm/call-ai.js +0 -62
- package/dist/llm/memory-infer-impl.js +0 -138
- 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/output/text/wiki.js +0 -16
- package/dist/registry/build-index.js +0 -386
- package/dist/scripts/migrate-storage.js +0 -19108
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/setup/legacy-config.js +0 -106
- package/dist/storage/repositories/consolidation-repository.js +0 -38
- package/dist/storage/repositories/recombine-repository.js +0 -213
- package/dist/wiki/wiki-templates.js +0 -15
- package/dist/wiki/wiki.js +0 -1012
- package/dist/workflows/db.js +0 -215
- package/docs/data-and-telemetry.md +0 -226
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
* Shared memory-content hashing primitives, extracted from the deleted
|
|
6
|
+
* `dedup.ts` (#617 dedup pre-pass, removed WI-7.3) so `consolidate.ts` /
|
|
7
|
+
* `consolidate/chunking.ts` / `distill.ts` keep a stable, dependency-free home
|
|
8
|
+
* for the case-preserving stripped-body hash they use for the body-embedding
|
|
9
|
+
* cache and (formerly) the fidelity-check body comparison.
|
|
10
|
+
*
|
|
11
|
+
* @module content-hash
|
|
12
|
+
*/
|
|
13
|
+
import { createHash } from "node:crypto";
|
|
14
|
+
import { parseFrontmatter } from "../../core/asset/frontmatter.js";
|
|
15
|
+
/**
|
|
16
|
+
* Strip frontmatter from raw memory content, returning the body text trimmed.
|
|
17
|
+
* Case and whitespace are preserved. Falls back to `raw.trim()` on
|
|
18
|
+
* unparseable frontmatter (consistent with the pre-existing load-time hot
|
|
19
|
+
* guard).
|
|
20
|
+
*/
|
|
21
|
+
export function stripFrontmatterBody(raw) {
|
|
22
|
+
try {
|
|
23
|
+
return parseFrontmatter(raw).content.trim();
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return raw.trim();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Hash used for change-detection and the body-embedding cache: case-/
|
|
31
|
+
* whitespace-preserving stripped body. Two memories with the same wording
|
|
32
|
+
* but different casing produce DIFFERENT hashes here, which is intentional —
|
|
33
|
+
* we embed the exact text and cache by its precise content.
|
|
34
|
+
*
|
|
35
|
+
* This is the `content_hash` stored in `body_embeddings`.
|
|
36
|
+
*/
|
|
37
|
+
export function cacheHash(raw) {
|
|
38
|
+
return createHash("sha256").update(stripFrontmatterBody(raw), "utf8").digest("hex");
|
|
39
|
+
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* (`effectiveProposalKind !== "knowledge"`) stays in the caller; these helpers
|
|
12
12
|
* assume the lesson path.
|
|
13
13
|
*/
|
|
14
|
-
import { assembleAssetFromString } from "../../../core/asset/asset-serialize.js";
|
|
14
|
+
import { assembleAssetFromString, serializeFrontmatterQuoted } from "../../../core/asset/asset-serialize.js";
|
|
15
15
|
import { parseFrontmatter } from "../../../core/asset/frontmatter.js";
|
|
16
16
|
import { repairTruncatedDescription } from "../../../core/text-truncation.js";
|
|
17
17
|
import { detectDoubleFrontmatter, isValidDescription, isValidWhenToUse, } from "../../proposal/validators/proposal-quality-validators.js";
|
|
@@ -82,9 +82,7 @@ export function autoRepairLessonFrontmatter(content, inputRef) {
|
|
|
82
82
|
...(missingDesc && descLine ? { description: descLine } : {}),
|
|
83
83
|
...(missingWtu && wtuLine ? { when_to_use: wtuLine } : {}),
|
|
84
84
|
};
|
|
85
|
-
const fmLines =
|
|
86
|
-
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
|
|
87
|
-
.join("\n");
|
|
85
|
+
const fmLines = serializeFrontmatterQuoted(repairedFm);
|
|
88
86
|
// Only rewrite content if we actually have at least one field to write.
|
|
89
87
|
// Otherwise leave the original content for the lint pass to reject.
|
|
90
88
|
if (Object.keys(repairedFm).length > 0) {
|
|
@@ -122,9 +120,7 @@ export function autoSwapDescriptionWhenToUse(content, inputRef) {
|
|
|
122
120
|
description: wtuRaw,
|
|
123
121
|
when_to_use: descRaw,
|
|
124
122
|
};
|
|
125
|
-
const swappedFmLines =
|
|
126
|
-
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
|
|
127
|
-
.join("\n");
|
|
123
|
+
const swappedFmLines = serializeFrontmatterQuoted(swappedFm);
|
|
128
124
|
return { content: assembleAssetFromString(swappedFmLines, parsedSwap.content), swapped: 1 };
|
|
129
125
|
}
|
|
130
126
|
}
|
|
@@ -146,9 +142,7 @@ export function repairLessonDescriptionTruncation(content) {
|
|
|
146
142
|
const repaired = repairTruncatedDescription(descRepairRaw, parsedRepair.content);
|
|
147
143
|
if (repaired === descRepairRaw)
|
|
148
144
|
return content;
|
|
149
|
-
const repairedFmLines =
|
|
150
|
-
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
|
|
151
|
-
.join("\n");
|
|
145
|
+
const repairedFmLines = serializeFrontmatterQuoted({ ...fmRepair, description: repaired });
|
|
152
146
|
return assembleAssetFromString(repairedFmLines, parsedRepair.content);
|
|
153
147
|
}
|
|
154
148
|
/**
|
|
@@ -18,40 +18,27 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import fs from "node:fs";
|
|
20
20
|
import { parseFrontmatter } from "../../../core/asset/frontmatter.js";
|
|
21
|
-
import { getDefaultLlmConfig } from "../../../core/config/config.js";
|
|
22
|
-
import { ConfigError } from "../../../core/errors.js";
|
|
23
21
|
import { appendEvent } from "../../../core/events.js";
|
|
24
|
-
import { parseEmbeddedJsonResponse } from "../../../
|
|
25
|
-
import {
|
|
26
|
-
import { createProposal, isProposalSkipped } from "../../proposal/repository.js";
|
|
22
|
+
import { parseEmbeddedJsonResponse } from "../../../core/parse.js";
|
|
23
|
+
import { isProposalSkipped } from "../../proposal/repository.js";
|
|
27
24
|
import { assessMemoryKnowledgePromotionCandidate } from "../distill-promotion-policy.js";
|
|
25
|
+
import { emitProposal } from "../proposal-envelope.js";
|
|
26
|
+
import { durableImproveRef } from "../source-identity.js";
|
|
28
27
|
import { persistOutputEncodingSalience, runLessonQualityJudge, writeQualityRejection } from "./quality-gate.js";
|
|
29
28
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
29
|
+
* Resolve the knowledge content to propose when a memory promotes to knowledge,
|
|
30
|
+
* reconciling it with any existing knowledge file at the destination (D-1 / #369).
|
|
31
|
+
*
|
|
32
|
+
* When the destination already exists and an LLM is configured, follows the
|
|
33
|
+
* mem0 ADD/UPDATE/NOOP pattern (arXiv:2504.19413 §3.2): ADD/UPDATE swap in the
|
|
34
|
+
* merged content, NOOP short-circuits with a terminal "skipped" result. Without
|
|
35
|
+
* an LLM the existing content is appended as reviewer-reference context so the
|
|
36
|
+
* merge can be done by hand. Logic is byte-identical to the prior inline block.
|
|
34
37
|
*/
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
: assessMemoryKnowledgePromotionCandidate({
|
|
40
|
-
inputRef,
|
|
41
|
-
assetContent,
|
|
42
|
-
feedbackEvents: ctx.filteredEvents.map((event) => ({
|
|
43
|
-
...(event.metadata !== undefined ? { metadata: event.metadata } : {}),
|
|
44
|
-
})),
|
|
45
|
-
});
|
|
46
|
-
if (!(promotion?.promote && promotion.content && (targetKind === "knowledge" || targetKind === "auto"))) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
// D-1 / #369: When the destination knowledge file already exists, route
|
|
50
|
-
// through the LLM for contradiction resolution instead of silently
|
|
51
|
-
// overwriting. Follows mem0 ADD/UPDATE/DELETE/NOOP pattern (arXiv:2504.19413 §3.2)
|
|
52
|
-
// and A-MEM dynamic linking (arXiv:2502.12110).
|
|
53
|
-
let resolvedPromotionContent = promotion.content;
|
|
54
|
-
const existingKnowledgePath = await lookup(promotion.knowledgeRef);
|
|
38
|
+
async function resolveKnowledgePromotionContent(ctx, baseContent, knowledgeRef) {
|
|
39
|
+
const durableInputRef = ctx.durableInputRef ?? ctx.inputRef;
|
|
40
|
+
let resolvedPromotionContent = baseContent;
|
|
41
|
+
const existingKnowledgePath = await ctx.lookup(durableImproveRef(knowledgeRef));
|
|
55
42
|
const existingKnowledgeContent = existingKnowledgePath && fs.existsSync(existingKnowledgePath)
|
|
56
43
|
? (() => {
|
|
57
44
|
try {
|
|
@@ -62,7 +49,7 @@ export async function promoteMemoryToKnowledge(ctx) {
|
|
|
62
49
|
}
|
|
63
50
|
})()
|
|
64
51
|
: null;
|
|
65
|
-
if (existingKnowledgeContent &&
|
|
52
|
+
if (existingKnowledgeContent && ctx.llmConfig) {
|
|
66
53
|
// Existing content found: call LLM for contradiction-resolution merge.
|
|
67
54
|
const mergePrompt = [
|
|
68
55
|
"You are merging two versions of a knowledge document.",
|
|
@@ -77,38 +64,38 @@ export async function promoteMemoryToKnowledge(ctx) {
|
|
|
77
64
|
"",
|
|
78
65
|
"## New content from distillation",
|
|
79
66
|
"```",
|
|
80
|
-
|
|
67
|
+
baseContent.slice(0, 3000),
|
|
81
68
|
"```",
|
|
82
69
|
].join("\n");
|
|
83
70
|
try {
|
|
84
|
-
const
|
|
85
|
-
if (!mergeLlm) {
|
|
86
|
-
throw new ConfigError("LLM is not configured for distillation merge.", "LLM_NOT_CONFIGURED");
|
|
87
|
-
}
|
|
88
|
-
const mergeResponse = await chat(mergeLlm, [
|
|
71
|
+
const mergeResponse = await ctx.chat(ctx.llmConfig, [
|
|
89
72
|
{ role: "system", content: "Return only valid JSON. No prose." },
|
|
90
73
|
{ role: "user", content: mergePrompt },
|
|
91
|
-
]);
|
|
74
|
+
], ctx.signal ? { signal: ctx.signal } : undefined);
|
|
92
75
|
const mergeResult = parseEmbeddedJsonResponse(mergeResponse);
|
|
93
76
|
if (mergeResult?.action === "NOOP") {
|
|
94
77
|
// Existing content is authoritative — no update needed.
|
|
95
78
|
appendEvent({
|
|
96
79
|
eventType: "distill_invoked",
|
|
97
|
-
|
|
80
|
+
// Use item_ref when resolved, otherwise the input conceptId.
|
|
81
|
+
ref: ctx.itemRef ?? durableInputRef,
|
|
98
82
|
metadata: {
|
|
99
83
|
outcome: "skipped",
|
|
100
|
-
|
|
84
|
+
proposalRef: knowledgeRef,
|
|
101
85
|
message: "D-1: LLM resolved destination conflict as NOOP — existing content kept",
|
|
102
|
-
...eligMeta,
|
|
86
|
+
...ctx.eligMeta,
|
|
103
87
|
},
|
|
104
|
-
});
|
|
88
|
+
}, ctx.eventsCtx);
|
|
105
89
|
return {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
90
|
+
earlyResult: {
|
|
91
|
+
schemaVersion: 1,
|
|
92
|
+
ok: true,
|
|
93
|
+
outcome: "skipped",
|
|
94
|
+
inputRef: ctx.inputRef,
|
|
95
|
+
proposalRef: knowledgeRef,
|
|
96
|
+
skipReason: "conflict_noop",
|
|
97
|
+
message: "Existing knowledge content unchanged (contradiction resolution: NOOP)",
|
|
98
|
+
},
|
|
112
99
|
};
|
|
113
100
|
}
|
|
114
101
|
if (mergeResult?.action && (mergeResult.action === "ADD" || mergeResult.action === "UPDATE")) {
|
|
@@ -122,11 +109,11 @@ export async function promoteMemoryToKnowledge(ctx) {
|
|
|
122
109
|
// The reviewer will see both versions in the proposal diff.
|
|
123
110
|
}
|
|
124
111
|
}
|
|
125
|
-
else if (existingKnowledgeContent
|
|
112
|
+
else if (existingKnowledgeContent) {
|
|
126
113
|
// No LLM configured: include existing content as context in the proposal
|
|
127
114
|
// so the reviewer can do the contradiction resolution manually.
|
|
128
115
|
resolvedPromotionContent = [
|
|
129
|
-
|
|
116
|
+
baseContent,
|
|
130
117
|
"",
|
|
131
118
|
"---",
|
|
132
119
|
"<!-- D-1 / #369: Existing knowledge content is shown below for reviewer reference. -->",
|
|
@@ -137,20 +124,55 @@ export async function promoteMemoryToKnowledge(ctx) {
|
|
|
137
124
|
existingKnowledgeContent,
|
|
138
125
|
].join("\n");
|
|
139
126
|
}
|
|
127
|
+
return { resolvedContent: resolvedPromotionContent };
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Run the memory→knowledge promotion branch. Returns the finished distill
|
|
131
|
+
* result when promotion fired (all paths terminal), or `null` when the ref is
|
|
132
|
+
* not a promotion candidate and the caller should continue to the ordinary
|
|
133
|
+
* lesson/knowledge distillation path.
|
|
134
|
+
*/
|
|
135
|
+
export async function promoteMemoryToKnowledge(ctx) {
|
|
136
|
+
const { targetKind, inputRef, assetContent, config, chat, stash, fetchSimilarLessonsFn, existingRefVocabulary, outcomeWeightEnabled, eligMeta, exclusionSetSize, filteredFeedbackCount, feedbackFullyFiltered, } = ctx;
|
|
137
|
+
const durableInputRef = ctx.durableInputRef ?? inputRef;
|
|
138
|
+
const promotion = targetKind === "lesson"
|
|
139
|
+
? null
|
|
140
|
+
: assessMemoryKnowledgePromotionCandidate({
|
|
141
|
+
inputRef: durableInputRef,
|
|
142
|
+
assetContent,
|
|
143
|
+
feedbackEvents: ctx.filteredEvents.map((event) => ({
|
|
144
|
+
...(event.metadata !== undefined ? { metadata: event.metadata } : {}),
|
|
145
|
+
})),
|
|
146
|
+
});
|
|
147
|
+
if (!(promotion?.promote && promotion.content && (targetKind === "knowledge" || targetKind === "auto"))) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
// D-1 / #369: When the destination knowledge file already exists, route
|
|
151
|
+
// through the LLM for contradiction resolution instead of silently
|
|
152
|
+
// overwriting. Follows mem0 ADD/UPDATE/DELETE/NOOP pattern (arXiv:2504.19413 §3.2)
|
|
153
|
+
// and A-MEM dynamic linking (arXiv:2502.12110).
|
|
154
|
+
const merged = await resolveKnowledgePromotionContent(ctx, promotion.content, promotion.knowledgeRef);
|
|
155
|
+
if ("earlyResult" in merged)
|
|
156
|
+
return merged.earlyResult;
|
|
157
|
+
const resolvedPromotionContent = merged.resolvedContent;
|
|
140
158
|
// Apply quality gate to fast-path knowledge promotion (Risk 4 fix).
|
|
141
159
|
// D-5 / #388: Three-band system — review_needed band queues to proposal
|
|
142
160
|
// queue with review_needed outcome rather than auto-rejecting.
|
|
143
161
|
let knowledgeJudgeConfidence;
|
|
144
|
-
if (
|
|
162
|
+
if (ctx.strategy?.processes?.distill?.qualityGate?.enabled ?? true) {
|
|
145
163
|
// D-4 / #390: retrieve top-3 similar lessons for dedup check in judge.
|
|
146
164
|
const similarLessons = await fetchSimilarLessonsFn(resolvedPromotionContent.slice(0, 500), 3);
|
|
147
|
-
const judgeResult = await runLessonQualityJudge(config, resolvedPromotionContent, assetContent ?? "", chat,
|
|
165
|
+
const judgeResult = await runLessonQualityJudge(config, resolvedPromotionContent, assetContent ?? "", chat, {
|
|
166
|
+
...(similarLessons.length > 0 ? { similarLessons } : {}),
|
|
167
|
+
...(ctx.llmConfig ? { llmConfig: ctx.llmConfig } : {}),
|
|
168
|
+
...(ctx.signal ? { signal: ctx.signal } : {}),
|
|
169
|
+
});
|
|
148
170
|
if (!judgeResult.pass) {
|
|
149
171
|
if (judgeResult.reviewNeeded) {
|
|
150
172
|
// Uncertainty band (2.5–3.5): queue as review_needed instead of rejecting.
|
|
151
|
-
return writeQualityRejection(stash, inputRef, promotion.knowledgeRef, resolvedPromotionContent, judgeResult.score, judgeResult.reason, { reviewNeeded: true }, ctx.eligibilitySource);
|
|
173
|
+
return writeQualityRejection(stash, inputRef, promotion.knowledgeRef, resolvedPromotionContent, judgeResult.score, judgeResult.reason, { reviewNeeded: true }, ctx.eligibilitySource, ctx.eventsCtx);
|
|
152
174
|
}
|
|
153
|
-
return writeQualityRejection(stash, inputRef, promotion.knowledgeRef, resolvedPromotionContent, judgeResult.score, judgeResult.reason, {}, ctx.eligibilitySource);
|
|
175
|
+
return writeQualityRejection(stash, inputRef, promotion.knowledgeRef, resolvedPromotionContent, judgeResult.score, judgeResult.reason, {}, ctx.eligibilitySource, ctx.eventsCtx);
|
|
154
176
|
}
|
|
155
177
|
// Normalize 1-5 judge score to [0, 1]. Only a real passing verdict reaches
|
|
156
178
|
// here (07 P0-2: the judge now fails CLOSED on no-LLM / timeout / parse
|
|
@@ -160,9 +182,11 @@ export async function promoteMemoryToKnowledge(ctx) {
|
|
|
160
182
|
knowledgeJudgeConfidence = judgeResult.score / 5;
|
|
161
183
|
}
|
|
162
184
|
const knowledgeParsed = parseFrontmatter(resolvedPromotionContent);
|
|
163
|
-
const proposalResult =
|
|
185
|
+
const proposalResult = emitProposal({ stashDir: stash, proposalsCtx: ctx.proposalsCtx }, {
|
|
164
186
|
ref: promotion.knowledgeRef,
|
|
165
187
|
source: "distill",
|
|
188
|
+
// §23.6 fingerprint model-id term (WI-6.4).
|
|
189
|
+
...(ctx.llmConfig?.model ? { modelId: ctx.llmConfig.model } : {}),
|
|
166
190
|
...(ctx.sourceRun !== undefined ? { sourceRun: ctx.sourceRun } : {}),
|
|
167
191
|
payload: {
|
|
168
192
|
content: resolvedPromotionContent,
|
|
@@ -171,38 +195,40 @@ export async function promoteMemoryToKnowledge(ctx) {
|
|
|
171
195
|
...(knowledgeJudgeConfidence !== undefined ? { confidence: knowledgeJudgeConfidence } : {}),
|
|
172
196
|
// Attribution tagging: persist the eligibility lane on the proposal.
|
|
173
197
|
...(ctx.eligibilitySource ? { eligibilitySource: ctx.eligibilitySource } : {}),
|
|
174
|
-
}
|
|
198
|
+
});
|
|
175
199
|
if (isProposalSkipped(proposalResult)) {
|
|
176
200
|
appendEvent({
|
|
177
201
|
eventType: "distill_invoked",
|
|
178
|
-
|
|
202
|
+
// Use item_ref when resolved, otherwise the input conceptId.
|
|
203
|
+
ref: ctx.itemRef ?? durableInputRef,
|
|
179
204
|
metadata: {
|
|
180
205
|
outcome: "skipped",
|
|
181
|
-
|
|
206
|
+
proposalRef: promotion.knowledgeRef,
|
|
182
207
|
message: proposalResult.message,
|
|
183
208
|
skipReason: proposalResult.reason,
|
|
184
209
|
...eligMeta,
|
|
185
210
|
},
|
|
186
|
-
});
|
|
211
|
+
}, ctx.eventsCtx);
|
|
187
212
|
return {
|
|
188
213
|
schemaVersion: 1,
|
|
189
214
|
ok: true,
|
|
190
215
|
outcome: "skipped",
|
|
191
216
|
inputRef,
|
|
192
|
-
|
|
217
|
+
proposalRef: promotion.knowledgeRef,
|
|
218
|
+
skipReason: proposalResult.reason,
|
|
193
219
|
message: proposalResult.message,
|
|
194
220
|
};
|
|
195
221
|
}
|
|
196
222
|
const proposal = proposalResult;
|
|
197
223
|
// G4: content-score the distilled OUTPUT so it carries a real encoding
|
|
198
224
|
// salience (encoding_source='content') from creation.
|
|
199
|
-
persistOutputEncodingSalience(promotion.knowledgeRef, resolvedPromotionContent, existingRefVocabulary, outcomeWeightEnabled);
|
|
225
|
+
persistOutputEncodingSalience(durableImproveRef(promotion.knowledgeRef), resolvedPromotionContent, existingRefVocabulary, outcomeWeightEnabled);
|
|
200
226
|
appendEvent({
|
|
201
227
|
eventType: "distill_invoked",
|
|
202
|
-
|
|
228
|
+
// Use item_ref when resolved, otherwise the input conceptId.
|
|
229
|
+
ref: ctx.itemRef ?? durableInputRef,
|
|
203
230
|
metadata: {
|
|
204
231
|
outcome: "queued",
|
|
205
|
-
lessonRef: promotion.knowledgeRef,
|
|
206
232
|
proposalRef: promotion.knowledgeRef,
|
|
207
233
|
proposalKind: "knowledge",
|
|
208
234
|
proposalId: proposal.id,
|
|
@@ -213,13 +239,12 @@ export async function promoteMemoryToKnowledge(ctx) {
|
|
|
213
239
|
...(exclusionSetSize > 0 ? { filteredFeedbackCount } : {}),
|
|
214
240
|
...eligMeta,
|
|
215
241
|
},
|
|
216
|
-
});
|
|
242
|
+
}, ctx.eventsCtx);
|
|
217
243
|
return {
|
|
218
244
|
schemaVersion: 1,
|
|
219
245
|
ok: true,
|
|
220
246
|
outcome: "queued",
|
|
221
247
|
inputRef,
|
|
222
|
-
lessonRef: promotion.knowledgeRef,
|
|
223
248
|
proposalRef: promotion.knowledgeRef,
|
|
224
249
|
proposalKind: "knowledge",
|
|
225
250
|
proposalId: proposal.id,
|
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import fs from "node:fs";
|
|
12
12
|
import path from "node:path";
|
|
13
|
-
import {
|
|
13
|
+
import { parseRefInput } from "../../../core/asset/resolve-ref.js";
|
|
14
14
|
import { timestampForFilename } from "../../../core/common.js";
|
|
15
|
-
import { getDefaultLlmConfig } from "../../../core/config/config.js";
|
|
16
15
|
import { appendEvent } from "../../../core/events.js";
|
|
16
|
+
import { parseEmbeddedJsonResponse } from "../../../core/parse.js";
|
|
17
17
|
import { withStateDb } from "../../../core/state-db.js";
|
|
18
|
-
import {
|
|
18
|
+
import { getDefaultLlmConfig } from "../../../integrations/agent/engine-resolution.js";
|
|
19
|
+
import { callStructured } from "../../../llm/structured-call.js";
|
|
19
20
|
import { akmSearch } from "../../read/search.js";
|
|
20
21
|
import { scoreEncodingSalience } from "../encoding-salience.js";
|
|
21
22
|
import { computeSalience, upsertAssetSalience } from "../salience.js";
|
|
@@ -98,39 +99,97 @@ export function buildJudgePrompt(lessonContent, sourceContent, similarLessons) {
|
|
|
98
99
|
lines.push('Return ONLY valid JSON, no prose: {"score": <average score 1-5 as float>, "reason": "<one sentence>"}');
|
|
99
100
|
return lines.join("\n");
|
|
100
101
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
102
|
+
function boundedDocument(content, maxChars = 6000) {
|
|
103
|
+
if (content.length <= maxChars)
|
|
104
|
+
return content;
|
|
105
|
+
const half = Math.floor((maxChars - 80) / 2);
|
|
106
|
+
return `${content.slice(0, half)}\n\n[... middle omitted for bounded judge context ...]\n\n${content.slice(-half)}`;
|
|
107
|
+
}
|
|
108
|
+
function buildChangedRegion(sourceContent, candidateContent) {
|
|
109
|
+
const source = sourceContent.split("\n");
|
|
110
|
+
const candidate = candidateContent.split("\n");
|
|
111
|
+
let prefix = 0;
|
|
112
|
+
while (prefix < source.length && prefix < candidate.length && source[prefix] === candidate[prefix])
|
|
113
|
+
prefix++;
|
|
114
|
+
let suffix = 0;
|
|
115
|
+
while (suffix < source.length - prefix &&
|
|
116
|
+
suffix < candidate.length - prefix &&
|
|
117
|
+
source[source.length - 1 - suffix] === candidate[candidate.length - 1 - suffix]) {
|
|
118
|
+
suffix++;
|
|
119
|
+
}
|
|
120
|
+
const removed = source.slice(prefix, source.length - suffix).join("\n");
|
|
121
|
+
const added = candidate.slice(prefix, candidate.length - suffix).join("\n");
|
|
122
|
+
return boundedDocument(`Removed or replaced:\n${removed || "(none)"}\n\nAdded or replacement:\n${added || "(none)"}`);
|
|
123
|
+
}
|
|
124
|
+
/** Build quality criteria for revising an existing asset in place. */
|
|
125
|
+
export function buildReflectJudgePrompt(candidateContent, sourceContent, feedback) {
|
|
126
|
+
return [
|
|
127
|
+
"You are evaluating a proposed revision to an existing akm asset.",
|
|
128
|
+
"",
|
|
129
|
+
"Score this revision on each criterion from 1 (poor) to 5 (excellent):",
|
|
130
|
+
"1. FEEDBACK ALIGNMENT: Does the revision address the supplied feedback or improve retrieval and clarity?",
|
|
131
|
+
"2. PRESERVATION: Does it retain the source's concrete facts, code, commands, examples, and structure without truncation?",
|
|
132
|
+
"3. QUALITY: Is the revision coherent, actionable, complete, and free of unsupported claims?",
|
|
133
|
+
"",
|
|
134
|
+
"Overlap with the source is expected and must not lower the score by itself; this is an in-place revision, not a new lesson.",
|
|
135
|
+
"",
|
|
136
|
+
"Feedback:",
|
|
137
|
+
"```",
|
|
138
|
+
(feedback.length > 0 ? feedback.join("\n") : "No explicit feedback supplied.").slice(0, 1000),
|
|
139
|
+
"```",
|
|
140
|
+
"",
|
|
141
|
+
"Source asset content:",
|
|
142
|
+
"```",
|
|
143
|
+
boundedDocument(sourceContent),
|
|
144
|
+
"```",
|
|
145
|
+
"",
|
|
146
|
+
"Proposed revision:",
|
|
147
|
+
"```",
|
|
148
|
+
boundedDocument(candidateContent),
|
|
149
|
+
"```",
|
|
150
|
+
"",
|
|
151
|
+
"Changed region:",
|
|
152
|
+
"```",
|
|
153
|
+
buildChangedRegion(sourceContent, candidateContent),
|
|
154
|
+
"```",
|
|
155
|
+
"",
|
|
156
|
+
'Return ONLY valid JSON, no prose: {"score": <average score 1-5 as float>, "reason": "<one sentence>"}',
|
|
157
|
+
].join("\n");
|
|
158
|
+
}
|
|
159
|
+
async function runQualityJudge(feature, config, prompt, chat, options = {}) {
|
|
160
|
+
const llmConfig = options.llmConfig ?? getDefaultLlmConfig(config);
|
|
119
161
|
if (!llmConfig) {
|
|
120
162
|
return { pass: false, score: -1, reason: "no LLM configured — cannot judge, failing closed" };
|
|
121
163
|
}
|
|
122
|
-
const judgeLlmConfig = llmConfig.judgeModel ? { ...llmConfig, model: llmConfig.judgeModel } : llmConfig;
|
|
123
|
-
const JUDGE_TIMEOUT_MS = 8_000;
|
|
124
164
|
try {
|
|
125
|
-
|
|
126
|
-
|
|
165
|
+
// UNGATED at the seam (no akmConfig): the quality gates' enablement is
|
|
166
|
+
// resolved by the caller before this function runs, and a transport throw
|
|
167
|
+
// propagates into the fail-closed catch below. `feature` labels the call.
|
|
168
|
+
const raw = await callStructured({
|
|
169
|
+
feature,
|
|
170
|
+
config: llmConfig,
|
|
171
|
+
messages: [
|
|
127
172
|
{ role: "system", content: "Return only valid JSON. No prose." },
|
|
128
|
-
{ role: "user", content:
|
|
129
|
-
]
|
|
130
|
-
|
|
131
|
-
|
|
173
|
+
{ role: "user", content: prompt },
|
|
174
|
+
],
|
|
175
|
+
request: {
|
|
176
|
+
enableThinking: false,
|
|
177
|
+
...(Object.hasOwn(options, "timeoutMs") ? { timeoutMs: options.timeoutMs } : {}),
|
|
178
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
179
|
+
...(chat ? { chat } : {}),
|
|
180
|
+
},
|
|
181
|
+
parse: (rawResponse) => rawResponse ?? "",
|
|
182
|
+
// Unreachable on the ungated path (errors propagate); fail closed anyway.
|
|
183
|
+
onError: () => "",
|
|
184
|
+
fallback: "",
|
|
185
|
+
});
|
|
132
186
|
const parsed = parseEmbeddedJsonResponse(raw);
|
|
133
|
-
if (!parsed ||
|
|
187
|
+
if (!parsed ||
|
|
188
|
+
typeof parsed.score !== "number" ||
|
|
189
|
+
!Number.isFinite(parsed.score) ||
|
|
190
|
+
parsed.score < 1 ||
|
|
191
|
+
parsed.score > 5 ||
|
|
192
|
+
typeof parsed.reason !== "string") {
|
|
134
193
|
return { pass: false, score: -1, reason: "judge parse failed — cannot judge, failing closed" };
|
|
135
194
|
}
|
|
136
195
|
// D-5 / #388: Three-band system (MT-Bench arXiv:2306.05685 — ~±0.5 judge variance).
|
|
@@ -139,19 +198,35 @@ similarLessons) {
|
|
|
139
198
|
// < 2.5: auto-reject (pass: false)
|
|
140
199
|
const score = parsed.score;
|
|
141
200
|
const reason = parsed.reason ?? "";
|
|
142
|
-
if (score >= 3.5)
|
|
201
|
+
if (score >= 3.5)
|
|
143
202
|
return { pass: true, score, reason };
|
|
144
|
-
|
|
145
|
-
if (score >= 2.5) {
|
|
146
|
-
// Uncertainty band: treat as failed for auto-queuing but flag for review.
|
|
203
|
+
if (score >= 2.5)
|
|
147
204
|
return { pass: false, score, reason, reviewNeeded: true };
|
|
148
|
-
}
|
|
149
205
|
return { pass: false, score, reason };
|
|
150
206
|
}
|
|
151
207
|
catch {
|
|
152
208
|
return { pass: false, score: -1, reason: "judge timeout/error — cannot judge, failing closed" };
|
|
153
209
|
}
|
|
154
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Run the LLM-as-judge quality gate on a proposal's content.
|
|
213
|
+
*
|
|
214
|
+
* Exported so reflect.ts can apply the same gate to reflect proposals (R-5 / #374).
|
|
215
|
+
* The selected strategy's distill/reflect quality-gate setting is resolved by
|
|
216
|
+
* the caller before this function runs.
|
|
217
|
+
*
|
|
218
|
+
* Fail-CLOSED (07 P0-2): returns `pass: false` (score -1) on timeout, parse
|
|
219
|
+
* failure, or missing LLM. Minted content that cannot be judged is rejected,
|
|
220
|
+
* not passed through — an unverifiable judge must never wave content into the
|
|
221
|
+
* stash. The rejection is `quality_rejected`, not `review_needed`.
|
|
222
|
+
*/
|
|
223
|
+
export async function runLessonQualityJudge(config, lessonContent, sourceContent, chat, options = {}) {
|
|
224
|
+
return runQualityJudge("lesson_quality_gate", config, buildJudgePrompt(lessonContent, sourceContent, options.similarLessons), chat, options);
|
|
225
|
+
}
|
|
226
|
+
/** Judge an in-place reflect revision without applying new-lesson novelty criteria. */
|
|
227
|
+
export async function runReflectQualityJudge(config, candidateContent, sourceContent, feedback, chat, options = {}) {
|
|
228
|
+
return runQualityJudge("proposal_quality_gate", config, buildReflectJudgePrompt(candidateContent, sourceContent, feedback), chat, options);
|
|
229
|
+
}
|
|
155
230
|
// ── Quality-rejection helper ─────────────────────────────────────────────────
|
|
156
231
|
/**
|
|
157
232
|
* Write a rejected lesson to `.akm/distill-rejected/`, append a `distill_invoked`
|
|
@@ -159,25 +234,26 @@ similarLessons) {
|
|
|
159
234
|
*
|
|
160
235
|
* @param stash - Root stash directory.
|
|
161
236
|
* @param inputRef - The original input ref (for the event).
|
|
162
|
-
* @param
|
|
237
|
+
* @param proposalRef - The proposed lesson/knowledge ref.
|
|
163
238
|
* @param content - The raw content that failed the quality gate.
|
|
164
239
|
* @param score - Quality score from the judge.
|
|
165
240
|
* @param reason - Human-readable rejection reason.
|
|
166
241
|
* @param extraMeta - Optional additional metadata for the event.
|
|
242
|
+
* @param eventsCtx - Events context so the emit takes appendEvent's fast path (R25).
|
|
167
243
|
*/
|
|
168
|
-
export function writeQualityRejection(stash, inputRef,
|
|
244
|
+
export function writeQualityRejection(stash, inputRef, proposalRef, content, score, reason, extraMeta = {}, eligibilitySource, eventsCtx) {
|
|
169
245
|
// D-5 / #388: reviewNeeded flag selects "review_needed" vs "quality_rejected" outcome.
|
|
170
246
|
const outcome = extraMeta.reviewNeeded ? "review_needed" : "quality_rejected";
|
|
171
247
|
const rejectDir = path.join(stash, ".akm", "distill-rejected");
|
|
172
248
|
fs.mkdirSync(rejectDir, { recursive: true });
|
|
173
249
|
const ts = timestampForFilename();
|
|
174
|
-
fs.writeFileSync(path.join(rejectDir, `${ts}-${
|
|
250
|
+
fs.writeFileSync(path.join(rejectDir, `${ts}-${proposalRef.replace(/[:/\\]/g, "-")}.md`), `---\nscore: ${score}\nreason: ${reason}\noutcome: ${outcome}\n---\n\n${content}`, "utf8");
|
|
175
251
|
appendEvent({
|
|
176
252
|
eventType: "distill_invoked",
|
|
177
253
|
ref: inputRef,
|
|
178
254
|
metadata: {
|
|
179
255
|
outcome,
|
|
180
|
-
|
|
256
|
+
proposalRef,
|
|
181
257
|
score,
|
|
182
258
|
reason,
|
|
183
259
|
...extraMeta,
|
|
@@ -185,13 +261,13 @@ export function writeQualityRejection(stash, inputRef, lessonRef, content, score
|
|
|
185
261
|
// sliced by lane downstream. See EligibilitySource.
|
|
186
262
|
...(eligibilitySource ? { eligibilitySource } : {}),
|
|
187
263
|
},
|
|
188
|
-
});
|
|
264
|
+
}, eventsCtx);
|
|
189
265
|
return {
|
|
190
266
|
schemaVersion: 1,
|
|
191
267
|
ok: true,
|
|
192
268
|
outcome,
|
|
193
269
|
inputRef,
|
|
194
|
-
|
|
270
|
+
proposalRef,
|
|
195
271
|
score,
|
|
196
272
|
reason,
|
|
197
273
|
...extraMeta,
|
|
@@ -212,7 +288,7 @@ export function persistOutputEncodingSalience(ref, body, existingRefVocabulary,
|
|
|
212
288
|
// preparation uses parity weights — inconsistent salience semantics.
|
|
213
289
|
outcomeWeightEnabled) {
|
|
214
290
|
try {
|
|
215
|
-
const parsedRef =
|
|
291
|
+
const parsedRef = parseRefInput(ref);
|
|
216
292
|
const salienceResult = scoreEncodingSalience({
|
|
217
293
|
body,
|
|
218
294
|
type: parsedRef.type,
|
|
@@ -96,7 +96,7 @@ export function checkDistillFidelity(proposalBody, sourceBodies, config) {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
// Also flag proposals whose
|
|
99
|
+
// Also flag proposals whose xrefs are empty (broken provenance).
|
|
100
100
|
// This is a degradation signal, not a contradiction, but worth surfacing.
|
|
101
101
|
return { contradictionDetected: false };
|
|
102
102
|
}
|