akm-cli 0.9.0-rc.0 → 0.9.0-rc.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1283 -22
- package/README.md +62 -37
- package/SECURITY.md +46 -31
- package/dist/akm +162 -38
- package/dist/akm-migrate +44 -0
- package/dist/assets/backends/schtasks-template.xml +2 -1
- package/dist/assets/hints/cli-hints-full.md +268 -118
- package/dist/assets/hints/cli-hints-short.md +87 -24
- package/dist/assets/{profiles → improve-strategies}/catchup.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/consolidate.json +3 -1
- package/dist/assets/{profiles → improve-strategies}/default.json +6 -7
- package/dist/assets/improve-strategies/frequent.json +15 -0
- package/dist/assets/{profiles → improve-strategies}/graph-refresh.json +4 -2
- package/dist/assets/{profiles → improve-strategies}/memory-focus.json +4 -1
- package/dist/assets/{profiles → improve-strategies}/proactive-maintenance.json +5 -5
- package/dist/assets/{profiles → improve-strategies}/quick.json +4 -2
- package/dist/assets/improve-strategies/reflect-distill.json +30 -0
- package/dist/assets/{profiles → improve-strategies}/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +5 -5
- package/dist/assets/prompts/extract-session.md +2 -6
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
- package/dist/assets/prompts/reflect-output-repair.md +3 -0
- package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
- package/dist/assets/stash-skeleton/README.md +38 -10
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +14 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +13 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +9 -1
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +11 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +9 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +8 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +100 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +64 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +136 -0
- package/dist/assets/tasks/core/extract.yml +3 -2
- package/dist/assets/tasks/core/improve.yml +2 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -0
- package/dist/assets/tasks/core/sync.yml +1 -0
- package/dist/assets/tasks/core/version-check.yml +2 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +5 -4
- package/dist/assets/workflows/workflow-template.md +31 -15
- package/dist/cli/invocation.js +279 -0
- package/dist/cli/parse-args.js +5 -90
- package/dist/cli/retired-commands.js +78 -0
- package/dist/cli/shared.js +158 -48
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +747 -293
- package/dist/commands/agent/agent-dispatch.js +19 -18
- package/dist/commands/agent/agent-support.js +0 -24
- package/dist/commands/agent/contribute-cli.js +43 -97
- package/dist/commands/completions.js +80 -23
- package/dist/commands/config-cli.js +44 -281
- package/dist/commands/env/env-binding.js +99 -0
- package/dist/commands/env/env-cli.js +84 -224
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +45 -61
- package/dist/commands/env/secret.js +32 -62
- package/dist/commands/feedback-cli.js +179 -85
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +7 -8
- package/dist/commands/health/checks.js +279 -94
- package/dist/commands/health/html-report.js +197 -578
- package/dist/commands/health/improve-metrics.js +277 -246
- package/dist/commands/health/llm-usage.js +19 -19
- package/dist/commands/health/md-report.js +16 -7
- package/dist/commands/health/metrics.js +67 -32
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +508 -0
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +16 -56
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/{migrate-storage-node.mjs → commands/health/types-checks.js} +1 -5
- package/dist/commands/health/types-improve.js +29 -0
- package/dist/{output/text/save.js → commands/health/types-metrics.js} +1 -2
- package/dist/commands/health/types-result.js +7 -0
- package/dist/commands/health/types-runs.js +4 -0
- package/dist/commands/health/types-session-log.js +4 -0
- package/dist/commands/health/types-windows.js +4 -0
- package/dist/commands/health/types.js +26 -21
- package/dist/commands/health/windows.js +2 -3
- package/dist/commands/health.js +296 -167
- package/dist/commands/improve/anti-collapse.js +5 -5
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +65 -52
- package/dist/commands/improve/consolidate/chunking.js +9 -7
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +454 -1354
- package/dist/commands/improve/content-hash.js +39 -0
- package/dist/commands/improve/distill/content-repair.js +4 -10
- package/dist/commands/improve/distill/promote-memory.js +89 -64
- package/dist/commands/improve/distill/quality-gate.js +118 -42
- package/dist/commands/improve/distill-guards.js +1 -1
- package/dist/commands/improve/distill-promotion-policy.js +33 -888
- package/dist/commands/improve/distill.js +607 -363
- package/dist/commands/improve/eligibility.js +165 -79
- package/dist/commands/improve/extract-cli.js +35 -126
- package/dist/commands/improve/extract-prompt.js +6 -35
- package/dist/commands/improve/extract.js +640 -391
- package/dist/commands/improve/feedback-valence.js +2 -12
- package/dist/commands/improve/improve-cli.js +134 -135
- package/dist/commands/improve/improve-result-file.js +30 -50
- package/dist/commands/improve/improve-run-types.js +4 -0
- package/dist/commands/improve/improve-strategies.js +135 -0
- package/dist/commands/improve/improve.js +904 -701
- package/dist/commands/improve/locks.js +64 -111
- package/dist/commands/improve/loop-stages.js +1110 -923
- package/dist/commands/improve/memory/derived-ref.js +124 -0
- package/dist/commands/improve/memory/memory-belief.js +79 -7
- package/dist/commands/improve/memory/memory-contradiction-detect.js +49 -52
- package/dist/commands/improve/memory/memory-improve.js +25 -37
- package/dist/commands/improve/outcome-loop.js +25 -88
- package/dist/commands/improve/preparation.js +1034 -813
- package/dist/commands/improve/proactive-maintenance.js +34 -9
- package/dist/commands/improve/proposal-envelope.js +31 -0
- package/dist/commands/improve/reflect.js +983 -794
- package/dist/commands/improve/run-context.js +119 -0
- package/dist/commands/improve/salience.js +24 -127
- package/dist/commands/improve/session-asset.js +7 -3
- package/dist/commands/improve/shared.js +14 -34
- package/dist/commands/improve/source-identity.js +28 -0
- package/dist/commands/improve/triage.js +20 -17
- package/dist/commands/lint/base-linter.js +340 -313
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +185 -30
- package/dist/commands/{events.js → log.js} +28 -38
- package/dist/commands/migrate-cli.js +54 -0
- package/dist/commands/migration-tool.js +55 -0
- package/dist/commands/observability-cli.js +70 -208
- package/dist/commands/proposal/diff-format.js +50 -0
- package/dist/commands/proposal/drain-policies.js +0 -6
- package/dist/commands/proposal/drain.js +91 -40
- package/dist/commands/proposal/proposal-cli.js +134 -132
- package/dist/commands/proposal/proposal-types.js +56 -0
- package/dist/commands/proposal/proposal.js +83 -65
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +105 -88
- package/dist/commands/proposal/repository.js +1303 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +16 -6
- package/dist/commands/proposal/validators/proposal-validators.js +61 -12
- package/dist/commands/proposal/validators/proposals.js +6 -8
- package/dist/commands/read/curate.js +78 -73
- package/dist/commands/read/knowledge.js +510 -13
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +84 -15
- package/dist/commands/read/search-cli.js +203 -96
- package/dist/commands/read/search.js +126 -94
- package/dist/commands/read/show.js +226 -250
- package/dist/commands/registry-cli.js +34 -60
- package/dist/commands/remember.js +18 -57
- package/dist/commands/sources/add-cli.js +104 -49
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +63 -0
- package/dist/commands/sources/info.js +27 -15
- package/dist/commands/sources/init.js +30 -40
- package/dist/commands/sources/installed-stashes.js +469 -172
- package/dist/commands/sources/migration-help.js +7 -4
- package/dist/commands/sources/schema-repair.js +10 -9
- package/dist/commands/sources/self-update.js +182 -121
- package/dist/commands/sources/source-add.js +169 -178
- package/dist/commands/sources/source-clone.js +144 -41
- package/dist/commands/sources/source-manage.js +94 -59
- package/dist/commands/sources/sources-cli.js +64 -205
- package/dist/commands/sources/stash-cli.js +91 -54
- package/dist/commands/sources/stash-skeleton.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +106 -104
- package/dist/commands/tasks/tasks.js +445 -262
- package/dist/commands/workflow-cli.js +232 -121
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/activation-policy.js +49 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
- package/dist/core/adapter/adapters/akm-adapter.js +528 -0
- package/dist/core/adapter/adapters/akm-lint.js +392 -0
- package/dist/core/adapter/adapters/akm-metadata.js +387 -0
- package/dist/core/adapter/adapters/akm-task-adapter.js +149 -0
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +180 -0
- package/dist/core/adapter/adapters/claude-adapter.js +61 -0
- package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
- package/dist/core/adapter/adapters/generic-files-adapter.js +119 -0
- package/dist/core/adapter/adapters/index.js +80 -0
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +419 -0
- package/dist/core/adapter/adapters/okf-adapter.js +391 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
- package/dist/core/adapter/adapters/shared.js +286 -0
- package/dist/core/adapter/adapters/tool-dir-shared.js +217 -0
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +155 -0
- package/dist/core/adapter/bundle-adapter.js +4 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +44 -0
- package/dist/core/adapter/registry.js +56 -0
- package/dist/core/adapter/types.js +4 -0
- package/dist/core/asset/akm-markdown.js +30 -0
- package/dist/core/asset/asset-placement.js +243 -0
- package/dist/core/asset/asset-ref.js +110 -79
- package/dist/core/asset/asset-serialize.js +20 -0
- package/dist/core/asset/frontmatter.js +28 -12
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +274 -0
- package/dist/core/asset/stash-meta.js +2 -2
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +281 -86
- package/dist/core/config/config-io.js +42 -128
- package/dist/core/config/config-schema.js +233 -834
- package/dist/core/config/config-sources.js +162 -39
- package/dist/core/config/config-types.js +16 -11
- package/dist/core/config/config-version.js +29 -0
- package/dist/core/config/config-walker.js +126 -37
- package/dist/core/config/config.js +154 -331
- package/dist/core/config/deep-merge.js +41 -0
- package/dist/core/config/engine-semantics.js +28 -0
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +38 -0
- package/dist/core/config/schema/engines.js +116 -0
- package/dist/core/config/schema/experimental.js +47 -0
- package/dist/core/config/schema/feedback.js +31 -0
- package/dist/core/config/schema/improve-processes.js +389 -0
- package/dist/core/config/schema/improve.js +94 -0
- package/dist/core/config/schema/index-config.js +176 -0
- package/dist/core/config/schema/output.js +18 -0
- package/dist/core/config/schema/primitives.js +94 -0
- package/dist/core/config/schema/search.js +30 -0
- package/dist/core/config/schema/setup.js +18 -0
- package/dist/core/config/schema/sources-bundles.js +169 -0
- package/dist/core/config/schema/workflow.js +29 -0
- package/dist/core/env-secret-ref.js +155 -20
- package/dist/core/errors.js +17 -15
- package/dist/core/events-types.js +4 -0
- package/dist/core/events.js +46 -128
- package/dist/core/extra-params.js +62 -0
- package/dist/core/file-change.js +17 -0
- package/dist/core/file-lock.js +202 -57
- package/dist/core/fs-txn.js +392 -0
- package/dist/core/git-message.js +59 -0
- package/dist/core/improve-result.js +167 -0
- package/dist/core/json-schema.js +142 -0
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +1 -1
- package/dist/core/maintenance-barrier.js +135 -0
- package/dist/core/migration-operation.js +44 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/paths.js +22 -25
- package/dist/core/platform.js +10 -0
- package/dist/core/recognition-util.js +128 -0
- package/dist/core/redaction.js +392 -0
- package/dist/core/standards/resolve-standards-context.js +36 -65
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +5 -5
- package/dist/core/state/migrations.js +242 -11
- package/dist/core/state-db.js +98 -10
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +303 -0
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/time.js +20 -0
- package/dist/core/type-presentation.js +130 -0
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +834 -118
- package/dist/indexer/bundle-identity-guard.js +92 -0
- package/dist/indexer/db/graph-db.js +1 -25
- package/dist/indexer/db/llm-cache.js +1 -1
- package/dist/indexer/ensure-index.js +30 -9
- package/dist/indexer/graph/graph-boost.js +9 -30
- package/dist/indexer/graph/graph-extraction.js +41 -27
- package/dist/indexer/graph/graph-types.js +4 -0
- package/dist/indexer/index-writer-lock.js +93 -49
- package/dist/indexer/index-written-assets.js +100 -53
- package/dist/indexer/indexer.js +746 -329
- package/dist/indexer/init.js +18 -25
- package/dist/indexer/installations.js +142 -0
- package/dist/indexer/passes/dir-staleness.js +18 -10
- package/dist/indexer/passes/memory-inference.js +25 -15
- package/dist/indexer/passes/metadata.js +412 -243
- package/dist/indexer/scan/doc-to-entry.js +160 -0
- package/dist/indexer/scan/drain-dir.js +134 -0
- package/dist/indexer/search/db-search.js +292 -108
- package/dist/indexer/search/fts-query.js +64 -0
- package/dist/indexer/search/ranking-contributors.js +145 -25
- package/dist/indexer/search/ranking-types.js +4 -0
- package/dist/indexer/search/ranking.js +28 -71
- package/dist/indexer/search/search-attribution.js +67 -0
- package/dist/indexer/search/search-fields.js +18 -3
- package/dist/indexer/search/search-hit-enrichers.js +30 -40
- package/dist/indexer/search/search-source.js +157 -111
- package/dist/indexer/search/semantic-status.js +4 -1
- package/dist/indexer/usage/usage-events.js +10 -30
- package/dist/indexer/walk/file-context.js +3 -45
- package/dist/indexer/walk/matchers.js +42 -34
- package/dist/indexer/walk/path-resolver.js +11 -5
- package/dist/indexer/walk/walker.js +42 -14
- package/dist/integrations/agent/builder-shared.js +7 -0
- package/dist/integrations/agent/builders.js +5 -56
- package/dist/integrations/agent/config.js +3 -143
- package/dist/integrations/agent/detect.js +17 -2
- package/dist/integrations/agent/engine-resolution.js +231 -0
- package/dist/integrations/agent/index.js +1 -2
- package/dist/integrations/agent/model-aliases.js +16 -2
- package/dist/integrations/agent/profiles.js +36 -62
- package/dist/integrations/agent/prompts.js +46 -18
- package/dist/integrations/agent/runner-dispatch.js +93 -4
- package/dist/integrations/agent/runner.js +76 -208
- package/dist/integrations/agent/spawn.js +88 -196
- package/dist/integrations/harnesses/aider/agent-builder.js +114 -0
- package/dist/integrations/harnesses/aider/index.js +48 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +147 -0
- package/dist/integrations/harnesses/amazonq/index.js +45 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -8
- package/dist/integrations/harnesses/claude/config-import.js +1 -3
- package/dist/integrations/harnesses/claude/index.js +24 -35
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/claude/session-log.js +27 -75
- package/dist/integrations/harnesses/codex/agent-builder.js +138 -0
- package/dist/integrations/harnesses/codex/index.js +52 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
- package/dist/integrations/harnesses/copilot/index.js +48 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +120 -0
- package/dist/integrations/harnesses/gemini/index.js +48 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/ids.js +24 -0
- package/dist/integrations/harnesses/index.js +54 -34
- package/dist/integrations/harnesses/opencode/agent-builder.js +23 -5
- package/dist/integrations/harnesses/opencode/config-import.js +1 -3
- package/dist/integrations/harnesses/opencode/index.js +14 -32
- package/dist/integrations/harnesses/opencode/session-log.js +67 -125
- package/dist/integrations/harnesses/opencode-sdk/harness.js +51 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +681 -108
- package/dist/integrations/harnesses/openhands/agent-builder.js +128 -0
- package/dist/integrations/harnesses/openhands/index.js +48 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +97 -0
- package/dist/integrations/harnesses/pi/index.js +45 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/shared.js +17 -0
- package/dist/integrations/harnesses/types.js +43 -32
- package/dist/integrations/lockfile.js +211 -24
- package/dist/integrations/session-logs/index.js +36 -39
- package/dist/integrations/session-logs/provider-base.js +113 -0
- package/dist/llm/client.js +182 -110
- package/dist/llm/embedders/deterministic.js +2 -2
- package/dist/llm/embedders/remote.js +21 -9
- package/dist/llm/feature-gate.js +17 -57
- package/dist/llm/graph-extract.js +12 -13
- package/dist/llm/index-passes.js +8 -42
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +45 -30
- package/dist/llm/structured-call.js +16 -8
- package/dist/llm/usage-persist.js +30 -5
- package/dist/llm/usage-telemetry.js +59 -6
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/command-registry.js +27 -0
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +251 -0
- package/dist/output/html-render.js +11 -16
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -279
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +58 -84
- package/dist/output/shapes/passthrough.js +11 -39
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes/registry.js +12 -6
- package/dist/output/shapes.js +0 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +562 -0
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/helpers.js +15 -1164
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +202 -0
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/registry.js +12 -6
- package/dist/output/text/show-directives.js +117 -0
- package/dist/output/text/show-format.js +103 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +332 -0
- package/dist/output/text/workflow.js +3 -2
- package/dist/output/text.js +10 -19
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +15 -25
- package/dist/registry/resolve.js +43 -94
- package/dist/registry/semver.js +43 -0
- package/dist/runtime.js +81 -12
- package/dist/scripts/akm-migrate.js +35529 -0
- package/dist/setup/detect.js +5 -7
- package/dist/setup/detected-engines.js +136 -0
- package/dist/setup/engine-config.js +100 -0
- package/dist/setup/registry-stash-loader.js +3 -3
- package/dist/setup/semantic-assets.js +12 -9
- package/dist/setup/setup.js +444 -208
- package/dist/setup/steps/connection-shared.js +120 -0
- package/dist/setup/steps/connection.js +108 -305
- package/dist/setup/steps/platforms.js +13 -12
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +21 -15
- package/dist/setup/steps/stashdir.js +6 -4
- package/dist/setup/steps/tasks.js +236 -119
- package/dist/setup/steps.js +3 -2
- package/dist/sources/freshness.js +39 -0
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +54 -56
- package/dist/sources/providers/git-stash.js +420 -91
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +47 -22
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +11 -10
- package/dist/sources/snapshot-fetchers/types.js +4 -0
- package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +110 -41
- package/dist/storage/database.js +60 -4
- package/dist/storage/engines/sqlite-migrations.js +156 -5
- package/dist/storage/locations.js +1 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +51 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -32
- package/dist/storage/repositories/index-connection.js +79 -0
- package/dist/storage/repositories/index-db.js +4 -3
- package/dist/storage/repositories/index-entries-repository.js +863 -0
- package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +19 -2
- package/dist/storage/repositories/index-entry-types.js +4 -0
- package/dist/storage/repositories/index-fts-repository.js +167 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +108 -0
- package/dist/storage/repositories/index-meta-repository.js +49 -0
- package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +226 -100
- package/dist/storage/repositories/index-sql.js +12 -0
- package/dist/storage/repositories/index-utility-repository.js +356 -0
- package/dist/storage/repositories/index-vec-repository.js +250 -0
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +317 -75
- package/dist/storage/repositories/registry-cache.js +1 -1
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +110 -3
- package/dist/storage/repositories/workflow-runs-repository.js +240 -19
- package/dist/tasks/backends/cron.js +169 -46
- package/dist/tasks/backends/exec-utils.js +76 -3
- package/dist/tasks/backends/index.js +6 -9
- package/dist/tasks/backends/launchd.js +292 -55
- package/dist/tasks/backends/schtasks.js +557 -70
- package/dist/tasks/backends/types.js +4 -0
- package/dist/tasks/command-executable.js +93 -0
- package/dist/tasks/embedded.js +56 -38
- package/dist/tasks/parser.js +156 -64
- package/dist/tasks/resolve-akm-bin.js +144 -51
- package/dist/tasks/runner.js +377 -209
- package/dist/tasks/schedule.js +108 -19
- package/dist/tasks/scheduler-invocation.js +296 -0
- package/dist/tasks/schema.js +1 -1
- package/dist/tasks/task-id.js +35 -0
- package/dist/tasks/validator.js +30 -16
- package/dist/text-import-hook.mjs +1 -1
- package/dist/workflows/authoring/authoring.js +104 -43
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/cli.js +0 -16
- package/dist/workflows/concurrency-policy.js +15 -0
- package/dist/workflows/exec/brief.js +450 -0
- package/dist/workflows/exec/frozen-judge.js +47 -0
- package/dist/workflows/exec/native-executor.js +1038 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1460 -0
- package/dist/workflows/exec/run-workflow.js +602 -0
- package/dist/workflows/exec/scheduler.js +71 -0
- package/dist/workflows/exec/step-work.js +1190 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/workflow-engine-gate.js +67 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +246 -0
- package/dist/workflows/ir/freeze.js +233 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +68 -0
- package/dist/workflows/ir/schema.js +540 -0
- package/dist/workflows/parser.js +878 -304
- package/dist/workflows/program/expressions.js +181 -0
- package/dist/workflows/program/schema.js +51 -0
- package/dist/workflows/renderer.js +100 -45
- package/dist/workflows/resource-limits.js +22 -0
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/checkin.js +1 -1
- package/dist/workflows/runtime/plan-classifier.js +131 -0
- package/dist/workflows/runtime/runs.js +376 -119
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/unit-phases.js +20 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +241 -40
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +2 -3
- package/dist/workflows/validator.js +52 -30
- package/docs/README.md +42 -78
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +9 -8
- package/docs/migration/release-notes/0.9.0.md +158 -14
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +844 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/data-and-telemetry.md +333 -0
- package/package.json +21 -17
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +4636 -0
- package/schemas/akm-task.json +87 -0
- package/schemas/akm-workflow.json +373 -0
- package/dist/akm-migrate-storage +0 -38
- package/dist/assets/help/help-accept.md +0 -12
- package/dist/assets/help/help-improve.md +0 -84
- package/dist/assets/help/help-proposals.md +0 -17
- package/dist/assets/help/help-propose.md +0 -17
- package/dist/assets/help/help-reject.md +0 -11
- package/dist/assets/profiles/frequent.json +0 -13
- package/dist/assets/profiles/recombine-only.json +0 -21
- package/dist/assets/profiles/reflect-distill.json +0 -30
- package/dist/assets/profiles/synthesize.json +0 -15
- package/dist/assets/prompts/procedural-system.md +0 -44
- package/dist/assets/prompts/recombine-system.md +0 -40
- package/dist/assets/prompts/staleness-detect-system.md +0 -6
- package/dist/assets/tasks/core/backup.yml +0 -4
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/assets/templates/html/default.html +0 -78
- package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
- package/dist/assets/wiki/index-template.md +0 -12
- package/dist/assets/wiki/ingest-workflow-template.md +0 -83
- package/dist/assets/wiki/log-template.md +0 -8
- package/dist/assets/wiki/schema-template.md +0 -61
- package/dist/cli/config-migrate.js +0 -150
- package/dist/cli/config-validate.js +0 -39
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -487
- package/dist/commands/improve/calibration.js +0 -161
- package/dist/commands/improve/dedup.js +0 -482
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/improve/hot-probation.js +0 -45
- package/dist/commands/improve/improve-auto-accept.js +0 -276
- package/dist/commands/improve/improve-profiles.js +0 -168
- package/dist/commands/improve/procedural.js +0 -398
- package/dist/commands/improve/recombine.js +0 -818
- package/dist/commands/improve/schema-similarity-gate.js +0 -168
- package/dist/commands/lint/agent-linter.js +0 -44
- package/dist/commands/lint/command-linter.js +0 -44
- package/dist/commands/lint/default-linter.js +0 -16
- package/dist/commands/lint/fact-linter.js +0 -39
- package/dist/commands/lint/knowledge-linter.js +0 -16
- package/dist/commands/lint/memory-linter.js +0 -61
- package/dist/commands/lint/registry.js +0 -41
- package/dist/commands/lint/skill-linter.js +0 -45
- package/dist/commands/lint/task-linter.js +0 -50
- package/dist/commands/lint/workflow-linter.js +0 -81
- package/dist/commands/proposal/legacy-import.js +0 -115
- package/dist/commands/sources/history.js +0 -196
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/commands/wiki-cli.js +0 -292
- package/dist/core/asset/asset-registry.js +0 -76
- package/dist/core/asset/asset-spec.js +0 -259
- package/dist/core/config/config-migration.js +0 -602
- package/dist/core/deep-merge.js +0 -38
- package/dist/core/eval/rank-metrics.js +0 -113
- package/dist/core/ripgrep/install.js +0 -163
- package/dist/core/ripgrep/resolve.js +0 -81
- package/dist/indexer/db/db.js +0 -1413
- package/dist/indexer/manifest.js +0 -170
- package/dist/indexer/passes/metadata-contributors.js +0 -31
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -94
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -49
- package/dist/llm/call-ai.js +0 -62
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/output/text/wiki.js +0 -16
- package/dist/registry/build-index.js +0 -386
- package/dist/scripts/migrate-storage.js +0 -19108
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -9411
- package/dist/scripts/migrations/v16-to-v17.js +0 -141
- package/dist/setup/legacy-config.js +0 -106
- package/dist/storage/repositories/consolidation-repository.js +0 -38
- package/dist/storage/repositories/recombine-repository.js +0 -213
- package/dist/wiki/wiki-templates.js +0 -15
- package/dist/wiki/wiki.js +0 -1012
- package/dist/workflows/db.js +0 -215
- package/docs/data-and-telemetry.md +0 -226
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
- /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
|
@@ -0,0 +1,508 @@
|
|
|
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
|
+
* Pure `AkmHealthResult` (+ report options) → `HealthReportViewModel`
|
|
6
|
+
* extractor for the health HTML report (chunk-9 WI-9.5a / H2, anchors C.6).
|
|
7
|
+
*
|
|
8
|
+
* Every computed number, string, boolean, and series the report shows is
|
|
9
|
+
* derived here — deltas, trends, staleness, rate/duration formatting, the
|
|
10
|
+
* synthesized verdict components, the summary-table rows, the action-item
|
|
11
|
+
* inputs. NOTHING in this module emits HTML: `html-report.ts` holds the thin
|
|
12
|
+
* VM→HTML fragment renderers that consume this shape (`buildEchartsTag`,
|
|
13
|
+
* `isoTimeTag`, the `<li>`/card builders, …).
|
|
14
|
+
*
|
|
15
|
+
* Determinism: nothing here depends on Date.now()/Math.random(). Runs are
|
|
16
|
+
* sorted by startedAt so the view model — and therefore the rendered report —
|
|
17
|
+
* is byte-identical for identical inputs.
|
|
18
|
+
*/
|
|
19
|
+
import { TASK_FAIL_RATE_WARN, } from "./types.js";
|
|
20
|
+
/** Distill skip-reasons hidden from the breakdown chart (steady-state noise). */
|
|
21
|
+
const DISTILL_REASONS_HIDDEN = new Set(["no new signal since last proposal"]);
|
|
22
|
+
// ── Small pure formatters (ports of render.py helpers; no HTML) ─────────────
|
|
23
|
+
export function num(value) {
|
|
24
|
+
return Math.round(value).toLocaleString("en-US");
|
|
25
|
+
}
|
|
26
|
+
/** Compact token/count formatter, e.g. 127345 → "127K", 1_500_000 → "1.5M". */
|
|
27
|
+
export function compact(value) {
|
|
28
|
+
const v = Math.round(value);
|
|
29
|
+
if (Math.abs(v) >= 1_000_000)
|
|
30
|
+
return `${(v / 1_000_000).toFixed(1).replace(/\.0$/, "")}M`;
|
|
31
|
+
if (Math.abs(v) >= 1_000)
|
|
32
|
+
return `${(v / 1_000).toFixed(1).replace(/\.0$/, "")}K`;
|
|
33
|
+
return String(v);
|
|
34
|
+
}
|
|
35
|
+
/** Humanize a camelCase / kebab / snake enum into reader-facing text. */
|
|
36
|
+
export function humanize(raw) {
|
|
37
|
+
return raw
|
|
38
|
+
.replace(/[-_]/g, " ")
|
|
39
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
40
|
+
.replace(/\s+/g, " ")
|
|
41
|
+
.trim()
|
|
42
|
+
.replace(/^./, (c) => c.toUpperCase());
|
|
43
|
+
}
|
|
44
|
+
export function fmtMs(ms) {
|
|
45
|
+
return ms ? `${(ms / 60000).toFixed(1)}m` : "—";
|
|
46
|
+
}
|
|
47
|
+
export function pct(rate, digits) {
|
|
48
|
+
return `${(rate * 100).toFixed(digits)}%`;
|
|
49
|
+
}
|
|
50
|
+
/** pctChange may be a number or an "+inf"/"-inf" sentinel (prior window was 0). */
|
|
51
|
+
function coercePct(raw) {
|
|
52
|
+
if (typeof raw === "number")
|
|
53
|
+
return raw;
|
|
54
|
+
if (typeof raw !== "string")
|
|
55
|
+
return undefined;
|
|
56
|
+
const s = raw.trim().toLowerCase();
|
|
57
|
+
if (s === "+inf" || s === "inf" || s === "infinity" || s === "+infinity")
|
|
58
|
+
return 1e9;
|
|
59
|
+
if (s === "-inf" || s === "-infinity")
|
|
60
|
+
return -1e9;
|
|
61
|
+
const parsed = Number.parseFloat(s.replace(/%$/, ""));
|
|
62
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
63
|
+
}
|
|
64
|
+
function reshapeRun(r) {
|
|
65
|
+
const cons = r.consolidation;
|
|
66
|
+
const mi = r.memoryInference;
|
|
67
|
+
const ge = r.graphExtraction;
|
|
68
|
+
const wall = r.wallTimeMs || 0;
|
|
69
|
+
const consMs = cons.durationMs || 0;
|
|
70
|
+
const miMs = mi.durationMs || 0;
|
|
71
|
+
const geMs = ge.durationMs || 0;
|
|
72
|
+
return {
|
|
73
|
+
id: r.id,
|
|
74
|
+
resultStatus: r.resultStatus ?? "valid",
|
|
75
|
+
resultComplete: r.resultComplete ?? (r.resultStatus === undefined || r.resultStatus === "valid"),
|
|
76
|
+
taskId: r.taskId ?? "manual",
|
|
77
|
+
strategy: r.strategy,
|
|
78
|
+
startedAt: r.startedAt,
|
|
79
|
+
completedAt: r.completedAt,
|
|
80
|
+
wallTimeMs: wall,
|
|
81
|
+
ok: r.ok,
|
|
82
|
+
mode: r.scope.mode,
|
|
83
|
+
consDurationMs: consMs,
|
|
84
|
+
miDurationMs: miMs,
|
|
85
|
+
geDurationMs: geMs,
|
|
86
|
+
otherMs: Math.max(0, wall - consMs - miMs - geMs),
|
|
87
|
+
consRan: cons.ran,
|
|
88
|
+
promoted: cons.promoted,
|
|
89
|
+
merged: cons.merged,
|
|
90
|
+
deleted: cons.deleted,
|
|
91
|
+
contradicted: cons.contradicted,
|
|
92
|
+
judgedNoAction: cons.judgedNoAction,
|
|
93
|
+
processed: cons.processed,
|
|
94
|
+
failedChunks: cons.failedChunks,
|
|
95
|
+
totalChunks: cons.totalChunks,
|
|
96
|
+
miWritten: mi.written,
|
|
97
|
+
miConsidered: mi.considered,
|
|
98
|
+
miYieldRate: mi.yieldRate,
|
|
99
|
+
miCacheHits: mi.cacheHits,
|
|
100
|
+
geEntities: ge.entities,
|
|
101
|
+
geRelations: ge.relations,
|
|
102
|
+
geCacheHitRate: ge.cacheHitRate,
|
|
103
|
+
geFailures: ge.failures,
|
|
104
|
+
distillSkipped: r.actions.distill.skipped,
|
|
105
|
+
distillQueued: r.actions.distill.queued,
|
|
106
|
+
distillLlmFailed: r.actions.distill.llmFailed,
|
|
107
|
+
distillByReason: r.actions.distill.skippedByReason,
|
|
108
|
+
reflectOk: r.actions.reflect.ok,
|
|
109
|
+
reflectFailed: r.actions.reflect.failed,
|
|
110
|
+
derived: r.memorySummary.derived,
|
|
111
|
+
eligible: r.memorySummary.eligible,
|
|
112
|
+
lintFlagged: r.lintFlagged,
|
|
113
|
+
lintFixed: r.lintFixed,
|
|
114
|
+
reflectsWithErrorContext: r.reflectsWithErrorContext,
|
|
115
|
+
orphansPurged: r.orphansPurged,
|
|
116
|
+
evalCasesWritten: r.evalCasesWritten,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function compareRuns(a, b) {
|
|
120
|
+
return (a.startedAt.localeCompare(b.startedAt) || a.completedAt.localeCompare(b.completedAt) || a.id.localeCompare(b.id));
|
|
121
|
+
}
|
|
122
|
+
// ── Trend classification (port of collect.py classify) ──────────────────────
|
|
123
|
+
function classify(deltas, metricKeys, lowerIsBetter = false) {
|
|
124
|
+
const changes = metricKeys
|
|
125
|
+
.map((key) => coercePct(deltas[key]?.pctChange))
|
|
126
|
+
.filter((c) => c !== undefined);
|
|
127
|
+
if (changes.length === 0)
|
|
128
|
+
return "flat";
|
|
129
|
+
const avg = changes.reduce((acc, c) => acc + c, 0) / changes.length;
|
|
130
|
+
if (Math.abs(avg) < 5)
|
|
131
|
+
return "flat";
|
|
132
|
+
const direction = avg > 0 ? "up" : "down";
|
|
133
|
+
if (lowerIsBetter)
|
|
134
|
+
return avg > 0 ? "down" : "up";
|
|
135
|
+
return direction;
|
|
136
|
+
}
|
|
137
|
+
function buildTrend(deltas) {
|
|
138
|
+
const decisionQuality = classify(deltas, ["improve.memoryInference.yieldRate", "improve.consolidation.promoted"]);
|
|
139
|
+
const outputVolume = classify(deltas, [
|
|
140
|
+
"improve.consolidation.promoted",
|
|
141
|
+
"improve.memoryInference.written",
|
|
142
|
+
"improve.sessionExtraction.proposalsCreated",
|
|
143
|
+
]);
|
|
144
|
+
const failures = classify(deltas, ["improve.graphExtraction.failures"], true);
|
|
145
|
+
const latency = classify(deltas, ["improve.wallTime.medianMs", "improve.wallTime.p95Ms"], true);
|
|
146
|
+
const score = [decisionQuality, outputVolume, failures, latency].reduce((acc, d) => acc + (d === "up" ? 1 : d === "down" ? -1 : 0), 0);
|
|
147
|
+
const overall = score >= 1 ? "improving" : score <= -1 ? "degrading" : "mixed";
|
|
148
|
+
return { decisionQuality, outputVolume, failures, latency, overall };
|
|
149
|
+
}
|
|
150
|
+
function readSemSearch(advisories) {
|
|
151
|
+
const check = advisories.find((a) => a.name === "semantic-search-runtime");
|
|
152
|
+
if (!check)
|
|
153
|
+
return { blocked: false, detail: "" };
|
|
154
|
+
const evidence = check.evidence ?? {};
|
|
155
|
+
const status = String(evidence.status ?? "unknown");
|
|
156
|
+
const blocked = check.status !== "pass" || status.toLowerCase().includes("block");
|
|
157
|
+
const entries = typeof evidence.entryCount === "number" ? evidence.entryCount : 0;
|
|
158
|
+
const embeddings = typeof evidence.embeddingCount === "number" ? evidence.embeddingCount : 0;
|
|
159
|
+
return { blocked, detail: `${num(entries)} entries, ${num(embeddings)} embeddings` };
|
|
160
|
+
}
|
|
161
|
+
// ── Report-window → time-slice candidates (data only; HTML wrapping is the
|
|
162
|
+
// renderer's job) ─────────────────────────────────────────────────────────
|
|
163
|
+
/** Parse an akm window string (`24h`, `7d`, `30m`, `2w`) to milliseconds; 0 if unparseable. */
|
|
164
|
+
export function windowToMs(window) {
|
|
165
|
+
const m = /^(\d+)\s*([mhdw])$/i.exec(window.trim());
|
|
166
|
+
if (!m)
|
|
167
|
+
return 0;
|
|
168
|
+
const n = Number(m[1]);
|
|
169
|
+
const mult = { m: 60_000, h: 3_600_000, d: 86_400_000, w: 604_800_000 }[m[2].toLowerCase()] ?? 0;
|
|
170
|
+
return n * mult;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Candidate sub-window slices strictly shorter than the report window,
|
|
174
|
+
* largest-first, capped at 4 — the data half of the filter bar's `<option>`s
|
|
175
|
+
* (the "All" option and the `<option>` tags themselves are the renderer's job).
|
|
176
|
+
*/
|
|
177
|
+
function computeSliceCandidates(window) {
|
|
178
|
+
const windowMs = windowToMs(window);
|
|
179
|
+
const HOUR = 3_600_000;
|
|
180
|
+
const DAY = 86_400_000;
|
|
181
|
+
const candidates = [
|
|
182
|
+
[6 * HOUR, "6h"],
|
|
183
|
+
[12 * HOUR, "12h"],
|
|
184
|
+
[DAY, "1d"],
|
|
185
|
+
[3 * DAY, "3d"],
|
|
186
|
+
[7 * DAY, "7d"],
|
|
187
|
+
[14 * DAY, "14d"],
|
|
188
|
+
];
|
|
189
|
+
return candidates
|
|
190
|
+
.filter(([ms]) => windowMs > 0 && ms < windowMs)
|
|
191
|
+
.sort((a, b) => b[0] - a[0])
|
|
192
|
+
.slice(0, 4);
|
|
193
|
+
}
|
|
194
|
+
function partitionRuns(result) {
|
|
195
|
+
const allRuns = (result.runs ?? []).map(reshapeRun).sort(compareRuns);
|
|
196
|
+
return {
|
|
197
|
+
invalidRuns: allRuns.filter((run) => run.resultStatus === "invalid"),
|
|
198
|
+
runs: allRuns.filter((run) => run.resultStatus !== "invalid"),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/** Aggregates (collect.py step 6) + the WS-5 sub-rollups + their formatted-rate strings. */
|
|
202
|
+
function buildAggregatesPhase(result, runsPhase) {
|
|
203
|
+
const { runs, invalidRuns } = runsPhase;
|
|
204
|
+
const improve = result.improve;
|
|
205
|
+
const cons = improve.consolidation;
|
|
206
|
+
const mi = improve.memoryInference;
|
|
207
|
+
const ge = improve.graphExtraction;
|
|
208
|
+
const wallTime = improve.wallTime;
|
|
209
|
+
// WS-5: perf telemetry, coverage, and degradation metrics.
|
|
210
|
+
const perf = improve.perfTelemetry ?? {
|
|
211
|
+
dedupPoolSize: 0,
|
|
212
|
+
llmPoolSize: 0,
|
|
213
|
+
embedMs: 0,
|
|
214
|
+
embedCacheHits: 0,
|
|
215
|
+
embedCacheMisses: 0,
|
|
216
|
+
overBudgetRuns: 0,
|
|
217
|
+
runsWithTelemetry: 0,
|
|
218
|
+
};
|
|
219
|
+
const coverage = improve.coverage;
|
|
220
|
+
const degradation = improve.degradation;
|
|
221
|
+
const minting = improve.enrichmentMinting;
|
|
222
|
+
// #576: real per-stage LLM token/time accounting (replaces the GPU-time
|
|
223
|
+
// proxy). Optional-guarded so reports built from older health JSON without
|
|
224
|
+
// the aggregate still render.
|
|
225
|
+
const llm = result.metrics.llmUsage ?? {
|
|
226
|
+
calls: 0,
|
|
227
|
+
totalDurationMs: 0,
|
|
228
|
+
promptTokens: 0,
|
|
229
|
+
completionTokens: 0,
|
|
230
|
+
totalTokens: 0,
|
|
231
|
+
reasoningTokens: 0,
|
|
232
|
+
byStage: {},
|
|
233
|
+
byProcess: {},
|
|
234
|
+
byEngine: {},
|
|
235
|
+
};
|
|
236
|
+
const totalRuns = runs.length;
|
|
237
|
+
const failedRuns = runs.filter((r) => !r.ok).length;
|
|
238
|
+
const invoked = improve.invoked || totalRuns;
|
|
239
|
+
const completed = improve.completed || totalRuns - failedRuns;
|
|
240
|
+
const miWritten = mi.written;
|
|
241
|
+
return {
|
|
242
|
+
consolidation: cons,
|
|
243
|
+
memoryInference: mi,
|
|
244
|
+
graphExtraction: ge,
|
|
245
|
+
wallTime,
|
|
246
|
+
perf,
|
|
247
|
+
coverage,
|
|
248
|
+
degradation,
|
|
249
|
+
minting,
|
|
250
|
+
llm,
|
|
251
|
+
memorySummary: improve.memorySummary,
|
|
252
|
+
includedResultRows: improve.resultRows?.included ?? totalRuns,
|
|
253
|
+
skippedInvalidResultRows: improve.resultRows?.skipped.invalid ?? invalidRuns.length,
|
|
254
|
+
invoked,
|
|
255
|
+
completed,
|
|
256
|
+
miWritten,
|
|
257
|
+
completionRate: invoked ? `${Math.round((100 * completed) / invoked)}%` : "0%",
|
|
258
|
+
completionPct: invoked ? (100 * completed) / invoked : 100,
|
|
259
|
+
taskFailRate: pct(result.metrics.taskFailRate, 1),
|
|
260
|
+
agentFailRate: pct(result.metrics.agentFailureRate, 2),
|
|
261
|
+
miYieldRate: pct(mi.yieldRate, 1),
|
|
262
|
+
medianDurMin: (wallTime.medianMs / 60000).toFixed(1),
|
|
263
|
+
p95DurMin: (wallTime.p95Ms / 60000).toFixed(1),
|
|
264
|
+
avgPromoted: totalRuns ? String(Math.round(cons.promoted / totalRuns)) : "0",
|
|
265
|
+
chunkFail: `${num(cons.failedChunks)} / ${num(cons.totalChunks)}`,
|
|
266
|
+
llmTokensCompact: compact(llm.totalTokens),
|
|
267
|
+
totalRuns,
|
|
268
|
+
failedRuns,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Meta (collect.py steps 10-11) + freshness. Staleness is computed
|
|
273
|
+
* deterministically (no Date.now()) from the gap between the window start
|
|
274
|
+
* (`since`) and the newest run we have: if no run landed in the window, or
|
|
275
|
+
* the newest run sits in the first 25% of a window wider than the 6h
|
|
276
|
+
* threshold (i.e. a long idle tail), we flag stale.
|
|
277
|
+
*/
|
|
278
|
+
function buildMetaPhase(result, runs) {
|
|
279
|
+
const sinceIso = result.since;
|
|
280
|
+
const reportDate = sinceIso.slice(0, 10);
|
|
281
|
+
const reportTitle = reportDate ? `AKM Health Report — ${reportDate}` : "AKM Health Report";
|
|
282
|
+
const lastRun = runs[runs.length - 1];
|
|
283
|
+
const generatedAt = lastRun ? lastRun.completedAt || lastRun.startedAt || sinceIso : sinceIso;
|
|
284
|
+
const latest = [...runs]
|
|
285
|
+
.filter((run) => run.resultComplete)
|
|
286
|
+
.sort(compareRuns)
|
|
287
|
+
.at(-1);
|
|
288
|
+
const STALE_MS = 6 * 60 * 60 * 1000;
|
|
289
|
+
const latestRunMs = lastRun ? Date.parse(lastRun.completedAt || lastRun.startedAt) : NaN;
|
|
290
|
+
const sinceMs = Date.parse(sinceIso);
|
|
291
|
+
const generatedMs = Date.parse(generatedAt);
|
|
292
|
+
const idleTailMs = Number.isFinite(latestRunMs) && Number.isFinite(generatedMs) ? Math.max(0, generatedMs - latestRunMs) : 0;
|
|
293
|
+
const isStale = runs.length === 0 || (Number.isFinite(latestRunMs) && Number.isFinite(sinceMs) && idleTailMs > STALE_MS);
|
|
294
|
+
return { sinceIso, reportDate, reportTitle, generatedAt, isStale, lastRun, latest };
|
|
295
|
+
}
|
|
296
|
+
const STATUS_LABEL = { pass: "PASS", warn: "WARN", fail: "FAIL" };
|
|
297
|
+
/**
|
|
298
|
+
* Synthesized verdict (one sentence + 2-3 drivers). The verdict WORD is the
|
|
299
|
+
* authoritative health status (hard checks). Concerns (failed improve runs,
|
|
300
|
+
* blocked search, pending proposals) are advisory and do NOT gate that word,
|
|
301
|
+
* so a green PASS is never paired with red "drivers" as if they were
|
|
302
|
+
* failures. When the status is PASS we frame concerns as "watch:" alongside
|
|
303
|
+
* the trend; only a degraded status (WARN/FAIL) leads with them.
|
|
304
|
+
*/
|
|
305
|
+
function buildVerdictPhase(result, trend, sem, proposals, failedRuns) {
|
|
306
|
+
const statusLabel = STATUS_LABEL[result.status];
|
|
307
|
+
const failOk = result.metrics.taskFailRate < TASK_FAIL_RATE_WARN;
|
|
308
|
+
const concerns = [];
|
|
309
|
+
if (failedRuns > 0)
|
|
310
|
+
concerns.push(`${failedRuns} failed run${failedRuns === 1 ? "" : "s"}`);
|
|
311
|
+
if (sem.blocked)
|
|
312
|
+
concerns.push("semantic search blocked");
|
|
313
|
+
if (proposals.length > 0)
|
|
314
|
+
concerns.push(`${proposals.length} pending proposal${proposals.length === 1 ? "" : "s"}`);
|
|
315
|
+
const trendClause = trend.overall === "improving"
|
|
316
|
+
? "throughput and latency improving"
|
|
317
|
+
: trend.overall === "degrading"
|
|
318
|
+
? "throughput or latency degrading"
|
|
319
|
+
: "throughput and latency steady";
|
|
320
|
+
const verdictWord = statusLabel;
|
|
321
|
+
let verdictRest;
|
|
322
|
+
if (result.status === "pass") {
|
|
323
|
+
const watch = concerns.length > 0 ? `; watch: ${concerns.slice(0, 3).join(", ")}` : "";
|
|
324
|
+
verdictRest = `healthy, ${trendClause}${watch}`;
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
const lead = concerns.length > 0 ? concerns.slice(0, 3).join("; ") : trendClause;
|
|
328
|
+
verdictRest = trend.overall === "degrading" && concerns.length > 0 ? `${lead}; ${trendClause}` : lead;
|
|
329
|
+
}
|
|
330
|
+
return { status: result.status, failOk, statusLabel, concerns, trendClause, verdictWord, verdictRest };
|
|
331
|
+
}
|
|
332
|
+
/** Distill skip-reason chart categories (collect.py chart payload step). */
|
|
333
|
+
function computeDistillReasons(runs) {
|
|
334
|
+
return [...new Set(runs.flatMap((r) => Object.keys(r.distillByReason)))]
|
|
335
|
+
.filter((reason) => !DISTILL_REASONS_HIDDEN.has(reason))
|
|
336
|
+
.sort();
|
|
337
|
+
}
|
|
338
|
+
/** Proposals grouped by `source`, sorted alphabetically (drain-proposals action item). */
|
|
339
|
+
function groupProposalsBySource(proposals) {
|
|
340
|
+
const bySource = new Map();
|
|
341
|
+
for (const p of proposals)
|
|
342
|
+
bySource.set(p.source, (bySource.get(p.source) ?? 0) + 1);
|
|
343
|
+
return [...bySource.entries()].sort(([a], [b]) => a.localeCompare(b));
|
|
344
|
+
}
|
|
345
|
+
/** Summary table rows: the base metric set + the WS-5 coverage/minting/perf/degradation extensions, when present. */
|
|
346
|
+
function buildSummaryRows(aggregates, trend) {
|
|
347
|
+
const { consolidation: cons, graphExtraction: ge, wallTime, llm, coverage, minting, perf, degradation } = aggregates;
|
|
348
|
+
const summaryRows = [
|
|
349
|
+
["Task fail rate", aggregates.taskFailRate, "flat"],
|
|
350
|
+
["Agent fail rate", aggregates.agentFailRate, "flat"],
|
|
351
|
+
["Improve completion", `${num(aggregates.completed)} / ${num(aggregates.invoked)}`, "flat"],
|
|
352
|
+
[
|
|
353
|
+
"MI yield rate",
|
|
354
|
+
aggregates.miYieldRate,
|
|
355
|
+
trend.decisionQuality,
|
|
356
|
+
"Memory-inference yield: share of considered candidates that produced a written fact.",
|
|
357
|
+
],
|
|
358
|
+
["MI written", num(aggregates.miWritten), trend.outputVolume, "Memory-inference: facts written this window."],
|
|
359
|
+
["Consolidation promoted", num(cons.promoted), trend.outputVolume],
|
|
360
|
+
["Consolidation merged", num(cons.merged), "flat"],
|
|
361
|
+
["Consolidation deleted", num(cons.deleted), "flat"],
|
|
362
|
+
["Consolidation contradicted", num(cons.contradicted), "flat"],
|
|
363
|
+
[
|
|
364
|
+
"Consolidation judged: no action",
|
|
365
|
+
num(cons.judgedNoAction),
|
|
366
|
+
"flat",
|
|
367
|
+
"Candidates reviewed but intentionally left unchanged (the 'judgedNoAction' field).",
|
|
368
|
+
],
|
|
369
|
+
["Chunk failure", aggregates.chunkFail, "flat"],
|
|
370
|
+
["Graph entities", num(ge.entities), "up"],
|
|
371
|
+
["Graph relations", num(ge.relations), "up"],
|
|
372
|
+
[
|
|
373
|
+
"Stash derived",
|
|
374
|
+
num(aggregates.memorySummary.derived),
|
|
375
|
+
"up",
|
|
376
|
+
"Whole-bundle recount of derived assets at report time — not a per-run sum.",
|
|
377
|
+
],
|
|
378
|
+
["Median wall time", fmtMs(wallTime.medianMs), trend.latency],
|
|
379
|
+
["P95 wall time", fmtMs(wallTime.p95Ms), trend.latency],
|
|
380
|
+
// #576: real LLM accounting (replaces the GPU-time proxy).
|
|
381
|
+
["LLM calls", num(llm.calls), "flat"],
|
|
382
|
+
["LLM total tokens", num(llm.totalTokens), "flat"],
|
|
383
|
+
["LLM prompt tokens", num(llm.promptTokens), "flat"],
|
|
384
|
+
["LLM completion tokens", num(llm.completionTokens), "flat"],
|
|
385
|
+
[
|
|
386
|
+
"LLM reasoning tokens",
|
|
387
|
+
num(llm.reasoningTokens),
|
|
388
|
+
"flat",
|
|
389
|
+
"Tokens spent on model reasoning/thinking, billed separately from prompt and completion.",
|
|
390
|
+
],
|
|
391
|
+
["LLM wall time", fmtMs(llm.totalDurationMs), trend.latency],
|
|
392
|
+
];
|
|
393
|
+
// WS-5: denominator-fixed coverage rows (only when we have real data).
|
|
394
|
+
if (coverage && !Number.isNaN(coverage.rate)) {
|
|
395
|
+
summaryRows.push([
|
|
396
|
+
"Coverage rate",
|
|
397
|
+
pct(coverage.rate, 1),
|
|
398
|
+
"flat",
|
|
399
|
+
"Distinct accepted refs / total stash assets (denominator-fixed). Shows what fraction of the corpus has been touched.",
|
|
400
|
+
], [
|
|
401
|
+
"Eligible fraction",
|
|
402
|
+
pct(coverage.eligibleFraction, 1),
|
|
403
|
+
"flat",
|
|
404
|
+
"Eligible assets / total stash assets. Fraction the improve pipeline actively considers.",
|
|
405
|
+
], [
|
|
406
|
+
"Coverage accepted",
|
|
407
|
+
num(coverage.acceptedProposals),
|
|
408
|
+
"flat",
|
|
409
|
+
"Total accepted proposals in the window (raw volume — includes repeated rewrites of the same asset).",
|
|
410
|
+
], [
|
|
411
|
+
"Churn ratio",
|
|
412
|
+
Number.isFinite(coverage.churnRatio) ? num(coverage.churnRatio) : "—",
|
|
413
|
+
Number.isFinite(coverage.churnRatio) && coverage.churnRatio > 1.5 ? "down" : "flat",
|
|
414
|
+
"Accepted proposals / distinct refs touched. >1.5 = the loop is repeatedly rewriting the same assets (churn, not coverage).",
|
|
415
|
+
]);
|
|
416
|
+
}
|
|
417
|
+
// Enrichment-vs-minting policy rollup (reporting-only).
|
|
418
|
+
if (minting && Number.isFinite(minting.share)) {
|
|
419
|
+
summaryRows.push([
|
|
420
|
+
"Enrichment-lane minted share",
|
|
421
|
+
pct(minting.share, 1),
|
|
422
|
+
minting.share > 0.05 ? "down" : "flat",
|
|
423
|
+
`New assets minted by enrichment lanes / their accepted total (${minting.minted} minted vs ${minting.updated} updated). Enrichment lanes are ratified to edit existing assets only; WARN >5%, FAIL >15%.`,
|
|
424
|
+
]);
|
|
425
|
+
}
|
|
426
|
+
// WS-5: perf telemetry rows (only when at least one run reported telemetry).
|
|
427
|
+
if (perf.runsWithTelemetry > 0) {
|
|
428
|
+
const embedCacheTotal = perf.embedCacheHits + perf.embedCacheMisses;
|
|
429
|
+
const embedCacheHitRate = embedCacheTotal > 0 ? pct(perf.embedCacheHits / embedCacheTotal, 1) : "—";
|
|
430
|
+
summaryRows.push([
|
|
431
|
+
"Embed cache hit rate",
|
|
432
|
+
embedCacheHitRate,
|
|
433
|
+
"flat",
|
|
434
|
+
"Fraction of embedding lookups served from cache (>95% is healthy). Aggregated across WS-5 runs.",
|
|
435
|
+
], [
|
|
436
|
+
"Embed wall time",
|
|
437
|
+
fmtMs(perf.embedMs),
|
|
438
|
+
"flat",
|
|
439
|
+
"Cumulative embedding wall-clock time across consolidation runs in the window.",
|
|
440
|
+
], [
|
|
441
|
+
"Dedup pool size",
|
|
442
|
+
num(perf.dedupPoolSize),
|
|
443
|
+
"flat",
|
|
444
|
+
"Memory pool size after incremental narrowing, before the limit cap. WS-5 perf telemetry.",
|
|
445
|
+
], [
|
|
446
|
+
"Over-budget consolidation runs",
|
|
447
|
+
String(perf.overBudgetRuns),
|
|
448
|
+
perf.overBudgetRuns > 0 ? "down" : "flat",
|
|
449
|
+
"Runs where consolidation alone exceeded the total run budget (estimatedBudgetFractionUsed > 1.0).",
|
|
450
|
+
]);
|
|
451
|
+
}
|
|
452
|
+
// WS-5: degradation metrics rows.
|
|
453
|
+
if (degradation) {
|
|
454
|
+
summaryRows.push([
|
|
455
|
+
"Corpus diversity (Gini)",
|
|
456
|
+
num(degradation.corpusCentroidDistance),
|
|
457
|
+
degradation.entrenchmentFlagged || degradation.salienceUniformityFlagged ? "down" : "flat",
|
|
458
|
+
"Gini coefficient of retrieval_salience for top-100 ranked assets. Two-tailed: >0.35 = entrenchment risk; <0.08 = collapsed toward uniform (ranking no longer discriminates).",
|
|
459
|
+
], [
|
|
460
|
+
"Merge fidelity contradiction rate",
|
|
461
|
+
pct(degradation.mergeFidelityContradictionRate, 1),
|
|
462
|
+
"flat",
|
|
463
|
+
"Fraction of consolidated proposals that involved a contradiction, from consolidation result envelopes.",
|
|
464
|
+
]);
|
|
465
|
+
}
|
|
466
|
+
return summaryRows;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Extract the health HTML report's view model from an `AkmHealthResult` +
|
|
470
|
+
* report options. Pure — no HTML, no I/O, no clock/RNG reads. Byte-identical
|
|
471
|
+
* output for identical inputs, mirroring the pre-split
|
|
472
|
+
* `buildHealthHtmlReplacements` arithmetic exactly. File-level decomposed
|
|
473
|
+
* (chunk-9 WI-9.5a) into one phase helper per section above; this function is
|
|
474
|
+
* the extract-then-compose glue.
|
|
475
|
+
*/
|
|
476
|
+
export function buildHealthReportViewModel(result, opts) {
|
|
477
|
+
const deltas = opts.deltas ?? {};
|
|
478
|
+
const proposals = opts.proposals;
|
|
479
|
+
const runsPhase = partitionRuns(result);
|
|
480
|
+
const sem = readSemSearch(result.advisories);
|
|
481
|
+
const trend = buildTrend(deltas);
|
|
482
|
+
const aggregates = buildAggregatesPhase(result, runsPhase);
|
|
483
|
+
const meta = buildMetaPhase(result, runsPhase.runs);
|
|
484
|
+
const verdict = buildVerdictPhase(result, trend, sem, proposals, aggregates.failedRuns);
|
|
485
|
+
const distillReasons = computeDistillReasons(runsPhase.runs);
|
|
486
|
+
const proposalsBySource = groupProposalsBySource(proposals);
|
|
487
|
+
const summaryRows = buildSummaryRows(aggregates, trend);
|
|
488
|
+
return {
|
|
489
|
+
window: opts.window,
|
|
490
|
+
compare: opts.compare,
|
|
491
|
+
comparisonMode: opts.comparisonMode ?? "duration",
|
|
492
|
+
...meta,
|
|
493
|
+
runs: runsPhase.runs,
|
|
494
|
+
invalidRuns: runsPhase.invalidRuns,
|
|
495
|
+
...verdict,
|
|
496
|
+
...aggregates,
|
|
497
|
+
trend,
|
|
498
|
+
deltas,
|
|
499
|
+
sem,
|
|
500
|
+
proposals,
|
|
501
|
+
proposalsBySource,
|
|
502
|
+
summaryRows,
|
|
503
|
+
sliceCandidates: computeSliceCandidates(opts.window),
|
|
504
|
+
distillReasons,
|
|
505
|
+
advisories: result.advisories,
|
|
506
|
+
sessionLogAdvisories: result.sessionLogAdvisories,
|
|
507
|
+
};
|
|
508
|
+
}
|
|
@@ -40,7 +40,7 @@ export function collectStashExposureAdvisory(stashDir, git = realGit) {
|
|
|
40
40
|
message: `${trackedFiles.length} env/secret file(s) are git-tracked AND a remote is configured — ` +
|
|
41
41
|
`a 'git push' can leak tokens/keys (${preview}). ` +
|
|
42
42
|
"Run 'git rm --cached' on them (a .gitignore rule alone does NOT untrack already-tracked " +
|
|
43
|
-
"files) and then add env/+secrets/ to .gitignore to prevent recurrence (akm
|
|
43
|
+
"files) and then add env/+secrets/ to .gitignore to prevent recurrence (akm bundle create scaffolds it).",
|
|
44
44
|
evidence: { trackedSecretFiles: trackedFiles },
|
|
45
45
|
};
|
|
46
46
|
}
|
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* The remaining `surfaces` advisory group for `akm health` (meta-review 08).
|
|
6
6
|
* `stash-git-exposure` (08-F1) shipped first in ./stash-exposure.ts; this
|
|
7
|
-
* module adds the other
|
|
7
|
+
* module adds the other three read-only checks the adjudication approved:
|
|
8
8
|
*
|
|
9
9
|
* - `secret-file-perms` — env/secret/backup files not 0600, dirs not 0700 (F4)
|
|
10
10
|
* - `binary-config-skew` — config.json written by a NEWER akm than this binary (F3)
|
|
11
|
-
* - `orphan-stores` — legacy config-backups dirs + 0-byte stash state.db decoy (F4/F7)
|
|
12
11
|
* - `egress-endpoints` — the remote-destination list, for eyeball diff (surfaces 3/9)
|
|
13
12
|
*
|
|
14
13
|
* Every collector is a pure projection over injected paths/config (no
|
|
@@ -18,7 +17,9 @@
|
|
|
18
17
|
*/
|
|
19
18
|
import fs from "node:fs";
|
|
20
19
|
import path from "node:path";
|
|
21
|
-
import {
|
|
20
|
+
import { MAX_CONFIG_FILE_BYTES, readTextFileWithLimit } from "../../core/common.js";
|
|
21
|
+
import { CURRENT_CONFIG_VERSION } from "../../core/config/config-schema.js";
|
|
22
|
+
import { compareConfigVersion } from "../../core/config/config-version.js";
|
|
22
23
|
const GROUP_OTHER_BITS = 0o077;
|
|
23
24
|
const OFFENDER_EVIDENCE_CAP = 50;
|
|
24
25
|
function modeOctal(mode) {
|
|
@@ -97,7 +98,7 @@ export function collectSecretPermsAdvisory(input, platform = process.platform) {
|
|
|
97
98
|
export function collectConfigSkewAdvisory(configPath) {
|
|
98
99
|
let raw;
|
|
99
100
|
try {
|
|
100
|
-
raw = JSON.parse(
|
|
101
|
+
raw = JSON.parse(readTextFileWithLimit(configPath, MAX_CONFIG_FILE_BYTES, "Config file"));
|
|
101
102
|
}
|
|
102
103
|
catch {
|
|
103
104
|
return undefined;
|
|
@@ -118,49 +119,6 @@ export function collectConfigSkewAdvisory(configPath) {
|
|
|
118
119
|
evidence: { onDiskConfigVersion: onDisk, binaryConfigVersion: CURRENT_CONFIG_VERSION },
|
|
119
120
|
};
|
|
120
121
|
}
|
|
121
|
-
/**
|
|
122
|
-
* `orphan-stores` (08-F4/F7): stores that look load-bearing but are dead —
|
|
123
|
-
* legacy `config-backups/` dirs in $DATA/$CONFIG (only `$CACHE/config-backups`
|
|
124
|
-
* is written and pruned today) and a 0-byte `<stash>/.akm/state.db` decoy that
|
|
125
|
-
* misleads debugging (the live state.db lives in the data dir). Read-only:
|
|
126
|
-
* this advisory NAMES them; removal stays an owner-approved per-path action.
|
|
127
|
-
*/
|
|
128
|
-
export function collectOrphanStoresAdvisory(input) {
|
|
129
|
-
const orphans = [];
|
|
130
|
-
for (const [label, dir] of [
|
|
131
|
-
["legacy data-dir backup location", path.join(input.dataDir, "config-backups")],
|
|
132
|
-
["legacy config-dir backup location", path.join(input.configDir, "config-backups")],
|
|
133
|
-
]) {
|
|
134
|
-
try {
|
|
135
|
-
if (fs.statSync(dir).isDirectory())
|
|
136
|
-
orphans.push(`${dir}/ (${label}; live backups are in $CACHE/config-backups)`);
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
// absent — fine
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
const decoy = path.join(input.stashDir, ".akm", "state.db");
|
|
143
|
-
try {
|
|
144
|
-
const stat = fs.statSync(decoy);
|
|
145
|
-
if (stat.isFile() && stat.size === 0) {
|
|
146
|
-
orphans.push(`${decoy} (0-byte decoy; the live state.db is in the data dir)`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
// absent — fine
|
|
151
|
-
}
|
|
152
|
-
if (orphans.length === 0)
|
|
153
|
-
return undefined;
|
|
154
|
-
return {
|
|
155
|
-
name: "orphan-stores",
|
|
156
|
-
kind: "deterministic",
|
|
157
|
-
status: "warn",
|
|
158
|
-
confidence: "high",
|
|
159
|
-
message: `${orphans.length} orphan store(s) found: ${orphans.join("; ")}. ` +
|
|
160
|
-
"These are dead locations that mislead debugging/recovery — review and remove them (owner-approved, per-path).",
|
|
161
|
-
evidence: { orphans },
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
122
|
/**
|
|
165
123
|
* `egress-endpoints` (08 surfaces 3/9): the full list of remote destinations
|
|
166
124
|
* akm can talk to under the effective config — registries, remote sources,
|
|
@@ -177,15 +135,18 @@ export function collectEgressAdvisory(config) {
|
|
|
177
135
|
continue;
|
|
178
136
|
endpoints.push(`registry ${reg.name ?? "(unnamed)"}: ${reg.url}`);
|
|
179
137
|
}
|
|
180
|
-
for (const
|
|
181
|
-
if (
|
|
138
|
+
for (const [key, bundle] of Object.entries(config.bundles ?? {})) {
|
|
139
|
+
if (!bundle)
|
|
140
|
+
continue;
|
|
141
|
+
const url = bundle.git ?? bundle.website?.url;
|
|
142
|
+
if (!url)
|
|
182
143
|
continue;
|
|
183
|
-
endpoints.push(`source ${
|
|
144
|
+
endpoints.push(`source ${key} (${bundle.git ? "git" : "website"}): ${url}`);
|
|
184
145
|
}
|
|
185
|
-
for (const [name,
|
|
186
|
-
if (!
|
|
146
|
+
for (const [name, engine] of Object.entries(config.engines ?? {})) {
|
|
147
|
+
if (engine?.kind !== "llm" || !engine.endpoint)
|
|
187
148
|
continue;
|
|
188
|
-
endpoints.push(`llm ${name}: ${
|
|
149
|
+
endpoints.push(`llm ${name}: ${engine.endpoint}`);
|
|
189
150
|
}
|
|
190
151
|
if (config.embedding?.endpoint)
|
|
191
152
|
endpoints.push(`embedding: ${config.embedding.endpoint}`);
|
|
@@ -202,14 +163,13 @@ export function collectEgressAdvisory(config) {
|
|
|
202
163
|
};
|
|
203
164
|
}
|
|
204
165
|
/**
|
|
205
|
-
* Aggregate the
|
|
206
|
-
* consumes. Order is fixed: perms → skew →
|
|
166
|
+
* Aggregate the three collectors into the advisories array shape `akmHealth`
|
|
167
|
+
* consumes. Order is fixed: perms → skew → egress.
|
|
207
168
|
*/
|
|
208
169
|
export function collectSurfacesAdvisories(input) {
|
|
209
170
|
const results = [
|
|
210
171
|
collectSecretPermsAdvisory({ stashDir: input.stashDir, cacheDir: input.cacheDir }, input.platform ?? process.platform),
|
|
211
172
|
collectConfigSkewAdvisory(input.configPath),
|
|
212
|
-
collectOrphanStoresAdvisory({ dataDir: input.dataDir, configDir: input.configDir, stashDir: input.stashDir }),
|
|
213
173
|
collectEgressAdvisory(input.config),
|
|
214
174
|
];
|
|
215
175
|
return results.filter((r) => r !== undefined);
|