akm-cli 0.9.17-alpha.2 → 0.9.17-alpha.4
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 +756 -0
- package/dist/akm +94 -196
- package/dist/cli/shared.js +6 -2
- package/dist/cli.js +22 -9
- package/dist/commands/agent/agent-dispatch.js +1 -1
- package/dist/commands/command/command-execution.js +24 -62
- package/dist/commands/feedback-cli.js +0 -1
- package/dist/commands/health/accept-rate.js +2 -2
- package/dist/commands/health/checks.js +30 -75
- package/dist/commands/health/config-skew.js +38 -0
- package/dist/commands/health/egress.js +54 -0
- package/dist/commands/health/html-report.js +0 -38
- package/dist/commands/health/improve-metrics.js +123 -562
- package/dist/commands/health/plugin-staleness.js +53 -3
- package/dist/commands/health/renderers.js +12 -4
- package/dist/commands/health/report-view-model.js +11 -106
- package/dist/commands/health/types-improve.js +4 -19
- package/dist/commands/health/windows.js +64 -73
- package/dist/commands/health.js +122 -143
- package/dist/commands/improve/consolidate/chunking.js +25 -100
- package/dist/commands/improve/consolidate/sanitize.js +54 -149
- package/dist/commands/improve/consolidate.js +538 -1075
- package/dist/commands/improve/content-hash.js +16 -24
- package/dist/commands/improve/distill/content-repair.js +18 -100
- package/dist/commands/improve/distill-guards.js +20 -81
- package/dist/commands/improve/distill-promotion-policy.js +23 -243
- package/dist/commands/improve/distill.js +608 -1075
- package/dist/commands/improve/eligibility.js +126 -400
- package/dist/commands/improve/execution.js +3 -5
- package/dist/commands/improve/extract.js +487 -1046
- package/dist/commands/improve/feedback-valence.js +0 -25
- package/dist/commands/improve/improve-cli.js +29 -166
- package/dist/commands/improve/improve-result-file.js +10 -66
- package/dist/commands/improve/improve-strategies.js +12 -7
- package/dist/commands/improve/improve-usage-report.js +18 -64
- package/dist/commands/improve/improve.js +443 -1063
- package/dist/commands/improve/ledger.js +114 -0
- package/dist/commands/improve/locks.js +2 -8
- package/dist/commands/improve/loop-stages.js +459 -1172
- package/dist/commands/improve/memory/derived-ref.js +12 -77
- package/dist/commands/improve/memory/memory-belief.js +14 -118
- package/dist/commands/improve/memory/memory-improve.js +4 -3
- package/dist/commands/improve/outcome-loop.js +28 -156
- package/dist/commands/improve/planner.js +5 -10
- package/dist/commands/improve/preparation.js +851 -2339
- package/dist/commands/improve/proactive-maintenance.js +34 -101
- package/dist/commands/improve/reflect-noise.js +104 -280
- package/dist/commands/improve/reflect.js +621 -1367
- package/dist/commands/improve/salience.js +46 -232
- package/dist/commands/improve/session-asset.js +19 -100
- package/dist/commands/improve/stage.js +323 -0
- package/dist/commands/proposal/drain.js +251 -644
- package/dist/commands/proposal/proposal-cli.js +3 -18
- package/dist/commands/proposal/proposal-types.js +20 -41
- package/dist/commands/proposal/proposal.js +1 -2
- package/dist/commands/proposal/propose.js +134 -160
- package/dist/commands/proposal/repository.js +502 -1487
- package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
- package/dist/commands/proposal/validators/proposal-validators.js +1 -1
- package/dist/commands/proposal/validators/proposals.js +13 -89
- package/dist/commands/read/curate.js +63 -413
- package/dist/commands/read/search-cli.js +16 -33
- package/dist/commands/read/search.js +17 -23
- package/dist/commands/read/show.js +2 -13
- package/dist/commands/sources/bundle-cli.js +25 -2
- package/dist/commands/sources/bundle-config-ops.js +7 -0
- package/dist/commands/sources/dangerous-env-audit.js +1 -2
- package/dist/commands/sources/info.js +2 -11
- package/dist/commands/sources/installed-stashes.js +197 -746
- package/dist/commands/sources/schema-repair.js +98 -129
- package/dist/commands/sources/source-add.js +62 -12
- package/dist/commands/sources/stash-cli.js +1 -1
- package/dist/commands/tasks/explain.js +10 -13
- package/dist/commands/tasks/tasks-cli.js +9 -8
- package/dist/commands/tasks/tasks.js +326 -930
- package/dist/commands/tasks/validate.js +42 -21
- package/dist/commands/workflow/plan.js +22 -29
- package/dist/commands/workflow-cli.js +4 -4
- package/dist/core/adapter/adapters/akm-adapter.js +0 -1
- package/dist/core/adapter/adapters/akm-lint.js +2 -3
- package/dist/core/adapter/adapters/akm-metadata.js +11 -12
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +17 -29
- package/dist/core/asset/resolve-ref.js +1 -1
- package/dist/core/bundle-id.js +42 -5
- package/dist/core/bundle-rename.js +291 -0
- package/dist/core/config/config-io.js +1 -2
- package/dist/core/config/config-schema.js +1 -33
- package/dist/core/config/config-walker.js +1 -1
- package/dist/core/config/config.js +163 -68
- package/dist/core/config/legacy-source-shape-shim.js +38 -9
- package/dist/core/config/schema/embedding.js +20 -5
- package/dist/core/config/schema/engines.js +5 -0
- package/dist/core/config/schema/execution.js +1 -1
- package/dist/core/config/schema/experimental.js +1 -1
- package/dist/core/config/schema/improve-processes.js +21 -95
- package/dist/core/config/schema/improve.js +4 -42
- package/dist/core/config/schema/scheduler.js +12 -12
- package/dist/core/config/schema/search.js +6 -22
- package/dist/core/env-secret-ref.js +0 -1
- package/dist/core/errors.js +8 -9
- package/dist/core/file-lock.js +76 -173
- package/dist/core/logs-db.js +2 -2
- package/dist/core/paths.js +0 -27
- package/dist/core/redaction.js +109 -2
- package/dist/core/run-lock.js +2 -5
- package/dist/core/spawn-env.js +1 -1
- package/dist/core/state/migrations.js +108 -61
- package/dist/core/state-db-scope.js +2 -4
- package/dist/core/state-db.js +126 -692
- package/dist/core/type-presentation.js +1 -9
- package/dist/core/write-source.js +293 -1012
- package/dist/execution/input-contract.js +1 -1
- package/dist/execution/resolved-request.js +135 -689
- package/dist/execution/source.js +63 -257
- package/dist/execution/target-ref.js +1 -1
- package/dist/indexer/bundle-identity-guard.js +2 -2
- package/dist/indexer/db/graph-db.js +106 -46
- package/dist/indexer/ensure-index.js +44 -85
- package/dist/indexer/graph/graph-extraction.js +340 -562
- package/dist/indexer/graph/graph-related.js +130 -0
- package/dist/indexer/index-rebuild-lock.js +3 -11
- package/dist/indexer/index-writer-lock.js +8 -17
- package/dist/indexer/index-written-assets.js +139 -151
- package/dist/indexer/indexer.js +524 -846
- package/dist/indexer/materialize-embeddings.js +60 -397
- package/dist/indexer/passes/memory-inference.js +81 -90
- package/dist/indexer/passes/metadata.js +132 -200
- package/dist/indexer/read-preflight.js +0 -7
- package/dist/indexer/scan/doc-to-entry.js +1 -3
- package/dist/indexer/scan/drain-dir.js +1 -1
- package/dist/indexer/search/db-search.js +181 -590
- package/dist/indexer/search/fts-query.js +30 -41
- package/dist/indexer/search/ranking.js +28 -154
- package/dist/indexer/search/search-attribution.js +12 -32
- package/dist/indexer/search/search-fields.js +11 -15
- package/dist/indexer/search/search-hit-enrichers.js +54 -85
- package/dist/indexer/search/search-source.js +1 -4
- package/dist/indexer/usage/usage-events.js +2 -7
- package/dist/integrations/agent/engine-fallback.js +23 -40
- package/dist/integrations/agent/engine-resolution.js +93 -183
- package/dist/integrations/agent/execution.js +507 -0
- package/dist/integrations/agent/model-map.js +28 -156
- package/dist/integrations/agent/request-lowering.js +66 -141
- package/dist/integrations/agent/runner-dispatch.js +143 -321
- package/dist/integrations/agent/runner.js +54 -14
- package/dist/integrations/lockfile.js +53 -101
- package/dist/llm/embedders/deterministic.js +2 -3
- package/dist/llm/embedders/profile.js +71 -0
- package/dist/llm/embedders/remote.js +10 -15
- package/dist/llm/graph-extract.js +3 -12
- package/dist/llm/index-passes.js +3 -5
- package/dist/llm/memory-infer.js +1 -2
- package/dist/llm/metadata-enhance.js +1 -2
- package/dist/llm/structured-call.js +5 -24
- package/dist/output/generic-render.js +23 -11
- package/dist/output/html-render.js +13 -10
- package/dist/output/render-registry.js +3 -32
- package/dist/output/shapes/helpers.js +2 -34
- package/dist/output/shapes/passthrough.js +1 -9
- package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
- package/dist/output/text/command-format.js +60 -23
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +5 -14
- package/dist/output/text/proposal-format.js +1 -2
- package/dist/output/text/workflow-format.js +0 -32
- package/dist/output/text.js +2 -0
- package/dist/registry/factory.js +4 -19
- package/dist/registry/network.js +66 -220
- package/dist/registry/providers/index.js +0 -2
- package/dist/registry/providers/skills-sh.js +3 -14
- package/dist/registry/providers/static-index.js +24 -26
- package/dist/registry/resolve.js +55 -131
- package/dist/scripts/akm-migrate-node.js +43937 -93313
- package/dist/scripts/akm-migrate.js +43697 -93071
- package/dist/setup/registry-stash-loader.js +4 -13
- package/dist/setup/semantic-assets.js +3 -44
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/tasks.js +25 -15
- package/dist/sources/provider-factory.js +17 -18
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +7 -1
- package/dist/sources/providers/git-provider.js +0 -3
- package/dist/sources/providers/git-stash.js +0 -17
- package/dist/sources/providers/npm.js +2 -4
- package/dist/sources/providers/provider-utils.js +5 -10
- package/dist/sources/providers/website.js +0 -2
- package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
- package/dist/sources/website-url.js +2 -2
- package/dist/storage/database.js +9 -35
- package/dist/storage/repositories/improve-ledger-repository.js +168 -0
- package/dist/storage/repositories/index-connection.js +34 -70
- package/dist/storage/repositories/index-entries-repository.js +69 -111
- package/dist/storage/repositories/index-entry-mapper.js +1 -2
- package/dist/storage/repositories/index-entry-schema.js +83 -269
- package/dist/storage/repositories/index-fts-repository.js +86 -256
- package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
- package/dist/storage/repositories/index-meta-repository.js +6 -4
- package/dist/storage/repositories/index-schema.js +192 -220
- package/dist/storage/repositories/index-utility-repository.js +8 -29
- package/dist/storage/repositories/index-vec-repository.js +133 -414
- package/dist/storage/repositories/outcome-repository.js +2 -1
- package/dist/storage/repositories/proposals-repository.js +35 -0
- package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
- package/dist/storage/repositories/task-history-repository.js +26 -4
- package/dist/storage/repositories/workflow-runs-repository.js +53 -244
- package/dist/storage/sqlite-migrations.js +136 -0
- package/dist/storage/sqlite-pragmas.js +11 -9
- package/dist/storage/sqlite-transaction.js +170 -0
- package/dist/storage/state-db-integrity.js +34 -27
- package/dist/tasks/activation-config.js +134 -62
- package/dist/tasks/backends/cron.js +129 -277
- package/dist/tasks/backends/exec-utils.js +2 -5
- package/dist/tasks/backends/launchd.js +125 -745
- package/dist/tasks/backends/schtasks.js +101 -620
- package/dist/tasks/prepare/prepare-support.js +5 -15
- package/dist/tasks/prepare/prepare.js +0 -2
- package/dist/tasks/resolve-akm-bin.js +20 -79
- package/dist/tasks/run/attempt-lifecycle.js +0 -1
- package/dist/tasks/scheduler-binding.js +18 -238
- package/dist/tasks/scheduler-invocation.js +52 -52
- package/dist/tasks/scheduler-lock.js +53 -0
- package/dist/tasks/scheduler-sync.js +363 -679
- package/dist/tasks/source/parse-task-source.js +160 -10
- package/dist/tasks/source/task-source-v3-frozen.js +3 -4
- package/dist/tasks/source/task-to-v4.js +2 -2
- package/dist/workflows/authoring/authoring.js +3 -12
- package/dist/workflows/compile.js +211 -0
- package/dist/workflows/concurrency-policy.js +13 -74
- package/dist/workflows/exec/child-invocation.js +3 -17
- package/dist/workflows/exec/child-workflow.js +32 -141
- package/dist/workflows/exec/dispatch-redaction.js +13 -53
- package/dist/workflows/exec/environment.js +98 -0
- package/dist/workflows/exec/exec-unit.js +33 -140
- package/dist/workflows/exec/frozen-judge.js +7 -59
- package/dist/workflows/exec/native-executor.js +82 -341
- package/dist/workflows/exec/param-secrets.js +29 -47
- package/dist/workflows/exec/run-workflow.js +154 -387
- package/dist/workflows/exec/scheduler.js +9 -36
- package/dist/workflows/exec/step-work.js +127 -430
- package/dist/workflows/exec/unit-dispatch.js +11 -63
- package/dist/workflows/exec/unit-writer.js +8 -52
- package/dist/workflows/exec/worktree.js +39 -273
- package/dist/workflows/freeze/child-output-references.js +4 -15
- package/dist/workflows/freeze/environment.js +99 -92
- package/dist/workflows/freeze/freeze.js +172 -0
- package/dist/workflows/freeze/step-values.js +19 -21
- package/dist/workflows/freeze/targets/child-workflow.js +23 -92
- package/dist/workflows/freeze/targets/command.js +10 -33
- package/dist/workflows/freeze/targets/script.js +5 -12
- package/dist/workflows/freeze/targets/shell.js +3 -6
- package/dist/workflows/freeze/targets/task.js +25 -80
- package/dist/workflows/freeze/task-bindings.js +20 -67
- package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
- package/dist/workflows/ir/params.js +6 -51
- package/dist/workflows/ir/plan-hash.js +2 -34
- package/dist/workflows/parser.js +140 -43
- package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
- package/dist/workflows/renderer.js +36 -69
- package/dist/workflows/resource-limits.js +12 -120
- package/dist/workflows/runtime/agent-identity.js +8 -40
- package/dist/workflows/runtime/run-outputs.js +3 -6
- package/dist/workflows/runtime/run-plan.js +316 -0
- package/dist/workflows/runtime/runs.js +48 -200
- package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
- package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
- package/dist/workflows/validate-summary.js +2 -7
- package/docs/integration/bundling-akm.md +49 -42
- package/docs/migration/README.md +1 -0
- package/docs/migration/release-notes/0.9.17.md +41 -0
- package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
- package/docs/reference/cli.md +182 -125
- package/docs/reference/configuration.md +49 -56
- package/docs/reference/data-and-telemetry.md +19 -20
- package/docs/reference/tasks.md +86 -38
- package/docs/reference/workflow-schema.md +14 -18
- package/docs/reference/workflows.md +6 -9
- package/package.json +1 -1
- package/schemas/akm-config.json +87 -406
- package/dist/commands/health/advisories.js +0 -150
- package/dist/commands/health/metrics.js +0 -329
- package/dist/commands/health/surfaces.js +0 -102
- package/dist/commands/improve/anti-collapse.js +0 -83
- package/dist/commands/improve/collapse-detector.js +0 -432
- package/dist/commands/improve/consolidate/eligibility.js +0 -48
- package/dist/commands/improve/consolidate/merge.js +0 -146
- package/dist/commands/improve/distill/promote-memory.js +0 -329
- package/dist/commands/improve/distill/quality-gate.js +0 -500
- package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
- package/dist/commands/improve/proposal-envelope.js +0 -31
- package/dist/commands/improve/run-context.js +0 -123
- package/dist/commands/improve/shared.js +0 -21
- package/dist/commands/improve/source-identity.js +0 -28
- package/dist/commands/improve/triage.js +0 -96
- package/dist/commands/proposal/drain-policies.js +0 -151
- package/dist/commands/sources/update-transaction.js +0 -220
- package/dist/core/action-contributors.js +0 -28
- package/dist/core/config/config-version-shim.js +0 -101
- package/dist/core/config/retired-experimental-keys-shim.js +0 -62
- package/dist/core/fs-txn.js +0 -405
- package/dist/core/lexical-score.js +0 -25
- package/dist/core/maintenance-barrier.js +0 -167
- package/dist/execution/executable-identity.js +0 -105
- package/dist/execution/guarded-source.js +0 -427
- package/dist/indexer/graph/graph-boost.js +0 -427
- package/dist/indexer/graph/graph-dedup.js +0 -95
- package/dist/indexer/search/name-match.js +0 -35
- package/dist/indexer/search/ranking-contributors.js +0 -515
- package/dist/indexer/walk/project-context.js +0 -192
- package/dist/integrations/agent/execution-cascade.js +0 -566
- package/dist/integrations/agent/execution-definitions.js +0 -202
- package/dist/integrations/agent/execution-lowering.js +0 -841
- package/dist/integrations/agent/execution-preparation.js +0 -98
- package/dist/integrations/agent/inline-execution.js +0 -74
- package/dist/registry/create-provider-registry.js +0 -29
- package/dist/registry/pinned-request-helper.js +0 -247
- package/dist/registry/pinned-transport.js +0 -717
- package/dist/sources/providers/index.js +0 -14
- package/dist/storage/engines/sqlite-migrations.js +0 -271
- package/dist/storage/repositories/canaries-repository.js +0 -107
- package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
- package/dist/storage/repositories/registry-cache.js +0 -113
- package/dist/tasks/scheduler-sync-preview.js +0 -52
- package/dist/workflows/freeze/resolve-steps.js +0 -86
- package/dist/workflows/freeze/source-freeze.js +0 -64
- package/dist/workflows/ir/compile.js +0 -321
- package/dist/workflows/ir/environment-v4.js +0 -330
- package/dist/workflows/ir/freeze-v4.js +0 -153
- package/dist/workflows/ir/schema-v4.js +0 -745
- package/dist/workflows/ir/schema.js +0 -354
- package/dist/workflows/program/schema.js +0 -78
- package/dist/workflows/runtime/checkin.js +0 -57
- package/dist/workflows/runtime/plan-classifier.js +0 -196
- package/dist/workflows/runtime/unit-checkin.js +0 -45
- package/dist/workflows/runtime/unit-phases.js +0 -20
- package/dist/workflows/schema.js +0 -4
- package/dist/workflows/source-ir/compile.js +0 -200
- package/dist/workflows/source-ir/program.js +0 -50
- package/dist/workflows/source-ir/result.js +0 -26
- package/dist/workflows/source-ir/schema.js +0 -786
- package/dist/workflows/source-ir/triggers.js +0 -79
- package/dist/workflows/source-ir/uses.js +0 -40
- package/dist/workflows/validator.js +0 -60
|
@@ -1,31 +1,6 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* Symmetric valence weighting for the improve eligibility sort (#614).
|
|
6
|
-
*
|
|
7
|
-
* BACKGROUND. The improve attention/eligibility ranking historically combined
|
|
8
|
-
* utility with a NEGATIVE-ONLY feedback term: `negative / (positive + negative)`.
|
|
9
|
-
* Under that formula a strong-positive asset contributes a feedback ratio of
|
|
10
|
-
* `0` — i.e. positive feedback never drives attention. Only complaints could
|
|
11
|
-
* lift an asset up the ranking, so a heavily-praised, heavily-used asset that
|
|
12
|
-
* deserves REINFORCEMENT (distill / promote the win) is treated identically to
|
|
13
|
-
* a never-rated one.
|
|
14
|
-
*
|
|
15
|
-
* FIX (gated, default-off). When symmetric valence is enabled we replace the
|
|
16
|
-
* negative-only ratio with a |valence| MAGNITUDE term so that BOTH strong
|
|
17
|
-
* positive and strong negative feedback drive attention. Utility remains the
|
|
18
|
-
* dominant ordering factor — valence is a secondary attention nudge with a
|
|
19
|
-
* small fixed weight, never a utility override.
|
|
20
|
-
*
|
|
21
|
-
* This module is intentionally pure and storage-free: it takes pre-aggregated
|
|
22
|
-
* positive/negative counts plus a utility lookup and returns a deterministic
|
|
23
|
-
* score and lane. All DB access stays in the caller.
|
|
24
|
-
*/
|
|
25
|
-
/** Weight on utility in the combined eligibility score. Utility is dominant. */
|
|
26
|
-
export const UTILITY_WEIGHT = 0.7;
|
|
27
|
-
/** Weight on the feedback attention term in the combined eligibility score. */
|
|
28
|
-
export const FEEDBACK_WEIGHT = 0.3;
|
|
29
4
|
/**
|
|
30
5
|
* Compute the symmetric-valence attention score for one asset's feedback.
|
|
31
6
|
*
|
|
@@ -31,15 +31,9 @@ export function _setAkmImproveForTests(fake) {
|
|
|
31
31
|
akmImproveForRun = fake ?? akmImprove;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* citty is non-strict, so the removed flag is silently absorbed rather than
|
|
38
|
-
* rejected — which is the dangerous case. The SPACE-separated spelling
|
|
39
|
-
* (`--auto-accept 90`) leaves `90` sitting in the positional slot, where it is
|
|
40
|
-
* read as the asset-type scope: the run then matches nothing and exits 0, so a
|
|
41
|
-
* 0.8-era crontab goes dark with no error at all. Warn about the flag, and drop
|
|
42
|
-
* the poisoned positional so the run behaves as an unscoped improve instead.
|
|
34
|
+
* `--auto-accept` (removed in 0.9): citty absorbs it silently, and
|
|
35
|
+
* `--auto-accept 90` would leave `90` as the scope — a 0.8-era crontab would
|
|
36
|
+
* match nothing and exit 0. Warn, and drop that positional.
|
|
43
37
|
*/
|
|
44
38
|
function resolveScopeAfterRetiredAutoAccept(scopeArg) {
|
|
45
39
|
const invocation = getParsedInvocation();
|
|
@@ -55,41 +49,22 @@ function resolveScopeAfterRetiredAutoAccept(scopeArg) {
|
|
|
55
49
|
}
|
|
56
50
|
return scopeArg;
|
|
57
51
|
}
|
|
58
|
-
/**
|
|
59
|
-
* `akm improve canary` was removed in 0.9 (moved to
|
|
60
|
-
* `scripts/refresh-canary-set.ts`). Without this check "canary" falls through
|
|
61
|
-
* to the generic scope positional, where resolveImproveScope treats any bare
|
|
62
|
-
* word as a type filter that matches zero entries — so an unmigrated caller
|
|
63
|
-
* silently acquires the improve lock and exits 0 having done nothing, instead
|
|
64
|
-
* of getting an error.
|
|
65
|
-
*/
|
|
52
|
+
/** `akm improve canary` (removed in 0.9) would otherwise be a type scope matching nothing, exiting 0. */
|
|
66
53
|
function rejectRetiredCanaryScope(scopeArg) {
|
|
67
54
|
if (scopeArg !== "canary")
|
|
68
55
|
return;
|
|
69
|
-
throw new UsageError('"akm improve canary" was removed in 0.9
|
|
56
|
+
throw new UsageError('"akm improve canary" was removed in 0.9; the collapse-detector canary set it managed no longer exists.', "INVALID_FLAG_VALUE");
|
|
70
57
|
}
|
|
71
|
-
/**
|
|
72
|
-
* `--target` was renamed to `--bundle` on `improve` in 0.9 (S8). citty is
|
|
73
|
-
* non-strict, so the retired spelling is silently absorbed rather than
|
|
74
|
-
* rejected — accepted proposals then write into the default bundle instead
|
|
75
|
-
* of the one the caller named, with exit 0 and no error. Reject it
|
|
76
|
-
* explicitly instead.
|
|
77
|
-
*/
|
|
58
|
+
/** `--target` (renamed `--bundle` in 0.9) would otherwise be absorbed and write to the default bundle. */
|
|
78
59
|
function rejectRetiredImproveTargetFlag() {
|
|
79
60
|
if (!getParsedInvocation().hasFlag("--target"))
|
|
80
61
|
return;
|
|
81
62
|
throw new UsageError("`akm improve --target` was renamed to `--bundle` in 0.9. Use `--bundle <name>` instead.", "INVALID_FLAG_VALUE");
|
|
82
63
|
}
|
|
83
64
|
/**
|
|
84
|
-
* `--require-engines` (#957):
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* it skips the affected processes and reports them in `skippedProcesses` —
|
|
88
|
-
* which is right for an interactive run but wrong for a scheduled one that
|
|
89
|
-
* would rather fail loudly than burn its budget re-indexing and then skip
|
|
90
|
-
* everything. Names the unresolved credential reference per process (not
|
|
91
|
-
* just the process name) so an operator whose own shell passes config
|
|
92
|
-
* validation can see exactly what the scheduler's environment is missing.
|
|
65
|
+
* `--require-engines` (#957): fail before any side effect when an enabled
|
|
66
|
+
* process cannot run, naming what each is missing — a scheduled run would
|
|
67
|
+
* rather fail loudly than index and then skip everything.
|
|
93
68
|
*/
|
|
94
69
|
function assertRequiredEnginesAvailable(plan) {
|
|
95
70
|
if (plan.engineUnavailable.length === 0)
|
|
@@ -97,11 +72,7 @@ function assertRequiredEnginesAvailable(plan) {
|
|
|
97
72
|
const lines = plan.engineUnavailable.map((item) => ` - ${item.process} (${item.configKey}): ${item.reason}`);
|
|
98
73
|
throw new ConfigError(`--require-engines: ${plan.engineUnavailable.length} improve process${plan.engineUnavailable.length === 1 ? "" : "es"} cannot run because ${plan.engineUnavailable.length === 1 ? "its" : "their"} engine is unavailable:\n${lines.join("\n")}`, "LLM_NOT_CONFIGURED");
|
|
99
74
|
}
|
|
100
|
-
/**
|
|
101
|
-
* Every distinct `kind: "llm"` connection the active strategy's plan would
|
|
102
|
-
* actually dispatch against — the main per-process runners plus triage's own
|
|
103
|
-
* judgment engine, which is resolved separately (#957).
|
|
104
|
-
*/
|
|
75
|
+
/** Every LLM connection the plan would dispatch to, triage's judgment engine included. */
|
|
105
76
|
function collectRequiredEngineTargets(plan) {
|
|
106
77
|
const targets = [];
|
|
107
78
|
for (const [processName, process] of Object.entries(plan.processes)) {
|
|
@@ -119,24 +90,10 @@ function collectRequiredEngineTargets(plan) {
|
|
|
119
90
|
return targets;
|
|
120
91
|
}
|
|
121
92
|
/**
|
|
122
|
-
* `--require-engines
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* model completion path with a tiny response and a three-second bound. The
|
|
127
|
-
* `/models` endpoint used by the lightweight health check is deliberately
|
|
128
|
-
* insufficient here: a gateway can list a model while its upstream completion
|
|
129
|
-
* route is dead (#980). Deduplicate by endpoint + model, not endpoint alone,
|
|
130
|
-
* because model backends behind one gateway can fail independently.
|
|
131
|
-
*
|
|
132
|
-
* R17: a probe that PASSES used to leave no trace — a slow or flapping
|
|
133
|
-
* gateway was invisible in the improve result. On success, return one
|
|
134
|
-
* {@link EngineProbeOutcome} per target (process, engine, endpoint,
|
|
135
|
-
* reachable, latencyMs) so the caller can record it on the run result;
|
|
136
|
-
* targets sharing a deduplicated probe share its measured latency.
|
|
137
|
-
*
|
|
138
|
-
* Exported for unit tests, which inject a fake `probeReachable` (the
|
|
139
|
-
* "probe seam") instead of hitting a real endpoint.
|
|
93
|
+
* `--require-engines`, live: probe each connection's real completion path
|
|
94
|
+
* (a gateway can list a model whose completion route is dead, #980) with a 3s
|
|
95
|
+
* bound, once per endpoint + model. Returns each target's latency for the run
|
|
96
|
+
* result (R17); an unreachable one fails the run.
|
|
140
97
|
*/
|
|
141
98
|
export async function assertRequiredEnginesReachable(plan, probeReachable = (connection) => probeLlmReachable(connection, 3_000)) {
|
|
142
99
|
const targets = collectRequiredEngineTargets(plan);
|
|
@@ -170,14 +127,7 @@ export async function assertRequiredEnginesReachable(plan, probeReachable = (con
|
|
|
170
127
|
latencyMs: item.latencyMs,
|
|
171
128
|
}));
|
|
172
129
|
}
|
|
173
|
-
/**
|
|
174
|
-
* `--show-prompt` (#952): render the composed reflect prompt for one asset ref
|
|
175
|
-
* and exit, before any lock, log, index write, or engine dispatch — the field
|
|
176
|
-
* had no cheap way to confirm the #952 prompt fix (unverified-feedback framing,
|
|
177
|
-
* no-truncation-marker instruction) without running a full improve cycle.
|
|
178
|
-
* Reuses `renderReflectPromptPreview` (reflect.ts), which stops before the
|
|
179
|
-
* dispatch lease reflect would otherwise acquire, so this never calls an engine.
|
|
180
|
-
*/
|
|
130
|
+
/** `--show-prompt` (#952): print reflect's composed prompt for one ref — no lock, write or dispatch. */
|
|
181
131
|
async function runShowPromptCli(refArg, parsedRef, taskArg, targetArg, resolvedPlan) {
|
|
182
132
|
const readSource = resolveImproveReadSource(resolvedPlan.config, parsedRef, targetArg);
|
|
183
133
|
const preview = await renderReflectPromptPreview({
|
|
@@ -201,30 +151,14 @@ async function runShowPromptCli(refArg, parsedRef, taskArg, targetArg, resolvedP
|
|
|
201
151
|
prompt: preview.prompt,
|
|
202
152
|
});
|
|
203
153
|
}
|
|
204
|
-
/**
|
|
205
|
-
* `akm improve report` (#944): a scope value that dispatches to the per-run
|
|
206
|
-
* LLM usage/routing report instead of a real improve run — "report" is not,
|
|
207
|
-
* and will never be, a real asset type (`DEFAULT_ALLOWED_TYPES` in
|
|
208
|
-
* improve-strategies.ts), so this already matched zero assets before this
|
|
209
|
-
* flag existed, matching the precedent `rejectRetiredCanaryScope` set for
|
|
210
|
-
* intercepting a special scope word ahead of any lock/log/index side effect.
|
|
211
|
-
*/
|
|
154
|
+
/** `akm improve report` (#944): the per-run LLM usage/routing report ("report" is no asset type). */
|
|
212
155
|
function runImproveReportCli(args) {
|
|
213
156
|
const runIdArg = getStringArg(args, "run");
|
|
214
157
|
const sinceArg = getStringArg(args, "since");
|
|
215
158
|
const result = runImproveReportQuery({ runId: runIdArg, since: sinceArg });
|
|
216
159
|
output("improve-report", { ok: true, ...result });
|
|
217
160
|
}
|
|
218
|
-
/**
|
|
219
|
-
* `--run`/`--since` only mean anything with the "report" scope, which
|
|
220
|
-
* intercepts before this point in the `run` handler below. citty is
|
|
221
|
-
* non-strict, so passing either with a real scope (or no scope at all) used
|
|
222
|
-
* to be silently ignored — the flag's value was read nowhere else, and the
|
|
223
|
-
* run proceeded as an ordinary improve run with no error, discarding the
|
|
224
|
-
* operator's intent. Reject explicitly instead, matching the precedent
|
|
225
|
-
* `rejectRetiredCanaryScope`/`rejectRetiredImproveTargetFlag` set for other
|
|
226
|
-
* flag misuse on this command.
|
|
227
|
-
*/
|
|
161
|
+
/** `--run`/`--since` belong to `improve report`; elsewhere citty would silently ignore them. */
|
|
228
162
|
function rejectReportOnlyFlags(args) {
|
|
229
163
|
const flag = getStringArg(args, "run") !== undefined
|
|
230
164
|
? "--run"
|
|
@@ -240,9 +174,7 @@ export const improveCommand = defineCommand({
|
|
|
240
174
|
name: "improve",
|
|
241
175
|
description: "Analyze existing AKM assets and generate improvement proposals; also consolidates memories when the selected strategy enables consolidate.",
|
|
242
176
|
},
|
|
243
|
-
//
|
|
244
|
-
// Without them citty treats `--format` as a boolean and its space-separated
|
|
245
|
-
// value falls through to the `scope` positional.
|
|
177
|
+
// Declared explicitly: otherwise citty takes `--format`'s value as the scope.
|
|
246
178
|
args: {
|
|
247
179
|
...GLOBAL_OUTPUT_ARGS,
|
|
248
180
|
scope: {
|
|
@@ -311,27 +243,16 @@ export const improveCommand = defineCommand({
|
|
|
311
243
|
},
|
|
312
244
|
async run({ args }) {
|
|
313
245
|
await runWithJsonErrors(async () => {
|
|
314
|
-
// #944 — dispatch before any lock/log/index side effect, same
|
|
315
|
-
// interception point as rejectRetiredCanaryScope below.
|
|
316
246
|
if (getStringArg(args, "scope") === "report") {
|
|
317
247
|
runImproveReportCli(args);
|
|
318
248
|
return;
|
|
319
249
|
}
|
|
320
250
|
rejectReportOnlyFlags(args);
|
|
321
251
|
rejectRetiredImproveTargetFlag();
|
|
322
|
-
// D7 — `--format` used to be rejected here outright. It is a global flag on
|
|
323
|
-
// a command that does emit an envelope through `output()` (always on
|
|
324
|
-
// `--dry-run`, otherwise with `--json-to-stdout`), so rejecting it made
|
|
325
|
-
// improve a fourth inconsistent format behaviour rather than a documented
|
|
326
|
-
// exemption. It now applies to that envelope; progress output stays on
|
|
327
|
-
// stderr regardless.
|
|
328
252
|
const jsonToStdout = args["json-to-stdout"];
|
|
329
253
|
const targetArg = getStringArg(args, "bundle");
|
|
330
254
|
const taskArg = getStringArg(args, "task");
|
|
331
|
-
//
|
|
332
|
-
// it must never fork the computation, only set the same flag. #952 —
|
|
333
|
-
// `--show-prompt` implies the same read-only posture (it never reaches
|
|
334
|
-
// akmImprove at all, but keeps writeTarget/resolvedPlan unset the same way).
|
|
255
|
+
// `--plan` is an alias for `--dry-run`; `--show-prompt` is read-only too.
|
|
335
256
|
const dryRun = args["dry-run"] || args.plan || args["show-prompt"];
|
|
336
257
|
const limitRaw = parsePositiveIntFlag(args.limit ?? undefined);
|
|
337
258
|
const timeoutMs = parsePositiveIntFlag(args["timeout-ms"], "--timeout-ms");
|
|
@@ -347,16 +268,9 @@ export const improveCommand = defineCommand({
|
|
|
347
268
|
: scopeRef
|
|
348
269
|
? resolveMutationTarget(effectiveConfig, scopeRef, targetArg).target
|
|
349
270
|
: resolveWriteTarget(effectiveConfig, targetArg);
|
|
350
|
-
//
|
|
351
|
-
//
|
|
352
|
-
// #800/#957 round 3 — `--dry-run`/`--plan` never dispatches, so the
|
|
353
|
-
// "no improve process can run" guard must not throw when every process
|
|
354
|
-
// is disabled purely by an unreachable credential; a live run keeps
|
|
355
|
-
// throwing (allowAllDisabled unset).
|
|
271
|
+
// Every model-backed process resolves before any side effect; a dry run
|
|
272
|
+
// never dispatches, so it tolerates every process being disabled.
|
|
356
273
|
const resolvedPlan = resolveImprovePlan(strategyArg, effectiveConfig, { allowAllDisabled: Boolean(dryRun) });
|
|
357
|
-
// #952 — same interception point as the `report` scope above: before any
|
|
358
|
-
// lock, log, or index side effect. Requires a single fully-qualified
|
|
359
|
-
// asset ref (not a type or whole-bundle scope).
|
|
360
274
|
if (args["show-prompt"]) {
|
|
361
275
|
if (!scopeArg || !scopeRef) {
|
|
362
276
|
throw new UsageError("`--show-prompt` requires a fully-qualified asset ref as the scope (e.g. `akm improve lessons/my-lesson --show-prompt`).", "INVALID_FLAG_VALUE");
|
|
@@ -371,9 +285,7 @@ export const improveCommand = defineCommand({
|
|
|
371
285
|
}
|
|
372
286
|
const selectedStrategyName = resolvedPlan.strategy.name;
|
|
373
287
|
const sensitiveValues = collectEngineCredentialValues(effectiveConfig);
|
|
374
|
-
// Only
|
|
375
|
-
// undefined unless `--sync`/`--no-sync` / `--push`/`--no-push` appears),
|
|
376
|
-
// so the resolved profile `sync` block wins by default.
|
|
288
|
+
// Only flags actually passed override the strategy's `sync` block.
|
|
377
289
|
const syncFlag = args.sync;
|
|
378
290
|
const pushFlag = args.push;
|
|
379
291
|
const syncOverride = {};
|
|
@@ -387,16 +299,10 @@ export const improveCommand = defineCommand({
|
|
|
387
299
|
}
|
|
388
300
|
const startedAtMs = Date.now();
|
|
389
301
|
const startedAtIso = new Date(startedAtMs).toISOString();
|
|
390
|
-
//
|
|
391
|
-
// record if the process is killed mid-run. Pre-2026-05-26 the runId
|
|
392
|
-
// was minted at end-of-run, so SIGTERM'd runs (cron timeout) left no
|
|
393
|
-
// row in improve_runs and effectively disappeared from `akm health`.
|
|
302
|
+
// The run id is minted up front so a killed run still leaves an improve_runs row.
|
|
394
303
|
const runId = buildImproveRunId();
|
|
395
304
|
const primaryStashDir = writeTarget?.source.path;
|
|
396
305
|
const inferredScopeMode = scopeRef ? "ref" : scopeArg ? "type" : "all";
|
|
397
|
-
// Signal handler + exception path both flow through this helper so
|
|
398
|
-
// every abnormal termination produces a row with ok:false and a
|
|
399
|
-
// reason in metadata.terminated.
|
|
400
306
|
let runRecorded = false;
|
|
401
307
|
const persistTerminated = (reason, errorMessage) => {
|
|
402
308
|
if (dryRun)
|
|
@@ -420,14 +326,7 @@ export const improveCommand = defineCommand({
|
|
|
420
326
|
process.stderr.write(`warning: failed to persist terminated improve run ${runId}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
421
327
|
}
|
|
422
328
|
};
|
|
423
|
-
//
|
|
424
|
-
// choreography lives in `runImproveSession`. It registers the
|
|
425
|
-
// SIGTERM/SIGINT/SIGHUP handlers (each persists the terminated-run row
|
|
426
|
-
// BEFORE process.exit so a SIGTERM'd run — e.g. cron timeout — always
|
|
427
|
-
// leaves a row in improve_runs), awaits the work, then removes the
|
|
428
|
-
// handlers on the way out. `onTerminate` persists synchronously
|
|
429
|
-
// (recordTerminatedImproveRun -> bun:sqlite writes are sync), and the
|
|
430
|
-
// 2000ms watchdog inside the session force-exits if that ever hangs.
|
|
329
|
+
// The session persists the terminated-run row before exiting on a signal.
|
|
431
330
|
let improveResult;
|
|
432
331
|
try {
|
|
433
332
|
improveResult = await runImproveSession({
|
|
@@ -446,11 +345,6 @@ export const improveCommand = defineCommand({
|
|
|
446
345
|
...(strategyArg !== undefined ? { strategy: strategyArg } : {}),
|
|
447
346
|
...(engineProbe !== undefined ? { engineProbe } : {}),
|
|
448
347
|
...(Object.keys(syncOverride).length > 0 ? { sync: syncOverride } : {}),
|
|
449
|
-
consolidateOptions: {
|
|
450
|
-
target: targetArg,
|
|
451
|
-
dryRun,
|
|
452
|
-
task: taskArg,
|
|
453
|
-
},
|
|
454
348
|
}),
|
|
455
349
|
}, {
|
|
456
350
|
signalSource: process,
|
|
@@ -462,10 +356,6 @@ export const improveCommand = defineCommand({
|
|
|
462
356
|
});
|
|
463
357
|
}
|
|
464
358
|
catch (err) {
|
|
465
|
-
// akmImprove threw — record the failure before letting runWithJsonErrors
|
|
466
|
-
// emit the standard JSON error envelope. Without this, exceptions in
|
|
467
|
-
// the main loop (LLM provider crash, OOM, etc.) leave no improve_runs
|
|
468
|
-
// row, matching the SIGTERM gap.
|
|
469
359
|
persistTerminated("exception", err instanceof Error ? err.message : String(err));
|
|
470
360
|
throw err;
|
|
471
361
|
}
|
|
@@ -473,57 +363,30 @@ export const improveCommand = defineCommand({
|
|
|
473
363
|
clearLogFile();
|
|
474
364
|
}
|
|
475
365
|
if (dryRun) {
|
|
476
|
-
// A dry
|
|
477
|
-
// channel. F4: was `process.exit(0)`, which terminates synchronously
|
|
478
|
-
// and skips pending cleanup (e.g. the `finally { clearLogFile(); }`
|
|
479
|
-
// above already ran, but any citty/runWithJsonErrors-level cleanup
|
|
480
|
-
// on the way out would not). Exit code is 0 either way — `return`
|
|
481
|
-
// alone is sufficient since success is the default `process.exitCode`.
|
|
366
|
+
// A dry run persists nothing: stdout is its only result channel.
|
|
482
367
|
output("improve", improveResult);
|
|
483
368
|
return;
|
|
484
369
|
}
|
|
485
|
-
//
|
|
486
|
-
//
|
|
487
|
-
|
|
488
|
-
// logs out of the terminal buffer. The existing `[improve] ...`
|
|
489
|
-
// progress log lines on stderr remain the canonical console UX — the
|
|
490
|
-
// usage-report table below (#944) follows that same convention
|
|
491
|
-
// (stderr, `[improve]`-prefixed), it is not new stdout noise.
|
|
492
|
-
//
|
|
493
|
-
// Pre-0.8.0 wrote `<stash>/.akm/runs/<run-id>/improve-result.json`;
|
|
494
|
-
// those files are no longer authored. Query recent runs with:
|
|
495
|
-
// sqlite3 "$AKM_DATA_DIR/state.db" \
|
|
496
|
-
// "SELECT id, started_at, ok, dry_run FROM improve_runs \
|
|
497
|
-
// ORDER BY started_at DESC LIMIT 10"
|
|
498
|
-
// runId + primaryStashDir minted up-top so signal handlers can record
|
|
499
|
-
// partial runs; reuse them here for the success path.
|
|
500
|
-
runRecorded = true; // Suppress any late signal-handler write — the success path owns the row now.
|
|
370
|
+
// A live run's result goes to state.db's improve_runs, not stdout
|
|
371
|
+
// (progress stays on stderr). The success path owns the row now.
|
|
372
|
+
runRecorded = true;
|
|
501
373
|
if (primaryStashDir) {
|
|
502
374
|
try {
|
|
503
375
|
recordImproveRunResult(primaryStashDir, runId, improveResult, startedAtIso, sensitiveValues);
|
|
504
376
|
}
|
|
505
377
|
catch (err) {
|
|
506
|
-
// Stderr warning on the failure path is preferable to crashing
|
|
507
|
-
// the run after all the work has completed.
|
|
508
378
|
process.stderr.write(`warning: failed to record improve run ${runId}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
509
379
|
}
|
|
510
380
|
}
|
|
511
381
|
else {
|
|
512
382
|
process.stderr.write(`warning: no writable bundle directory resolved; improve result not persisted to state.db (use --json-to-stdout to capture)\n`);
|
|
513
383
|
}
|
|
514
|
-
//
|
|
515
|
-
// real (non-dry-run) run so an operator sees the routing/cost split
|
|
516
|
-
// without a separate command. Omitted when the run made no LLM calls
|
|
517
|
-
// and skipped no enabled process (nothing to report).
|
|
384
|
+
// The `akm improve report` table, on stderr, when there is anything to report (#944).
|
|
518
385
|
if (improveResult.usageReport) {
|
|
519
386
|
process.stderr.write(`${formatUsageReportTable(improveResult.usageReport)}\n`);
|
|
520
387
|
}
|
|
521
388
|
if (jsonToStdout)
|
|
522
389
|
output("improve", improveResult);
|
|
523
|
-
// F4: was `process.exit(0)` — the run has already been fully recorded
|
|
524
|
-
// above (recordImproveRunResult / the warning path), so nothing here
|
|
525
|
-
// depends on an immediate synchronous exit. This is the last statement
|
|
526
|
-
// in the handler, so a plain fall-through is equivalent.
|
|
527
390
|
});
|
|
528
391
|
},
|
|
529
392
|
});
|
|
@@ -2,72 +2,31 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - Default: the full result is recorded as a single row in the
|
|
9
|
-
* `improve_runs` table of `state.db` (migration 003). Stdout is empty.
|
|
10
|
-
* The existing `[improve] ...` progress log lines on stderr remain the
|
|
11
|
-
* canonical console UX.
|
|
12
|
-
* - `--json-to-stdout` additionally emits the persisted result as JSON.
|
|
13
|
-
*
|
|
14
|
-
* v0.8.0 storage change (this module): the previous on-disk artifact at
|
|
15
|
-
* `<stash>/.akm/runs/<runId>/improve-result.json` is no longer written. The
|
|
16
|
-
* canonical record now lives in `improve_runs` (see
|
|
17
|
-
* `src/core/state-db.ts`). Pre-existing files from older runs are not
|
|
18
|
-
* deleted by this change — they become historical artifacts. Zero current
|
|
19
|
-
* code paths read them, so no consumers needed to update.
|
|
20
|
-
*
|
|
21
|
-
* Run-id format: ISO-8601 timestamp (colons/dots replaced by `-`) plus an
|
|
22
|
-
* 8-char hex random suffix. There is no existing canonical run-id helper for
|
|
23
|
-
* persistent per-command artefacts on disk — the `workflow_runs` table uses
|
|
24
|
-
* `randomUUID()` but is database-scoped, and `consolidate-journal.json` is a
|
|
25
|
-
* single-slot artefact. We mint a fresh timestamped id for each improve run.
|
|
5
|
+
* Persist an `akm improve` result as one `improve_runs` row in state.db (since
|
|
6
|
+
* 0.8.0 stdout stays empty unless `--json-to-stdout`). A run that did not
|
|
7
|
+
* complete still gets a row.
|
|
26
8
|
*/
|
|
27
9
|
import crypto from "node:crypto";
|
|
28
10
|
import { decodeImproveResult } from "../../core/improve-result.js";
|
|
29
11
|
import { redactSensitiveValue } from "../../core/redaction.js";
|
|
30
12
|
import { withImmediateTransaction, withStateDb } from "../../core/state-db.js";
|
|
31
13
|
import { recordImproveRun } from "../../storage/repositories/improve-runs-repository.js";
|
|
32
|
-
/**
|
|
33
|
-
* Build a stable run-id for a single improve invocation.
|
|
34
|
-
*
|
|
35
|
-
* Shape: `<iso-8601-utc-with-dashes>-<8 hex chars>`, e.g.
|
|
36
|
-
* `2026-05-19T17-30-22-123Z-a1b2c3d4`.
|
|
37
|
-
*
|
|
38
|
-
* The hex suffix protects against same-millisecond collisions when multiple
|
|
39
|
-
* runs happen back-to-back in tests or scripts.
|
|
40
|
-
*/
|
|
14
|
+
/** `<iso-8601 with dashes>-<8 hex>`, e.g. `2026-05-19T17-30-22-123Z-a1b2c3d4` (the suffix breaks same-ms ties). */
|
|
41
15
|
export function buildImproveRunId(now = new Date()) {
|
|
42
16
|
const iso = now.toISOString().replace(/[:.]/g, "-");
|
|
43
17
|
const rand = crypto.randomBytes(4).toString("hex");
|
|
44
18
|
return `${iso}-${rand}`;
|
|
45
19
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Persist the full improve result into the `improve_runs` table of state.db.
|
|
48
|
-
*
|
|
49
|
-
* The state.db row carries the scope and dry-run flag from `result.scope`
|
|
50
|
-
* and `result.dryRun`, plus the full result JSON for full fidelity. The
|
|
51
|
-
* dry-run column is indexed so productivity audits can filter cleanly
|
|
52
|
-
* (closes the dry-run/real-run artifact-trap recorded in MEMORY.md
|
|
53
|
-
* `feedback_akm_dryrun_artifact_trap`).
|
|
54
|
-
*
|
|
55
|
-
*/
|
|
20
|
+
/** Record a finished run (the full result, redacted; dry runs stay filterable). */
|
|
56
21
|
export function recordImproveRunResult(stashDir, runId, result, startedAt, sensitiveValues = []) {
|
|
57
22
|
const decoded = decodeImproveResult(result);
|
|
58
23
|
const persistedResult = redactSensitiveValue(result, sensitiveValues);
|
|
59
24
|
withStateDb((db) => {
|
|
60
25
|
const completedAt = new Date().toISOString();
|
|
61
|
-
//
|
|
62
|
-
// CLI entry point). If omitted, fall back to the run-id's embedded timestamp
|
|
63
|
-
// so started_at != completed_at even on older call sites.
|
|
26
|
+
// Without a launch timestamp, the one embedded in the run id.
|
|
64
27
|
const resolvedStartedAt = startedAt ??
|
|
65
28
|
runId.slice(0, 24).replace(/^(\d{4}-\d{2}-\d{2}T)(\d{2})-(\d{2})-(\d{2})-(\d{3})Z$/, "$1$2:$3:$4.$5Z");
|
|
66
|
-
//
|
|
67
|
-
// instead of a bare write — this INSERT used to rely solely on the
|
|
68
|
-
// connection's 30s busy_timeout, with no retry and no friendly
|
|
69
|
-
// reclassification on exhaustion, so a raw "database is locked" from
|
|
70
|
-
// improve's own ledger write could reach the CLI as exit 70.
|
|
29
|
+
// BEGIN IMMEDIATE with retry: a bare write surfaced "database is locked" (#948).
|
|
71
30
|
withImmediateTransaction(db, () => {
|
|
72
31
|
recordImproveRun(db, {
|
|
73
32
|
id: runId,
|
|
@@ -86,21 +45,9 @@ export function recordImproveRunResult(stashDir, runId, result, startedAt, sensi
|
|
|
86
45
|
});
|
|
87
46
|
}
|
|
88
47
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* `improve_runs` row was written because the writer only fired at successful
|
|
93
|
-
* end-of-run, so the run vanished from `akm health --detail per-run` even
|
|
94
|
-
* though it had consumed 30 min of LLM time and produced 29 ref-level
|
|
95
|
-
* proposals. This helper closes that gap: signal handlers and the CLI
|
|
96
|
-
* try/catch wrapper call it on the abnormal-exit paths so the row exists
|
|
97
|
-
* with `ok: false` and `metadata.terminated.reason` set.
|
|
98
|
-
*
|
|
99
|
-
* The persisted result envelope is minimal — we don't try to reconstruct
|
|
100
|
-
* the in-flight `actions[]` because that state lives inside `akmImprove`
|
|
101
|
-
* and is gone by the time the signal handler runs. The row captures
|
|
102
|
-
* enough to know: a run started, was scoped to X, did NOT complete, and
|
|
103
|
-
* why.
|
|
48
|
+
* Record a run that did not complete (a signal, e.g. a cron timeout, or an
|
|
49
|
+
* exception) so it does not vanish from `akm health`: `ok: false` with the
|
|
50
|
+
* reason. The in-flight actions are gone by then, so the envelope is minimal.
|
|
104
51
|
*/
|
|
105
52
|
export function recordTerminatedImproveRun(stashDir, runId, startedAt, reason, ctx) {
|
|
106
53
|
const completedAt = new Date().toISOString();
|
|
@@ -123,9 +70,6 @@ export function recordTerminatedImproveRun(stashDir, runId, startedAt, reason, c
|
|
|
123
70
|
},
|
|
124
71
|
}, ctx.sensitiveValues ?? []);
|
|
125
72
|
withStateDb((db) => {
|
|
126
|
-
// #948: same rationale as recordImproveRunResult above — this is the
|
|
127
|
-
// signal-handler/terminated-run write path, which must not itself raise
|
|
128
|
-
// a raw "database is locked" while trying to record why the run ended.
|
|
129
73
|
withImmediateTransaction(db, () => {
|
|
130
74
|
recordImproveRun(db, {
|
|
131
75
|
id: runId,
|
|
@@ -17,6 +17,7 @@ import { ConfigError } from "../../core/errors.js";
|
|
|
17
17
|
import { describeLlmCredentialAvailability } from "../../integrations/agent/engine-resolution.js";
|
|
18
18
|
import { applyAutonomyGate } from "./autonomy-gate.js";
|
|
19
19
|
import { resolveImproveExecution, resolveImproveLlmExecution } from "./execution.js";
|
|
20
|
+
import { stripBundle } from "./ledger.js";
|
|
20
21
|
export const DEFAULT_ALLOWED_TYPES = {
|
|
21
22
|
reflect: ["agent", "command", "knowledge", "lesson", "memory", "skill", "workflow"],
|
|
22
23
|
distill: ["memory"],
|
|
@@ -27,13 +28,9 @@ export function resolveProcessEnabled(processName, strategy) {
|
|
|
27
28
|
const processes = strategy.processes;
|
|
28
29
|
return processes?.[processName]?.enabled === true;
|
|
29
30
|
}
|
|
30
|
-
/** `
|
|
31
|
+
/** An `excludeRefPrefixes` entry as a bare conceptId without a trailing `/` (else `startsWith(".../raw//")` never matches). */
|
|
31
32
|
function stripBundlePrefix(value) {
|
|
32
|
-
|
|
33
|
-
const stripped = boundary >= 0 ? value.slice(boundary + 2) : value;
|
|
34
|
-
// A trailing `/` (e.g. "knowledge/wikis/articles/raw/") would otherwise turn the
|
|
35
|
-
// segment-boundary check below into `startsWith(".../raw//")`, which never matches.
|
|
36
|
-
return stripped.replace(/\/+$/, "");
|
|
33
|
+
return stripBundle(value).replace(/\/+$/, "");
|
|
37
34
|
}
|
|
38
35
|
export function shouldSkipRef(ref, processName, strategy) {
|
|
39
36
|
const process = strategy.processes?.[processName];
|
|
@@ -59,6 +56,14 @@ export function shouldSkipRef(ref, processName, strategy) {
|
|
|
59
56
|
}
|
|
60
57
|
return { skip: false, reason: "" };
|
|
61
58
|
}
|
|
59
|
+
const REF_SCOPED_PROCESSES = new Set(["reflect", "distill", "consolidate"]);
|
|
60
|
+
/** How many refs a ref-scoped process would act on (`undefined` for any other process). */
|
|
61
|
+
export function eligibleRefCount(refs, process, strategy) {
|
|
62
|
+
if (!REF_SCOPED_PROCESSES.has(process))
|
|
63
|
+
return undefined;
|
|
64
|
+
const name = process;
|
|
65
|
+
return refs.filter((entry) => !shouldSkipRef(entry.ref, name, strategy).skip).length;
|
|
66
|
+
}
|
|
62
67
|
export function isStrategyFilteredForAllPasses(ref, strategy) {
|
|
63
68
|
return shouldSkipRef(ref, "reflect", strategy).skip && shouldSkipRef(ref, "distill", strategy).skip;
|
|
64
69
|
}
|
|
@@ -140,7 +145,7 @@ export function projectResolvedProcessRouting(plan) {
|
|
|
140
145
|
}
|
|
141
146
|
return rows;
|
|
142
147
|
}
|
|
143
|
-
function cloneAndFreeze(value) {
|
|
148
|
+
export function cloneAndFreeze(value) {
|
|
144
149
|
const clone = structuredClone(value);
|
|
145
150
|
const freeze = (item) => {
|
|
146
151
|
if (typeof item !== "object" || item === null || Object.isFrozen(item))
|