akm-cli 0.8.3 → 0.9.0-beta.1
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 +209 -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/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 -3862
- 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 +94 -262
- package/dist/commands/{consolidate.js → improve/consolidate.js} +48 -36
- 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} +44 -22
- package/dist/commands/{improve-profiles.js → improve/improve-profiles.js} +13 -7
- package/dist/commands/{improve-result-file.js → improve/improve-result-file.js} +1 -1
- package/dist/commands/{improve.js → improve/improve.js} +517 -253
- 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 +3 -3
- package/dist/commands/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} +31 -45
- 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} +6 -6
- 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/{stash-skeleton.js → sources/stash-skeleton.js} +2 -1
- 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/{stash-meta.js → asset/stash-meta.js} +1 -1
- 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/core/ripgrep/install.js +2 -2
- package/dist/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 +311 -9
- package/dist/setup/harness-config-import.js +6 -120
- package/dist/setup/setup.js +454 -43
- 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
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
export { stripJsonComments } from "./config-io";
|
|
11
|
-
import { getCacheDir, getConfigPath } from "
|
|
12
|
-
import { warn } from "
|
|
6
|
+
import { ConfigError } from "../errors.js";
|
|
7
|
+
import { backupExistingConfig, parseConfigText, withConfigLock, writeConfigAtomic } from "./config-io.js";
|
|
8
|
+
import { CURRENT_CONFIG_VERSION, compareConfigVersion, migrateConfigShape } from "./config-migration.js";
|
|
9
|
+
import { AkmConfigSchema } from "./config-schema.js";
|
|
10
|
+
export { stripJsonComments } from "./config-io.js";
|
|
11
|
+
import { getCacheDir, getConfigPath } from "../paths.js";
|
|
12
|
+
import { warn } from "../warn.js";
|
|
13
|
+
// Canonical harness-id source of truth (#565) — runtime value re-export.
|
|
14
|
+
export { VALID_HARNESS_IDS } from "./config-types.js";
|
|
13
15
|
// ── Feedback failure-mode constants (F-3 / #384) ────────────────────────────
|
|
14
16
|
/**
|
|
15
17
|
* Curated taxonomy of failure modes for negative feedback.
|
|
@@ -409,7 +411,7 @@ export function getIndexPassConfig(config, passName) {
|
|
|
409
411
|
return entry;
|
|
410
412
|
}
|
|
411
413
|
// Re-export source runtime helpers — implementation lives in config-sources.ts.
|
|
412
|
-
export { parseSourceSpec, resolveConfiguredSources } from "./config-sources";
|
|
414
|
+
export { parseSourceSpec, resolveConfiguredSources } from "./config-sources.js";
|
|
413
415
|
/**
|
|
414
416
|
* Merge a partial user-config override onto a base config. Used by
|
|
415
417
|
* {@link loadUserConfig} (DEFAULT_CONFIG + on-disk) and {@link updateConfig}
|
|
@@ -0,0 +1,90 @@
|
|
|
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
|
+
* Shared ref-resolution helpers for the `env` and `secret` command families
|
|
6
|
+
* (WS6). These were duplicated/co-located inline in `src/cli.ts`; hoisting them
|
|
7
|
+
* here lets `src/commands/env/env-cli.ts` and `src/commands/env/secret-cli.ts` import a
|
|
8
|
+
* single copy of the parse/resolve/make + path-traversal-guard logic (the WS6
|
|
9
|
+
* "env traversal-guard copies 5 → 1" KPI). Behaviour is byte-identical to the
|
|
10
|
+
* inline forms: env/secret VALUES are never read or surfaced here — these
|
|
11
|
+
* helpers only resolve refs to absolute paths and guard against directory
|
|
12
|
+
* traversal.
|
|
13
|
+
*/
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import { resolveSourceEntries } from "../indexer/search/search-source.js";
|
|
16
|
+
import { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath } from "./asset/asset-create.js";
|
|
17
|
+
import { parseAssetRef } from "./asset/asset-ref.js";
|
|
18
|
+
import { resolveAssetPathFromName } from "./asset/asset-spec.js";
|
|
19
|
+
import { isWithin } from "./common.js";
|
|
20
|
+
import { loadConfig } from "./config/config.js";
|
|
21
|
+
import { NotFoundError, UsageError } from "./errors.js";
|
|
22
|
+
export function parseEnvRef(ref) {
|
|
23
|
+
return parseAssetRef(ref.includes(":") ? ref : `env:${ref}`);
|
|
24
|
+
}
|
|
25
|
+
export function findEnvSource(origin) {
|
|
26
|
+
const sources = resolveSourceEntries(undefined, loadConfig());
|
|
27
|
+
if (sources.length === 0) {
|
|
28
|
+
throw new UsageError("No stashes configured. Run `akm init` to create your working stash.");
|
|
29
|
+
}
|
|
30
|
+
if (!origin || origin === "local")
|
|
31
|
+
return sources[0];
|
|
32
|
+
const named = sources.find((source) => source.registryId === origin);
|
|
33
|
+
if (!named) {
|
|
34
|
+
throw new NotFoundError(`Source not found for origin: ${origin}`);
|
|
35
|
+
}
|
|
36
|
+
return named;
|
|
37
|
+
}
|
|
38
|
+
export function makeEnvRef(name, source) {
|
|
39
|
+
return source?.registryId ? `${source.registryId}//env:${name}` : `env:${name}`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve an env ref to an absolute `.env` path. Accepts `env:` and
|
|
43
|
+
* `environment:` (alias) refs as well as bare names. The path is returned even
|
|
44
|
+
* when the file does not yet exist (so `create` writes under `env/`).
|
|
45
|
+
*/
|
|
46
|
+
export function resolveEnvPath(ref) {
|
|
47
|
+
const parsed = parseEnvRef(ref);
|
|
48
|
+
if (parsed.type !== "env") {
|
|
49
|
+
throw new UsageError(`Expected an env ref (env:<name>); got "${ref}".`);
|
|
50
|
+
}
|
|
51
|
+
const source = findEnvSource(parsed.origin);
|
|
52
|
+
const envRoot = path.join(source.path, "env");
|
|
53
|
+
const envPath = resolveAssetPathFromName("env", envRoot, parsed.name);
|
|
54
|
+
// Defense-in-depth: ensure the resolved path stays inside the env directory.
|
|
55
|
+
// validateName already rejects traversal patterns like "../../foo", but an
|
|
56
|
+
// absolute-path override or symlink-based attack could still escape without
|
|
57
|
+
// this second check.
|
|
58
|
+
if (!isWithin(envPath, envRoot)) {
|
|
59
|
+
throw new UsageError(`Env name "${parsed.name}" escapes the env directory.`);
|
|
60
|
+
}
|
|
61
|
+
return { name: parsed.name, absPath: envPath, source, parsedRef: parsed, dir: "env" };
|
|
62
|
+
}
|
|
63
|
+
export function parseSecretRef(ref) {
|
|
64
|
+
return parseAssetRef(ref.includes(":") ? ref : `secret:${ref}`);
|
|
65
|
+
}
|
|
66
|
+
export function makeSecretRef(name, source) {
|
|
67
|
+
return source?.registryId ? `${source.registryId}//secret:${name}` : `secret:${name}`;
|
|
68
|
+
}
|
|
69
|
+
export function resolveSecretPath(ref,
|
|
70
|
+
// Create-only (`secret set`): enforce a flat ref name and apply `--path` as
|
|
71
|
+
// the subdirectory. Lookup callers omit this so nested refs keep resolving.
|
|
72
|
+
create) {
|
|
73
|
+
const parsed = parseSecretRef(ref);
|
|
74
|
+
if (parsed.type !== "secret") {
|
|
75
|
+
throw new UsageError(`Expected a secret ref (secret:<name>); got "${ref}".`);
|
|
76
|
+
}
|
|
77
|
+
if (create) {
|
|
78
|
+
assertFlatAssetName(parsed.name);
|
|
79
|
+
parsed.name = combineCreatePath(normalizeCreateSubPath(create.subPath), parsed.name);
|
|
80
|
+
}
|
|
81
|
+
// Source resolution is identical for every asset type; reuse the env helper.
|
|
82
|
+
const source = findEnvSource(parsed.origin);
|
|
83
|
+
const typeRoot = path.join(source.path, "secrets");
|
|
84
|
+
const absPath = resolveAssetPathFromName("secret", typeRoot, parsed.name);
|
|
85
|
+
// Defense-in-depth: ensure the resolved path stays inside the secrets dir.
|
|
86
|
+
if (!isWithin(absPath, typeRoot)) {
|
|
87
|
+
throw new UsageError(`Secret name "${parsed.name}" escapes the secrets directory.`);
|
|
88
|
+
}
|
|
89
|
+
return { name: parsed.name, absPath, source };
|
|
90
|
+
}
|
package/dist/core/errors.js
CHANGED
|
@@ -34,8 +34,16 @@ const NOT_FOUND_HINTS = {
|
|
|
34
34
|
WORKFLOW_NOT_FOUND: "Run `akm workflow list --active` to see runs.",
|
|
35
35
|
FILE_NOT_FOUND: "Check the path exists and is readable.",
|
|
36
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Base class for all akm-thrown, classified errors. Carries the `kind`
|
|
39
|
+
* discriminant consumed by the CLI exit-code classifier. Errors that are NOT
|
|
40
|
+
* instances of `AkmError` are treated as genuinely unexpected (INTERNAL).
|
|
41
|
+
*/
|
|
42
|
+
export class AkmError extends Error {
|
|
43
|
+
}
|
|
37
44
|
/** Raised when configuration or environment is invalid or missing. */
|
|
38
|
-
export class ConfigError extends
|
|
45
|
+
export class ConfigError extends AkmError {
|
|
46
|
+
kind = "config";
|
|
39
47
|
code;
|
|
40
48
|
_hint;
|
|
41
49
|
constructor(msg, code = "INVALID_CONFIG_FILE", hint) {
|
|
@@ -51,7 +59,8 @@ export class ConfigError extends Error {
|
|
|
51
59
|
}
|
|
52
60
|
}
|
|
53
61
|
/** Raised when the user supplies invalid arguments or input. */
|
|
54
|
-
export class UsageError extends
|
|
62
|
+
export class UsageError extends AkmError {
|
|
63
|
+
kind = "usage";
|
|
55
64
|
code;
|
|
56
65
|
_hint;
|
|
57
66
|
constructor(msg, code = "INVALID_FLAG_VALUE", hint) {
|
|
@@ -67,7 +76,8 @@ export class UsageError extends Error {
|
|
|
67
76
|
}
|
|
68
77
|
}
|
|
69
78
|
/** Raised when a requested resource (asset, entry, file) is not found. */
|
|
70
|
-
export class NotFoundError extends
|
|
79
|
+
export class NotFoundError extends AkmError {
|
|
80
|
+
kind = "not-found";
|
|
71
81
|
code;
|
|
72
82
|
_hint;
|
|
73
83
|
constructor(msg, code = "ASSET_NOT_FOUND", hint) {
|
package/dist/core/events.js
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Append-only events stream — backed by state.db (#204, Phase 3).
|
|
6
|
+
*
|
|
7
|
+
* Every mutating CLI verb funnels through `appendEvent` so external
|
|
8
|
+
* observers (sync, replication, audit, dashboards) can react to stash
|
|
9
|
+
* changes. Events are stored in the `events` table in `state.db`
|
|
10
|
+
* (SQLite, WAL mode) instead of a flat `events.jsonl` file.
|
|
11
|
+
*
|
|
12
|
+
* The helper is the only thing in akm that writes to the events table. It
|
|
13
|
+
* accepts an injectable `dbPath` (via `EventsContext`) so tests can pin a
|
|
14
|
+
* tmpdir without any global mutation.
|
|
15
|
+
*
|
|
16
|
+
* Format (each EventEnvelope):
|
|
17
|
+
* { "schemaVersion": 1, "id": <number>, "ts": "<ISO>",
|
|
18
|
+
* "eventType": "<verb>", "ref"?: "<asset-ref>", ... }
|
|
19
|
+
*
|
|
20
|
+
* - `id` is a monotonic SQLite AUTOINCREMENT rowid. Callers can persist it
|
|
21
|
+
* as a durable cursor for `--since` resumption (replaces the old byte-offset
|
|
22
|
+
* cursor). The public API still surfaces this as `nextOffset` (an opaque
|
|
23
|
+
* number) for backward compatibility with callers that stored byte-offset
|
|
24
|
+
* cursors.
|
|
25
|
+
* - `ts` is ISO-8601 (UTC, millisecond precision).
|
|
26
|
+
*/
|
|
4
27
|
import path from "node:path";
|
|
5
|
-
import { rethrowIfTestIsolationError } from "./errors";
|
|
6
|
-
import { getDataDir } from "./paths";
|
|
7
|
-
import { insertEvent, openStateDatabase, readStateEvents } from "./state-db";
|
|
8
|
-
import { error } from "./warn";
|
|
28
|
+
import { rethrowIfTestIsolationError } from "./errors.js";
|
|
29
|
+
import { getDataDir } from "./paths.js";
|
|
30
|
+
import { insertEvent, openStateDatabase, readStateEvents } from "./state-db.js";
|
|
31
|
+
import { error } from "./warn.js";
|
|
9
32
|
/**
|
|
10
33
|
* Legacy events.jsonl path — used only by the migration script
|
|
11
34
|
* (`scripts/migrate-storage.ts`) to import existing event history into
|
package/dist/core/file-lock.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import fs from "node:fs";
|
|
5
|
-
import { isProcessAlive } from "./common";
|
|
5
|
+
import { isProcessAlive } from "./common.js";
|
|
6
6
|
/**
|
|
7
7
|
* Atomically create a sentinel at `lockPath` with `payload` as the body.
|
|
8
8
|
* Returns true if we now own the lock, false if a sentinel already
|
|
@@ -0,0 +1,48 @@
|
|
|
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
|
+
import { assertNever } from "./assert.js";
|
|
5
|
+
/**
|
|
6
|
+
* Map an {@link ImproveActionMode} to its coarse audit bucket. Single source of
|
|
7
|
+
* truth shared by `state-db.ts#computeImproveRunMetrics` and
|
|
8
|
+
* `improve.ts#emitImproveCompletedEvent` so the aggregate accepted/rejected/
|
|
9
|
+
* error counts can never disagree between the persisted `metrics_json` and the
|
|
10
|
+
* emitted `improve_completed` event.
|
|
11
|
+
*
|
|
12
|
+
* Buckets:
|
|
13
|
+
* - `accepted` — a write/content-authoring action succeeded.
|
|
14
|
+
* - `rejected` — the action was deliberately not applied (cooldown, skip,
|
|
15
|
+
* distill-skip, or a content-policy guard rejection). NOTE: as of the
|
|
16
|
+
* round-2 health pass `reflect-guard-rejected` is bucketed here. Previously
|
|
17
|
+
* the `state-db.ts` switch omitted it entirely (no case, no default), so a
|
|
18
|
+
* guard rejection silently vanished from accepted/rejected/error totals — a
|
|
19
|
+
* data-integrity miscount. It is a deliberate non-application of the action,
|
|
20
|
+
* so it belongs with the other "rejected" outcomes.
|
|
21
|
+
* - `error` — the action failed (LLM/runtime error).
|
|
22
|
+
* - `noop` — bookkeeping that is neither a write nor a rejection (memory-prune);
|
|
23
|
+
* intentionally counted in none of the three numeric buckets.
|
|
24
|
+
*
|
|
25
|
+
* The `default: assertNever(mode)` arm makes any future union variant a
|
|
26
|
+
* compile-time error here, forcing an explicit bucket choice.
|
|
27
|
+
*/
|
|
28
|
+
export function classifyImproveAction(mode) {
|
|
29
|
+
switch (mode) {
|
|
30
|
+
case "reflect":
|
|
31
|
+
case "distill":
|
|
32
|
+
case "memory-inference":
|
|
33
|
+
case "graph-extraction":
|
|
34
|
+
return "accepted";
|
|
35
|
+
case "reflect-cooldown":
|
|
36
|
+
case "reflect-skipped":
|
|
37
|
+
case "distill-skipped":
|
|
38
|
+
case "reflect-guard-rejected":
|
|
39
|
+
return "rejected";
|
|
40
|
+
case "reflect-failed":
|
|
41
|
+
case "error":
|
|
42
|
+
return "error";
|
|
43
|
+
case "memory-prune":
|
|
44
|
+
return "noop";
|
|
45
|
+
default:
|
|
46
|
+
return assertNever(mode);
|
|
47
|
+
}
|
|
48
|
+
}
|
package/dist/core/lesson-lint.js
CHANGED
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
* without dragging in the rest of the runtime.
|
|
24
24
|
*/
|
|
25
25
|
import fs from "node:fs";
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
26
|
+
import { parseFrontmatter } from "./asset/frontmatter.js";
|
|
27
|
+
import { UsageError } from "./errors.js";
|
|
28
28
|
function isNonEmptyString(value) {
|
|
29
29
|
return typeof value === "string" && value.trim().length > 0;
|
|
30
30
|
}
|
package/dist/core/paths.js
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import os from "node:os";
|
|
12
12
|
import path from "node:path";
|
|
13
|
-
import { IS_WINDOWS } from "./common";
|
|
14
|
-
import { ConfigError } from "./errors";
|
|
13
|
+
import { IS_WINDOWS } from "./common.js";
|
|
14
|
+
import { ConfigError } from "./errors.js";
|
|
15
15
|
/**
|
|
16
16
|
* Returns true when the current process appears to be running under
|
|
17
17
|
* `bun test` (either via the BUN_TEST sentinel Bun sets on the test
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
|
-
import { IS_WINDOWS } from "../common";
|
|
8
|
-
import { RG_BINARY, resolveRg } from "./resolve";
|
|
7
|
+
import { IS_WINDOWS } from "../common.js";
|
|
8
|
+
import { RG_BINARY, resolveRg } from "./resolve.js";
|
|
9
9
|
/**
|
|
10
10
|
* Platform and architecture detection for ripgrep binary downloads.
|
|
11
11
|
*/
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import { IS_WINDOWS } from "../common";
|
|
7
|
-
import { getBinDir } from "../paths";
|
|
6
|
+
import { IS_WINDOWS } from "../common.js";
|
|
7
|
+
import { getBinDir } from "../paths.js";
|
|
8
8
|
export const RG_BINARY = IS_WINDOWS ? "rg.exe" : "rg";
|
|
9
9
|
function canExecute(filePath) {
|
|
10
10
|
if (!fs.existsSync(filePath))
|
package/dist/core/state-db.js
CHANGED
|
@@ -49,11 +49,13 @@
|
|
|
49
49
|
*
|
|
50
50
|
* @module state-db
|
|
51
51
|
*/
|
|
52
|
-
import { Database } from "bun:sqlite";
|
|
53
52
|
import fs from "node:fs";
|
|
54
53
|
import path from "node:path";
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
54
|
+
import { openDatabase } from "../storage/database.js";
|
|
55
|
+
import { runMigrations as runSqliteMigrations } from "../storage/engines/sqlite-migrations.js";
|
|
56
|
+
import { classifyImproveAction } from "./improve-types.js";
|
|
57
|
+
import { getDataDir } from "./paths.js";
|
|
58
|
+
import { error } from "./warn.js";
|
|
57
59
|
// ── Path helper ──────────────────────────────────────────────────────────────
|
|
58
60
|
/**
|
|
59
61
|
* Default path: `<dataDir>/state.db`.
|
|
@@ -96,7 +98,7 @@ export function openStateDatabase(dbPath) {
|
|
|
96
98
|
if (!fs.existsSync(dir)) {
|
|
97
99
|
fs.mkdirSync(dir, { recursive: true });
|
|
98
100
|
}
|
|
99
|
-
const db =
|
|
101
|
+
const db = openDatabase(resolvedPath);
|
|
100
102
|
// PRAGMAs must run before any DDL or DML.
|
|
101
103
|
db.exec("PRAGMA journal_mode = WAL");
|
|
102
104
|
db.exec("PRAGMA foreign_keys = ON");
|
|
@@ -104,6 +106,12 @@ export function openStateDatabase(dbPath) {
|
|
|
104
106
|
runMigrations(db);
|
|
105
107
|
return db;
|
|
106
108
|
}
|
|
109
|
+
// ── Migration engine ─────────────────────────────────────────────────────────
|
|
110
|
+
//
|
|
111
|
+
// The runner itself (ensureMigrationsTable + runMigrations) lives in the shared
|
|
112
|
+
// engine at src/storage/engines/sqlite-migrations.ts. This module owns only its
|
|
113
|
+
// own MIGRATIONS array and delegates application to that shared runner. The
|
|
114
|
+
// {@link Migration} interface is imported from there.
|
|
107
115
|
/**
|
|
108
116
|
* All migrations in application order. New migrations are APPENDED to this
|
|
109
117
|
* array — never inserted in the middle or reordered.
|
|
@@ -451,41 +459,16 @@ const MIGRATIONS = [
|
|
|
451
459
|
`,
|
|
452
460
|
},
|
|
453
461
|
];
|
|
454
|
-
/**
|
|
455
|
-
* Create the migrations table if it does not exist. This must be called
|
|
456
|
-
* unconditionally on every open so a fresh database bootstraps correctly.
|
|
457
|
-
*/
|
|
458
|
-
function ensureMigrationsTable(db) {
|
|
459
|
-
db.exec(`
|
|
460
|
-
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
461
|
-
id TEXT PRIMARY KEY,
|
|
462
|
-
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
463
|
-
);
|
|
464
|
-
`);
|
|
465
|
-
}
|
|
466
462
|
/**
|
|
467
463
|
* Apply every pending migration in a single transaction per migration.
|
|
468
464
|
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
* inserted AFTER the DDL succeeds, so a crash mid-migration leaves no row and
|
|
472
|
-
* the migration will be retried on next open (all DDL in `up` uses IF NOT
|
|
473
|
-
* EXISTS so the retry is safe).
|
|
465
|
+
* Delegates to the shared SQLite migration engine; state.db has no
|
|
466
|
+
* pre-versioning bootstrap step, so no `bootstrap` hook is passed.
|
|
474
467
|
*
|
|
475
468
|
* Called automatically by `openStateDatabase()`.
|
|
476
469
|
*/
|
|
477
470
|
export function runMigrations(db) {
|
|
478
|
-
|
|
479
|
-
const appliedRows = db.prepare("SELECT id FROM schema_migrations").all();
|
|
480
|
-
const applied = new Set(appliedRows.map((r) => r.id));
|
|
481
|
-
for (const migration of MIGRATIONS) {
|
|
482
|
-
if (applied.has(migration.id))
|
|
483
|
-
continue;
|
|
484
|
-
db.transaction(() => {
|
|
485
|
-
db.exec(migration.up);
|
|
486
|
-
db.prepare("INSERT INTO schema_migrations (id) VALUES (?)").run(migration.id);
|
|
487
|
-
})();
|
|
488
|
-
}
|
|
471
|
+
runSqliteMigrations(db, MIGRATIONS);
|
|
489
472
|
}
|
|
490
473
|
/**
|
|
491
474
|
* Convert a raw `EventRow` from the database to the public `EventEnvelope`
|
|
@@ -779,6 +762,47 @@ export function queryTaskHistory(db, options = {}) {
|
|
|
779
762
|
FROM task_history ${where} ORDER BY started_at DESC`)
|
|
780
763
|
.all(...params);
|
|
781
764
|
}
|
|
765
|
+
/**
|
|
766
|
+
* Read COMPLETED `akm-improve` task_history runs whose `started_at` falls in
|
|
767
|
+
* `[since, until)` (or `started_at >= since` when `until` is omitted), ordered
|
|
768
|
+
* oldest-first by `started_at`. Only rows with a non-null `completed_at` are
|
|
769
|
+
* returned (in-flight runs are excluded). The `task_id = 'akm-improve'`
|
|
770
|
+
* predicate is fixed because the only caller (commands/health.ts
|
|
771
|
+
* `loadTaskIntervals`) builds wall-time intervals for the improve cron task.
|
|
772
|
+
*
|
|
773
|
+
* Owns the SQL formerly inlined in commands/health.ts. Note the bound is
|
|
774
|
+
* EXCLUSIVE on the upper end (`started_at < ?`) — callers pass an already
|
|
775
|
+
* widened window; this helper does not widen.
|
|
776
|
+
*
|
|
777
|
+
* Connection-lifetime rule (WS5): `.all()` materializes a plain array before
|
|
778
|
+
* returning.
|
|
779
|
+
*/
|
|
780
|
+
export function queryCompletedTaskIntervals(db, since, until) {
|
|
781
|
+
const sql = until
|
|
782
|
+
? "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"
|
|
783
|
+
: "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";
|
|
784
|
+
return (until ? db.prepare(sql).all(since, until) : db.prepare(sql).all(since));
|
|
785
|
+
}
|
|
786
|
+
// ── schema introspection ─────────────────────────────────────────────────────
|
|
787
|
+
/**
|
|
788
|
+
* Return the subset of `names` that exist as TABLEs in this database, ordered
|
|
789
|
+
* by name. Used by health's state-db-schema check to detect missing required
|
|
790
|
+
* tables without leaking a `sqlite_master` query into command code.
|
|
791
|
+
*
|
|
792
|
+
* The `IN (...)` predicate is built from parameter placeholders so table names
|
|
793
|
+
* are bound, never interpolated.
|
|
794
|
+
*
|
|
795
|
+
* Connection-lifetime rule (WS5): `.all()` materializes a plain array before
|
|
796
|
+
* returning.
|
|
797
|
+
*/
|
|
798
|
+
export function listExistingTableNames(db, names) {
|
|
799
|
+
if (names.length === 0)
|
|
800
|
+
return [];
|
|
801
|
+
const placeholders = names.map(() => "?").join(", ");
|
|
802
|
+
return db
|
|
803
|
+
.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${placeholders}) ORDER BY name`)
|
|
804
|
+
.all(...names);
|
|
805
|
+
}
|
|
782
806
|
// ── events.jsonl import ──────────────────────────────────────────────────────
|
|
783
807
|
/**
|
|
784
808
|
* Import all events from an `events.jsonl` file into the `events` table.
|
|
@@ -877,25 +901,23 @@ export function computeImproveRunMetrics(result) {
|
|
|
877
901
|
let autoAcceptedCount = 0;
|
|
878
902
|
let errorCount = 0;
|
|
879
903
|
for (const action of actions) {
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
904
|
+
// Bucketing delegated to the shared classifyImproveAction so this aggregate
|
|
905
|
+
// and the improve_completed event in improve.ts can never disagree, and so a
|
|
906
|
+
// new union variant is a compile error rather than a silent drop. Note:
|
|
907
|
+
// `reflect-guard-rejected` now counts as "rejected" (previously this switch
|
|
908
|
+
// omitted it entirely — a data-integrity miscount). "noop" (memory-prune) is
|
|
909
|
+
// intentionally counted in none of the three numeric buckets.
|
|
910
|
+
switch (classifyImproveAction(action.mode)) {
|
|
911
|
+
case "accepted":
|
|
885
912
|
acceptedCount++;
|
|
886
913
|
break;
|
|
887
|
-
case "
|
|
888
|
-
case "reflect-skipped":
|
|
889
|
-
case "distill-skipped":
|
|
914
|
+
case "rejected":
|
|
890
915
|
rejectedCount++;
|
|
891
916
|
break;
|
|
892
|
-
case "reflect-failed":
|
|
893
917
|
case "error":
|
|
894
918
|
errorCount++;
|
|
895
919
|
break;
|
|
896
|
-
case "
|
|
897
|
-
// Prune is bookkeeping, not "accepted" content authoring; count
|
|
898
|
-
// separately as a no-op for the audit aggregate.
|
|
920
|
+
case "noop":
|
|
899
921
|
break;
|
|
900
922
|
}
|
|
901
923
|
// Legacy: pre-gate action results may carry autoAccepted: true (reflect path).
|
|
@@ -929,6 +951,26 @@ export function recordImproveRun(db, input) {
|
|
|
929
951
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
930
952
|
`).run(input.id, input.startedAt, input.completedAt, input.stashDir, input.dryRun ? 1 : 0, input.profile, input.scopeMode, input.scopeValue, input.guidance, input.ok ? 1 : 0, JSON.stringify(input.result), JSON.stringify(metricsObj), JSON.stringify(input.metadata ?? {}));
|
|
931
953
|
}
|
|
954
|
+
/**
|
|
955
|
+
* Read real (non-dry-run) improve_runs rows whose `started_at` falls in the
|
|
956
|
+
* window `[since, until)`. When `until` is omitted the window is open-ended
|
|
957
|
+
* (`started_at >= since`). Rows are returned newest-first (`ORDER BY
|
|
958
|
+
* started_at DESC`).
|
|
959
|
+
*
|
|
960
|
+
* Owns the SQL formerly inlined in commands/health.ts (`loadImproveRunRows`).
|
|
961
|
+
* The `dry_run = 0` filter is first-class so dry-run probes never pollute
|
|
962
|
+
* productivity audits.
|
|
963
|
+
*
|
|
964
|
+
* Connection-lifetime rule (WS5): `.all()` fully materializes the result set
|
|
965
|
+
* into a plain array before returning — no live cursor escapes the caller's
|
|
966
|
+
* `openStateDatabase` scope.
|
|
967
|
+
*/
|
|
968
|
+
export function queryImproveRuns(db, since, until) {
|
|
969
|
+
const sql = until
|
|
970
|
+
? "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"
|
|
971
|
+
: "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";
|
|
972
|
+
return (until ? db.prepare(sql).all(since, until) : db.prepare(sql).all(since));
|
|
973
|
+
}
|
|
932
974
|
/**
|
|
933
975
|
* Delete improve_runs rows older than `retentionDays` (default: 90). Mirrors
|
|
934
976
|
* {@link purgeOldEvents} — same default, same return shape (number of rows
|
|
@@ -1027,7 +1069,7 @@ export function shouldSkipAlreadyExtractedSession(prior, liveSessionEndedAtMs) {
|
|
|
1027
1069
|
// ── registry_index_cache (goes in index.db, not state.db) ───────────────────
|
|
1028
1070
|
/**
|
|
1029
1071
|
* DDL for the `registry_index_cache` table that lives in the EXISTING index.db
|
|
1030
|
-
* (managed by src/indexer/db.ts).
|
|
1072
|
+
* (managed by src/indexer/db/db.ts).
|
|
1031
1073
|
*
|
|
1032
1074
|
* Design: uses the same migration-safe ADD COLUMN approach. The table is
|
|
1033
1075
|
* created with CREATE TABLE IF NOT EXISTS so it is safe to call inside
|
|
@@ -1051,7 +1093,7 @@ export function shouldSkipAlreadyExtractedSession(prior, liveSessionEndedAtMs) {
|
|
|
1051
1093
|
* ALTER TABLE registry_index_cache ADD COLUMN error_message TEXT DEFAULT NULL;
|
|
1052
1094
|
*
|
|
1053
1095
|
* To add this table to index.db, call ensureRegistryIndexCacheSchema(db) from
|
|
1054
|
-
* within ensureSchema() in src/indexer/db.ts, or add it as a new CREATE TABLE
|
|
1096
|
+
* within ensureSchema() in src/indexer/db/db.ts, or add it as a new CREATE TABLE
|
|
1055
1097
|
* IF NOT EXISTS block inside the existing ensureSchema() call.
|
|
1056
1098
|
*/
|
|
1057
1099
|
export const REGISTRY_INDEX_CACHE_DDL = `
|