akm-cli 0.9.30 → 0.10.261001-beta
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 +438 -0
- package/README.md +10 -10
- package/ROADMAP.md +112 -0
- package/STABILITY.md +99 -57
- package/dist/api-node.mjs +20 -0
- package/dist/api.d.ts +23 -0
- package/dist/api.js +45 -0
- package/dist/assets/hints/cli-hints-full.md +15 -29
- package/dist/assets/hints/cli-hints-short.md +2 -2
- package/dist/assets/improve-strategies/default.json +3 -3
- package/dist/assets/prompts/consolidate-pair.md +9 -7
- package/dist/assets/stash-skeleton/README.md +1 -1
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
- package/dist/cli/shared.js +31 -48
- package/dist/cli/unknown-flags.js +6 -43
- package/dist/cli.js +8 -34
- package/dist/commands/agent/contribute-cli.js +1 -1
- package/dist/commands/completions.js +1 -2
- package/dist/commands/config-cli.js +5 -28
- package/dist/commands/env/env-cli.js +5 -5
- package/dist/commands/env/secret-cli.js +2 -2
- package/dist/commands/feedback-cli.js +75 -49
- package/dist/commands/health/checks.js +41 -16
- package/dist/commands/health/plugin-staleness.js +52 -22
- package/dist/commands/improve/autonomy-gate.js +5 -3
- package/dist/commands/improve/consolidate/chunking.js +3 -10
- package/dist/commands/improve/consolidate/continuity-check.js +4 -4
- package/dist/commands/improve/consolidate/pair-pass.js +29 -10
- package/dist/commands/improve/consolidate.js +10 -65
- package/dist/commands/improve/distill/lesson-update.js +91 -0
- package/dist/commands/improve/distill-guards.js +1 -43
- package/dist/commands/improve/distill.js +148 -21
- package/dist/commands/improve/eligibility.js +14 -1
- package/dist/commands/improve/extract-cli.js +1 -1
- package/dist/commands/improve/extract-prompt.js +17 -7
- package/dist/commands/improve/extract.js +5 -7
- package/dist/commands/improve/improve-cli.js +125 -118
- package/dist/commands/improve/improve-strategies.js +8 -12
- package/dist/commands/improve/improve.js +134 -52
- package/dist/commands/improve/loop-stages.js +18 -5
- package/dist/commands/improve/planner.js +0 -1
- package/dist/commands/improve/preparation.js +40 -99
- package/dist/commands/improve/proactive-maintenance.js +2 -2
- package/dist/commands/improve/reflect-noise.js +3 -55
- package/dist/commands/improve/reflect.js +29 -34
- package/dist/commands/improve/retrieval-queries.js +37 -0
- package/dist/commands/improve/retrieval-scope.js +2 -2
- package/dist/commands/improve/salience.js +2 -9
- package/dist/commands/improve/session-asset.js +4 -1
- package/dist/commands/improve/stage.js +23 -12
- package/dist/commands/lint/index.js +5 -20
- package/dist/commands/observability-cli.js +3 -9
- package/dist/commands/proposal/drain.js +43 -6
- package/dist/commands/proposal/proposal-cli.js +11 -31
- package/dist/commands/proposal/repository.js +20 -14
- package/dist/commands/proposal/validators/proposal-quality-validators.js +0 -3
- package/dist/commands/read/knowledge.js +3 -3
- package/dist/commands/read/remember-cli.js +0 -13
- package/dist/commands/read/search-cli.js +29 -97
- package/dist/commands/read/search.js +0 -11
- package/dist/commands/read/show.js +0 -19
- package/dist/commands/sources/plugin-upgrade.js +164 -101
- package/dist/commands/sources/sources-cli.js +1 -15
- package/dist/commands/sources/stash-cli.js +6 -14
- package/dist/commands/tasks/tasks-cli.js +4 -115
- package/dist/commands/workflow/plan.js +11 -33
- package/dist/commands/workflow-cli.js +2 -7
- package/dist/core/adapter/adapter-ids.js +1 -2
- package/dist/core/adapter/adapters/agent-skills-adapter.js +0 -4
- package/dist/core/adapter/adapters/akm-adapter.js +9 -48
- package/dist/core/adapter/adapters/akm-lint.js +10 -26
- package/dist/core/adapter/adapters/akm-metadata.js +2 -72
- package/dist/core/adapter/adapters/akm-task-adapter.js +0 -5
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +9 -28
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -20
- package/dist/core/adapter/adapters/generic-files-adapter.js +0 -10
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +0 -4
- package/dist/core/adapter/adapters/tool-dir-shared.js +0 -24
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -4
- package/dist/core/adapter/recognize-match.js +3 -4
- package/dist/core/common.js +18 -2
- package/dist/core/config/config-schema.js +12 -15
- package/dist/core/config/config-types.js +6 -15
- package/dist/core/config/config-walker.js +6 -23
- package/dist/core/config/config.js +17 -80
- package/dist/core/config/engine-semantics.js +7 -3
- package/dist/core/config/schema/engines.js +7 -7
- package/dist/core/config/schema/improve-processes.js +10 -63
- package/dist/core/config/schema/improve.js +2 -21
- package/dist/core/config/schema/index-config.js +6 -39
- package/dist/core/env-secret-ref.js +2 -45
- package/dist/core/errors.js +1 -2
- package/dist/core/extra-params.js +2 -86
- package/dist/core/file-lock.js +12 -7
- package/dist/core/improve-result.js +13 -1
- package/dist/core/mutation-target.js +2 -2
- package/dist/core/paths.js +4 -0
- package/dist/core/recognition-util.js +4 -5
- package/dist/core/run-lock.js +1 -1
- package/dist/core/subprocess.js +49 -0
- package/dist/core/warn.js +21 -4
- package/dist/core/write-source.js +3 -3
- package/dist/execution/target-ref.js +1 -2
- package/dist/indexer/indexer.js +15 -6
- package/dist/indexer/passes/memory-inference.js +15 -6
- package/dist/indexer/search/db-search.js +49 -36
- package/dist/indexer/search/fts-query.js +0 -19
- package/dist/indexer/search/ranking.js +29 -1
- package/dist/indexer/usage/usage-events.js +21 -16
- package/dist/integrations/agent/engine-resolution.js +5 -2
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +41 -98
- package/dist/integrations/agent/request-lowering.js +3 -3
- package/dist/integrations/harnesses/aider/index.js +5 -0
- package/dist/integrations/harnesses/amazonq/index.js +1 -0
- package/dist/integrations/harnesses/claude/config-import.js +2 -3
- package/dist/integrations/harnesses/claude/index.js +5 -0
- package/dist/integrations/harnesses/codex/index.js +1 -0
- package/dist/integrations/harnesses/copilot/index.js +1 -0
- package/dist/integrations/harnesses/gemini/index.js +1 -0
- package/dist/integrations/harnesses/index.js +18 -39
- package/dist/integrations/harnesses/opencode/agent-builder.js +60 -35
- package/dist/integrations/harnesses/opencode/config-import.js +121 -52
- package/dist/integrations/harnesses/opencode/index.js +22 -0
- package/dist/integrations/harnesses/opencode/plugin-layout.js +68 -0
- package/dist/integrations/harnesses/opencode/session-log-types.js +12 -0
- package/dist/integrations/harnesses/opencode/session-log-v1.js +72 -0
- package/dist/integrations/harnesses/opencode/session-log-v2.js +140 -0
- package/dist/integrations/harnesses/opencode/session-log.js +104 -115
- package/dist/integrations/harnesses/opencode/version.js +98 -0
- package/dist/integrations/harnesses/opencode-sdk/{harness.js → index.js} +5 -17
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +105 -206
- package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +199 -0
- package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +254 -0
- package/dist/integrations/harnesses/opencode-sdk/wire.js +66 -0
- package/dist/integrations/harnesses/openhands/index.js +1 -0
- package/dist/integrations/harnesses/pi/index.js +1 -0
- package/dist/integrations/harnesses/shared.js +2 -0
- package/dist/integrations/harnesses/types.js +2 -0
- package/dist/llm/client.js +74 -14
- package/dist/output/cli-hints.js +1 -1
- package/dist/output/context.js +10 -19
- package/dist/output/format-exempt.js +5 -8
- package/dist/output/shapes/helpers.js +1 -22
- package/dist/output/shapes/passthrough.js +0 -1
- package/dist/output/shapes.js +3 -31
- package/dist/output/stdout.js +5 -1
- package/dist/output/text/command-format.js +6 -1
- package/dist/output/text/workflow-format.js +4 -22
- package/dist/scripts/akm-migrate-node.js +15769 -16731
- package/dist/scripts/akm-migrate.js +16339 -17297
- package/dist/setup/detect.js +10 -4
- package/dist/setup/harness-config-import.js +5 -14
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/tasks.js +12 -13
- package/dist/sources/providers/git-stash.js +94 -13
- package/dist/storage/repositories/index-utility-repository.js +2 -32
- package/dist/storage/repositories/index-vec-repository.js +4 -0
- package/dist/storage/repositories/task-history-repository.js +0 -5
- package/dist/storage/repositories/workflow-runs-repository.js +5 -15
- package/dist/tasks/embedded.js +2 -1
- package/dist/tasks/run/run-command-task.js +9 -1
- package/dist/tasks/run/run-workflow-task.js +4 -3
- package/dist/tasks/run/task-history.js +0 -2
- package/dist/tasks/run/task-log.js +38 -1
- package/dist/tasks/schedule-gates.js +39 -0
- package/dist/tasks/scheduler-binding.js +0 -16
- package/dist/tasks/scheduler-sync.js +3 -97
- package/dist/tasks/source/bounded-document.js +1 -1
- package/dist/tasks/source/task-source-v4.js +2 -12
- package/dist/tasks/task-run-reserved-flags.js +2 -31
- package/dist/workflows/authoring/authoring.js +6 -6
- package/dist/workflows/compile.js +8 -65
- package/dist/workflows/exec/child-workflow.js +22 -3
- package/dist/workflows/exec/native-executor.js +12 -147
- package/dist/workflows/exec/run-workflow.js +31 -103
- package/dist/workflows/exec/step-work.js +9 -178
- package/dist/workflows/exec/unit-dispatch.js +0 -10
- package/dist/workflows/freeze/environment.js +3 -44
- package/dist/workflows/freeze/freeze.js +8 -41
- package/dist/workflows/freeze/targets/child-workflow.js +27 -63
- package/dist/workflows/freeze/targets/command.js +2 -16
- package/dist/workflows/freeze/targets/shell.js +0 -2
- package/dist/workflows/freeze/task-bindings.js +2 -28
- package/dist/workflows/ir/params.js +12 -2
- package/dist/workflows/parser.js +82 -232
- package/dist/workflows/plan.js +1 -1
- package/dist/workflows/renderer.js +10 -19
- package/dist/workflows/runtime/run-plan.js +11 -53
- package/dist/workflows/runtime/runs.js +4 -27
- package/dist/workflows/source-files.js +12 -16
- package/dist/workflows/source-semantics.js +1 -93
- package/docs/README.md +43 -42
- package/docs/agents/README.md +15 -0
- package/docs/agents/agent-install.md +14 -0
- package/docs/architecture/0.10-process-rules.md +827 -0
- package/docs/architecture/README.md +67 -0
- package/docs/architecture/adapters.md +258 -0
- package/docs/architecture/akm-architecture-decision-history.md +2055 -0
- package/docs/architecture/akm-core-principles.md +126 -0
- package/docs/architecture/architecture.md +578 -0
- package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +550 -0
- package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +72 -0
- package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +142 -0
- package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +189 -0
- package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +97 -0
- package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +108 -0
- package/docs/architecture/decisions/0006-task-source-version-routing.md +124 -0
- package/docs/architecture/decisions/0007-workflow-composition-bounds.md +83 -0
- package/docs/architecture/decisions/0008-task-binding-normalization.md +88 -0
- package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +80 -0
- package/docs/architecture/decisions/0010-driver-protocol-cut.md +36 -0
- package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +125 -0
- package/docs/architecture/decisions/README.md +62 -0
- package/docs/architecture/improvement.md +479 -0
- package/docs/architecture/internals/classification.md +154 -0
- package/docs/architecture/internals/fresh-host-rebuild-runbook.md +40 -0
- package/docs/architecture/internals/functional-contract-patterns.md +340 -0
- package/docs/architecture/internals/health-advisories.md +110 -0
- package/docs/architecture/internals/improve-workflow.md +719 -0
- package/docs/architecture/internals/indexing.md +498 -0
- package/docs/architecture/internals/registry-network-boundary.md +57 -0
- package/docs/architecture/internals/search.md +248 -0
- package/docs/architecture/internals/storage-locations.md +943 -0
- package/docs/architecture/persisted-data-compat.md +68 -0
- package/docs/architecture/reviews/env-secret-access.md +319 -0
- package/docs/architecture/runtime-boundary-design.md +153 -0
- package/docs/architecture/specs/0.9.0-close-out-plan.md +361 -0
- package/docs/architecture/specs/0.9.0-decisions.md +532 -0
- package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +745 -0
- package/docs/architecture/specs/0.9.0-open-items-register.md +135 -0
- package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +740 -0
- package/docs/architecture/specs/0.9.0-release-surface-review.md +636 -0
- package/docs/architecture/specs/agent-command-engine-model-design.md +513 -0
- package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +501 -0
- package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +291 -0
- package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +2059 -0
- package/docs/architecture/specs/di-seams-plan.md +539 -0
- package/docs/architecture/specs/driver-protocol-keep-or-cut.md +275 -0
- package/docs/architecture/specs/fact-asset-type.md +142 -0
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +634 -0
- package/docs/architecture/specs/okf-support.md +148 -0
- package/docs/architecture/specs/ref.md +329 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/README.md +72 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +152 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +352 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +300 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +402 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +758 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +645 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +602 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +27 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +27 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +74 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +15 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +132 -0
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +147 -0
- package/docs/architecture/specs/stash-conventions-code-spec.md +275 -0
- package/docs/architecture/specs/stash-organization-conventions.md +377 -0
- package/docs/architecture/specs/task-workflow-format-unification.md +721 -0
- package/docs/architecture/specs/workflow-engine-buy-vs-build.md +231 -0
- package/docs/architecture/specs/workflow-format-unification.md +432 -0
- package/docs/architecture/testing/manual-testing-checklist.md +3411 -0
- package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +924 -0
- package/docs/architecture/testing/task-workflow-manual-tests.md +1720 -0
- package/docs/architecture/testing/testing-workflow.md +446 -0
- package/docs/architecture/workflow-engine.md +223 -0
- package/docs/guides/README.md +33 -0
- package/docs/guides/author-bundles.md +310 -0
- package/docs/guides/author-workflows.md +490 -0
- package/docs/guides/bundles.md +323 -0
- package/docs/guides/capture-knowledge.md +136 -0
- package/docs/guides/claude-code-vs-akm-workflows.md +29 -0
- package/docs/guides/concepts.md +93 -0
- package/docs/guides/discover-and-load.md +158 -0
- package/docs/guides/getting-started.md +240 -0
- package/docs/guides/improve-the-library.md +247 -0
- package/docs/guides/knowledge-management.md +18 -0
- package/docs/guides/recipes/headless-install.md +97 -0
- package/docs/guides/recipes/website-source.md +28 -0
- package/docs/guides/run-workflows.md +279 -0
- package/docs/guides/scheduling.md +131 -0
- package/docs/guides/use-with-any-agent.md +174 -0
- package/docs/guides/wikis.md +81 -0
- package/docs/integration/bundling-akm.md +7 -6
- package/docs/maintainers/README.md +19 -0
- package/docs/maintainers/curate-workmap.md +335 -0
- package/docs/maintainers/eval.md +3 -0
- package/docs/maintainers/local-development.md +108 -0
- package/docs/maintainers/release-checklist.md +135 -0
- package/docs/migration/README.md +4 -2
- package/docs/migration/release-notes/0.0.13.md +1 -1
- package/docs/migration/release-notes/0.1.0.md +1 -1
- package/docs/migration/release-notes/0.10.0.md +201 -0
- package/docs/migration/release-notes/0.2.0.md +1 -1
- package/docs/migration/release-notes/0.3.0.md +1 -1
- package/docs/migration/release-notes/0.5.0.md +1 -1
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.7.3.md +2 -2
- package/docs/migration/release-notes/0.7.4.md +1 -1
- package/docs/migration/release-notes/0.7.5.md +1 -1
- package/docs/migration/release-notes/0.8.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +1 -1
- package/docs/migration/release-notes/0.9.14.md +1 -1
- package/docs/migration/release-notes/0.9.15.md +1 -1
- package/docs/migration/release-notes/0.9.16.md +1 -1
- package/docs/migration/release-notes/0.9.17.md +1 -1
- package/docs/migration/release-notes/0.9.19.md +1 -1
- package/docs/migration/release-notes/0.9.2.md +1 -1
- package/docs/migration/release-notes/README.md +28 -31
- package/docs/migration/v0.5-to-v0.6.md +759 -0
- package/docs/migration/v0.8-to-v0.9.md +1 -1
- package/docs/migration/v0.9-to-v0.10.md +507 -0
- package/docs/plans/0.9.2-agent-command-workflow-plan.md +423 -0
- package/docs/posts/README.md +30 -0
- package/docs/posts/akm-command-tour.md +495 -0
- package/docs/posts/akm-logo-sized.webp +0 -0
- package/docs/posts/belief-aware-memory-12.md +139 -0
- package/docs/posts/config-v2-lessons-16.md +191 -0
- package/docs/posts/improve-loop-autonomous-10.md +225 -0
- package/docs/posts/improve-pipeline-debugging-0803.md +179 -0
- package/docs/posts/intro-part-01.md +76 -0
- package/docs/posts/intro-part-02.md +221 -0
- package/docs/posts/intro-part-03.md +190 -0
- package/docs/posts/intro-part-04.md +221 -0
- package/docs/posts/llm-mode-reflect-13.md +166 -0
- package/docs/posts/openpalm-built-on-akm.md +86 -0
- package/docs/posts/progressive-disclosure-06.md +129 -0
- package/docs/posts/proposal-safety-net-15.md +112 -0
- package/docs/posts/release-0.5.0.md +247 -0
- package/docs/posts/release-0.6.0.md +117 -0
- package/docs/posts/release-0.7.0.md +159 -0
- package/docs/posts/release-0.8.0.md +332 -0
- package/docs/posts/scattered-skills-05.md +100 -0
- package/docs/posts/task-assets-persistent-workflows-11.md +222 -0
- package/docs/posts/team-skills-07.md +198 -0
- package/docs/posts/wiki-agent-knowledge-08.md +223 -0
- package/docs/posts/workflows-vaults-09.md +321 -0
- package/docs/product-surface.md +54 -0
- package/docs/reference/README.md +2 -2
- package/docs/reference/api.md +65 -0
- package/docs/reference/asset-types.md +166 -0
- package/docs/reference/bundle-types.md +2 -4
- package/docs/reference/cli.md +163 -192
- package/docs/reference/configuration.md +101 -20
- package/docs/reference/data-and-telemetry.md +2 -2
- package/docs/reference/env-and-secrets.md +126 -0
- package/docs/reference/memory.md +124 -0
- package/docs/reference/refs.md +156 -0
- package/docs/reference/registry.md +489 -0
- package/docs/reference/supported-formats.md +3 -4
- package/docs/reference/tasks.md +12 -19
- package/docs/reference/website-sources.md +141 -0
- package/docs/reference/workflow-schema.md +89 -317
- package/docs/reference/workflows.md +20 -48
- package/package.json +23 -16
- package/schemas/akm-config.json +2 -243
- package/schemas/akm-task.json +2 -3
- package/schemas/akm-workflow.json +47 -84
- package/dist/assets/improve-strategies/catchup.json +0 -41
- package/dist/assets/improve-strategies/proactive-maintenance.json +0 -24
- package/dist/assets/improve-strategies/quick.json +0 -17
- package/dist/assets/improve-strategies/reflect-distill.json +0 -29
- package/dist/assets/improve-strategies/thorough.json +0 -49
- package/dist/assets/prompts/retrieval-relevance-judge.md +0 -6
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +0 -6
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +0 -4
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +0 -4
- package/dist/cli/retired-commands.js +0 -118
- package/dist/commands/improve/retrieval-gate.js +0 -132
- package/dist/commands/tasks/validate.js +0 -176
- package/dist/core/config/legacy-source-shape-shim.js +0 -117
- package/dist/indexer/feedback/utility-policy.js +0 -75
- package/dist/integrations/harnesses/ids.js +0 -28
- package/dist/tasks/source/task-source-v3-frozen.js +0 -424
- package/dist/tasks/source/task-to-v4.js +0 -863
- package/dist/workflows/exec/worktree.js +0 -372
- package/dist/workflows/freeze/child-output-references.js +0 -83
- package/dist/workflows/freeze/identity.js +0 -22
- package/dist/workflows/freeze/targets/script.js +0 -50
- package/dist/workflows/freeze/targets/task.js +0 -124
- package/dist/workflows/github-yaml.js +0 -506
- package/dist/workflows/runtime/run-outputs.js +0 -80
|
@@ -28,7 +28,7 @@ import { resolveEntryContentDir, resolveSourceEntries } from "../../indexer/sear
|
|
|
28
28
|
import { collectEngineCredentialValues } from "../../integrations/agent/engine-resolution.js";
|
|
29
29
|
import { installLlmUsagePersistence } from "../../llm/usage-persist.js";
|
|
30
30
|
import { withLlmStage } from "../../llm/usage-telemetry.js";
|
|
31
|
-
import { isGitBackedStash, listGitChangedPaths, resolveWritableOverride, saveGitStash, } from "../../sources/providers/git.js";
|
|
31
|
+
import { GitStashPushError, isGitBackedStash, listGitChangedPaths, resolveWritableOverride, saveGitStash, } from "../../sources/providers/git.js";
|
|
32
32
|
import { closeDatabase, openExistingDatabase } from "../../storage/repositories/index-connection.js";
|
|
33
33
|
import { getEntryCount } from "../../storage/repositories/index-entries-repository.js";
|
|
34
34
|
import { openSqliteReadSnapshot, SqliteReadSnapshotUnavailableError } from "../../storage/sqlite-read-snapshot.js";
|
|
@@ -70,7 +70,8 @@ export function renderSyncCommitMessage(template, result, nowMs) {
|
|
|
70
70
|
export const FIRST_ENGINE_RESPONSE_HEARTBEAT_MS = 5_000;
|
|
71
71
|
/**
|
|
72
72
|
* Abort the run at the budget; force-exit (0 — budget exhaustion is a normal
|
|
73
|
-
* scheduled-task outcome) only if the drain overruns the grace period
|
|
73
|
+
* scheduled-task outcome) only if the drain overruns the grace period, after
|
|
74
|
+
* `onHardKill` has persisted what the killed run left behind.
|
|
74
75
|
* Returns an idempotent disposer.
|
|
75
76
|
*/
|
|
76
77
|
export function armBudgetWatchdog(budgetMs, controller, deps) {
|
|
@@ -81,7 +82,15 @@ export function armBudgetWatchdog(budgetMs, controller, deps) {
|
|
|
81
82
|
let hardKillTimer;
|
|
82
83
|
const budgetTimer = setTimeoutFn(() => {
|
|
83
84
|
controller.abort("improve budget exhausted");
|
|
84
|
-
hardKillTimer = setTimeoutFn(() =>
|
|
85
|
+
hardKillTimer = setTimeoutFn(() => {
|
|
86
|
+
try {
|
|
87
|
+
deps?.onHardKill?.();
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Best-effort: the forced exit must still happen.
|
|
91
|
+
}
|
|
92
|
+
exitFn(0);
|
|
93
|
+
}, hardKillGraceMs);
|
|
85
94
|
hardKillTimer.unref?.();
|
|
86
95
|
}, budgetMs);
|
|
87
96
|
return () => {
|
|
@@ -101,6 +110,7 @@ export async function akmImprove(options = {}) {
|
|
|
101
110
|
// Set by the usage sink when any engine call terminates, prepass included.
|
|
102
111
|
let firstEngineResponseSeen = false;
|
|
103
112
|
let initialGitPaths = new Set();
|
|
113
|
+
let preRunSync;
|
|
104
114
|
// The write-provenance journal (#652) spans exactly the window this run holds the lock.
|
|
105
115
|
let journal;
|
|
106
116
|
const closeJournal = () => {
|
|
@@ -155,7 +165,20 @@ export async function akmImprove(options = {}) {
|
|
|
155
165
|
});
|
|
156
166
|
if (!options.dryRun) {
|
|
157
167
|
const remainingBudget = budgetAbortController.signal.remainingBudgetMs;
|
|
158
|
-
clearBudgetTimer = armBudgetWatchdog(Math.max(1, remainingBudget ?? budgetMs), budgetAbortController
|
|
168
|
+
clearBudgetTimer = armBudgetWatchdog(Math.max(1, remainingBudget ?? budgetMs), budgetAbortController, {
|
|
169
|
+
// The forced exit skips every finally and the CLI catch: leave a terminated
|
|
170
|
+
// run record and bank the files this run wrote (journal is in memory) first.
|
|
171
|
+
// Local commit only — a push to a dead remote must not hang the exit.
|
|
172
|
+
onHardKill: () => {
|
|
173
|
+
try {
|
|
174
|
+
options.onBudgetHardKill?.();
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// best-effort
|
|
178
|
+
}
|
|
179
|
+
commitStashBatch({ scope, plannedRefs: collected?.plannedRefs ?? [], runId: options.runId }, { push: false });
|
|
180
|
+
},
|
|
181
|
+
});
|
|
159
182
|
}
|
|
160
183
|
try {
|
|
161
184
|
if (!options.dryRun) {
|
|
@@ -174,6 +197,9 @@ export async function akmImprove(options = {}) {
|
|
|
174
197
|
});
|
|
175
198
|
exitBackstop = releaseRunLock;
|
|
176
199
|
process.on("exit", exitBackstop);
|
|
200
|
+
// Pull in what another host pushed before anything reads the bundle (#1091). This also commits
|
|
201
|
+
// pending managed-path changes, as `akm sync` does, so they are not mistaken for this run's writes.
|
|
202
|
+
preRunSync = syncBeforeRun(setup, eventsCtx);
|
|
177
203
|
initialGitPaths =
|
|
178
204
|
syncRepoDir && isGitBackedStash(syncRepoDir) ? new Set(listGitChangedPaths(syncRepoDir)) : new Set();
|
|
179
205
|
journal = beginWriteProvenance();
|
|
@@ -246,6 +272,8 @@ export async function akmImprove(options = {}) {
|
|
|
246
272
|
if (writtenPaths.length > 0)
|
|
247
273
|
result.writtenPaths = writtenPaths;
|
|
248
274
|
result.sync = commitStashBatch(result);
|
|
275
|
+
if (preRunSync)
|
|
276
|
+
result.preRunSync = preRunSync;
|
|
249
277
|
return result;
|
|
250
278
|
}
|
|
251
279
|
catch (err) {
|
|
@@ -654,7 +682,7 @@ function buildResultExecutionPlan(run, preparation, collected, dryRun) {
|
|
|
654
682
|
enabled: scope.mode !== "ref" && resolvedPlan.processes.triage.enabled,
|
|
655
683
|
configuredMode: configuredTriage?.applyMode ?? "queue",
|
|
656
684
|
mode: improveProfile.processes?.triage?.applyMode ?? "queue",
|
|
657
|
-
maxAcceptsPerRun: configuredTriage?.maxAcceptsPerRun ??
|
|
685
|
+
maxAcceptsPerRun: configuredTriage?.maxAcceptsPerRun ?? 200,
|
|
658
686
|
},
|
|
659
687
|
});
|
|
660
688
|
}
|
|
@@ -674,7 +702,7 @@ async function runTriagePrePass(run) {
|
|
|
674
702
|
...(options.target ? { target: options.target } : {}),
|
|
675
703
|
config: options.config,
|
|
676
704
|
applyMode: triageConfig?.applyMode ?? "queue",
|
|
677
|
-
maxAccepts: triageConfig?.maxAcceptsPerRun ??
|
|
705
|
+
maxAccepts: triageConfig?.maxAcceptsPerRun ?? 200,
|
|
678
706
|
dryRun: false,
|
|
679
707
|
excludeIds: new Set(),
|
|
680
708
|
judgment: resolvedPlan.triageJudgment,
|
|
@@ -712,60 +740,114 @@ export function resolveSyncPathSet(input) {
|
|
|
712
740
|
unattributed: changedPaths.filter((p) => !attributed.has(p) && !initialPaths.has(p) && inScope(p)).sort(),
|
|
713
741
|
};
|
|
714
742
|
}
|
|
743
|
+
/**
|
|
744
|
+
* One `saveGitStash` call for the run's write-target bundle, shared by the
|
|
745
|
+
* pre-run sync and the auto-sync commit: never throws, records a `stash_synced`
|
|
746
|
+
* event, and returns undefined when the bundle is not git-backed, there is no
|
|
747
|
+
* primary stash, or sync is disabled (`--no-sync` / `sync.enabled: false`).
|
|
748
|
+
* `scopePaths` runs inside the guard; leaving `paths` undefined means what
|
|
749
|
+
* `akm sync` stages (the managed paths).
|
|
750
|
+
*/
|
|
751
|
+
function runStashSync(run, eventsCtx, phase, input) {
|
|
752
|
+
const { writeTarget, primaryStashDir, effectiveSync, options, config, improveProfile } = run;
|
|
753
|
+
const repoDir = writeTarget?.source.repoPath ?? primaryStashDir;
|
|
754
|
+
if (!primaryStashDir || !repoDir || effectiveSync.enabled === false || !isGitBackedStash(repoDir)) {
|
|
755
|
+
return undefined;
|
|
756
|
+
}
|
|
757
|
+
const saveGitStashFn = options.saveGitStashFn ?? saveGitStash;
|
|
758
|
+
const writableOverride = writeTarget ? resolveWritable(writeTarget.config) : resolveWritableOverride(config);
|
|
759
|
+
const push = input.push ?? options.sync?.push ?? improveProfile.sync?.push ?? true;
|
|
760
|
+
const record = (metadata) => appendEvent({ eventType: "stash_synced", metadata: { phase, ...metadata } }, eventsCtx);
|
|
761
|
+
try {
|
|
762
|
+
const { paths, unattributed } = input.scopePaths({
|
|
763
|
+
repoDir,
|
|
764
|
+
assetRoot: writeTarget?.source.path ?? primaryStashDir,
|
|
765
|
+
});
|
|
766
|
+
const syncResult = saveGitStashFn(undefined, input.message, writableOverride, {
|
|
767
|
+
push,
|
|
768
|
+
repoDir,
|
|
769
|
+
...(paths ? { paths } : {}),
|
|
770
|
+
});
|
|
771
|
+
record({
|
|
772
|
+
committed: syncResult.committed,
|
|
773
|
+
pushed: syncResult.pushed,
|
|
774
|
+
skipped: syncResult.skipped,
|
|
775
|
+
reason: syncResult.reason ?? null,
|
|
776
|
+
...(paths ? { attributed: paths.length, unattributed: unattributed ?? 0 } : {}),
|
|
777
|
+
});
|
|
778
|
+
return {
|
|
779
|
+
committed: syncResult.committed,
|
|
780
|
+
pushed: syncResult.pushed,
|
|
781
|
+
skipped: syncResult.skipped,
|
|
782
|
+
...(syncResult.reason !== undefined ? { reason: syncResult.reason } : {}),
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
catch (syncErr) {
|
|
786
|
+
const reason = errMessage(syncErr);
|
|
787
|
+
warn(`improve: stash sync failed (non-fatal): ${reason}`);
|
|
788
|
+
// A push that failed after the commit landed still left the commit in the repo.
|
|
789
|
+
const committed = syncErr instanceof GitStashPushError;
|
|
790
|
+
record({ committed, pushed: false, skipped: true, reason });
|
|
791
|
+
return { committed, pushed: false, skipped: true, reason };
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* The pre-run sync (#1091): the same fetch / fast-forward-or-merge / commit /
|
|
796
|
+
* push `akm sync` runs for the write-target bundle, before the index and plan
|
|
797
|
+
* stages so they see what another host pushed. A conflict or fetch failure is
|
|
798
|
+
* a warning, never an abort: the run continues on the local state.
|
|
799
|
+
*/
|
|
800
|
+
function syncBeforeRun(run, eventsCtx) {
|
|
801
|
+
const outcome = runStashSync(run, eventsCtx, "pre-run", {
|
|
802
|
+
message: "akm improve pre-run sync",
|
|
803
|
+
scopePaths: ({ repoDir, assetRoot }) => {
|
|
804
|
+
// A bundle whose content sits in a subdirectory of the repo stages only that subdirectory, as
|
|
805
|
+
// `akm sync` does for a content root; a root-level bundle leaves `paths` to the managed-path default.
|
|
806
|
+
const assetPrefix = path.relative(repoDir, assetRoot).replaceAll(path.sep, "/");
|
|
807
|
+
if (!assetPrefix)
|
|
808
|
+
return {};
|
|
809
|
+
return resolveSyncPathSet({
|
|
810
|
+
repoDir,
|
|
811
|
+
assetPrefix,
|
|
812
|
+
changedPaths: listGitChangedPaths(repoDir),
|
|
813
|
+
initialPaths: new Set(),
|
|
814
|
+
writtenPaths: [],
|
|
815
|
+
provenance: false,
|
|
816
|
+
});
|
|
817
|
+
},
|
|
818
|
+
});
|
|
819
|
+
if (outcome?.reason)
|
|
820
|
+
warn(`[improve] pre-run sync: ${outcome.reason}; continuing on the local state`);
|
|
821
|
+
return outcome;
|
|
822
|
+
}
|
|
715
823
|
/**
|
|
716
824
|
* The auto-sync commit (#662), used at end of run and from the crash path:
|
|
717
825
|
* idempotent and never throws. The getters read bindings reassigned after this
|
|
718
826
|
* factory runs.
|
|
719
827
|
*/
|
|
720
828
|
function makeCommitStashBatch(deps) {
|
|
721
|
-
const {
|
|
722
|
-
return (messageContext) => {
|
|
723
|
-
const eventsCtx = deps.getEventsCtx();
|
|
829
|
+
const { effectiveSync } = deps.run;
|
|
830
|
+
return (messageContext, override) => {
|
|
724
831
|
const writeJournal = deps.getWriteJournal();
|
|
725
|
-
const repoDir = writeTarget?.source.repoPath ?? primaryStashDir;
|
|
726
|
-
if (!primaryStashDir || !repoDir || effectiveSync.enabled === false || !isGitBackedStash(repoDir)) {
|
|
727
|
-
return undefined;
|
|
728
|
-
}
|
|
729
|
-
const saveGitStashFn = options.saveGitStashFn ?? saveGitStash;
|
|
730
|
-
const writableOverride = writeTarget ? resolveWritable(writeTarget.config) : resolveWritableOverride(config);
|
|
731
|
-
const push = options.sync?.push ?? improveProfile.sync?.push ?? true;
|
|
732
832
|
const message = renderSyncCommitMessage(effectiveSync.message ?? "akm improve auto-sync", messageContext, Date.now());
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
skipped: syncResult.skipped,
|
|
752
|
-
reason: syncResult.reason ?? null,
|
|
753
|
-
attributed: paths.length,
|
|
754
|
-
unattributed: unattributed.length,
|
|
755
|
-
});
|
|
756
|
-
return {
|
|
757
|
-
committed: syncResult.committed,
|
|
758
|
-
pushed: syncResult.pushed,
|
|
759
|
-
skipped: syncResult.skipped,
|
|
760
|
-
...(syncResult.reason !== undefined ? { reason: syncResult.reason } : {}),
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
|
-
catch (syncErr) {
|
|
764
|
-
const reason = errMessage(syncErr);
|
|
765
|
-
warn(`improve: stash sync failed (non-fatal): ${reason}`);
|
|
766
|
-
record({ committed: false, pushed: false, skipped: true, reason });
|
|
767
|
-
return { committed: false, pushed: false, skipped: true, reason };
|
|
768
|
-
}
|
|
833
|
+
return runStashSync(deps.run, deps.getEventsCtx(), "end-of-run", {
|
|
834
|
+
message,
|
|
835
|
+
push: override?.push,
|
|
836
|
+
scopePaths: ({ repoDir, assetRoot }) => {
|
|
837
|
+
const { paths, unattributed } = resolveSyncPathSet({
|
|
838
|
+
repoDir,
|
|
839
|
+
assetPrefix: path.relative(repoDir, assetRoot).replaceAll(path.sep, "/"),
|
|
840
|
+
changedPaths: listGitChangedPaths(repoDir),
|
|
841
|
+
initialPaths: deps.getInitialGitPaths(),
|
|
842
|
+
writtenPaths: writeJournal?.writtenPaths() ?? [],
|
|
843
|
+
provenance: writeJournal !== undefined,
|
|
844
|
+
});
|
|
845
|
+
if (unattributed.length > 0) {
|
|
846
|
+
warnVerbose(`[improve] auto-sync left ${unattributed.length} path(s) uncommitted — not written by this run: ${unattributed.join(", ")}`);
|
|
847
|
+
}
|
|
848
|
+
return { paths, unattributed: unattributed.length };
|
|
849
|
+
},
|
|
850
|
+
});
|
|
769
851
|
};
|
|
770
852
|
}
|
|
771
853
|
/**
|
|
@@ -22,7 +22,7 @@ import { getLiveRefSnapshot, isRefLiveInSnapshot, } from "../../storage/reposito
|
|
|
22
22
|
import { clearAssetOutcomeMissing, countAssetOutcomeMissing, deleteAssetOutcomeMissingBefore, listAssetOutcomeMissingState, stampAssetOutcomeMissing, } from "../../storage/repositories/outcome-repository.js";
|
|
23
23
|
import { clearAssetSalienceMissing, countAssetSalienceMissing, deleteAssetSalienceMissingBefore, listAssetSalienceMissingState, stampAssetSalienceMissing, } from "../../storage/repositories/salience-repository.js";
|
|
24
24
|
import { readFreelistInfo, STATE_DB_VACUUMED_EVENT, vacuumIfReclaimable } from "../../storage/state-db-integrity.js";
|
|
25
|
-
import { purgeOldTaskLogFiles } from "../../tasks/run/task-log.js";
|
|
25
|
+
import { purgeOldRunLogFiles, purgeOldTaskLogFiles } from "../../tasks/run/task-log.js";
|
|
26
26
|
import { expireStaleProposals, purgeOrphanProposals } from "../proposal/repository.js";
|
|
27
27
|
import { checkDeadUrls } from "../url-checker.js";
|
|
28
28
|
import { isDistillCandidateRef } from "./eligibility.js";
|
|
@@ -148,7 +148,6 @@ async function runLoopReflectPass(planned, env, tally) {
|
|
|
148
148
|
...(options.sourceName && primaryStashDir ? { target: { source: options.sourceName, root: primaryStashDir } } : {}),
|
|
149
149
|
...(reflectErrors.length > 0 ? { avoidPatterns: [...reflectErrors] } : {}),
|
|
150
150
|
eventSource: "improve",
|
|
151
|
-
lowValueFilter: improveProfile.processes?.reflect?.lowValueFilter?.enabled === true,
|
|
152
151
|
...(improveProfile.processes?.reflect?.defectFilter
|
|
153
152
|
? { defectFilter: improveProfile.processes.reflect.defectFilter }
|
|
154
153
|
: {}),
|
|
@@ -174,10 +173,18 @@ async function runLoopReflectPass(planned, env, tally) {
|
|
|
174
173
|
result,
|
|
175
174
|
});
|
|
176
175
|
// A quality rejection recorded itself, and the judge's text is no lesson for
|
|
177
|
-
// the next prompt; skips revisit on the `unchanged` cadence.
|
|
176
|
+
// the next prompt; skips revisit on the `unchanged` cadence. A transient
|
|
177
|
+
// failure (transport, parse, timeout, budget abort, crash) is not a verdict
|
|
178
|
+
// on the asset and writes no row, like distill: a `failed` row would advance
|
|
179
|
+
// the ledger cursor and consume the feedback that planned the ref. Only a
|
|
180
|
+
// guard rejection records `failed`.
|
|
178
181
|
if (!result.ok && reason !== "quality_rejected") {
|
|
179
|
-
|
|
180
|
-
|
|
182
|
+
if (skipped)
|
|
183
|
+
recordLoopAttempt(planned, env, "reflect", "unchanged", reason);
|
|
184
|
+
else if (reason === "content_policy_reject")
|
|
185
|
+
recordLoopAttempt(planned, env, "reflect", "failed", reason);
|
|
186
|
+
// A budget abort is no lesson for the next prompt either.
|
|
187
|
+
if (!skipped && reason !== "aborted") {
|
|
181
188
|
tally.recentErrorPushes.push({
|
|
182
189
|
originator: "reflect",
|
|
183
190
|
message: result.error ?? reason ?? "unknown reflect error",
|
|
@@ -588,6 +595,12 @@ export function runRetentionPurgePass(ctx) {
|
|
|
588
595
|
catch (err) {
|
|
589
596
|
warnings.push(`task log files purge failed: ${errMessage(err)}`);
|
|
590
597
|
}
|
|
598
|
+
try {
|
|
599
|
+
report("run_log_files_purged", "run_log_files/_purge", purgeOldRunLogFiles(retentionDays), "improve/index run log file(s)");
|
|
600
|
+
}
|
|
601
|
+
catch (err) {
|
|
602
|
+
warnings.push(`run log files purge failed: ${errMessage(err)}`);
|
|
603
|
+
}
|
|
591
604
|
return { warnings };
|
|
592
605
|
}
|
|
593
606
|
/**
|
|
@@ -99,7 +99,6 @@ export function buildImproveExecutionPlan(input) {
|
|
|
99
99
|
effective: { ...input.consolidation.effective },
|
|
100
100
|
gates: {
|
|
101
101
|
profile: { ...input.consolidation.gates.profile },
|
|
102
|
-
minimumPool: { ...input.consolidation.gates.minimumPool },
|
|
103
102
|
delta: { ...input.consolidation.gates.delta },
|
|
104
103
|
},
|
|
105
104
|
},
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* Candidate selection reads the improve ledger plus one set of signals: a ref
|
|
10
10
|
* is eligible for a source when feedback newer than its last attempt landed and
|
|
11
11
|
* no ledger window holds it, and reflect reads only negative feedback. Refs
|
|
12
|
-
* without recent feedback can still be picked by the
|
|
13
|
-
*
|
|
12
|
+
* without recent feedback can still be picked by the proactive-maintenance
|
|
13
|
+
* lane, which plans them with the rest; the survivors are ranked
|
|
14
14
|
* by salience, checked on disk and capped. A plan-only run evaluates the same
|
|
15
15
|
* selectors against read snapshots and writes nothing.
|
|
16
16
|
*/
|
|
@@ -35,7 +35,7 @@ import { isAutonomyLaneAllowed } from "./autonomy-gate.js";
|
|
|
35
35
|
import { akmConsolidate, inspectConsolidationPool, loadExistingKnowledgeBodyHashes, makeConsolidateResult, } from "./consolidate.js";
|
|
36
36
|
import { computeSafeChunkSize, DEFAULT_CONTEXT_LENGTH_TOKENS } from "./consolidate/chunking.js";
|
|
37
37
|
import { contentHash } from "./content-hash.js";
|
|
38
|
-
import { assetTypeOf, buildUtilityMap, dedupeRefs, findAssetFilePath, isDistillCandidateRef, isLessonCandidate,
|
|
38
|
+
import { assetTypeOf, buildUtilityMap, dedupeRefs, findAssetFilePath, isDistillCandidateRef, isLessonCandidate, withIndexDb, } from "./eligibility.js";
|
|
39
39
|
import { akmExtract, countNewExtractCandidates } from "./extract.js";
|
|
40
40
|
import { computeValenceScore } from "./feedback-valence.js";
|
|
41
41
|
import { isLedgerBlocked, lastAttemptByRef, ledgerRowFor, loadLedgerSnapshot, stateKey, } from "./ledger.js";
|
|
@@ -81,7 +81,7 @@ export function pickDefined(source, keys) {
|
|
|
81
81
|
out[key] = source[key];
|
|
82
82
|
return out;
|
|
83
83
|
}
|
|
84
|
-
export const CONSOLIDATION_CONFIG_KEYS = ["enabled", "
|
|
84
|
+
export const CONSOLIDATION_CONFIG_KEYS = ["enabled", "limit", "maxChunkSize"];
|
|
85
85
|
/** Emit an aggregate `improve_skipped` row (never one per ref). */
|
|
86
86
|
export function recordImproveSkip(eventsCtx, ref, metadata) {
|
|
87
87
|
appendEvent({ eventType: "improve_skipped", ref, metadata }, eventsCtx);
|
|
@@ -96,19 +96,13 @@ export function pushRecentError(recentErrors, originator, msg) {
|
|
|
96
96
|
}
|
|
97
97
|
// ── Consolidation ────────────────────────────────────────────────────────────
|
|
98
98
|
/**
|
|
99
|
-
* The consolidation gates and pool, with no model call: the profile toggle
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* judged recently and unchanged since means nothing to do).
|
|
99
|
+
* The consolidation gates and pool, with no model call: the profile toggle
|
|
100
|
+
* and the ledger delta (every memory judged recently and unchanged since
|
|
101
|
+
* means nothing to do).
|
|
103
102
|
*/
|
|
104
103
|
function planConsolidationPass(args) {
|
|
105
|
-
const { options, primaryStashDir,
|
|
104
|
+
const { options, primaryStashDir, resolvedPlan } = args;
|
|
106
105
|
const processConfig = args.improveProfile?.processes?.consolidate;
|
|
107
|
-
const volumeTriggered = memorySummary.eligible > 100 && resolvedPlan.processes.consolidate.runner !== null;
|
|
108
|
-
const minPoolSize = typeof processConfig?.minPoolSize === "number" ? processConfig.minPoolSize : 0;
|
|
109
|
-
const eligiblePoolSize = typeof memorySummary.eligible === "number" ? memorySummary.eligible : 0;
|
|
110
|
-
const userNamed = options.strategy !== undefined || resolveImproveScope(options.scope).mode === "ref";
|
|
111
|
-
const poolBelowMinSize = !volumeTriggered && !userNamed && minPoolSize > 0 && eligiblePoolSize < minPoolSize;
|
|
112
106
|
const pool = primaryStashDir
|
|
113
107
|
? inspectConsolidationPool({
|
|
114
108
|
config: options.config,
|
|
@@ -127,18 +121,13 @@ function planConsolidationPass(args) {
|
|
|
127
121
|
DEFAULT_CONTEXT_LENGTH_TOKENS, 500, processConfig?.maxChunkSize);
|
|
128
122
|
const profilePassed = processConfig?.enabled !== false;
|
|
129
123
|
const deltaPassed = pool.candidatePoolSize > 0 || pool.judgedUnchanged === 0;
|
|
130
|
-
const wouldRun = profilePassed &&
|
|
131
|
-
const belowMin = `pool ${eligiblePoolSize} is below minPoolSize ${minPoolSize}`;
|
|
124
|
+
const wouldRun = profilePassed && deltaPassed && pool.candidatePoolSize > 0;
|
|
132
125
|
const unchanged = "every memory was judged recently and is unchanged since";
|
|
133
126
|
return {
|
|
134
|
-
poolBelowMinSize,
|
|
135
|
-
eligiblePoolSize,
|
|
136
|
-
minPoolSize,
|
|
137
127
|
plan: {
|
|
138
128
|
configured: pickDefined(processConfig, CONSOLIDATION_CONFIG_KEYS),
|
|
139
129
|
effective: {
|
|
140
130
|
enabled: profilePassed,
|
|
141
|
-
minPoolSize,
|
|
142
131
|
...(processConfig?.limit !== undefined ? { limit: processConfig.limit } : {}),
|
|
143
132
|
chunkSize,
|
|
144
133
|
},
|
|
@@ -149,10 +138,6 @@ function planConsolidationPass(args) {
|
|
|
149
138
|
passed: profilePassed,
|
|
150
139
|
reason: profilePassed ? "consolidation enabled" : "disabled by improve profile",
|
|
151
140
|
},
|
|
152
|
-
minimumPool: {
|
|
153
|
-
passed: !poolBelowMinSize,
|
|
154
|
-
reason: poolBelowMinSize ? belowMin : `pool satisfies minPoolSize ${minPoolSize}`,
|
|
155
|
-
},
|
|
156
141
|
delta: {
|
|
157
142
|
passed: deltaPassed,
|
|
158
143
|
reason: !deltaPassed
|
|
@@ -165,13 +150,11 @@ function planConsolidationPass(args) {
|
|
|
165
150
|
wouldRun,
|
|
166
151
|
reason: !profilePassed
|
|
167
152
|
? "disabled by improve profile"
|
|
168
|
-
:
|
|
169
|
-
?
|
|
170
|
-
:
|
|
171
|
-
?
|
|
172
|
-
:
|
|
173
|
-
? "candidate pool is empty after narrowing"
|
|
174
|
-
: "all consolidation gates pass",
|
|
153
|
+
: !deltaPassed
|
|
154
|
+
? unchanged
|
|
155
|
+
: pool.candidatePoolSize === 0
|
|
156
|
+
? "candidate pool is empty after narrowing"
|
|
157
|
+
: "all consolidation gates pass",
|
|
175
158
|
estimatedChunks: wouldRun ? Math.ceil(pool.candidatePoolSize / chunkSize) : 0,
|
|
176
159
|
},
|
|
177
160
|
};
|
|
@@ -186,14 +169,6 @@ async function runConsolidationPass(args) {
|
|
|
186
169
|
if (!planned.plan.gates.profile.passed) {
|
|
187
170
|
info("[improve] consolidation skipped (disabled by improve profile)");
|
|
188
171
|
}
|
|
189
|
-
else if (planned.poolBelowMinSize) {
|
|
190
|
-
recordImproveSkip(eventsCtx, "memories/_consolidation", {
|
|
191
|
-
reason: "pool_below_min_size",
|
|
192
|
-
poolSize: planned.eligiblePoolSize,
|
|
193
|
-
minPoolSize: planned.minPoolSize,
|
|
194
|
-
});
|
|
195
|
-
info(`[improve] consolidation skipped (pool ${planned.eligiblePoolSize} < minPoolSize ${planned.minPoolSize})`);
|
|
196
|
-
}
|
|
197
172
|
else if (!planned.plan.gates.delta.passed) {
|
|
198
173
|
recordImproveSkip(eventsCtx, "memories/_consolidation", { reason: "consolidation_no_memory_updates" });
|
|
199
174
|
info("[improve] consolidation skipped (every memory was judged recently and is unchanged)");
|
|
@@ -212,7 +187,6 @@ async function runConsolidationPass(args) {
|
|
|
212
187
|
limit: processConfig?.limit,
|
|
213
188
|
maxChunkSize: processConfig?.maxChunkSize,
|
|
214
189
|
signal: args.budgetSignal,
|
|
215
|
-
p90ChunkSecondsDefault: processConfig?.p90ChunkSecondsDefault,
|
|
216
190
|
// Its read-only proposal lookups go through the run's own state.db handle.
|
|
217
191
|
...(eventsCtx?.db ? { proposalsCtx: { db: eventsCtx.db } } : {}),
|
|
218
192
|
}));
|
|
@@ -671,7 +645,7 @@ export function buildSnapshotManifest(args) {
|
|
|
671
645
|
* - distillOnlyRefs: only distill's passes (any signal, a positive or a note
|
|
672
646
|
* included), on a distill candidate;
|
|
673
647
|
* - noFeedbackPool: no recent feedback and no reflect window, left to the
|
|
674
|
-
*
|
|
648
|
+
* proactive-maintenance lane;
|
|
675
649
|
* - fullySkippedCount: feedback on record but nothing new, or a live window.
|
|
676
650
|
* An explicit `--scope <ref>` bypasses every gate.
|
|
677
651
|
*/
|
|
@@ -722,12 +696,12 @@ export function partitionBySignalDelta(args) {
|
|
|
722
696
|
return out;
|
|
723
697
|
}
|
|
724
698
|
/**
|
|
725
|
-
* Pick the loop's refs: signal delta, the
|
|
726
|
-
* `--require-feedback-signal
|
|
727
|
-
*
|
|
699
|
+
* Pick the loop's refs: signal delta, the proactive-maintenance lane (unless
|
|
700
|
+
* `--require-feedback-signal`), lane attribution, salience, the no-op-dampened
|
|
701
|
+
* ranking, the disk check and the limit.
|
|
728
702
|
*/
|
|
729
703
|
async function selectLoopCandidates(args, postCleanupRefs, validationFailureRefs, actions, persist) {
|
|
730
|
-
const { scope, options, primaryStashDir, eventsCtx
|
|
704
|
+
const { scope, options, primaryStashDir, eventsCtx } = args;
|
|
731
705
|
const snapshot = buildSnapshotManifest({
|
|
732
706
|
postCleanupRefs,
|
|
733
707
|
validationFailureRefs,
|
|
@@ -739,9 +713,8 @@ async function selectLoopCandidates(args, postCleanupRefs, validationFailureRefs
|
|
|
739
713
|
const processableRefs = [...partition.eligibleRefs, ...partition.distillOnlyRefs];
|
|
740
714
|
const signalFiltered = processableRefs.filter((c) => snapshot.feedback.get(c.ref)?.hasSignal === true);
|
|
741
715
|
const signalBearingSet = new Set(signalFiltered.map((r) => r.ref));
|
|
742
|
-
// The
|
|
743
|
-
//
|
|
744
|
-
// never processed (#986). Evaluated once per candidate.
|
|
716
|
+
// The proactive lane has no usage evidence of its own: it picks only what
|
|
717
|
+
// retrieval returned or new material improve never processed (#986). Evaluated once per candidate.
|
|
745
718
|
const fallbackEligible = postCleanupRefs.filter((c) => !validationFailureRefs.has(c.ref));
|
|
746
719
|
const allowFallbacks = options.requireFeedbackSignal !== true;
|
|
747
720
|
const retrievalScope = scope.mode === "ref" || !allowFallbacks
|
|
@@ -753,22 +726,20 @@ async function selectLoopCandidates(args, postCleanupRefs, validationFailureRefs
|
|
|
753
726
|
...partition.noFeedbackPool,
|
|
754
727
|
]);
|
|
755
728
|
const noFeedbackCandidates = noFeedbackPool.filter((r) => !unscoped.has(r.ref));
|
|
756
|
-
// Only a ref
|
|
729
|
+
// Only a ref the proactive lane may not pick is charged to the retrieval gate.
|
|
757
730
|
const outOfScope = new Set(noFeedbackPool.filter((r) => unscoped.has(r.ref)).map((r) => r.ref));
|
|
758
731
|
const retrieval = fetchRetrievalSignals(options, signalFiltered, noFeedbackCandidates, eventsCtx, persist);
|
|
759
732
|
const proactive = allowFallbacks
|
|
760
733
|
? selectProactiveMaintenanceLane(args, noFeedbackCandidates, snapshot, retrieval, persist)
|
|
761
734
|
: { proactiveRefs: [] };
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
//
|
|
766
|
-
//
|
|
767
|
-
const signalAndRetrievalRefs = dedupeRefs([...signalFiltered, ...proactive.proactiveRefs, ...highSalienceRefs]);
|
|
768
|
-
const mergedRefs = scope.mode === "ref" ? processableRefs : signalFiltered;
|
|
769
|
-
const scoredRefs = scope.mode === "ref" ? processableRefs : signalAndRetrievalRefs;
|
|
770
|
-
// Lane attribution: signal-delta, and an explicit ref scope over it.
|
|
735
|
+
// Planned: signal-delta refs plus the proactive lane's picks (whole-stash / type scope); an explicit ref scope
|
|
736
|
+
// acts on its own refs.
|
|
737
|
+
const mergedRefs = scope.mode === "ref" ? processableRefs : dedupeRefs([...signalFiltered, ...proactive.proactiveRefs]);
|
|
738
|
+
// Lane attribution, weakest first so the strongest wins: proactive < signal-delta, and an explicit ref scope
|
|
739
|
+
// over everything.
|
|
771
740
|
const sourceByRef = new Map();
|
|
741
|
+
for (const r of proactive.proactiveRefs)
|
|
742
|
+
sourceByRef.set(r.ref, "proactive");
|
|
772
743
|
for (const r of signalFiltered)
|
|
773
744
|
sourceByRef.set(r.ref, "signal-delta");
|
|
774
745
|
if (scope.mode === "ref")
|
|
@@ -776,7 +747,7 @@ async function selectLoopCandidates(args, postCleanupRefs, validationFailureRefs
|
|
|
776
747
|
sourceByRef.set(r.ref, "scope");
|
|
777
748
|
for (const r of mergedRefs)
|
|
778
749
|
r.eligibilitySource = sourceByRef.get(r.ref) ?? "unknown";
|
|
779
|
-
const salienceMap = scoreSalience(args,
|
|
750
|
+
const salienceMap = scoreSalience(args, mergedRefs, snapshot.feedback, retrieval.retrievalCounts, persist);
|
|
780
751
|
// Rank by salience; a ref skipped as a no-op repeatedly sorts lower (its stored rank is untouched).
|
|
781
752
|
const noOps = new Map();
|
|
782
753
|
withRunState(eventsCtx, persist, (db) => {
|
|
@@ -795,8 +766,8 @@ async function selectLoopCandidates(args, postCleanupRefs, validationFailureRefs
|
|
|
795
766
|
distillOnlyRefs: partition.distillOnlyRefs,
|
|
796
767
|
limit: options.limit,
|
|
797
768
|
});
|
|
798
|
-
if (
|
|
799
|
-
info(`[improve] ${
|
|
769
|
+
if (mergedRefs.length > 0) {
|
|
770
|
+
info(`[improve] ${mergedRefs.length} refs with usage signals (${signalFiltered.length} feedback)`);
|
|
800
771
|
}
|
|
801
772
|
if (validationFailureRefs.size > 0)
|
|
802
773
|
info(`[improve] ${validationFailureRefs.size} with validation failures excluded`);
|
|
@@ -883,11 +854,11 @@ function fetchRetrievalSignals(options, signalFiltered, noFeedbackCandidates, ev
|
|
|
883
854
|
return out;
|
|
884
855
|
}
|
|
885
856
|
/**
|
|
886
|
-
* Proactive maintenance (default
|
|
887
|
-
* assets due for a revisit
|
|
888
|
-
*
|
|
889
|
-
*
|
|
890
|
-
*
|
|
857
|
+
* Proactive maintenance (default on, whole-stash/type runs): pick stable
|
|
858
|
+
* assets due for a revisit and plan them with the feedback-bearing refs. The
|
|
859
|
+
* cap against a proposal flood: `maxPerRun` limits the picks per run, the due
|
|
860
|
+
* gate admits only an asset not reflected or distilled for `dueDays` (so each
|
|
861
|
+
* comes up at most once per `dueDays`), and reflect's `limit` bounds the run.
|
|
891
862
|
*/
|
|
892
863
|
function selectProactiveMaintenanceLane(args, candidates, snapshot, retrieval, persist) {
|
|
893
864
|
if (args.scope.mode === "ref" || !args.resolvedPlan.processes.proactiveMaintenance.enabled) {
|
|
@@ -895,7 +866,7 @@ function selectProactiveMaintenanceLane(args, candidates, snapshot, retrieval, p
|
|
|
895
866
|
}
|
|
896
867
|
const pmCfg = args.improveProfile.processes?.proactiveMaintenance;
|
|
897
868
|
const dueDays = pmCfg?.dueDays ?? DEFAULT_DUE_DAYS;
|
|
898
|
-
const maxPerRun = pmCfg?.maxPerRun ??
|
|
869
|
+
const maxPerRun = pmCfg?.maxPerRun ?? DEFAULT_MAX_PER_RUN;
|
|
899
870
|
const selection = selectProactiveMaintenanceRefs({
|
|
900
871
|
candidates,
|
|
901
872
|
lastReflectTs: snapshot.lastReflectAttemptAt,
|
|
@@ -927,7 +898,7 @@ function selectProactiveMaintenanceLane(args, candidates, snapshot, retrieval, p
|
|
|
927
898
|
proactiveRefs: selection.selected,
|
|
928
899
|
proactiveMaintenanceSummary: { ...summary, selectedRefs },
|
|
929
900
|
proactivePlan: {
|
|
930
|
-
configured: pickDefined(pmCfg, ["dueDays", "maxPerRun"
|
|
901
|
+
configured: pickDefined(pmCfg, ["dueDays", "maxPerRun"]),
|
|
931
902
|
effective: { dueDays, maxPerRun },
|
|
932
903
|
candidatePool: candidates.length,
|
|
933
904
|
...summary,
|
|
@@ -935,41 +906,13 @@ function selectProactiveMaintenanceLane(args, candidates, snapshot, retrieval, p
|
|
|
935
906
|
},
|
|
936
907
|
};
|
|
937
908
|
}
|
|
938
|
-
/**
|
|
939
|
-
* High salience: zero-feedback refs whose content-derived encoding score (not
|
|
940
|
-
* a per-type stub) reaches `salienceThreshold` and that were never reflected,
|
|
941
|
-
* top-N by score, capped at 10% of the effective limit. The picks are scored,
|
|
942
|
-
* never planned.
|
|
943
|
-
*/
|
|
944
|
-
function selectHighSalienceLane(options, improveProfile, eventsCtx, candidates, lastReflectAttemptAt, persist) {
|
|
945
|
-
const threshold = (options.config ?? loadConfig()).improve?.salience?.salienceThreshold ?? 0.75;
|
|
946
|
-
const effectiveLimit = options.limit ?? improveProfile?.processes?.reflect?.limit ?? improveProfile.limit ?? 10;
|
|
947
|
-
const selected = withRunState(eventsCtx, persist, (db) => candidates
|
|
948
|
-
.flatMap((r) => {
|
|
949
|
-
const row = getAssetSalience(db, keyOf(r));
|
|
950
|
-
return row &&
|
|
951
|
-
isContentEncodingRow(row) &&
|
|
952
|
-
row.encoding_salience >= threshold &&
|
|
953
|
-
!lastReflectAttemptAt.has(r.ref)
|
|
954
|
-
? [{ ref: r, score: row.encoding_salience }]
|
|
955
|
-
: [];
|
|
956
|
-
})
|
|
957
|
-
.sort((a, b) => b.score - a.score)
|
|
958
|
-
.slice(0, Math.max(1, Math.floor(effectiveLimit * 0.1)))
|
|
959
|
-
.map((q) => q.ref)) ?? [];
|
|
960
|
-
if (selected.length > 0) {
|
|
961
|
-
info(`[improve] high-salience lane admitted ${selected.length} content-scored ref(s) ` +
|
|
962
|
-
`(threshold=${threshold}, requires content-derived encoding_source)`);
|
|
963
|
-
}
|
|
964
|
-
return selected;
|
|
965
|
-
}
|
|
966
909
|
/**
|
|
967
910
|
* Score the merged refs: update `asset_outcome` (projected on a plan-only
|
|
968
911
|
* run), compute each salience vector (keeping a stored content-derived
|
|
969
912
|
* encoding score), then persist it.
|
|
970
913
|
*/
|
|
971
914
|
function scoreSalience(args, mergedRefs, feedback, retrievalCounts, persist) {
|
|
972
|
-
const {
|
|
915
|
+
const { eventsCtx } = args;
|
|
973
916
|
const utilityMap = buildUtilityMap(mergedRefs, !persist);
|
|
974
917
|
const lastUseMsByRef = withIndexDb(!persist, (db) => getLastUseMsByRef(db, mergedRefs)) ?? new Map();
|
|
975
918
|
const outcomeSalience = updateOutcomeScores({
|
|
@@ -982,7 +925,6 @@ function scoreSalience(args, mergedRefs, feedback, retrievalCounts, persist) {
|
|
|
982
925
|
eventsCtx,
|
|
983
926
|
persist,
|
|
984
927
|
});
|
|
985
|
-
const outcomeWeightEnabled = (options.config ?? loadConfig()).improve?.salience?.outcomeWeightEnabled !== false;
|
|
986
928
|
const storedEncoding = new Map();
|
|
987
929
|
withRunState(eventsCtx, persist, (db) => {
|
|
988
930
|
for (const r of mergedRefs) {
|
|
@@ -1005,7 +947,6 @@ function scoreSalience(args, mergedRefs, feedback, retrievalCounts, persist) {
|
|
|
1005
947
|
outcomeSalience: outcomeSalience.get(r.ref),
|
|
1006
948
|
sizeBytes: fileSize(r.filePath),
|
|
1007
949
|
now,
|
|
1008
|
-
outcomeWeightEnabled,
|
|
1009
950
|
}));
|
|
1010
951
|
}
|
|
1011
952
|
if (persist) {
|
|
@@ -6,8 +6,8 @@ import { computeSalience } from "./salience.js";
|
|
|
6
6
|
const DAY_MS = 86_400_000;
|
|
7
7
|
/** An asset is due when last reflected/distilled more than this many days ago (or never). */
|
|
8
8
|
export const DEFAULT_DUE_DAYS = 30;
|
|
9
|
-
/**
|
|
10
|
-
export const DEFAULT_MAX_PER_RUN =
|
|
9
|
+
/** Fallback for `maxPerRun`; the same as the shipped `default` strategy. */
|
|
10
|
+
export const DEFAULT_MAX_PER_RUN = 15;
|
|
11
11
|
/** Size floor for the cost term, so tiny files don't divide by ~0. */
|
|
12
12
|
const SIZE_FLOOR_BYTES = 200;
|
|
13
13
|
/**
|