akm-cli 0.9.16 → 0.9.17-alpha.10
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 +2101 -0
- package/STABILITY.md +11 -10
- package/dist/akm +124 -193
- package/dist/akm-migrate +38 -19
- package/dist/assets/hints/cli-hints-full.md +6 -7
- package/dist/assets/improve-strategies/catchup.json +0 -3
- package/dist/assets/improve-strategies/consolidate.json +0 -1
- package/dist/assets/improve-strategies/default.json +1 -2
- package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
- package/dist/assets/improve-strategies/quick.json +1 -2
- package/dist/assets/improve-strategies/reflect-distill.json +1 -2
- package/dist/assets/improve-strategies/thorough.json +0 -3
- package/dist/assets/prompts/consolidate-pair.md +20 -0
- package/dist/assets/prompts/consolidate-system.md +4 -11
- package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
- package/dist/assets/templates/html/health.html +3 -5
- package/dist/cli/retired-commands.js +1 -1
- package/dist/cli/shared.js +6 -2
- package/dist/cli/unknown-flags.js +24 -1
- package/dist/cli.js +68 -10
- 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 +6 -0
- package/dist/commands/health/archive-usage.js +92 -0
- package/dist/commands/health/checks.js +83 -74
- package/dist/commands/health/config-skew.js +38 -0
- package/dist/commands/health/data-dir-usage.js +25 -13
- package/dist/commands/health/egress.js +54 -0
- package/dist/commands/health/html-report.js +1 -42
- package/dist/commands/health/improve-metrics.js +136 -591
- package/dist/commands/health/md-report.js +1 -6
- 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 +14 -120
- package/dist/commands/health/types-improve.js +4 -19
- package/dist/commands/health/windows.js +64 -74
- package/dist/commands/health.js +145 -143
- package/dist/commands/improve/consolidate/chunking.js +26 -117
- package/dist/commands/improve/consolidate/continuity-check.js +137 -0
- package/dist/commands/improve/consolidate/pair-pass.js +791 -0
- package/dist/commands/improve/consolidate/sanitize.js +54 -149
- package/dist/commands/improve/consolidate.js +589 -1127
- 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 -1041
- package/dist/commands/improve/eligibility.js +126 -390
- package/dist/commands/improve/execution.js +8 -10
- package/dist/commands/improve/extract-prompt.js +1 -2
- package/dist/commands/improve/extract.js +487 -1046
- package/dist/commands/improve/feedback-valence.js +0 -25
- package/dist/commands/improve/improve-cli.js +75 -169
- package/dist/commands/improve/improve-result-file.js +10 -66
- package/dist/commands/improve/improve-strategies.js +52 -4
- package/dist/commands/improve/improve-usage-report.js +18 -64
- package/dist/commands/improve/improve.js +480 -1074
- package/dist/commands/improve/ledger.js +119 -0
- package/dist/commands/improve/locks.js +2 -8
- package/dist/commands/improve/loop-stages.js +415 -1073
- package/dist/commands/improve/memory/derived-ref.js +12 -77
- package/dist/commands/improve/memory/memory-belief.js +16 -118
- package/dist/commands/improve/memory/memory-improve.js +266 -14
- package/dist/commands/improve/outcome-loop.js +28 -156
- package/dist/commands/improve/planner.js +5 -15
- package/dist/commands/improve/preparation.js +779 -2319
- package/dist/commands/improve/proactive-maintenance.js +34 -101
- package/dist/commands/improve/reflect-noise.js +104 -280
- package/dist/commands/improve/reflect.js +642 -1353
- package/dist/commands/improve/retrieval-gate.js +127 -0
- package/dist/commands/improve/retrieval-scope.js +92 -0
- package/dist/commands/improve/salience.js +41 -240
- package/dist/commands/improve/session-asset.js +19 -100
- package/dist/commands/improve/stage.js +322 -0
- package/dist/commands/lint/base-linter.js +37 -15
- package/dist/commands/proposal/drain.js +261 -578
- package/dist/commands/proposal/proposal-cli.js +19 -20
- package/dist/commands/proposal/proposal-types.js +31 -24
- package/dist/commands/proposal/proposal.js +38 -8
- package/dist/commands/proposal/propose.js +134 -160
- package/dist/commands/proposal/repository.js +1097 -1394
- 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 +22 -89
- package/dist/commands/read/curate.js +105 -462
- package/dist/commands/read/knowledge.js +3 -2
- package/dist/commands/read/search-cli.js +16 -33
- package/dist/commands/read/search.js +17 -23
- package/dist/commands/read/show.js +57 -108
- package/dist/commands/sources/bundle-cli.js +25 -2
- package/dist/commands/sources/bundle-config-ops.js +4 -0
- package/dist/commands/sources/dangerous-env-audit.js +1 -2
- package/dist/commands/sources/info.js +127 -29
- 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/source-manage.js +9 -2
- package/dist/commands/sources/stash-cli.js +24 -4
- package/dist/commands/tasks/explain.js +10 -13
- package/dist/commands/tasks/tasks-cli.js +12 -13
- package/dist/commands/tasks/tasks.js +350 -936
- package/dist/commands/tasks/validate.js +26 -24
- package/dist/commands/workflow/plan.js +22 -29
- package/dist/commands/workflow-cli.js +4 -4
- package/dist/core/adapter/adapters/akm-adapter.js +2 -1
- package/dist/core/adapter/adapters/akm-lint.js +2 -3
- package/dist/core/adapter/adapters/akm-metadata.js +42 -12
- package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +17 -29
- package/dist/core/asset/asset-placement.js +4 -13
- package/dist/core/asset/frontmatter.js +106 -1
- package/dist/core/asset/resolve-ref.js +1 -1
- package/dist/core/bundle-id.js +42 -5
- package/dist/core/bundle-rename.js +285 -0
- package/dist/core/config/config-io.js +1 -2
- package/dist/core/config/config-schema.js +9 -34
- package/dist/core/config/config-walker.js +1 -1
- package/dist/core/config/config.js +184 -111
- package/dist/core/config/engine-semantics.js +0 -2
- 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 +54 -125
- package/dist/core/config/schema/improve.js +4 -42
- package/dist/core/config/schema/index-config.js +9 -48
- 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-change.js +13 -5
- package/dist/core/file-lock.js +76 -173
- package/dist/core/improve-result.js +35 -7
- package/dist/core/improve-types.js +0 -1
- package/dist/core/logs-db.js +2 -2
- package/dist/core/loopback.js +7 -12
- package/dist/core/non-task-input.js +20 -0
- package/dist/core/parse.js +13 -16
- package/dist/core/paths.js +0 -24
- 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 +123 -61
- package/dist/core/state-db-scope.js +2 -4
- package/dist/core/state-db.js +126 -692
- package/dist/core/time.js +0 -20
- package/dist/core/type-presentation.js +1 -9
- package/dist/core/write-source.js +294 -1005
- 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/llm-cache.js +2 -2
- package/dist/indexer/ensure-index.js +77 -73
- 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 +141 -154
- package/dist/indexer/indexer.js +400 -1124
- package/dist/indexer/links/declared-links.js +90 -0
- package/dist/indexer/materialize-embeddings.js +60 -397
- package/dist/indexer/passes/memory-inference.js +96 -90
- package/dist/indexer/passes/metadata.js +132 -219
- package/dist/indexer/read-preflight.js +0 -7
- package/dist/indexer/scan/doc-to-entry.js +2 -3
- package/dist/indexer/scan/drain-dir.js +1 -1
- package/dist/indexer/search/db-search.js +190 -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 +36 -7
- package/dist/indexer/walk/walker.js +3 -4
- 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/client.js +18 -6
- package/dist/llm/embedders/deterministic.js +2 -3
- package/dist/llm/embedders/profile.js +71 -0
- package/dist/llm/embedders/remote.js +11 -17
- package/dist/llm/feature-gate.js +0 -8
- package/dist/llm/index-passes.js +3 -5
- package/dist/llm/memory-infer.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 +25 -38
- package/dist/output/shapes/passthrough.js +1 -9
- package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
- package/dist/output/text/command-format.js +69 -31
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +5 -14
- package/dist/output/text/proposal-format.js +48 -3
- package/dist/output/text/show-format.js +13 -17
- 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 +42948 -92369
- package/dist/scripts/akm-migrate.js +42935 -92354
- 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/connection.js +5 -6
- package/dist/setup/steps/platforms.js +2 -2
- 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 +83 -21
- 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 +209 -0
- package/dist/storage/repositories/index-connection.js +39 -72
- package/dist/storage/repositories/index-entries-repository.js +131 -129
- package/dist/storage/repositories/index-entry-mapper.js +1 -2
- package/dist/storage/repositories/index-entry-schema.js +101 -268
- package/dist/storage/repositories/index-fts-repository.js +86 -256
- package/dist/storage/repositories/index-links-repository.js +143 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
- package/dist/storage/repositories/index-meta-repository.js +6 -4
- package/dist/storage/repositories/index-schema.js +257 -325
- 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 +104 -1
- package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
- package/dist/storage/repositories/salience-repository.js +1 -19
- 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 +130 -0
- package/dist/tasks/activation-config.js +134 -62
- package/dist/tasks/backends/cron.js +191 -302
- package/dist/tasks/backends/exec-utils.js +2 -5
- package/dist/tasks/backends/launchd.js +141 -748
- package/dist/tasks/backends/schtasks.js +119 -623
- 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/run/load-task.js +1 -1
- package/dist/tasks/scheduler-binding.js +20 -238
- package/dist/tasks/scheduler-invocation.js +136 -244
- package/dist/tasks/scheduler-lock.js +53 -0
- package/dist/tasks/scheduler-sync.js +368 -679
- package/dist/tasks/source/parse-task-source.js +55 -9
- package/dist/tasks/source/task-source-v3-frozen.js +3 -4
- package/dist/tasks/source/task-to-v4.js +464 -88
- 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 +43 -0
- package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
- package/docs/reference/cli.md +232 -135
- package/docs/reference/configuration.md +71 -57
- package/docs/reference/data-and-telemetry.md +20 -21
- package/docs/reference/tasks.md +105 -39
- 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 +115 -738
- package/schemas/akm-workflow.json +1 -0
- package/dist/assets/improve-strategies/graph-refresh.json +0 -15
- package/dist/assets/prompts/contradiction-judge.md +0 -33
- package/dist/assets/prompts/graph-extract-system.md +0 -1
- package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
- package/dist/assets/prompts/metadata-enhance-system.md +0 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
- 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 -149
- package/dist/commands/improve/distill/promote-memory.js +0 -291
- package/dist/commands/improve/distill/quality-gate.js +0 -337
- package/dist/commands/improve/eval-cases.js +0 -52
- 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 -31
- 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/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/db/graph-db.js +0 -444
- package/dist/indexer/graph/graph-boost.js +0 -427
- package/dist/indexer/graph/graph-dedup.js +0 -95
- package/dist/indexer/graph/graph-extraction.js +0 -1108
- package/dist/indexer/search/name-match.js +0 -35
- package/dist/indexer/search/ranking-contributors.js +0 -515
- package/dist/indexer/search/ranking-types.js +0 -4
- 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/llm/graph-extract.js +0 -728
- package/dist/llm/metadata-enhance.js +0 -96
- 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/tasks/source/task-to-v3.js +0 -507
- 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 -77
- 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
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* `memory-cleanup-archive` advisory for `akm health` (item 4, 0.9.17-alpha.9
|
|
6
|
+
* plan §5.4/§8 step 8).
|
|
7
|
+
*
|
|
8
|
+
* Reports the archive's size and file count for every bundle, git-backed or
|
|
9
|
+
* not. A bundle with no `.git` of its own keeps every retirement's archived
|
|
10
|
+
* bytes forever (the purge sweep never runs there at all), so that alone is
|
|
11
|
+
* reported. A git-backed bundle can ALSO have bytes the purge sweep will
|
|
12
|
+
* never remove: `.git` presence alone does not prove a retirement was ever
|
|
13
|
+
* committed (`proposal accept` only commits for a `kind: "git"` write
|
|
14
|
+
* target, and a `kind: "filesystem"` bundle that merely happens to have a
|
|
15
|
+
* `.git` directory never gets one) — those bytes sit there indefinitely,
|
|
16
|
+
* however old they get, with nothing else to say so. This checks the SAME
|
|
17
|
+
* git state `purgeGracedArchive` checks (tracked, clean, verifiable) and
|
|
18
|
+
* reports how much of the archive fails it.
|
|
19
|
+
*
|
|
20
|
+
* Silent whenever there is nothing to say: the archive does not exist or is
|
|
21
|
+
* empty, or (for a git-backed bundle) every byte in it is purgeable once it
|
|
22
|
+
* ages out.
|
|
23
|
+
*/
|
|
24
|
+
import fs from "node:fs";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
import { MEMORY_ARCHIVE_REL } from "../../core/asset/memory-archive.js";
|
|
27
|
+
import { toPosix } from "../../core/common.js";
|
|
28
|
+
import { checkGitPathSafety, isGitBackedStash } from "../../sources/providers/git-stash.js";
|
|
29
|
+
import { MAX_WALK_ENTRIES, sizeOfPath } from "./data-dir-usage.js";
|
|
30
|
+
/**
|
|
31
|
+
* Build the `memory-cleanup-archive` advisory, or `undefined` when there is
|
|
32
|
+
* nothing to report.
|
|
33
|
+
*/
|
|
34
|
+
export function collectArchiveUsageAdvisory(stashDir) {
|
|
35
|
+
const archiveRoot = path.join(stashDir, MEMORY_ARCHIVE_REL);
|
|
36
|
+
if (!fs.existsSync(archiveRoot))
|
|
37
|
+
return undefined;
|
|
38
|
+
if (!isGitBackedStash(stashDir)) {
|
|
39
|
+
const usage = sizeOfPath(archiveRoot, { remaining: MAX_WALK_ENTRIES });
|
|
40
|
+
if (usage.files === 0)
|
|
41
|
+
return undefined;
|
|
42
|
+
const lowerBound = usage.truncated ? ` (a lower bound — the walk stopped after ${MAX_WALK_ENTRIES} entries)` : "";
|
|
43
|
+
return {
|
|
44
|
+
name: "memory-cleanup-archive",
|
|
45
|
+
kind: "deterministic",
|
|
46
|
+
status: "pass",
|
|
47
|
+
confidence: "high",
|
|
48
|
+
message: `${usage.files} archived file(s), ${usage.bytes} byte(s)${lowerBound} in .akm/memory-cleanup/archive — ` +
|
|
49
|
+
"this bundle has no git history, so the purge sweep leaves it untouched.",
|
|
50
|
+
evidence: { files: usage.files, bytes: usage.bytes, truncated: usage.truncated },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// Git-backed: the SAME three checks purgeGracedArchive runs (B1, G10) —
|
|
54
|
+
// computed once here, not per file, and reused via `onFile` below instead
|
|
55
|
+
// of a second walk of the same tree. A failed git check here fails the
|
|
56
|
+
// same way purgeGracedArchive's own sweep would: nothing in the archive
|
|
57
|
+
// can be proven purgeable, so every byte counts as unpurgeable rather
|
|
58
|
+
// than guessing (`checkGitPathSafety`'s `isSafe` is always `false` when
|
|
59
|
+
// `ok` is `false`).
|
|
60
|
+
const gitSafety = checkGitPathSafety(stashDir, MEMORY_ARCHIVE_REL);
|
|
61
|
+
let unpurgeableFiles = 0;
|
|
62
|
+
let unpurgeableBytes = 0;
|
|
63
|
+
const usage = sizeOfPath(archiveRoot, { remaining: MAX_WALK_ENTRIES }, (filePath, bytes) => {
|
|
64
|
+
const key = toPosix(path.relative(stashDir, filePath));
|
|
65
|
+
if (!gitSafety.isSafe(key)) {
|
|
66
|
+
unpurgeableFiles++;
|
|
67
|
+
unpurgeableBytes += bytes;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
if (usage.files === 0)
|
|
71
|
+
return undefined;
|
|
72
|
+
if (unpurgeableFiles === 0)
|
|
73
|
+
return undefined; // everything here is purgeable once it ages out — nothing to say
|
|
74
|
+
const lowerBound = usage.truncated ? ` (a lower bound — the walk stopped after ${MAX_WALK_ENTRIES} entries)` : "";
|
|
75
|
+
return {
|
|
76
|
+
name: "memory-cleanup-archive",
|
|
77
|
+
kind: "deterministic",
|
|
78
|
+
status: "warn",
|
|
79
|
+
confidence: "high",
|
|
80
|
+
message: `${usage.files} archived file(s), ${usage.bytes} byte(s)${lowerBound} in .akm/memory-cleanup/archive; ` +
|
|
81
|
+
`${unpurgeableFiles} file(s), ${unpurgeableBytes} byte(s) of that cannot be purged (untracked, modified, ` +
|
|
82
|
+
"or unverifiable in git) — commit them so the purge sweep can remove them once they age out.",
|
|
83
|
+
evidence: {
|
|
84
|
+
files: usage.files,
|
|
85
|
+
bytes: usage.bytes,
|
|
86
|
+
truncated: usage.truncated,
|
|
87
|
+
unpurgeableFiles,
|
|
88
|
+
unpurgeableBytes,
|
|
89
|
+
gitStateKnown: gitSafety.ok,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
@@ -10,9 +10,10 @@ import { EXTRACT_INFRASTRUCTURE_SKIP_REASONS } from "../../core/improve-types.js
|
|
|
10
10
|
import { listPendingStateMigrations } from "../../core/state-db.js";
|
|
11
11
|
import { withEngineFallback } from "../../integrations/agent/engine-fallback.js";
|
|
12
12
|
import { isLlmCredentialAvailable, resolveEngine, } from "../../integrations/agent/engine-resolution.js";
|
|
13
|
-
import { executionEngineDefinitionsFromConfig } from "../../integrations/agent/execution
|
|
13
|
+
import { executionEngineDefinitionsFromConfig } from "../../integrations/agent/execution.js";
|
|
14
14
|
import { loadModelMap, mergeModelMapLayers, parseModelMapLayer, readInstalledModelMapText, resolveModelMapAlias, userModelMapPath, } from "../../integrations/agent/model-map.js";
|
|
15
15
|
import { probeEndpointOnce } from "../../llm/client.js";
|
|
16
|
+
import { STATE_DB_FREELIST_WARN_RATIO, } from "../../storage/state-db-integrity.js";
|
|
16
17
|
import { listKeys } from "../env/env.js";
|
|
17
18
|
import { resolveImprovePlan } from "../improve/improve-strategies.js";
|
|
18
19
|
import { ENGINE_LAST_USED_LOOKBACK_DAYS } from "./engine-usage.js";
|
|
@@ -783,16 +784,10 @@ export function runSelectedModelAliasesProbe(deps = {}) {
|
|
|
783
784
|
};
|
|
784
785
|
}
|
|
785
786
|
/**
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
*
|
|
789
|
-
*
|
|
790
|
-
* corresponding managed open would refuse outright because a pending
|
|
791
|
-
* migration is historical-destructive (see `beforeMigrationLocked` in
|
|
792
|
-
* `src/core/state/migrations.ts`). This is what lets `akm health` report that
|
|
793
|
-
* refusal as an ordinary `fail` check instead of crashing the whole command —
|
|
794
|
-
* and what replaces a bundler grepping akm's refusal error text
|
|
795
|
-
* to detect the same case.
|
|
787
|
+
* `state-db-migrations` when the open itself failed: the migrations still
|
|
788
|
+
* pending after a failed apply, from a read-only listing that never applies
|
|
789
|
+
* anything. A `fail` row, not a crash, is what a bundler watches for instead
|
|
790
|
+
* of grepping akm's error text.
|
|
796
791
|
*/
|
|
797
792
|
export function runPendingStateMigrationsCheck(stateDbPath, deps = {}) {
|
|
798
793
|
const pending = (deps.listPendingStateMigrations ?? listPendingStateMigrations)(stateDbPath);
|
|
@@ -816,6 +811,27 @@ export function runPendingStateMigrationsCheck(stateDbPath, deps = {}) {
|
|
|
816
811
|
evidence: { path: stateDbPath, pending },
|
|
817
812
|
};
|
|
818
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* Hard check: state.db's ledger is current. Every open applies the pending
|
|
816
|
+
* migrations (copying the file aside first when one drops schema), so after
|
|
817
|
+
* health's own open nothing is pending; this names what that open applied, so
|
|
818
|
+
* an upgrade that migrated state.db is visible in the report.
|
|
819
|
+
*/
|
|
820
|
+
export function appliedStateMigrationsCheck(stateDbPath, report) {
|
|
821
|
+
const { applied, backupPath } = report;
|
|
822
|
+
const range = applied.length > 1 ? `${applied[0]} … ${applied[applied.length - 1]}` : applied[0];
|
|
823
|
+
return {
|
|
824
|
+
name: "state-db-migrations",
|
|
825
|
+
kind: "deterministic",
|
|
826
|
+
status: "pass",
|
|
827
|
+
confidence: "high",
|
|
828
|
+
message: applied.length === 0
|
|
829
|
+
? "state.db has no pending migrations."
|
|
830
|
+
: `Applied ${applied.length} pending state.db migration(s) on open (${range})` +
|
|
831
|
+
(backupPath ? `; the pre-migration copy is ${backupPath}.` : "."),
|
|
832
|
+
evidence: { path: stateDbPath, pending: [], applied, ...(backupPath ? { backupPath } : {}) },
|
|
833
|
+
};
|
|
834
|
+
}
|
|
819
835
|
/**
|
|
820
836
|
* #943: name the dominant `detail.reason` behind `task-fail-rate`'s warning
|
|
821
837
|
* when one reason accounts for at least half of the window's command-task
|
|
@@ -868,10 +884,65 @@ export const HEALTH_CHECKS = [
|
|
|
868
884
|
evidence: { path: ctx.stateDbPath, durationMs: ctx.probe.durationMs },
|
|
869
885
|
}),
|
|
870
886
|
},
|
|
887
|
+
{
|
|
888
|
+
// R0: nothing looked at state.db's own SQLite-level integrity before
|
|
889
|
+
// this — the round-trip probe above only proves one row can be appended
|
|
890
|
+
// and read back, which stays true on a database that fails
|
|
891
|
+
// `PRAGMA quick_check` elsewhere (corrupt indexes, out-of-order rowids).
|
|
892
|
+
// Also reports the freelist ratio (fraction of pages VACUUM could
|
|
893
|
+
// reclaim) so a bloated-but-uncorrupted file is visible as a warning
|
|
894
|
+
// rather than silence.
|
|
895
|
+
name: "state-db-integrity",
|
|
896
|
+
channel: "hard",
|
|
897
|
+
run: (ctx) => {
|
|
898
|
+
const { ok, lines, error } = ctx.stateDbIntegrity;
|
|
899
|
+
const { ratio: freelistRatio, error: freelistError } = ctx.stateDbFreelist;
|
|
900
|
+
if (!ok) {
|
|
901
|
+
const detail = error ?? lines.join("; ");
|
|
902
|
+
return {
|
|
903
|
+
name: "state-db-integrity",
|
|
904
|
+
kind: "deterministic",
|
|
905
|
+
status: "fail",
|
|
906
|
+
confidence: "high",
|
|
907
|
+
message: `state.db failed PRAGMA quick_check: ${detail}. Repair: back up state.db, then run ` +
|
|
908
|
+
`sqlite3 state.db ".recover" | sqlite3 state.new.db, verify state.new.db passes quick_check, stop ` +
|
|
909
|
+
"every akm process, then delete state.db-wal and state.db-shm before swapping state.new.db in as " +
|
|
910
|
+
"state.db — a leftover WAL from the OLD database is replayed onto the new one and corrupts it.",
|
|
911
|
+
evidence: { path: ctx.stateDbPath, lines, freelistRatio },
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
if (freelistError) {
|
|
915
|
+
return {
|
|
916
|
+
name: "state-db-integrity",
|
|
917
|
+
kind: "deterministic",
|
|
918
|
+
status: "fail",
|
|
919
|
+
confidence: "high",
|
|
920
|
+
message: `state.db passed PRAGMA quick_check, but reading its freelist/page-count failed: ${freelistError}.`,
|
|
921
|
+
evidence: { path: ctx.stateDbPath, lines, freelistError },
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
const freelistWarn = freelistRatio > STATE_DB_FREELIST_WARN_RATIO;
|
|
925
|
+
return {
|
|
926
|
+
name: "state-db-integrity",
|
|
927
|
+
kind: "deterministic",
|
|
928
|
+
status: freelistWarn ? "warn" : "pass",
|
|
929
|
+
confidence: "high",
|
|
930
|
+
message: freelistWarn
|
|
931
|
+
? `state.db passed PRAGMA quick_check, but ${(freelistRatio * 100).toFixed(1)}% of its pages are free (reclaimable by VACUUM).`
|
|
932
|
+
: "state.db passed PRAGMA quick_check.",
|
|
933
|
+
evidence: {
|
|
934
|
+
path: ctx.stateDbPath,
|
|
935
|
+
freelistCount: ctx.stateDbFreelist.freelistCount,
|
|
936
|
+
pageCount: ctx.stateDbFreelist.pageCount,
|
|
937
|
+
freelistRatio,
|
|
938
|
+
},
|
|
939
|
+
};
|
|
940
|
+
},
|
|
941
|
+
},
|
|
871
942
|
{
|
|
872
943
|
name: "state-db-migrations",
|
|
873
944
|
channel: "hard",
|
|
874
|
-
run: (ctx) =>
|
|
945
|
+
run: (ctx) => appliedStateMigrationsCheck(ctx.stateDbPath, ctx.stateDbMigrations),
|
|
875
946
|
},
|
|
876
947
|
{
|
|
877
948
|
name: "task-history-read",
|
|
@@ -885,20 +956,6 @@ export const HEALTH_CHECKS = [
|
|
|
885
956
|
evidence: { rows: ctx.taskRowCount, since: ctx.since },
|
|
886
957
|
}),
|
|
887
958
|
},
|
|
888
|
-
{
|
|
889
|
-
name: "task-log-backing",
|
|
890
|
-
channel: "hard",
|
|
891
|
-
run: (ctx) => ({
|
|
892
|
-
name: "task-log-backing",
|
|
893
|
-
kind: "deterministic",
|
|
894
|
-
status: ctx.logBackingRate === 1 ? "pass" : "fail",
|
|
895
|
-
confidence: "high",
|
|
896
|
-
message: ctx.logBackingRate === 1
|
|
897
|
-
? "Every task_history log_path resolved on disk."
|
|
898
|
-
: `${ctx.taskRowsWithLogsCount - ctx.existingLogRowsCount} task log(s) referenced in task_history are missing.`,
|
|
899
|
-
evidence: { totalWithLogs: ctx.taskRowsWithLogsCount, existingLogs: ctx.existingLogRowsCount },
|
|
900
|
-
}),
|
|
901
|
-
},
|
|
902
959
|
{
|
|
903
960
|
name: "active-runs",
|
|
904
961
|
channel: "hard",
|
|
@@ -1073,54 +1130,6 @@ export const HEALTH_CHECKS = [
|
|
|
1073
1130
|
};
|
|
1074
1131
|
},
|
|
1075
1132
|
},
|
|
1076
|
-
{
|
|
1077
|
-
// #603: pool-saturation advisory. The raw `sessionsScanned` count fired on
|
|
1078
|
-
// normal cadence changes (the Jun 12 false alarm). Instead track the ratio
|
|
1079
|
-
// of NEW (unseen) sessions to the total session pool extract evaluated in
|
|
1080
|
-
// the window: a low ratio is the *expected* steady state, only a near-zero
|
|
1081
|
-
// ratio signals a possible discovery/dedup bug.
|
|
1082
|
-
//
|
|
1083
|
-
// unseen ≈ `sessionsScanned` (extract only processes new sessions; already-
|
|
1084
|
-
// seen ones are deduped into `sessionsSkipped`). total = scanned + skipped.
|
|
1085
|
-
// This is a heuristic approximation — `sessionsSkipped` also folds in
|
|
1086
|
-
// too-short skips — so the check is informational and never gates status.
|
|
1087
|
-
name: "pool-saturation",
|
|
1088
|
-
channel: "advisory",
|
|
1089
|
-
run: (ctx) => {
|
|
1090
|
-
const sx = ctx.sessionExtraction;
|
|
1091
|
-
const total = sx.sessionsScanned + sx.sessionsSkipped;
|
|
1092
|
-
const unseen = sx.sessionsScanned;
|
|
1093
|
-
const ratio = total > 0 ? unseen / total : null;
|
|
1094
|
-
const pct = ratio === null ? null : Math.round(ratio * 1000) / 10;
|
|
1095
|
-
let status = "pass";
|
|
1096
|
-
let confidence = "low";
|
|
1097
|
-
let message;
|
|
1098
|
-
if (!sx.ran || ratio === null) {
|
|
1099
|
-
message = "Pool saturation: no extract activity in the window — no signal.";
|
|
1100
|
-
}
|
|
1101
|
-
else if (ratio < 0.02) {
|
|
1102
|
-
status = "warn";
|
|
1103
|
-
confidence = "medium";
|
|
1104
|
-
message = `Session pool near-exhausted: only ${pct}% of the ${total}-session pool was new (<2%). Possible discovery/dedup bug — verify extract is still finding new sessions.`;
|
|
1105
|
-
}
|
|
1106
|
-
else if (ratio < 0.1) {
|
|
1107
|
-
confidence = "medium";
|
|
1108
|
-
message = `Session pool saturation: ${pct}% of ${total} sessions were new (<10%, steady-state expected — informational).`;
|
|
1109
|
-
}
|
|
1110
|
-
else {
|
|
1111
|
-
confidence = "medium";
|
|
1112
|
-
message = `Session pool healthy: ${pct}% of ${total} sessions were new.`;
|
|
1113
|
-
}
|
|
1114
|
-
return {
|
|
1115
|
-
name: "pool-saturation",
|
|
1116
|
-
kind: "heuristic",
|
|
1117
|
-
status,
|
|
1118
|
-
confidence,
|
|
1119
|
-
message,
|
|
1120
|
-
evidence: { totalSessions: total, unseenSessions: unseen, saturationRatio: ratio },
|
|
1121
|
-
};
|
|
1122
|
-
},
|
|
1123
|
-
},
|
|
1124
1133
|
{
|
|
1125
1134
|
name: "auto-accept-validation",
|
|
1126
1135
|
channel: "advisory",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* `binary-config-skew` advisory for `akm health`: warn when config.json
|
|
6
|
+
* carries a `configVersion` NEWER than (or unorderable against) this binary's
|
|
7
|
+
* CURRENT_CONFIG_VERSION — a newer akm wrote the shared config, so this
|
|
8
|
+
* install is stale. That is the proven multi-install incident class. Silent
|
|
9
|
+
* for current or older versions and for unreadable configs (config loading
|
|
10
|
+
* reports its own errors).
|
|
11
|
+
*/
|
|
12
|
+
import { readTextFile } from "../../core/common.js";
|
|
13
|
+
import { CURRENT_CONFIG_VERSION } from "../../core/config/config-schema.js";
|
|
14
|
+
import { compareConfigVersion } from "../../core/config/config-version.js";
|
|
15
|
+
export function collectConfigSkewAdvisory(configPath) {
|
|
16
|
+
let raw;
|
|
17
|
+
try {
|
|
18
|
+
raw = JSON.parse(readTextFile(configPath, "Config file"));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
const onDisk = raw.configVersion;
|
|
24
|
+
const order = compareConfigVersion(onDisk, CURRENT_CONFIG_VERSION);
|
|
25
|
+
const skewed = order === 1 || (onDisk !== undefined && order === undefined);
|
|
26
|
+
if (!skewed)
|
|
27
|
+
return undefined;
|
|
28
|
+
return {
|
|
29
|
+
name: "binary-config-skew",
|
|
30
|
+
kind: "deterministic",
|
|
31
|
+
status: "warn",
|
|
32
|
+
confidence: "high",
|
|
33
|
+
message: `config.json has configVersion ${JSON.stringify(onDisk)} but this binary knows ${CURRENT_CONFIG_VERSION} — ` +
|
|
34
|
+
"a newer akm wrote the shared config, so this install is stale. Upgrade this install; do not keep a stale " +
|
|
35
|
+
"binary against the shared config/DBs.",
|
|
36
|
+
evidence: { onDiskConfigVersion: onDisk, binaryConfigVersion: CURRENT_CONFIG_VERSION },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -41,7 +41,7 @@ const DOMINANT_SUBDIR_PERCENT_THRESHOLD = 50;
|
|
|
41
41
|
* cap the walk stops descending further and the advisory says its size
|
|
42
42
|
* figures are a lower bound.
|
|
43
43
|
*/
|
|
44
|
-
const MAX_WALK_ENTRIES = 100_000;
|
|
44
|
+
export const MAX_WALK_ENTRIES = 100_000;
|
|
45
45
|
/**
|
|
46
46
|
* Below this the data dir is not worth an opinion. The advisory exists for
|
|
47
47
|
* disk blowups (74 GB in the incident); on a small directory a ratio is
|
|
@@ -59,31 +59,42 @@ function liveDbBytesFor(name, sizes) {
|
|
|
59
59
|
return ((sizes.get(name)?.bytes ?? 0) + (sizes.get(`${name}-wal`)?.bytes ?? 0) + (sizes.get(`${name}-shm`)?.bytes ?? 0));
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
-
* Recursively sum file sizes under `root` (stat-only,
|
|
63
|
-
* followed so a cyclic or huge-target symlink can't blow up the
|
|
64
|
-
* `budget` is a shared mutable counter across the whole tree so the
|
|
65
|
-
*
|
|
62
|
+
* Recursively sum file sizes (and count files) under `root` (stat-only,
|
|
63
|
+
* symlinks not followed so a cyclic or huge-target symlink can't blow up the
|
|
64
|
+
* walk). `budget` is a shared mutable counter across the whole tree so the
|
|
65
|
+
* entry cap applies to the walk as a whole, not per-branch — callers
|
|
66
|
+
* typically pass {@link MAX_WALK_ENTRIES}, sized for this module's own data
|
|
67
|
+
* dir walk, but a smaller/larger budget is fine for a different tree.
|
|
68
|
+
* Shared with the `archive-usage` advisory (N2) — the same "don't let a
|
|
69
|
+
* pathological tree hang a health check" concern applies to both.
|
|
70
|
+
*
|
|
71
|
+
* `onFile`, when given, is called once per leaf file (path, bytes) as the
|
|
72
|
+
* walk visits it — `archive-usage` uses this to classify each file's git
|
|
73
|
+
* state without a second, separate walk of the same tree.
|
|
66
74
|
*/
|
|
67
|
-
function sizeOfPath(root, budget) {
|
|
75
|
+
export function sizeOfPath(root, budget, onFile) {
|
|
68
76
|
let stat;
|
|
69
77
|
try {
|
|
70
78
|
stat = fs.lstatSync(root);
|
|
71
79
|
}
|
|
72
80
|
catch {
|
|
73
|
-
return { bytes: 0, truncated: false };
|
|
81
|
+
return { bytes: 0, files: 0, truncated: false };
|
|
74
82
|
}
|
|
75
83
|
if (stat.isSymbolicLink())
|
|
76
|
-
return { bytes: 0, truncated: false };
|
|
77
|
-
if (!stat.isDirectory())
|
|
78
|
-
|
|
84
|
+
return { bytes: 0, files: 0, truncated: false };
|
|
85
|
+
if (!stat.isDirectory()) {
|
|
86
|
+
onFile?.(root, stat.size);
|
|
87
|
+
return { bytes: stat.size, files: 1, truncated: false };
|
|
88
|
+
}
|
|
79
89
|
let entries;
|
|
80
90
|
try {
|
|
81
91
|
entries = fs.readdirSync(root, { withFileTypes: true });
|
|
82
92
|
}
|
|
83
93
|
catch {
|
|
84
|
-
return { bytes: 0, truncated: false };
|
|
94
|
+
return { bytes: 0, files: 0, truncated: false };
|
|
85
95
|
}
|
|
86
96
|
let bytes = 0;
|
|
97
|
+
let files = 0;
|
|
87
98
|
let truncated = false;
|
|
88
99
|
for (const entry of entries) {
|
|
89
100
|
if (budget.remaining <= 0) {
|
|
@@ -91,12 +102,13 @@ function sizeOfPath(root, budget) {
|
|
|
91
102
|
break;
|
|
92
103
|
}
|
|
93
104
|
budget.remaining--;
|
|
94
|
-
const sub = sizeOfPath(path.join(root, entry.name), budget);
|
|
105
|
+
const sub = sizeOfPath(path.join(root, entry.name), budget, onFile);
|
|
95
106
|
bytes += sub.bytes;
|
|
107
|
+
files += sub.files;
|
|
96
108
|
if (sub.truncated)
|
|
97
109
|
truncated = true;
|
|
98
110
|
}
|
|
99
|
-
return { bytes, truncated };
|
|
111
|
+
return { bytes, files, truncated };
|
|
100
112
|
}
|
|
101
113
|
/** `1610612736` -> `"1.5G"`. Values under 10 in a unit keep one decimal; 10+ round to an integer. */
|
|
102
114
|
function formatBytes(bytes) {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* `egress-endpoints` advisory for `akm health` (meta-review 08, surfaces 3/9):
|
|
6
|
+
* the remote-destination list, for eyeball diff. A pure projection over the
|
|
7
|
+
* effective config (no process.env reads); silent when nothing remote is
|
|
8
|
+
* configured, matching the `stash-git-exposure` / `binary-config-skew`
|
|
9
|
+
* advisories' pattern.
|
|
10
|
+
*/
|
|
11
|
+
import { formatRegistryUrl } from "../../core/registry-url.js";
|
|
12
|
+
/**
|
|
13
|
+
* `egress-endpoints` (08 surfaces 3/9): the full list of remote destinations
|
|
14
|
+
* akm can talk to under the effective config — registries, remote sources,
|
|
15
|
+
* LLM endpoints, embedding endpoint — as one pass-status informational entry
|
|
16
|
+
* for eyeball diff against expectations. Silent only when nothing remote is
|
|
17
|
+
* configured at all.
|
|
18
|
+
*/
|
|
19
|
+
export function collectEgressAdvisory(config) {
|
|
20
|
+
if (!config)
|
|
21
|
+
return undefined;
|
|
22
|
+
const endpoints = [];
|
|
23
|
+
for (const reg of config.registries ?? []) {
|
|
24
|
+
if (reg.enabled === false || !reg.url)
|
|
25
|
+
continue;
|
|
26
|
+
endpoints.push(`registry ${reg.name ?? "(unnamed)"}: ${formatRegistryUrl(reg.url)}`);
|
|
27
|
+
}
|
|
28
|
+
for (const [key, bundle] of Object.entries(config.bundles ?? {})) {
|
|
29
|
+
if (!bundle)
|
|
30
|
+
continue;
|
|
31
|
+
const url = bundle.git ?? bundle.website?.url;
|
|
32
|
+
if (!url)
|
|
33
|
+
continue;
|
|
34
|
+
endpoints.push(`source ${key} (${bundle.git ? "git" : "website"}): ${url}`);
|
|
35
|
+
}
|
|
36
|
+
for (const [name, engine] of Object.entries(config.engines ?? {})) {
|
|
37
|
+
if (engine?.kind !== "llm" || !engine.endpoint)
|
|
38
|
+
continue;
|
|
39
|
+
endpoints.push(`llm ${name}: ${engine.endpoint}`);
|
|
40
|
+
}
|
|
41
|
+
if (config.embedding?.endpoint)
|
|
42
|
+
endpoints.push(`embedding: ${config.embedding.endpoint}`);
|
|
43
|
+
if (endpoints.length === 0)
|
|
44
|
+
return undefined;
|
|
45
|
+
return {
|
|
46
|
+
name: "egress-endpoints",
|
|
47
|
+
kind: "deterministic",
|
|
48
|
+
status: "pass",
|
|
49
|
+
confidence: "high",
|
|
50
|
+
message: `${endpoints.length} remote endpoint(s) in the effective config (registries/sources/LLM/embedding) — ` +
|
|
51
|
+
"review the evidence list for unexpected destinations.",
|
|
52
|
+
evidence: { endpoints },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -131,7 +131,6 @@ function renderExecSummary(vm) {
|
|
|
131
131
|
const trendRows = [
|
|
132
132
|
trendLi("Decision quality", vm.trend.decisionQuality),
|
|
133
133
|
trendLi("Output volume", vm.trend.outputVolume),
|
|
134
|
-
trendLi("Failures", vm.trend.failures),
|
|
135
134
|
trendLi("Latency", vm.trend.latency),
|
|
136
135
|
].join("");
|
|
137
136
|
const deltaRows = [
|
|
@@ -151,7 +150,6 @@ function renderExecSummary(vm) {
|
|
|
151
150
|
li("Promoted", String(vm.latest.promoted)),
|
|
152
151
|
li("Judged: no action", `<abbr title="Candidates reviewed but intentionally left unchanged on this run.">${vm.latest.judgedNoAction}</abbr>`),
|
|
153
152
|
li("MI written", String(vm.latest.miWritten)),
|
|
154
|
-
li("Graph entities/relations", `${vm.latest.geEntities} / ${vm.latest.geRelations}`),
|
|
155
153
|
].join("")
|
|
156
154
|
: '<li><span class="k">No runs in window</span><span class="v">—</span></li>';
|
|
157
155
|
const windowRows = [
|
|
@@ -197,7 +195,7 @@ function renderExecSummary(vm) {
|
|
|
197
195
|
</div>
|
|
198
196
|
</div>
|
|
199
197
|
<div class="overall">Overall trend: <b>${esc(vm.trend.overall)}</b> ${overallEmoji}
|
|
200
|
-
· based on decision quality, output volume,
|
|
198
|
+
· based on decision quality, output volume, and latency ${vm.comparisonMode === "custom" ? "across the selected windows" : "vs the prior window"}.</div>`.trim();
|
|
201
199
|
}
|
|
202
200
|
/**
|
|
203
201
|
* Color is a health SIGNAL, not decoration: green/yellow/red where a card has
|
|
@@ -221,7 +219,6 @@ function renderKpiCards(vm) {
|
|
|
221
219
|
kpiCard("neutral", "Median Duration", `${vm.medianDurMin}m`, `p95 = ${vm.p95DurMin}m`),
|
|
222
220
|
kpiCard("blue", "Total Promoted", num(vm.consolidation.promoted), `avg ${vm.avgPromoted} / run`),
|
|
223
221
|
kpiCard("blue", "MI Written", num(vm.miWritten), `${vm.miYieldRate} yield rate`),
|
|
224
|
-
kpiCard("purple", "Graph Entities", num(vm.graphExtraction.entities), `+${num(vm.graphExtraction.relations)} relations`),
|
|
225
222
|
kpiCard("neutral", "Stash Derived", num(vm.memorySummary.derived), `of ${num(vm.memorySummary.eligible)} eligible (whole-stash)`),
|
|
226
223
|
// #576: real LLM work — duration leads, tokens compact, not a GPU proxy.
|
|
227
224
|
kpiCard(vm.llm.calls > 0 ? "purple" : "neutral", "🧠 LLM Work", `${vm.llmTokensCompact} tok`, `${fmtMs(vm.llm.totalDurationMs)} · ${num(vm.llm.calls)} calls · ${compact(vm.llm.reasoningTokens)} reasoning`),
|
|
@@ -331,44 +328,6 @@ function renderActionItems(vm) {
|
|
|
331
328
|
descHtml: `Newest run is ${esc(latestRunHuman)} — older than the 6h freshness threshold. Check the improve scheduler/cron.`,
|
|
332
329
|
});
|
|
333
330
|
}
|
|
334
|
-
// WS-5: corpus entrenchment flag.
|
|
335
|
-
if (vm.degradation?.entrenchmentFlagged) {
|
|
336
|
-
pushItem({
|
|
337
|
-
key: "corpus-entrenchment",
|
|
338
|
-
prio: "P2",
|
|
339
|
-
cls: "warn",
|
|
340
|
-
title: "Corpus entrenchment risk: retrieval_salience Gini > 0.35",
|
|
341
|
-
descHtml: "A small set of assets dominates retrieval — retrieval diversity is low. " +
|
|
342
|
-
"Review top-ranked assets for stale or over-represented content. " +
|
|
343
|
-
`Corpus diversity proxy: ${esc(String(vm.degradation.corpusCentroidDistance))}.`,
|
|
344
|
-
remedy: "akm health --format json | jq '.improve.degradation'",
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
// Low-tail companion: salience distribution collapsed toward uniform.
|
|
348
|
-
if (vm.degradation?.salienceUniformityFlagged) {
|
|
349
|
-
pushItem({
|
|
350
|
-
key: "salience-uniformity-collapse",
|
|
351
|
-
prio: "P2",
|
|
352
|
-
cls: "warn",
|
|
353
|
-
title: "Salience distribution collapsed: retrieval_salience Gini < 0.08",
|
|
354
|
-
descHtml: `The ${vm.degradation.retrievalSalienceSampleSize} observed, resolvable salience scores are near-uniform — ` +
|
|
355
|
-
"ranking carries little discrimination among assets with retrieval evidence. " +
|
|
356
|
-
`Corpus diversity proxy: ${esc(String(vm.degradation.corpusCentroidDistance))}.`,
|
|
357
|
-
remedy: "akm health --format json | jq '.improve.degradation'",
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
// WS-5: over-budget consolidation advisory.
|
|
361
|
-
if (vm.perf.overBudgetRuns > 0) {
|
|
362
|
-
pushItem({
|
|
363
|
-
key: "over-budget-consolidation",
|
|
364
|
-
prio: "P2",
|
|
365
|
-
cls: "warn",
|
|
366
|
-
title: `${vm.perf.overBudgetRuns} consolidation run${vm.perf.overBudgetRuns === 1 ? "" : "s"} exceeded budget`,
|
|
367
|
-
descHtml: "Consolidation phase wall time exceeded the total run budget on these runs. " +
|
|
368
|
-
"Consider increasing the timeout or reducing the consolidation pool via strategy config.",
|
|
369
|
-
remedy: "akm config list",
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
331
|
items.sort((a, b) => PRIO_RANK[a.prio] - PRIO_RANK[b.prio]);
|
|
373
332
|
return items.length > 0
|
|
374
333
|
? items.map(actionItemCard).join("\n")
|