akm-cli 0.8.1 → 0.9.0-beta.0
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 +258 -0
- package/dist/assets/help/help-proposals.md +1 -2
- package/dist/assets/hints/cli-hints-full.md +34 -19
- package/dist/assets/hints/cli-hints-short.md +1 -1
- package/dist/assets/profiles/catchup.json +13 -0
- package/dist/assets/profiles/consolidate.json +13 -0
- package/dist/assets/profiles/frequent.json +13 -0
- package/dist/assets/stash-skeleton/README.md +76 -0
- package/dist/assets/tasks/core/backup.yml +4 -0
- package/dist/assets/tasks/core/extract.yml +4 -0
- package/dist/assets/tasks/core/improve.yml +4 -0
- package/dist/assets/tasks/core/index-refresh.yml +4 -0
- package/dist/assets/tasks/core/sync.yml +4 -0
- package/dist/assets/tasks/core/update-stashes.yml +4 -0
- package/dist/assets/tasks/core/version-check.yml +4 -0
- package/dist/cli/config-migrate.js +6 -6
- package/dist/cli/config-validate.js +4 -4
- package/dist/cli/confirm.js +3 -3
- package/dist/cli/parse-args.js +1 -1
- package/dist/cli/shared.js +51 -14
- package/dist/cli-node.mjs +26 -0
- package/dist/cli.js +171 -3857
- package/dist/commands/{agent-dispatch.js → agent/agent-dispatch.js} +6 -6
- package/dist/commands/{agent-support.js → agent/agent-support.js} +2 -2
- package/dist/commands/agent/contribute-cli.js +200 -0
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +240 -3
- package/dist/commands/config-edit.js +344 -0
- package/dist/commands/db-cli.js +2 -2
- package/dist/commands/env/env-cli.js +529 -0
- package/dist/commands/env/env.js +410 -0
- package/dist/commands/env/secret-cli.js +259 -0
- package/dist/commands/{secret.js → env/secret.js} +6 -47
- package/dist/commands/events.js +4 -4
- package/dist/commands/feedback-cli.js +18 -34
- package/dist/commands/graph/graph-cli.js +132 -0
- package/dist/commands/{graph.js → graph/graph.js} +22 -16
- package/dist/commands/health/checks.js +279 -0
- package/dist/commands/health.js +101 -249
- package/dist/commands/{consolidate.js → improve/consolidate.js} +52 -40
- package/dist/commands/{distill-promotion-policy.js → improve/distill-promotion-policy.js} +3 -3
- package/dist/commands/{distill.js → improve/distill.js} +39 -18
- package/dist/commands/{eval-cases.js → improve/eval-cases.js} +1 -1
- package/dist/commands/{extract-cli.js → improve/extract-cli.js} +4 -4
- package/dist/commands/{extract-prompt.js → improve/extract-prompt.js} +2 -2
- package/dist/commands/{extract.js → improve/extract.js} +185 -26
- package/dist/commands/{improve-auto-accept.js → improve/improve-auto-accept.js} +4 -4
- package/dist/commands/{improve-cli.js → improve/improve-cli.js} +45 -23
- package/dist/commands/{improve-profiles.js → improve/improve-profiles.js} +13 -7
- package/dist/commands/{improve-result-file.js → improve/improve-result-file.js} +10 -5
- package/dist/commands/{improve.js → improve/improve.js} +536 -248
- package/dist/{core → commands/improve/memory}/memory-belief.js +2 -2
- package/dist/{core → commands/improve/memory}/memory-contradiction-detect.js +5 -5
- package/dist/{core → commands/improve/memory}/memory-improve.js +4 -4
- package/dist/commands/{reflect.js → improve/reflect.js} +33 -28
- package/dist/commands/improve/session-asset.js +248 -0
- package/dist/commands/lint/agent-linter.js +1 -1
- package/dist/commands/lint/base-linter.js +55 -37
- package/dist/commands/lint/command-linter.js +1 -1
- package/dist/commands/lint/default-linter.js +1 -1
- package/dist/commands/lint/env-key-rules.js +1 -1
- package/dist/commands/lint/index.js +19 -25
- package/dist/commands/lint/knowledge-linter.js +1 -1
- package/dist/commands/lint/memory-linter.js +1 -1
- package/dist/commands/lint/registry.js +8 -8
- package/dist/commands/lint/skill-linter.js +1 -1
- package/dist/commands/lint/task-linter.js +1 -1
- package/dist/commands/lint/workflow-linter.js +1 -1
- package/dist/commands/lint.js +1 -1
- package/dist/commands/observability-cli.js +244 -0
- package/dist/commands/{proposal-drain-policies.js → proposal/drain-policies.js} +3 -3
- package/dist/commands/{proposal-drain.js → proposal/drain.js} +15 -10
- package/dist/commands/proposal/proposal-cli.js +478 -0
- package/dist/commands/{proposal.js → proposal/proposal.js} +5 -5
- package/dist/commands/{propose.js → proposal/propose.js} +11 -11
- package/dist/{core → commands/proposal/validators}/proposal-quality-validators.js +8 -3
- package/dist/{core → commands/proposal/validators}/proposal-validators.js +5 -5
- package/dist/{core → commands/proposal/validators}/proposals.js +13 -7
- package/dist/commands/{curate.js → read/curate.js} +7 -7
- package/dist/commands/{knowledge.js → read/knowledge.js} +22 -9
- package/dist/commands/{registry-search.js → read/registry-search.js} +5 -5
- package/dist/commands/{remember-cli.js → read/remember-cli.js} +15 -7
- package/dist/commands/read/search-cli.js +207 -0
- package/dist/commands/{search.js → read/search.js} +22 -27
- package/dist/commands/{show.js → read/show.js} +77 -44
- package/dist/commands/registry-cli.js +8 -8
- package/dist/commands/remember.js +8 -8
- package/dist/commands/sources/add-cli.js +293 -0
- package/dist/commands/{history.js → sources/history.js} +27 -25
- package/dist/commands/{info.js → sources/info.js} +6 -6
- package/dist/commands/{init.js → sources/init.js} +10 -5
- package/dist/commands/{installed-stashes.js → sources/installed-stashes.js} +12 -12
- package/dist/commands/{migration-help.js → sources/migration-help.js} +3 -2
- package/dist/commands/{schema-repair.js → sources/schema-repair.js} +8 -8
- package/dist/commands/{self-update.js → sources/self-update.js} +10 -9
- package/dist/commands/{source-add.js → sources/source-add.js} +10 -10
- package/dist/commands/{source-clone.js → sources/source-clone.js} +7 -7
- package/dist/commands/{source-manage.js → sources/source-manage.js} +4 -4
- package/dist/commands/sources/sources-cli.js +305 -0
- package/dist/commands/sources/stash-cli.js +219 -0
- package/dist/commands/sources/stash-skeleton.js +79 -0
- package/dist/commands/tasks/default-tasks.js +173 -0
- package/dist/commands/tasks/tasks-cli.js +210 -0
- package/dist/commands/{tasks.js → tasks/tasks.js} +14 -14
- package/dist/commands/wiki-cli.js +307 -0
- package/dist/commands/workflow-cli.js +329 -0
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/assert.js +40 -0
- package/dist/core/asset/asset-create.js +54 -0
- package/dist/core/{asset-ref.js → asset/asset-ref.js} +21 -4
- package/dist/core/{asset-registry.js → asset/asset-registry.js} +3 -3
- package/dist/core/{asset-spec.js → asset/asset-spec.js} +17 -31
- package/dist/core/{markdown.js → asset/markdown.js} +1 -1
- package/dist/core/asset/stash-meta.js +110 -0
- package/dist/core/best-effort.js +64 -0
- package/dist/core/common.js +32 -18
- package/dist/core/{config-io.js → config/config-io.js} +29 -19
- package/dist/core/{config-migration.js → config/config-migration.js} +11 -9
- package/dist/core/{config-schema.js → config/config-schema.js} +45 -1
- package/dist/core/config/config-types.js +16 -0
- package/dist/core/{config-walker.js → config/config-walker.js} +2 -2
- package/dist/core/{config.js → config/config.js} +10 -8
- package/dist/core/env-secret-ref.js +90 -0
- package/dist/core/errors.js +13 -3
- package/dist/core/events.js +27 -4
- package/dist/core/file-lock.js +1 -1
- package/dist/core/improve-types.js +48 -0
- package/dist/core/lesson-lint.js +2 -2
- package/dist/core/paths.js +2 -2
- package/dist/{setup/ripgrep-install.js → core/ripgrep/install.js} +2 -2
- package/dist/{setup/ripgrep-resolve.js → core/ripgrep/resolve.js} +2 -2
- package/dist/core/state-db.js +88 -46
- package/dist/core/text-truncation.js +148 -0
- package/dist/core/time.js +1 -1
- package/dist/core/write-source.js +98 -85
- package/dist/indexer/{db-backup.js → db/db-backup.js} +9 -24
- package/dist/indexer/{db.js → db/db.js} +126 -116
- package/dist/indexer/{graph-db.js → db/graph-db.js} +9 -4
- package/dist/indexer/{llm-cache.js → db/llm-cache.js} +15 -12
- package/dist/indexer/ensure-index.js +4 -4
- package/dist/indexer/{graph-boost.js → graph/graph-boost.js} +1 -1
- package/dist/indexer/{graph-extraction.js → graph/graph-extraction.js} +55 -13
- package/dist/indexer/indexer.js +37 -30
- package/dist/indexer/init.js +54 -0
- package/dist/indexer/manifest.js +10 -10
- package/dist/indexer/{memory-inference.js → passes/memory-inference.js} +92 -23
- package/dist/indexer/{metadata-contributors.js → passes/metadata-contributors.js} +10 -8
- package/dist/indexer/{metadata.js → passes/metadata.js} +15 -19
- package/dist/indexer/{staleness-detect.js → passes/staleness-detect.js} +53 -12
- package/dist/indexer/{db-search.js → search/db-search.js} +28 -16
- package/dist/indexer/{ranking-contributors.js → search/ranking-contributors.js} +1 -1
- package/dist/indexer/{ranking.js → search/ranking.js} +2 -2
- package/dist/indexer/{search-hit-enrichers.js → search/search-hit-enrichers.js} +3 -3
- package/dist/indexer/{search-source.js → search/search-source.js} +8 -8
- package/dist/indexer/{semantic-status.js → search/semantic-status.js} +3 -3
- package/dist/indexer/usage/unmigrated-vaults-guard.js +94 -0
- package/dist/indexer/{usage-events.js → usage/usage-events.js} +32 -0
- package/dist/indexer/{file-context.js → walk/file-context.js} +10 -15
- package/dist/indexer/{matchers.js → walk/matchers.js} +13 -9
- package/dist/indexer/{path-resolver.js → walk/path-resolver.js} +6 -6
- package/dist/indexer/{project-context.js → walk/project-context.js} +1 -1
- package/dist/indexer/{walker.js → walk/walker.js} +4 -3
- package/dist/integrations/agent/builder-shared.js +39 -0
- package/dist/integrations/agent/builders.js +14 -81
- package/dist/integrations/agent/config.js +6 -4
- package/dist/integrations/agent/detect.js +1 -1
- package/dist/integrations/agent/index.js +23 -8
- package/dist/integrations/agent/prompts.js +2 -3
- package/dist/integrations/agent/runner.js +22 -3
- package/dist/integrations/agent/spawn.js +9 -10
- package/dist/integrations/harnesses/claude/agent-builder.js +48 -0
- package/dist/integrations/harnesses/claude/config-import.js +70 -0
- package/dist/integrations/harnesses/claude/index.js +64 -0
- package/dist/integrations/{session-logs/providers/claude-code.js → harnesses/claude/session-log.js} +16 -1
- package/dist/integrations/harnesses/index.js +144 -0
- package/dist/integrations/harnesses/opencode/agent-builder.js +43 -0
- package/dist/integrations/harnesses/opencode/config-import.js +82 -0
- package/dist/integrations/harnesses/opencode/index.js +59 -0
- package/dist/integrations/{session-logs/providers/opencode.js → harnesses/opencode/session-log.js} +1 -1
- package/dist/integrations/harnesses/opencode-sdk/index.js +49 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +234 -0
- package/dist/integrations/harnesses/types.js +43 -0
- package/dist/integrations/lockfile.js +7 -16
- package/dist/integrations/session-logs/index.js +82 -9
- package/dist/llm/call-ai.js +4 -4
- package/dist/llm/client.js +131 -6
- package/dist/llm/embedder.js +6 -6
- package/dist/llm/embedders/local.js +9 -22
- package/dist/llm/embedders/remote.js +2 -2
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/graph-extract.js +31 -12
- package/dist/llm/index-passes.js +1 -1
- package/dist/llm/memory-infer.js +12 -5
- package/dist/llm/metadata-enhance.js +2 -2
- package/dist/output/context.js +6 -44
- package/dist/output/renderers.js +88 -58
- package/dist/output/shapes/curate.js +7 -3
- package/dist/output/shapes/distill.js +7 -3
- package/dist/output/shapes/env-list.js +18 -16
- package/dist/output/shapes/events.js +5 -4
- package/dist/output/shapes/helpers.js +2 -4
- package/dist/output/shapes/history.js +7 -3
- package/dist/output/shapes/passthrough.js +8 -11
- package/dist/output/shapes/{proposal-accept.js → proposal/accept.js} +7 -3
- package/dist/output/shapes/{proposal-diff.js → proposal/diff.js} +7 -3
- package/dist/output/shapes/{proposal-list.js → proposal/list.js} +7 -3
- package/dist/output/shapes/{proposal-producer.js → proposal/producer.js} +5 -4
- package/dist/output/shapes/{proposal-reject.js → proposal/reject.js} +7 -3
- package/dist/output/shapes/{proposal-show.js → proposal/show.js} +7 -3
- package/dist/output/shapes/registry-search.js +7 -3
- package/dist/output/shapes/registry.js +12 -0
- package/dist/output/shapes/search.js +7 -3
- package/dist/output/shapes/secret-list.js +18 -16
- package/dist/output/shapes/show.js +7 -3
- package/dist/output/shapes.js +55 -30
- package/dist/output/text/add.js +2 -3
- package/dist/output/text/clone.js +2 -3
- package/dist/output/text/config.js +2 -3
- package/dist/output/text/curate.js +4 -3
- package/dist/output/text/distill.js +2 -3
- package/dist/output/text/enable-disable.js +5 -4
- package/dist/output/text/env.js +13 -0
- package/dist/output/text/events.js +5 -4
- package/dist/output/text/feedback.js +4 -3
- package/dist/output/text/helpers.js +54 -39
- package/dist/output/text/history.js +2 -3
- package/dist/output/text/import.js +2 -3
- package/dist/output/text/index.js +2 -3
- package/dist/output/text/info.js +2 -3
- package/dist/output/text/init.js +2 -3
- package/dist/output/text/list.js +2 -3
- package/dist/output/text/proposal/producer.js +9 -0
- package/dist/output/text/proposal/proposal.js +13 -0
- package/dist/output/text/registry-commands.js +8 -7
- package/dist/output/text/registry.js +12 -0
- package/dist/output/text/remember.js +4 -3
- package/dist/output/text/remove.js +2 -3
- package/dist/output/text/save.js +2 -3
- package/dist/output/text/search.js +4 -3
- package/dist/output/text/show.js +4 -3
- package/dist/output/text/update.js +2 -3
- package/dist/output/text/upgrade.js +2 -3
- package/dist/output/text/wiki.js +12 -11
- package/dist/output/text/workflow.js +12 -10
- package/dist/output/text.js +66 -32
- package/dist/registry/build-index.js +11 -10
- package/dist/registry/factory.js +1 -1
- package/dist/registry/origin-resolve.js +1 -1
- package/dist/registry/providers/index.js +2 -2
- package/dist/registry/providers/skills-sh.js +91 -72
- package/dist/registry/providers/static-index.js +75 -52
- package/dist/registry/resolve.js +3 -3
- package/dist/runtime.js +242 -0
- package/dist/scripts/migrate-storage.js +1594 -673
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +240 -166
- package/dist/setup/detect.js +338 -9
- package/dist/setup/harness-config-import.js +56 -0
- package/dist/setup/registry-stash-loader.js +99 -0
- package/dist/setup/setup.js +664 -96
- package/dist/sources/include.js +1 -1
- package/dist/sources/provider-factory.js +2 -2
- package/dist/sources/providers/filesystem.js +3 -3
- package/dist/sources/providers/git.js +9 -9
- package/dist/sources/providers/index.js +4 -4
- package/dist/sources/providers/npm.js +6 -6
- package/dist/sources/providers/provider-utils.js +13 -20
- package/dist/sources/providers/sync-from-ref.js +5 -5
- package/dist/sources/providers/tar-utils.js +2 -2
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +5 -5
- package/dist/sources/website-ingest.js +5 -5
- package/dist/storage/database.js +102 -0
- package/dist/storage/engines/sqlite-migrations.js +42 -0
- package/dist/storage/locations.js +25 -0
- package/dist/storage/repositories/index-db.js +43 -0
- package/dist/storage/repositories/workflow-runs-repository.js +141 -0
- package/dist/tasks/backends/cron.js +4 -4
- package/dist/tasks/backends/exec-utils.js +32 -0
- package/dist/tasks/backends/index.js +3 -3
- package/dist/tasks/backends/launchd.js +7 -14
- package/dist/tasks/backends/schtasks.js +7 -16
- package/dist/tasks/embedded.js +71 -0
- package/dist/tasks/parser.js +2 -2
- package/dist/tasks/resolveAkmBin.js +1 -1
- package/dist/tasks/runner.js +28 -15
- package/dist/tasks/schedule.js +1 -1
- package/dist/tasks/validator.js +7 -7
- package/dist/text-import-hook.mjs +51 -0
- package/dist/version.js +2 -1
- package/dist/wiki/wiki.js +7 -7
- package/dist/workflows/{authoring.js → authoring/authoring.js} +6 -6
- package/dist/workflows/{scope-key.js → authoring/scope-key.js} +1 -1
- package/dist/workflows/cli.js +1 -1
- package/dist/workflows/db.js +50 -32
- package/dist/workflows/parser.js +4 -4
- package/dist/workflows/renderer.js +5 -5
- package/dist/workflows/runtime/agent-identity.js +56 -0
- package/dist/workflows/runtime/checkin.js +57 -0
- package/dist/workflows/{runs.js → runtime/runs.js} +197 -101
- package/dist/workflows/validate-summary.js +82 -0
- package/docs/README.md +1 -1
- package/docs/data-and-telemetry.md +6 -6
- package/package.json +16 -8
- package/dist/commands/add-cli.js +0 -279
- package/dist/commands/env.js +0 -213
- package/dist/integrations/agent/sdk-runner.js +0 -126
- package/dist/output/shapes/vault-list.js +0 -19
- package/dist/output/text/proposal-producer.js +0 -8
- package/dist/output/text/proposal.js +0 -12
- package/dist/output/text/vault.js +0 -16
- /package/dist/core/{asset-serialize.js → asset/asset-serialize.js} +0 -0
- /package/dist/core/{frontmatter.js → asset/frontmatter.js} +0 -0
- /package/dist/core/{config-sources.js → config/config-sources.js} +0 -0
- /package/dist/indexer/{graph-dedup.js → graph/graph-dedup.js} +0 -0
- /package/dist/{core/config-types.js → indexer/passes/pass-context.js} +0 -0
- /package/dist/indexer/{search-fields.js → search/search-fields.js} +0 -0
- /package/dist/indexer/{index-context.js → walk/index-context.js} +0 -0
- /package/dist/workflows/{document-cache.js → runtime/document-cache.js} +0 -0
package/dist/commands/health.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import { spawnSync } from "node:child_process";
|
|
5
4
|
import fs from "node:fs";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { getExecutionLogCandidates } from "../integrations/session-logs";
|
|
5
|
+
import { ConfigError, UsageError } from "../core/errors.js";
|
|
6
|
+
import { appendEvent, readEvents } from "../core/events.js";
|
|
7
|
+
import { getStateDbPathInDataDir } from "../core/paths.js";
|
|
8
|
+
import { listExistingTableNames, openStateDatabase, queryCompletedTaskIntervals, queryImproveRuns, queryTaskHistory, } from "../core/state-db.js";
|
|
9
|
+
import { parseSinceToIso } from "../core/time.js";
|
|
10
|
+
import { readSemanticStatus } from "../indexer/search/semantic-status.js";
|
|
11
|
+
import { getExecutionLogCandidates } from "../integrations/session-logs/index.js";
|
|
12
|
+
import { HEALTH_CHECKS } from "./health/checks.js";
|
|
15
13
|
const DEFAULT_SINCE_MS = 24 * 60 * 60 * 1000;
|
|
16
14
|
const IMPROVE_COMPLETED_EVENT = "improve_completed";
|
|
17
15
|
const HEALTH_PROBE_EVENT = "health_probe";
|
|
@@ -71,6 +69,7 @@ function createUnknownImproveMetrics() {
|
|
|
71
69
|
graphExtraction: 0,
|
|
72
70
|
error: 0,
|
|
73
71
|
},
|
|
72
|
+
autoAccept: { promoted: 0, validationFailed: 0 },
|
|
74
73
|
reflectsWithErrorContext: 0,
|
|
75
74
|
coverageGapCount: 0,
|
|
76
75
|
evalCasesWritten: 0,
|
|
@@ -103,6 +102,7 @@ function createUnknownImproveMetrics() {
|
|
|
103
102
|
ran: false,
|
|
104
103
|
considered: 0,
|
|
105
104
|
cacheHits: 0,
|
|
105
|
+
retryAttempts: 0,
|
|
106
106
|
freshAttempts: 0,
|
|
107
107
|
splitParents: 0,
|
|
108
108
|
written: 0,
|
|
@@ -110,6 +110,7 @@ function createUnknownImproveMetrics() {
|
|
|
110
110
|
skippedChildExists: 0,
|
|
111
111
|
skippedAborted: 0,
|
|
112
112
|
unaccounted: 0,
|
|
113
|
+
htmlErrorCount: 0,
|
|
113
114
|
yieldEligibleRuns: 0,
|
|
114
115
|
yieldEligibleConsidered: 0,
|
|
115
116
|
yieldEligibleWritten: 0,
|
|
@@ -127,6 +128,8 @@ function createUnknownImproveMetrics() {
|
|
|
127
128
|
cacheHitRate: 0,
|
|
128
129
|
truncations: 0,
|
|
129
130
|
failures: 0,
|
|
131
|
+
htmlErrors: 0,
|
|
132
|
+
retryAttempts: 0,
|
|
130
133
|
durationMs: 0,
|
|
131
134
|
},
|
|
132
135
|
sessionExtraction: {
|
|
@@ -293,6 +296,8 @@ function projectRunMetrics(result) {
|
|
|
293
296
|
}
|
|
294
297
|
}
|
|
295
298
|
}
|
|
299
|
+
metrics.autoAccept.promoted += toFiniteNumber(result.gateAutoAcceptedCount);
|
|
300
|
+
metrics.autoAccept.validationFailed += toFiniteNumber(result.gateAutoAcceptFailedCount);
|
|
296
301
|
metrics.reflectsWithErrorContext += toFiniteNumber(result.reflectsWithErrorContext);
|
|
297
302
|
if (Array.isArray(result.coverageGaps))
|
|
298
303
|
metrics.coverageGapCount += result.coverageGaps.length;
|
|
@@ -334,18 +339,26 @@ function projectRunMetrics(result) {
|
|
|
334
339
|
metrics.consolidation.mergedSecondaries += toFiniteNumber(consolidation.mergedSecondaries);
|
|
335
340
|
metrics.consolidation.failedChunkMemories += toFiniteNumber(consolidation.failedChunkMemories);
|
|
336
341
|
// Structured emitter (new on this branch): consolidate.ts now pushes
|
|
337
|
-
// `{
|
|
338
|
-
// post-LLM rejection.
|
|
339
|
-
//
|
|
342
|
+
// per-ref grouped `{ref, skips: [{op, reason}]}` entries to `skipReasons`
|
|
343
|
+
// for every deterministic post-LLM rejection. Each ref appears once but
|
|
344
|
+
// may carry multiple skips; aggregate every reason. Pre-fix envelopes have
|
|
345
|
+
// neither field, so be defensive.
|
|
340
346
|
const skipReasons = consolidation.skipReasons;
|
|
341
347
|
if (Array.isArray(skipReasons)) {
|
|
342
348
|
for (const entry of skipReasons) {
|
|
343
349
|
if (!entry || typeof entry !== "object")
|
|
344
350
|
continue;
|
|
345
|
-
const
|
|
346
|
-
if (
|
|
351
|
+
const skips = entry.skips;
|
|
352
|
+
if (!Array.isArray(skips))
|
|
347
353
|
continue;
|
|
348
|
-
|
|
354
|
+
for (const skip of skips) {
|
|
355
|
+
if (!skip || typeof skip !== "object")
|
|
356
|
+
continue;
|
|
357
|
+
const reason = skip.reason;
|
|
358
|
+
if (typeof reason !== "string" || !reason.trim())
|
|
359
|
+
continue;
|
|
360
|
+
metrics.consolidation.skipReasons[reason] = (metrics.consolidation.skipReasons[reason] ?? 0) + 1;
|
|
361
|
+
}
|
|
349
362
|
}
|
|
350
363
|
}
|
|
351
364
|
}
|
|
@@ -355,12 +368,14 @@ function projectRunMetrics(result) {
|
|
|
355
368
|
const writtenFacts = toFiniteNumber(memoryInference.writtenFacts);
|
|
356
369
|
metrics.memoryInference.considered += considered;
|
|
357
370
|
metrics.memoryInference.cacheHits += toFiniteNumber(memoryInference.cacheHits);
|
|
371
|
+
metrics.memoryInference.retryAttempts += toFiniteNumber(memoryInference.retryAttempts);
|
|
358
372
|
metrics.memoryInference.splitParents += toFiniteNumber(memoryInference.splitParents);
|
|
359
373
|
metrics.memoryInference.written += writtenFacts;
|
|
360
374
|
metrics.memoryInference.skippedNoFacts += toFiniteNumber(memoryInference.skippedNoFacts);
|
|
361
375
|
metrics.memoryInference.skippedChildExists += toFiniteNumber(memoryInference.skippedChildExists);
|
|
362
376
|
metrics.memoryInference.skippedAborted += toFiniteNumber(memoryInference.skippedAborted);
|
|
363
377
|
metrics.memoryInference.unaccounted += toFiniteNumber(memoryInference.unaccounted);
|
|
378
|
+
metrics.memoryInference.htmlErrorCount += toFiniteNumber(memoryInference.htmlErrorCount);
|
|
364
379
|
// Yield-rate gating: pre-cache-feature envelopes lack the `cacheHits`
|
|
365
380
|
// field entirely. Treating their `considered` as freshAttempts (since
|
|
366
381
|
// cacheHits=0) is mathematically tempting but operationally wrong —
|
|
@@ -388,6 +403,8 @@ function projectRunMetrics(result) {
|
|
|
388
403
|
metrics.graphExtraction.cacheMisses += toFiniteNumber(telemetry.cacheMisses);
|
|
389
404
|
metrics.graphExtraction.truncations += toFiniteNumber(telemetry.truncationCount);
|
|
390
405
|
metrics.graphExtraction.failures += toFiniteNumber(telemetry.failureCount);
|
|
406
|
+
metrics.graphExtraction.htmlErrors += toFiniteNumber(telemetry.htmlErrorCount);
|
|
407
|
+
metrics.graphExtraction.retryAttempts += toFiniteNumber(telemetry.retryAttempts);
|
|
391
408
|
}
|
|
392
409
|
}
|
|
393
410
|
metrics.graphExtraction.durationMs += toFiniteNumber(result.graphExtractionDurationMs);
|
|
@@ -481,6 +498,8 @@ function mergeImproveMetrics(dst, src) {
|
|
|
481
498
|
dst.actions.memoryInference += src.actions.memoryInference;
|
|
482
499
|
dst.actions.graphExtraction += src.actions.graphExtraction;
|
|
483
500
|
dst.actions.error += src.actions.error;
|
|
501
|
+
dst.autoAccept.promoted += src.autoAccept.promoted;
|
|
502
|
+
dst.autoAccept.validationFailed += src.autoAccept.validationFailed;
|
|
484
503
|
dst.reflectsWithErrorContext += src.reflectsWithErrorContext;
|
|
485
504
|
dst.coverageGapCount += src.coverageGapCount;
|
|
486
505
|
dst.evalCasesWritten += src.evalCasesWritten;
|
|
@@ -515,6 +534,7 @@ function mergeImproveMetrics(dst, src) {
|
|
|
515
534
|
dst.memoryInference.skippedChildExists += src.memoryInference.skippedChildExists;
|
|
516
535
|
dst.memoryInference.skippedAborted += src.memoryInference.skippedAborted;
|
|
517
536
|
dst.memoryInference.unaccounted += src.memoryInference.unaccounted;
|
|
537
|
+
dst.memoryInference.htmlErrorCount += src.memoryInference.htmlErrorCount;
|
|
518
538
|
dst.memoryInference.yieldEligibleRuns += src.memoryInference.yieldEligibleRuns;
|
|
519
539
|
dst.memoryInference.yieldEligibleConsidered += src.memoryInference.yieldEligibleConsidered;
|
|
520
540
|
dst.memoryInference.yieldEligibleWritten += src.memoryInference.yieldEligibleWritten;
|
|
@@ -526,6 +546,7 @@ function mergeImproveMetrics(dst, src) {
|
|
|
526
546
|
dst.graphExtraction.cacheMisses += src.graphExtraction.cacheMisses;
|
|
527
547
|
dst.graphExtraction.truncations += src.graphExtraction.truncations;
|
|
528
548
|
dst.graphExtraction.failures += src.graphExtraction.failures;
|
|
549
|
+
dst.graphExtraction.htmlErrors += src.graphExtraction.htmlErrors;
|
|
529
550
|
dst.graphExtraction.durationMs += src.graphExtraction.durationMs;
|
|
530
551
|
dst.sessionExtraction.sessionsScanned += src.sessionExtraction.sessionsScanned;
|
|
531
552
|
dst.sessionExtraction.sessionsExtracted += src.sessionExtraction.sessionsExtracted;
|
|
@@ -534,15 +555,9 @@ function mergeImproveMetrics(dst, src) {
|
|
|
534
555
|
dst.sessionExtraction.warnings += src.sessionExtraction.warnings;
|
|
535
556
|
dst.sessionExtraction.durationMs += src.sessionExtraction.durationMs;
|
|
536
557
|
}
|
|
537
|
-
function loadImproveRunRows(db, since, until) {
|
|
538
|
-
const sql = until
|
|
539
|
-
? "SELECT id, started_at, completed_at, ok, scope_mode, scope_value, result_json FROM improve_runs WHERE started_at >= ? AND started_at < ? AND dry_run = 0 ORDER BY started_at DESC"
|
|
540
|
-
: "SELECT id, started_at, completed_at, ok, scope_mode, scope_value, result_json FROM improve_runs WHERE started_at >= ? AND dry_run = 0 ORDER BY started_at DESC";
|
|
541
|
-
return (until ? db.prepare(sql).all(since, until) : db.prepare(sql).all(since));
|
|
542
|
-
}
|
|
543
558
|
function summarizeImproveRuns(db, since, until) {
|
|
544
559
|
const accum = createUnknownImproveMetrics();
|
|
545
|
-
const rows =
|
|
560
|
+
const rows = queryImproveRuns(db, since, until);
|
|
546
561
|
// Per-phase wall-time samples. Each entry is one envelope's durationMs for
|
|
547
562
|
// that phase. Phases that did not run on a given envelope are simply
|
|
548
563
|
// omitted (NOT counted as 0) so the median/p95 reflect actual phase work.
|
|
@@ -661,10 +676,7 @@ function loadTaskIntervals(db, since, until) {
|
|
|
661
676
|
const untilMs = until ? new Date(until).getTime() : Number.POSITIVE_INFINITY;
|
|
662
677
|
const widenedSince = new Date(sinceMs - 5 * 60 * 1000).toISOString();
|
|
663
678
|
const widenedUntil = Number.isFinite(untilMs) ? new Date(untilMs + 5 * 60 * 1000).toISOString() : undefined;
|
|
664
|
-
const
|
|
665
|
-
? "SELECT started_at, completed_at FROM task_history WHERE task_id = 'akm-improve' AND started_at >= ? AND started_at < ? AND completed_at IS NOT NULL ORDER BY started_at"
|
|
666
|
-
: "SELECT started_at, completed_at FROM task_history WHERE task_id = 'akm-improve' AND started_at >= ? AND completed_at IS NOT NULL ORDER BY started_at";
|
|
667
|
-
const rows = (widenedUntil ? db.prepare(sql).all(widenedSince, widenedUntil) : db.prepare(sql).all(widenedSince));
|
|
679
|
+
const rows = queryCompletedTaskIntervals(db, widenedSince, widenedUntil);
|
|
668
680
|
const intervals = [];
|
|
669
681
|
for (const row of rows) {
|
|
670
682
|
const startMs = new Date(row.started_at).getTime();
|
|
@@ -697,18 +709,27 @@ function findContainingTaskInterval(timestampMs, intervals) {
|
|
|
697
709
|
return undefined;
|
|
698
710
|
}
|
|
699
711
|
function buildPerRunSummaries(db, since, until) {
|
|
700
|
-
const rows =
|
|
712
|
+
const rows = queryImproveRuns(db, since, until);
|
|
701
713
|
const taskIntervals = loadTaskIntervals(db, since, until);
|
|
702
714
|
const summaries = [];
|
|
703
715
|
for (const row of rows) {
|
|
704
716
|
const startMs = new Date(row.started_at).getTime();
|
|
705
717
|
const endMs = new Date(row.completed_at).getTime();
|
|
706
|
-
// Prefer the
|
|
707
|
-
//
|
|
708
|
-
//
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
718
|
+
// Prefer the improve_runs row's own (completed_at - started_at) delta:
|
|
719
|
+
// recordImproveRun now persists distinct start/end timestamps, so the
|
|
720
|
+
// row's own delta is the authoritative per-run wall time even for
|
|
721
|
+
// manually-invoked `akm improve` runs with no enclosing task_history.
|
|
722
|
+
// Only fall back to the task_history containing-interval join for legacy/
|
|
723
|
+
// backfill rows where started_at == completed_at (row delta is 0).
|
|
724
|
+
const hasRowDelta = Number.isFinite(startMs) && Number.isFinite(endMs) && endMs > startMs;
|
|
725
|
+
let wallTimeMs;
|
|
726
|
+
if (hasRowDelta) {
|
|
727
|
+
wallTimeMs = endMs - startMs;
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
const interval = Number.isFinite(startMs) ? findContainingTaskInterval(startMs, taskIntervals) : undefined;
|
|
731
|
+
wallTimeMs = interval?.durationMs ?? 0;
|
|
732
|
+
}
|
|
712
733
|
summaries.push(projectImproveRunSummary(row, wallTimeMs));
|
|
713
734
|
}
|
|
714
735
|
return summaries;
|
|
@@ -754,108 +775,11 @@ function probeStateDbRoundTrip(stateDbPath) {
|
|
|
754
775
|
}
|
|
755
776
|
return { ok: true, durationMs };
|
|
756
777
|
}
|
|
757
|
-
function runAgentProbe() {
|
|
758
|
-
const config = loadConfig();
|
|
759
|
-
// v2: check profiles.agent first
|
|
760
|
-
if (config.profiles?.agent) {
|
|
761
|
-
const defaultName = config.defaults?.agent;
|
|
762
|
-
const profileCount = Object.keys(config.profiles.agent).length;
|
|
763
|
-
if (profileCount === 0) {
|
|
764
|
-
return {
|
|
765
|
-
name: "agent-profile",
|
|
766
|
-
kind: "deterministic",
|
|
767
|
-
status: "unknown",
|
|
768
|
-
confidence: "high",
|
|
769
|
-
message: "No agent profiles configured in profiles.agent.",
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
const profileName = defaultName ?? Object.keys(config.profiles.agent)[0];
|
|
773
|
-
const profile = config.profiles.agent[profileName];
|
|
774
|
-
return {
|
|
775
|
-
name: "agent-profile",
|
|
776
|
-
kind: "deterministic",
|
|
777
|
-
status: "pass",
|
|
778
|
-
confidence: "high",
|
|
779
|
-
message: `v2 agent profile "${profileName}" configured (platform: ${profile?.platform ?? "unknown"}).`,
|
|
780
|
-
evidence: { profile: profileName, platform: profile?.platform, profileCount },
|
|
781
|
-
};
|
|
782
|
-
}
|
|
783
|
-
if (!config.profiles?.agent && !config.defaults?.agent) {
|
|
784
|
-
return {
|
|
785
|
-
name: "agent-profile",
|
|
786
|
-
kind: "deterministic",
|
|
787
|
-
status: "unknown",
|
|
788
|
-
confidence: "high",
|
|
789
|
-
message: "No agent config present.",
|
|
790
|
-
};
|
|
791
|
-
}
|
|
792
|
-
let profile;
|
|
793
|
-
try {
|
|
794
|
-
profile = requireAgentProfile(config);
|
|
795
|
-
}
|
|
796
|
-
catch (error) {
|
|
797
|
-
return {
|
|
798
|
-
name: "agent-profile",
|
|
799
|
-
kind: "deterministic",
|
|
800
|
-
status: "warn",
|
|
801
|
-
confidence: "high",
|
|
802
|
-
message: error instanceof Error ? error.message : String(error),
|
|
803
|
-
};
|
|
804
|
-
}
|
|
805
|
-
if (profile.sdkMode === true) {
|
|
806
|
-
return {
|
|
807
|
-
name: "agent-profile",
|
|
808
|
-
kind: "deterministic",
|
|
809
|
-
status: profile.model ? "pass" : "warn",
|
|
810
|
-
confidence: "high",
|
|
811
|
-
message: profile.model
|
|
812
|
-
? `SDK mode profile "${profile.name}" is configured.`
|
|
813
|
-
: `SDK mode profile "${profile.name}" has no explicit model.`,
|
|
814
|
-
evidence: { profile: profile.name, sdkMode: true, model: profile.model ?? null },
|
|
815
|
-
};
|
|
816
|
-
}
|
|
817
|
-
const detections = detectAgentCliProfiles(config);
|
|
818
|
-
const detection = detections.find((entry) => entry.name === profile.name);
|
|
819
|
-
if (!detection?.available) {
|
|
820
|
-
return {
|
|
821
|
-
name: "agent-profile",
|
|
822
|
-
kind: "deterministic",
|
|
823
|
-
status: "fail",
|
|
824
|
-
confidence: "high",
|
|
825
|
-
message: `Default agent profile "${profile.name}" is not available on PATH.`,
|
|
826
|
-
evidence: { profile: profile.name, bin: profile.bin },
|
|
827
|
-
};
|
|
828
|
-
}
|
|
829
|
-
const version = spawnSync(profile.bin, ["--version"], { encoding: "utf8", timeout: 5_000 });
|
|
830
|
-
if ((version.status ?? 1) !== 0) {
|
|
831
|
-
return {
|
|
832
|
-
name: "agent-profile",
|
|
833
|
-
kind: "deterministic",
|
|
834
|
-
status: "warn",
|
|
835
|
-
confidence: "medium",
|
|
836
|
-
message: `Agent binary "${profile.bin}" was found but \`--version\` failed.`,
|
|
837
|
-
evidence: {
|
|
838
|
-
profile: profile.name,
|
|
839
|
-
bin: profile.bin,
|
|
840
|
-
exitCode: version.status ?? null,
|
|
841
|
-
stderr: (version.stderr ?? "").trim(),
|
|
842
|
-
},
|
|
843
|
-
};
|
|
844
|
-
}
|
|
845
|
-
return {
|
|
846
|
-
name: "agent-profile",
|
|
847
|
-
kind: "deterministic",
|
|
848
|
-
status: "pass",
|
|
849
|
-
confidence: "high",
|
|
850
|
-
message: `Agent profile "${profile.name}" is available.`,
|
|
851
|
-
evidence: { profile: profile.name, bin: profile.bin, version: (version.stdout ?? "").trim() },
|
|
852
|
-
};
|
|
853
|
-
}
|
|
854
778
|
/**
|
|
855
779
|
* Parse a `--window-compare <duration>` shorthand into two adjacent windows
|
|
856
780
|
* (current, prior). Duration syntax matches {@link parseHealthSince}.
|
|
857
781
|
*/
|
|
858
|
-
function resolveWindowCompare(duration) {
|
|
782
|
+
function resolveWindowCompare(duration, now = () => Date.now()) {
|
|
859
783
|
const trimmed = duration.trim();
|
|
860
784
|
const durationMatch = trimmed.match(/^(\d+)([dhm])$/i);
|
|
861
785
|
if (!durationMatch) {
|
|
@@ -868,10 +792,10 @@ function resolveWindowCompare(duration) {
|
|
|
868
792
|
}
|
|
869
793
|
const multiplier = unit === "h" ? 60 * 60 * 1000 : unit === "m" ? 60 * 1000 : 24 * 60 * 60 * 1000;
|
|
870
794
|
const ms = amount * multiplier;
|
|
871
|
-
const
|
|
872
|
-
const currentSince = new Date(
|
|
873
|
-
const currentUntil = new Date(
|
|
874
|
-
const priorSince = new Date(
|
|
795
|
+
const nowMs = now();
|
|
796
|
+
const currentSince = new Date(nowMs - ms).toISOString();
|
|
797
|
+
const currentUntil = new Date(nowMs).toISOString();
|
|
798
|
+
const priorSince = new Date(nowMs - 2 * ms).toISOString();
|
|
875
799
|
const priorUntil = currentSince;
|
|
876
800
|
return [
|
|
877
801
|
{ name: "current", since: currentSince, until: currentUntil },
|
|
@@ -919,10 +843,14 @@ const INTERESTING_DELTA_PATHS = [
|
|
|
919
843
|
"improve.memoryInference.written",
|
|
920
844
|
"improve.memoryInference.yieldRate",
|
|
921
845
|
"improve.memoryInference.skippedNoFacts",
|
|
846
|
+
"improve.memoryInference.htmlErrorCount",
|
|
922
847
|
"improve.graphExtraction.cacheHitRate",
|
|
923
848
|
"improve.graphExtraction.failures",
|
|
849
|
+
"improve.graphExtraction.htmlErrors",
|
|
924
850
|
"improve.sessionExtraction.sessionsScanned",
|
|
925
851
|
"improve.sessionExtraction.proposalsCreated",
|
|
852
|
+
"improve.autoAccept.promoted",
|
|
853
|
+
"improve.autoAccept.validationFailed",
|
|
926
854
|
"improve.wallTime.medianMs",
|
|
927
855
|
"improve.wallTime.p95Ms",
|
|
928
856
|
];
|
|
@@ -954,7 +882,7 @@ function computeDeltas(first, last) {
|
|
|
954
882
|
}
|
|
955
883
|
return out;
|
|
956
884
|
}
|
|
957
|
-
function buildWindowMetrics(db, stateDbPath, since, until) {
|
|
885
|
+
function buildWindowMetrics(db, stateDbPath, since, until, now = () => Date.now()) {
|
|
958
886
|
const taskRows = queryTaskHistory(db, { since }).filter((row) => {
|
|
959
887
|
const startMs = new Date(row.started_at).getTime();
|
|
960
888
|
const untilMs = new Date(until).getTime();
|
|
@@ -964,7 +892,7 @@ function buildWindowMetrics(db, stateDbPath, since, until) {
|
|
|
964
892
|
const existingLogRows = taskRowsWithLogs.filter((row) => row.log_path && fs.existsSync(row.log_path));
|
|
965
893
|
const failedTaskRows = taskRows.filter((row) => row.status === "failed");
|
|
966
894
|
const activeRows = taskRows.filter((row) => row.status === "active");
|
|
967
|
-
const stuckActiveRuns = activeRows.filter((row) =>
|
|
895
|
+
const stuckActiveRuns = activeRows.filter((row) => now() - new Date(row.started_at).getTime() > ACTIVE_RUN_WARN_MS).length;
|
|
968
896
|
const promptRows = taskRows.filter((row) => row.target_kind === "prompt");
|
|
969
897
|
const promptFailures = promptRows.filter((row) => {
|
|
970
898
|
const detail = parseTaskMetadata(row).detail;
|
|
@@ -1020,8 +948,9 @@ function validateAkmHealthOptions(options) {
|
|
|
1020
948
|
}
|
|
1021
949
|
export function akmHealth(options = {}) {
|
|
1022
950
|
validateAkmHealthOptions(options);
|
|
951
|
+
const now = options.now ?? (() => Date.now());
|
|
1023
952
|
const since = parseHealthSince(options.since);
|
|
1024
|
-
const stateDbPath = getStateDbPathInDataDir();
|
|
953
|
+
const stateDbPath = options.stateDbPath ?? getStateDbPathInDataDir();
|
|
1025
954
|
const hardChecks = [];
|
|
1026
955
|
const advisories = [];
|
|
1027
956
|
const getExecutionLogCandidatesFn = options.getExecutionLogCandidatesFn ?? getExecutionLogCandidates;
|
|
@@ -1033,37 +962,17 @@ export function akmHealth(options = {}) {
|
|
|
1033
962
|
throw new ConfigError(`Unable to open state.db: ${error instanceof Error ? error.message : String(error)}`, "INVALID_CONFIG_FILE");
|
|
1034
963
|
}
|
|
1035
964
|
try {
|
|
1036
|
-
const tables = db
|
|
1037
|
-
.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name IN ('events', 'task_history', 'proposals', 'schema_migrations') ORDER BY name")
|
|
1038
|
-
.all();
|
|
965
|
+
const tables = listExistingTableNames(db, ["events", "task_history", "proposals", "schema_migrations"]);
|
|
1039
966
|
const tableNames = tables.map((row) => row.name).sort();
|
|
1040
967
|
const requiredTables = ["events", "proposals", "schema_migrations", "task_history"];
|
|
1041
968
|
const missingTables = requiredTables.filter((name) => !tableNames.includes(name));
|
|
1042
|
-
hardChecks.push({
|
|
1043
|
-
name: "state-db-schema",
|
|
1044
|
-
kind: "deterministic",
|
|
1045
|
-
status: missingTables.length === 0 ? "pass" : "fail",
|
|
1046
|
-
confidence: "high",
|
|
1047
|
-
message: missingTables.length === 0
|
|
1048
|
-
? "state.db opened and required tables are present."
|
|
1049
|
-
: `state.db is missing required tables: ${missingTables.join(", ")}`,
|
|
1050
|
-
evidence: { path: stateDbPath, tables: tableNames },
|
|
1051
|
-
});
|
|
1052
969
|
const probe = probeStateDbRoundTrip(stateDbPath);
|
|
1053
|
-
hardChecks.push({
|
|
1054
|
-
name: "state-db-round-trip",
|
|
1055
|
-
kind: "deterministic",
|
|
1056
|
-
status: probe.ok ? "pass" : "fail",
|
|
1057
|
-
confidence: "high",
|
|
1058
|
-
message: probe.ok ? "state.db append/read round-trip succeeded." : `state.db round-trip failed: ${probe.error}`,
|
|
1059
|
-
evidence: { path: stateDbPath, durationMs: probe.durationMs },
|
|
1060
|
-
});
|
|
1061
970
|
const taskRows = queryTaskHistory(db, { since });
|
|
1062
971
|
const taskRowsWithLogs = taskRows.filter((row) => row.log_path !== null);
|
|
1063
972
|
const existingLogRows = taskRowsWithLogs.filter((row) => row.log_path && fs.existsSync(row.log_path));
|
|
1064
973
|
const failedTaskRows = taskRows.filter((row) => row.status === "failed");
|
|
1065
974
|
const activeRows = taskRows.filter((row) => row.status === "active");
|
|
1066
|
-
const stuckActiveRuns = activeRows.filter((row) =>
|
|
975
|
+
const stuckActiveRuns = activeRows.filter((row) => now() - new Date(row.started_at).getTime() > ACTIVE_RUN_WARN_MS).length;
|
|
1067
976
|
const promptRows = taskRows.filter((row) => row.target_kind === "prompt");
|
|
1068
977
|
const promptFailures = promptRows.filter((row) => {
|
|
1069
978
|
const detail = parseTaskMetadata(row).detail;
|
|
@@ -1072,51 +981,7 @@ export function akmHealth(options = {}) {
|
|
|
1072
981
|
const logBackingRate = taskRowsWithLogs.length === 0 ? 1 : existingLogRows.length / taskRowsWithLogs.length;
|
|
1073
982
|
const taskFailRate = taskRows.length === 0 ? 0 : failedTaskRows.length / taskRows.length;
|
|
1074
983
|
const agentFailureRate = promptRows.length === 0 ? 0 : promptFailures.length / promptRows.length;
|
|
1075
|
-
hardChecks.push({
|
|
1076
|
-
name: "task-history-read",
|
|
1077
|
-
kind: "deterministic",
|
|
1078
|
-
status: "pass",
|
|
1079
|
-
confidence: "high",
|
|
1080
|
-
message: `Read ${taskRows.length} task-history row(s) since ${since}.`,
|
|
1081
|
-
evidence: { rows: taskRows.length, since },
|
|
1082
|
-
});
|
|
1083
|
-
hardChecks.push({
|
|
1084
|
-
name: "task-log-backing",
|
|
1085
|
-
kind: "deterministic",
|
|
1086
|
-
status: logBackingRate === 1 ? "pass" : "fail",
|
|
1087
|
-
confidence: "high",
|
|
1088
|
-
message: logBackingRate === 1
|
|
1089
|
-
? "Every task_history log_path resolved on disk."
|
|
1090
|
-
: `${taskRowsWithLogs.length - existingLogRows.length} task log(s) referenced in task_history are missing.`,
|
|
1091
|
-
evidence: { totalWithLogs: taskRowsWithLogs.length, existingLogs: existingLogRows.length },
|
|
1092
|
-
});
|
|
1093
|
-
hardChecks.push({
|
|
1094
|
-
name: "active-runs",
|
|
1095
|
-
kind: "deterministic",
|
|
1096
|
-
status: stuckActiveRuns === 0 ? "pass" : "warn",
|
|
1097
|
-
confidence: "high",
|
|
1098
|
-
message: stuckActiveRuns === 0
|
|
1099
|
-
? "No active task runs exceeded the stale threshold."
|
|
1100
|
-
: `${stuckActiveRuns} active task run(s) are older than ${Math.round(ACTIVE_RUN_WARN_MS / 60000)} minutes.`,
|
|
1101
|
-
evidence: { stuckActiveRuns },
|
|
1102
|
-
});
|
|
1103
|
-
hardChecks.push(runAgentProbe());
|
|
1104
984
|
const semanticStatus = readSemanticStatus();
|
|
1105
|
-
advisories.push({
|
|
1106
|
-
name: "semantic-search-runtime",
|
|
1107
|
-
kind: "deterministic",
|
|
1108
|
-
status: !semanticStatus ||
|
|
1109
|
-
semanticStatus.status === "pending" ||
|
|
1110
|
-
semanticStatus.status === "ready-js" ||
|
|
1111
|
-
semanticStatus.status === "ready-vec"
|
|
1112
|
-
? "pass"
|
|
1113
|
-
: "warn",
|
|
1114
|
-
confidence: "medium",
|
|
1115
|
-
message: semanticStatus
|
|
1116
|
-
? `Semantic search status: ${semanticStatus.status}`
|
|
1117
|
-
: "No semantic-search runtime status recorded yet.",
|
|
1118
|
-
evidence: semanticStatus ? { ...semanticStatus } : undefined,
|
|
1119
|
-
});
|
|
1120
985
|
const improveInvoked = readEvents({ since, type: "improve_invoked" }, { dbPath: stateDbPath }).events.length;
|
|
1121
986
|
const improveCompletedEvents = readEvents({ since, type: IMPROVE_COMPLETED_EVENT }, { dbPath: stateDbPath }).events;
|
|
1122
987
|
const improveSkippedEvents = readEvents({ since, type: "improve_skipped" }, { dbPath: stateDbPath }).events;
|
|
@@ -1132,7 +997,7 @@ export function akmHealth(options = {}) {
|
|
|
1132
997
|
improveSummary.wallTime = computeWallTimeStats(wallTimes, improveSummary.wallTime.byPhase);
|
|
1133
998
|
let sessionLogEntries = [];
|
|
1134
999
|
try {
|
|
1135
|
-
const sinceDays = Math.max(0, Math.ceil((
|
|
1000
|
+
const sinceDays = Math.max(0, Math.ceil((now() - new Date(since).getTime()) / (24 * 60 * 60 * 1000)));
|
|
1136
1001
|
sessionLogEntries = getExecutionLogCandidatesFn(sinceDays).map((entry) => ({
|
|
1137
1002
|
topic: entry.topic,
|
|
1138
1003
|
frequency: entry.frequency,
|
|
@@ -1143,46 +1008,33 @@ export function akmHealth(options = {}) {
|
|
|
1143
1008
|
catch {
|
|
1144
1009
|
sessionLogEntries = [];
|
|
1145
1010
|
}
|
|
1146
|
-
//
|
|
1147
|
-
//
|
|
1148
|
-
//
|
|
1149
|
-
//
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
? `Session extraction degraded: ${sxWarnReasons.join("; ")}.`
|
|
1174
|
-
: `Session extraction healthy: ${sx.sessionsScanned} scanned, ${sx.sessionsExtracted} extracted, ${sx.proposalsCreated} proposal(s) created.`
|
|
1175
|
-
: "Session extraction not active (feature disabled or no harness available).",
|
|
1176
|
-
evidence: {
|
|
1177
|
-
ran: sx.ran,
|
|
1178
|
-
sessionsScanned: sx.sessionsScanned,
|
|
1179
|
-
sessionsExtracted: sx.sessionsExtracted,
|
|
1180
|
-
sessionsSkipped: sx.sessionsSkipped,
|
|
1181
|
-
proposalsCreated: sx.proposalsCreated,
|
|
1182
|
-
warnings: sx.warnings,
|
|
1183
|
-
durationMs: sx.durationMs,
|
|
1184
|
-
},
|
|
1185
|
-
});
|
|
1011
|
+
// Run the ordered health-check registry. Each check projects the shared
|
|
1012
|
+
// context computed above into one HealthCheckResult; `channel` routes it to
|
|
1013
|
+
// hardChecks or advisories. Declaration order in HEALTH_CHECKS is the
|
|
1014
|
+
// emission order — see src/commands/health/checks.ts.
|
|
1015
|
+
const checkContext = {
|
|
1016
|
+
stateDbPath,
|
|
1017
|
+
since,
|
|
1018
|
+
tableNames,
|
|
1019
|
+
missingTables,
|
|
1020
|
+
probe,
|
|
1021
|
+
taskRowCount: taskRows.length,
|
|
1022
|
+
taskRowsWithLogsCount: taskRowsWithLogs.length,
|
|
1023
|
+
existingLogRowsCount: existingLogRows.length,
|
|
1024
|
+
logBackingRate,
|
|
1025
|
+
stuckActiveRuns,
|
|
1026
|
+
semanticStatus,
|
|
1027
|
+
sessionLogEntries,
|
|
1028
|
+
sessionExtraction: improveSummary.sessionExtraction,
|
|
1029
|
+
autoAccept: improveSummary.autoAccept,
|
|
1030
|
+
};
|
|
1031
|
+
for (const check of HEALTH_CHECKS) {
|
|
1032
|
+
const result = check.run(checkContext);
|
|
1033
|
+
if (check.channel === "hard")
|
|
1034
|
+
hardChecks.push(result);
|
|
1035
|
+
else
|
|
1036
|
+
advisories.push(result);
|
|
1037
|
+
}
|
|
1186
1038
|
const metrics = {
|
|
1187
1039
|
taskFailRate: roundRate(taskFailRate),
|
|
1188
1040
|
agentFailureRate: roundRate(agentFailureRate),
|
|
@@ -1196,7 +1048,7 @@ export function akmHealth(options = {}) {
|
|
|
1196
1048
|
// ── Window-compare mode (Phase 3) ─────────────────────────────────────
|
|
1197
1049
|
let windowSpecs;
|
|
1198
1050
|
if (options.windowCompare) {
|
|
1199
|
-
windowSpecs = resolveWindowCompare(options.windowCompare);
|
|
1051
|
+
windowSpecs = resolveWindowCompare(options.windowCompare, now);
|
|
1200
1052
|
}
|
|
1201
1053
|
else if (options.windows && options.windows.length > 0) {
|
|
1202
1054
|
windowSpecs = options.windows;
|
|
@@ -1209,8 +1061,8 @@ export function akmHealth(options = {}) {
|
|
|
1209
1061
|
if (windowSpecs && db) {
|
|
1210
1062
|
windowResults = windowSpecs.map((spec) => {
|
|
1211
1063
|
const winSince = parseHealthSince(spec.since);
|
|
1212
|
-
const winUntil = spec.until ? parseHealthSince(spec.until) : new Date().toISOString();
|
|
1213
|
-
const bundle = buildWindowMetrics(db, stateDbPath, winSince, winUntil);
|
|
1064
|
+
const winUntil = spec.until ? parseHealthSince(spec.until) : new Date(now()).toISOString();
|
|
1065
|
+
const bundle = buildWindowMetrics(db, stateDbPath, winSince, winUntil, now);
|
|
1214
1066
|
return {
|
|
1215
1067
|
name: spec.name,
|
|
1216
1068
|
since: winSince,
|