akm-cli 0.8.0-rc2 → 0.8.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/{.github/CHANGELOG.md → CHANGELOG.md} +191 -3
- package/README.md +22 -6
- package/SECURITY.md +93 -0
- package/dist/cli/config-migrate.js +144 -0
- package/dist/cli/config-validate.js +39 -0
- package/dist/cli/confirm.js +73 -0
- package/dist/cli/parse-args.js +93 -3
- package/dist/cli/shared.js +129 -0
- package/dist/cli.js +2141 -1268
- package/dist/commands/add-cli.js +279 -0
- package/dist/commands/agent-dispatch.js +20 -12
- package/dist/commands/agent-support.js +11 -5
- package/dist/commands/completions.js +3 -0
- package/dist/commands/config-cli.js +129 -517
- package/dist/commands/consolidate.js +1533 -144
- package/dist/commands/curate.js +44 -3
- package/dist/commands/db-cli.js +23 -0
- package/dist/commands/distill-promotion-policy.js +5 -3
- package/dist/commands/distill.js +906 -100
- package/dist/commands/env.js +213 -0
- package/dist/commands/eval-cases.js +3 -0
- package/dist/commands/events.js +3 -0
- package/dist/commands/extract-cli.js +127 -0
- package/dist/commands/extract-prompt.js +204 -0
- package/dist/commands/extract.js +477 -0
- package/dist/commands/feedback-cli.js +331 -0
- package/dist/commands/graph.js +260 -5
- package/dist/commands/health.js +977 -51
- package/dist/commands/help/help-accept.md +6 -3
- package/dist/commands/help/help-improve.md +36 -8
- package/dist/commands/help/help-proposals.md +7 -4
- package/dist/commands/help/help-reject.md +5 -2
- package/dist/commands/history.js +51 -16
- package/dist/commands/improve-auto-accept.js +97 -0
- package/dist/commands/improve-cli.js +236 -0
- package/dist/commands/improve-profiles.js +184 -0
- package/dist/commands/improve-result-file.js +167 -0
- package/dist/commands/improve.js +1725 -332
- package/dist/commands/info.js +3 -0
- package/dist/commands/init.js +49 -1
- package/dist/commands/installed-stashes.js +6 -23
- package/dist/commands/knowledge.js +3 -0
- package/dist/commands/lint/agent-linter.js +3 -0
- package/dist/commands/lint/base-linter.js +199 -5
- package/dist/commands/lint/command-linter.js +3 -0
- package/dist/commands/lint/default-linter.js +3 -0
- package/dist/commands/lint/env-key-rules.js +154 -0
- package/dist/commands/lint/index.js +92 -3
- package/dist/commands/lint/knowledge-linter.js +3 -0
- package/dist/commands/lint/markdown-insertion.js +343 -0
- package/dist/commands/lint/memory-linter.js +3 -0
- package/dist/commands/lint/registry.js +3 -0
- package/dist/commands/lint/skill-linter.js +3 -0
- package/dist/commands/lint/task-linter.js +15 -12
- package/dist/commands/lint/types.js +3 -0
- package/dist/commands/lint/workflow-linter.js +3 -0
- package/dist/commands/lint.js +3 -0
- package/dist/commands/migration-help.js +5 -2
- package/dist/commands/proposal-drain-policies.js +128 -0
- package/dist/commands/proposal-drain.js +477 -0
- package/dist/commands/proposal.js +60 -6
- package/dist/commands/propose.js +24 -19
- package/dist/commands/reflect.js +1004 -94
- package/dist/commands/registry-cli.js +150 -0
- package/dist/commands/registry-search.js +3 -0
- package/dist/commands/remember-cli.js +257 -0
- package/dist/commands/remember.js +15 -6
- package/dist/commands/schema-repair.js +88 -15
- package/dist/commands/search.js +99 -14
- package/dist/commands/secret.js +173 -0
- package/dist/commands/self-update.js +3 -0
- package/dist/commands/show.js +32 -13
- package/dist/commands/source-add.js +7 -35
- package/dist/commands/source-clone.js +3 -0
- package/dist/commands/source-manage.js +3 -0
- package/dist/commands/tasks.js +161 -95
- package/dist/commands/url-checker.js +3 -0
- package/dist/core/action-contributors.js +3 -0
- package/dist/core/asset-ref.js +13 -2
- package/dist/core/asset-registry.js +9 -2
- package/dist/core/asset-serialize.js +88 -0
- package/dist/core/asset-spec.js +61 -5
- package/dist/core/common.js +93 -5
- package/dist/core/concurrent.js +3 -0
- package/dist/core/config-io.js +347 -0
- package/dist/core/config-migration.js +622 -0
- package/dist/core/config-schema.js +558 -0
- package/dist/core/config-sources.js +108 -0
- package/dist/core/config-types.js +4 -0
- package/dist/core/config-walker.js +337 -0
- package/dist/core/config.js +366 -1077
- package/dist/core/errors.js +42 -20
- package/dist/core/events.js +31 -25
- package/dist/core/file-lock.js +104 -0
- package/dist/core/frontmatter.js +75 -10
- package/dist/core/lesson-lint.js +3 -0
- package/dist/core/markdown.js +3 -0
- package/dist/core/memory-belief.js +62 -0
- package/dist/core/memory-contradiction-detect.js +274 -0
- package/dist/core/memory-improve.js +142 -14
- package/dist/core/parse.js +3 -0
- package/dist/core/paths.js +218 -50
- package/dist/core/proposal-quality-validators.js +380 -0
- package/dist/core/proposal-validators.js +11 -3
- package/dist/core/proposals.js +464 -5
- package/dist/core/state-db.js +349 -56
- package/dist/core/text-truncation.js +107 -0
- package/dist/core/time.js +3 -0
- package/dist/core/tty.js +59 -0
- package/dist/core/warn.js +7 -2
- package/dist/core/write-source.js +12 -0
- package/dist/indexer/db-backup.js +391 -0
- package/dist/indexer/db-search.js +136 -28
- package/dist/indexer/db.js +661 -166
- package/dist/indexer/ensure-index.js +3 -0
- package/dist/indexer/file-context.js +3 -0
- package/dist/indexer/graph-boost.js +162 -40
- package/dist/indexer/graph-db.js +241 -51
- package/dist/indexer/graph-dedup.js +3 -7
- package/dist/indexer/graph-extraction.js +242 -149
- package/dist/indexer/index-context.js +3 -9
- package/dist/indexer/indexer.js +84 -14
- package/dist/indexer/llm-cache.js +24 -19
- package/dist/indexer/manifest.js +3 -0
- package/dist/indexer/matchers.js +184 -11
- package/dist/indexer/memory-inference.js +94 -50
- package/dist/indexer/metadata-contributors.js +3 -0
- package/dist/indexer/metadata.js +110 -50
- package/dist/indexer/path-resolver.js +3 -0
- package/dist/indexer/project-context.js +192 -0
- package/dist/indexer/ranking-contributors.js +134 -7
- package/dist/indexer/ranking.js +8 -1
- package/dist/indexer/search-fields.js +5 -9
- package/dist/indexer/search-hit-enrichers.js +91 -2
- package/dist/indexer/search-source.js +20 -1
- package/dist/indexer/semantic-status.js +4 -1
- package/dist/indexer/staleness-detect.js +447 -0
- package/dist/indexer/usage-events.js +12 -9
- package/dist/indexer/walker.js +3 -0
- package/dist/integrations/agent/builders.js +135 -0
- package/dist/integrations/agent/config.js +121 -401
- package/dist/integrations/agent/detect.js +3 -0
- package/dist/integrations/agent/index.js +6 -14
- package/dist/integrations/agent/model-aliases.js +55 -0
- package/dist/integrations/agent/profiles.js +3 -0
- package/dist/integrations/agent/prompts.js +137 -8
- package/dist/integrations/agent/runner.js +208 -0
- package/dist/integrations/agent/sdk-runner.js +8 -2
- package/dist/integrations/agent/spawn.js +54 -14
- package/dist/integrations/github.js +3 -0
- package/dist/integrations/lockfile.js +22 -51
- package/dist/integrations/session-logs/index.js +4 -0
- package/dist/integrations/session-logs/inline-refs.js +35 -0
- package/dist/integrations/session-logs/pre-filter.js +152 -0
- package/dist/integrations/session-logs/providers/claude-code.js +226 -0
- package/dist/integrations/session-logs/providers/opencode.js +231 -25
- package/dist/integrations/session-logs/types.js +3 -0
- package/dist/llm/call-ai.js +14 -26
- package/dist/llm/client.js +16 -2
- package/dist/llm/embedder.js +20 -29
- package/dist/llm/embedders/cache.js +3 -7
- package/dist/llm/embedders/local.js +42 -1
- package/dist/llm/embedders/remote.js +20 -8
- package/dist/llm/embedders/types.js +3 -7
- package/dist/llm/feature-gate.js +92 -56
- package/dist/llm/graph-extract.js +401 -30
- package/dist/llm/index-passes.js +44 -29
- package/dist/llm/memory-infer.js +30 -2
- package/dist/llm/metadata-enhance.js +3 -7
- package/dist/llm/prompts/extract-session.md +80 -0
- package/dist/llm/prompts/graph-extract-user-prompt.md +24 -1
- package/dist/output/cli-hints-full.md +60 -32
- package/dist/output/cli-hints-short.md +10 -7
- package/dist/output/cli-hints.js +5 -2
- package/dist/output/context.js +60 -8
- package/dist/output/renderers.js +170 -194
- package/dist/output/shapes/curate.js +56 -0
- package/dist/output/shapes/distill.js +10 -0
- package/dist/output/shapes/env-list.js +19 -0
- package/dist/output/shapes/events.js +11 -0
- package/dist/output/shapes/helpers.js +424 -0
- package/dist/output/shapes/history.js +7 -0
- package/dist/output/shapes/passthrough.js +105 -0
- package/dist/output/shapes/proposal-accept.js +7 -0
- package/dist/output/shapes/proposal-diff.js +7 -0
- package/dist/output/shapes/proposal-list.js +7 -0
- package/dist/output/shapes/proposal-producer.js +11 -0
- package/dist/output/shapes/proposal-reject.js +7 -0
- package/dist/output/shapes/proposal-show.js +7 -0
- package/dist/output/shapes/registry-search.js +6 -0
- package/dist/output/shapes/registry.js +30 -0
- package/dist/output/shapes/search.js +6 -0
- package/dist/output/shapes/secret-list.js +19 -0
- package/dist/output/shapes/show.js +6 -0
- package/dist/output/shapes/vault-list.js +19 -0
- package/dist/output/shapes.js +51 -549
- package/dist/output/text/add.js +6 -0
- package/dist/output/text/clone.js +6 -0
- package/dist/output/text/config.js +6 -0
- package/dist/output/text/curate.js +6 -0
- package/dist/output/text/distill.js +7 -0
- package/dist/output/text/enable-disable.js +7 -0
- package/dist/output/text/events.js +10 -0
- package/dist/output/text/feedback.js +6 -0
- package/dist/output/text/helpers.js +1059 -0
- package/dist/output/text/history.js +7 -0
- package/dist/output/text/import.js +6 -0
- package/dist/output/text/index.js +6 -0
- package/dist/output/text/info.js +6 -0
- package/dist/output/text/init.js +6 -0
- package/dist/output/text/list.js +6 -0
- package/dist/output/text/proposal-producer.js +8 -0
- package/dist/output/text/proposal.js +12 -0
- package/dist/output/text/registry-commands.js +11 -0
- package/dist/output/text/registry.js +30 -0
- package/dist/output/text/remember.js +6 -0
- package/dist/output/text/remove.js +6 -0
- package/dist/output/text/save.js +6 -0
- package/dist/output/text/search.js +6 -0
- package/dist/output/text/show.js +6 -0
- package/dist/output/text/update.js +6 -0
- package/dist/output/text/upgrade.js +6 -0
- package/dist/output/text/vault.js +16 -0
- package/dist/output/text/wiki.js +15 -0
- package/dist/output/text/workflow.js +14 -0
- package/dist/output/text.js +44 -1329
- package/dist/registry/build-index.js +3 -0
- package/dist/registry/create-provider-registry.js +3 -0
- package/dist/registry/factory.js +4 -1
- package/dist/registry/origin-resolve.js +3 -0
- package/dist/registry/providers/index.js +3 -0
- package/dist/registry/providers/skills-sh.js +11 -2
- package/dist/registry/providers/static-index.js +10 -1
- package/dist/registry/providers/types.js +3 -24
- package/dist/registry/resolve.js +11 -16
- package/dist/registry/types.js +3 -0
- package/dist/scripts/migrate-storage.js +17767 -0
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +9031 -0
- package/dist/scripts/migrations/v16-to-v17.js +141 -0
- package/dist/setup/detect.js +3 -0
- package/dist/setup/ripgrep-install.js +3 -0
- package/dist/setup/ripgrep-resolve.js +3 -0
- package/dist/setup/setup.js +306 -67
- package/dist/setup/steps.js +3 -15
- package/dist/sources/include.js +3 -0
- package/dist/sources/provider-factory.js +3 -11
- package/dist/sources/provider.js +3 -20
- package/dist/sources/providers/filesystem.js +19 -23
- package/dist/sources/providers/git.js +171 -21
- package/dist/sources/providers/index.js +3 -0
- package/dist/sources/providers/install-types.js +3 -13
- package/dist/sources/providers/npm.js +3 -4
- package/dist/sources/providers/provider-utils.js +3 -0
- package/dist/sources/providers/sync-from-ref.js +3 -11
- package/dist/sources/providers/tar-utils.js +3 -0
- package/dist/sources/providers/website.js +18 -22
- package/dist/sources/resolve.js +3 -0
- package/dist/sources/types.js +3 -0
- package/dist/sources/website-ingest.js +3 -0
- package/dist/tasks/backends/cron.js +3 -0
- package/dist/tasks/backends/exec-utils.js +3 -0
- package/dist/tasks/backends/index.js +3 -11
- package/dist/tasks/backends/launchd.js +3 -0
- package/dist/tasks/backends/schtasks.js +3 -0
- package/dist/tasks/parser.js +51 -38
- package/dist/tasks/resolveAkmBin.js +3 -0
- package/dist/tasks/runner.js +35 -9
- package/dist/tasks/schedule.js +20 -1
- package/dist/tasks/schema.js +5 -3
- package/dist/tasks/validator.js +6 -3
- package/dist/version.js +3 -0
- package/dist/wiki/wiki-templates.js +3 -0
- package/dist/wiki/wiki.js +3 -0
- package/dist/workflows/authoring.js +3 -0
- package/dist/workflows/cli.js +3 -0
- package/dist/workflows/db.js +140 -10
- package/dist/workflows/document-cache.js +3 -10
- package/dist/workflows/parser.js +3 -0
- package/dist/workflows/renderer.js +3 -0
- package/dist/workflows/runs.js +18 -1
- package/dist/workflows/schema.js +3 -0
- package/dist/workflows/scope-key.js +3 -0
- package/dist/workflows/validator.js +5 -9
- package/docs/README.md +7 -2
- package/docs/data-and-telemetry.md +225 -0
- package/docs/migration/release-notes/0.7.5.md +2 -2
- package/docs/migration/release-notes/0.8.0.md +57 -5
- package/docs/migration/v0.7-to-v0.8.md +1378 -0
- package/package.json +28 -11
- package/.github/LICENSE +0 -374
- package/dist/commands/install-audit.js +0 -385
- package/dist/commands/vault.js +0 -310
- package/dist/indexer/match-contributors.js +0 -141
- package/dist/integrations/agent/pipeline.js +0 -39
- package/dist/integrations/agent/runners.js +0 -31
|
@@ -0,0 +1,184 @@
|
|
|
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 { parseAssetRef } from "../core/asset-ref";
|
|
5
|
+
import { warn } from "../core/warn";
|
|
6
|
+
/** Profile name used as the final fallback when nothing else resolves. */
|
|
7
|
+
const FALLBACK_PROFILE_NAME = "default";
|
|
8
|
+
// Built-in default allowed types per process
|
|
9
|
+
export const DEFAULT_ALLOWED_TYPES = {
|
|
10
|
+
reflect: ["agent", "command", "knowledge", "lesson", "memory", "skill", "wiki", "workflow"],
|
|
11
|
+
distill: ["memory"],
|
|
12
|
+
consolidate: ["memory"],
|
|
13
|
+
};
|
|
14
|
+
const BUILTIN_PROFILES = {
|
|
15
|
+
default: {
|
|
16
|
+
description: "Standard improve pass — all sub-processes, markdown asset types.",
|
|
17
|
+
processes: {
|
|
18
|
+
reflect: { enabled: true, allowedTypes: DEFAULT_ALLOWED_TYPES.reflect },
|
|
19
|
+
distill: { enabled: true, allowedTypes: DEFAULT_ALLOWED_TYPES.distill },
|
|
20
|
+
consolidate: { enabled: true, allowedTypes: DEFAULT_ALLOWED_TYPES.consolidate },
|
|
21
|
+
memoryInference: { enabled: true },
|
|
22
|
+
graphExtraction: { enabled: true },
|
|
23
|
+
// validation: deliberately undefined — third-tier classifier is opt-in.
|
|
24
|
+
triage: { enabled: false, applyMode: "queue", policy: "personal-stash" },
|
|
25
|
+
},
|
|
26
|
+
sync: { enabled: true, push: true },
|
|
27
|
+
},
|
|
28
|
+
quick: {
|
|
29
|
+
description: "Reflect-only pass — no distill, consolidate, memoryInference, or graphExtraction.",
|
|
30
|
+
processes: {
|
|
31
|
+
reflect: { enabled: true, allowedTypes: DEFAULT_ALLOWED_TYPES.reflect },
|
|
32
|
+
distill: { enabled: false },
|
|
33
|
+
consolidate: { enabled: false },
|
|
34
|
+
memoryInference: { enabled: false },
|
|
35
|
+
graphExtraction: { enabled: false },
|
|
36
|
+
triage: { enabled: false },
|
|
37
|
+
},
|
|
38
|
+
// Lightweight passes opt out of end-of-run sync: a reflect-only `quick`
|
|
39
|
+
// run should not auto-commit/push the git-backed stash to its remote.
|
|
40
|
+
// (The auto-sync gate in improve.ts treats an absent sync block as
|
|
41
|
+
// ENABLED + push, so we set this explicitly to avoid a surprise push.)
|
|
42
|
+
sync: { enabled: false },
|
|
43
|
+
},
|
|
44
|
+
thorough: {
|
|
45
|
+
// Reserved for future divergence; for now behaviorally identical to
|
|
46
|
+
// `default`. Documented here so callers picking `--profile thorough` do
|
|
47
|
+
// not expect a different code path until we wire stricter limits in.
|
|
48
|
+
description: "All sub-processes enabled (currently identical to default; reserved for future divergence).",
|
|
49
|
+
processes: {
|
|
50
|
+
reflect: { enabled: true, allowedTypes: DEFAULT_ALLOWED_TYPES.reflect },
|
|
51
|
+
distill: { enabled: true, allowedTypes: DEFAULT_ALLOWED_TYPES.distill },
|
|
52
|
+
consolidate: { enabled: true, allowedTypes: DEFAULT_ALLOWED_TYPES.consolidate },
|
|
53
|
+
memoryInference: { enabled: true },
|
|
54
|
+
graphExtraction: { enabled: true },
|
|
55
|
+
triage: { enabled: true, applyMode: "queue" },
|
|
56
|
+
},
|
|
57
|
+
sync: { enabled: true, push: true },
|
|
58
|
+
},
|
|
59
|
+
"memory-focus": {
|
|
60
|
+
description: "Memory and lesson improvement only — no distill or consolidate.",
|
|
61
|
+
processes: {
|
|
62
|
+
reflect: { enabled: true, allowedTypes: ["memory", "lesson"] },
|
|
63
|
+
distill: { enabled: false },
|
|
64
|
+
consolidate: { enabled: false },
|
|
65
|
+
memoryInference: { enabled: true },
|
|
66
|
+
graphExtraction: { enabled: false },
|
|
67
|
+
triage: { enabled: false },
|
|
68
|
+
},
|
|
69
|
+
// Limited pass opts out of end-of-run sync for the same reason as `quick`:
|
|
70
|
+
// a memory/lesson-only run should not auto-commit/push the stash. Explicit
|
|
71
|
+
// here because improve.ts treats an absent sync block as ENABLED + push.
|
|
72
|
+
sync: { enabled: false },
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Default enabled-state for known improve processes when neither the user
|
|
77
|
+
* profile nor the built-in default profile specifies an override.
|
|
78
|
+
*
|
|
79
|
+
* These mirror the legacy `LlmFeatureFlags` defaults so callers that bypass
|
|
80
|
+
* the profile system (rare — most run through `resolveImproveProfile`) get
|
|
81
|
+
* the same answer.
|
|
82
|
+
*/
|
|
83
|
+
const IMPROVE_PROCESS_DEFAULTS = {
|
|
84
|
+
reflect: true,
|
|
85
|
+
distill: true,
|
|
86
|
+
consolidate: true,
|
|
87
|
+
memoryInference: true,
|
|
88
|
+
graphExtraction: true,
|
|
89
|
+
validation: false,
|
|
90
|
+
// session-extraction reads native session files from claude-code / opencode
|
|
91
|
+
// and queues durable-insight proposals. Default on — opt out via
|
|
92
|
+
// profiles.improve.default.processes.extract.enabled: false.
|
|
93
|
+
extract: true,
|
|
94
|
+
// proposal-queue triage drains the standing backlog. Opt-in (default off),
|
|
95
|
+
// like `validation` — needs an explicit `enabled: true`.
|
|
96
|
+
triage: false,
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Compute the effective enabled-state for a named improve process.
|
|
100
|
+
*
|
|
101
|
+
* Resolution order: explicit `profile.processes.<name>.enabled` (boolean) →
|
|
102
|
+
* the built-in {@link IMPROVE_PROCESS_DEFAULTS} fallback → `false`.
|
|
103
|
+
*/
|
|
104
|
+
export function resolveProcessEnabled(processName, profile) {
|
|
105
|
+
const processes = profile.processes;
|
|
106
|
+
const entry = processes?.[processName];
|
|
107
|
+
if (entry && typeof entry.enabled === "boolean")
|
|
108
|
+
return entry.enabled;
|
|
109
|
+
return IMPROVE_PROCESS_DEFAULTS[processName] ?? false;
|
|
110
|
+
}
|
|
111
|
+
function deepMerge(base, override) {
|
|
112
|
+
if (typeof base !== "object" || base === null)
|
|
113
|
+
return override ?? base;
|
|
114
|
+
const result = { ...base };
|
|
115
|
+
for (const key of Object.keys(override)) {
|
|
116
|
+
const ov = override[key];
|
|
117
|
+
// Treat `null` the same as `undefined` so user overrides never wipe a
|
|
118
|
+
// built-in field with `null`. The on-disk parser already strips nulls,
|
|
119
|
+
// but the programmatic API exposes this path and callers occasionally
|
|
120
|
+
// pass JSON-shaped objects with explicit nulls.
|
|
121
|
+
if (ov !== undefined && ov !== null) {
|
|
122
|
+
const bv = base[key];
|
|
123
|
+
if (typeof bv === "object" && bv !== null && typeof ov === "object" && ov !== null && !Array.isArray(bv)) {
|
|
124
|
+
result[key] = deepMerge(bv, ov);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
result[key] = ov;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
export function resolveImproveProfile(name, config) {
|
|
134
|
+
const requestedName = name ??
|
|
135
|
+
(typeof config.defaults?.improve === "string" ? config.defaults.improve : undefined) ??
|
|
136
|
+
FALLBACK_PROFILE_NAME;
|
|
137
|
+
const hasBuiltin = requestedName in BUILTIN_PROFILES;
|
|
138
|
+
const hasUserDefined = !!config.profiles?.improve?.[requestedName];
|
|
139
|
+
let effectiveName = requestedName;
|
|
140
|
+
if (!hasBuiltin && !hasUserDefined && requestedName !== FALLBACK_PROFILE_NAME) {
|
|
141
|
+
warn(`[akm] Improve profile "${requestedName}" not found in built-ins or config. ` +
|
|
142
|
+
`Falling back to "${FALLBACK_PROFILE_NAME}".`);
|
|
143
|
+
effectiveName = FALLBACK_PROFILE_NAME;
|
|
144
|
+
}
|
|
145
|
+
const builtin = BUILTIN_PROFILES[effectiveName] ?? BUILTIN_PROFILES[FALLBACK_PROFILE_NAME];
|
|
146
|
+
const userOverride = config.profiles?.improve?.[effectiveName] ?? {};
|
|
147
|
+
return deepMerge(builtin, userOverride);
|
|
148
|
+
}
|
|
149
|
+
export function shouldSkipRef(ref, processName, profile) {
|
|
150
|
+
const cfg = profile.processes?.[processName];
|
|
151
|
+
// Check if the process itself is disabled
|
|
152
|
+
if (cfg?.enabled === false)
|
|
153
|
+
return { skip: true, reason: "process-disabled" };
|
|
154
|
+
const parsed = parseAssetRef(ref);
|
|
155
|
+
const allowed = cfg?.allowedTypes ?? DEFAULT_ALLOWED_TYPES[processName];
|
|
156
|
+
if (!allowed.includes(parsed.type))
|
|
157
|
+
return { skip: true, reason: "type-filter" };
|
|
158
|
+
// Hardcoded: wiki raw directories are never processed by any improve process.
|
|
159
|
+
if (parsed.type === "wiki" && parsed.name.split("/")[1] === "raw") {
|
|
160
|
+
return { skip: true, reason: "raw-wiki" };
|
|
161
|
+
}
|
|
162
|
+
return { skip: false, reason: "" };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Planner-level pre-filter: return `true` when every per-ref improve pass that
|
|
166
|
+
* participates in the in-loop dispatch (today: `reflect` and `distill`) would
|
|
167
|
+
* refuse this ref under the active profile. Such refs cannot produce any work
|
|
168
|
+
* downstream — they only generate synthetic skip actions and inflate
|
|
169
|
+
* `plannedRefs` by a constant factor per cron run.
|
|
170
|
+
*
|
|
171
|
+
* Companion to `shouldSkipRef`. The 2026-05-27 planner/profile/metrics deep
|
|
172
|
+
* analysis (`/tmp/akm-health-investigations/planner-profile-metrics-deep-analysis.md`)
|
|
173
|
+
* documents the 99.07% synthetic-skip emission rate this pre-filter eliminates.
|
|
174
|
+
*
|
|
175
|
+
* NOTE: passes that operate on their own candidate set (consolidate,
|
|
176
|
+
* memoryInference, graphExtraction) are deliberately excluded — they do not
|
|
177
|
+
* iterate `plannedRefs` per-ref, so a ref being profile-incompatible at the
|
|
178
|
+
* reflect+distill layer says nothing about their work.
|
|
179
|
+
*/
|
|
180
|
+
export function isProfileFilteredForAllPasses(ref, profile) {
|
|
181
|
+
const reflectSkip = shouldSkipRef(ref, "reflect", profile);
|
|
182
|
+
const distillSkip = shouldSkipRef(ref, "distill", profile);
|
|
183
|
+
return reflectSkip.skip && distillSkip.skip;
|
|
184
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
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
|
+
* Helpers for persisting the `akm improve` result envelope.
|
|
6
|
+
*
|
|
7
|
+
* v0.8.0 behavioural default change:
|
|
8
|
+
* - Default: the full result is recorded as a single row in the
|
|
9
|
+
* `improve_runs` table of `state.db` (migration 003). Stdout is empty.
|
|
10
|
+
* The existing `[improve] ...` progress log lines on stderr remain the
|
|
11
|
+
* canonical console UX.
|
|
12
|
+
* - `--json-to-stdout` restores the prior behaviour: full JSON to stdout,
|
|
13
|
+
* nothing written to state.db.
|
|
14
|
+
*
|
|
15
|
+
* v0.8.0 storage change (this module): the previous on-disk artifact at
|
|
16
|
+
* `<stash>/.akm/runs/<runId>/improve-result.json` is no longer written. The
|
|
17
|
+
* canonical record now lives in `improve_runs` (see
|
|
18
|
+
* `src/core/state-db.ts`). Pre-existing files from older runs are not
|
|
19
|
+
* deleted by this change — they become historical artifacts. Zero current
|
|
20
|
+
* code paths read them, so no consumers needed to update.
|
|
21
|
+
*
|
|
22
|
+
* Run-id format: ISO-8601 timestamp (colons/dots replaced by `-`) plus an
|
|
23
|
+
* 8-char hex random suffix. There is no existing canonical run-id helper for
|
|
24
|
+
* persistent per-command artefacts on disk — the `workflow_runs` table uses
|
|
25
|
+
* `randomUUID()` but is database-scoped, and `consolidate-journal.json` is a
|
|
26
|
+
* single-slot artefact. We mint a fresh timestamped id for each improve run.
|
|
27
|
+
*/
|
|
28
|
+
import crypto from "node:crypto";
|
|
29
|
+
import path from "node:path";
|
|
30
|
+
import { openStateDatabase, recordImproveRun } from "../core/state-db";
|
|
31
|
+
/**
|
|
32
|
+
* Build a stable run-id for a single improve invocation.
|
|
33
|
+
*
|
|
34
|
+
* Shape: `<iso-8601-utc-with-dashes>-<8 hex chars>`, e.g.
|
|
35
|
+
* `2026-05-19T17-30-22-123Z-a1b2c3d4`.
|
|
36
|
+
*
|
|
37
|
+
* The hex suffix protects against same-millisecond collisions when multiple
|
|
38
|
+
* runs happen back-to-back in tests or scripts.
|
|
39
|
+
*/
|
|
40
|
+
export function buildImproveRunId(now = new Date()) {
|
|
41
|
+
const iso = now.toISOString().replace(/[:.]/g, "-");
|
|
42
|
+
const rand = crypto.randomBytes(4).toString("hex");
|
|
43
|
+
return `${iso}-${rand}`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Return a stable, human-recognisable reference for a given improve run.
|
|
47
|
+
*
|
|
48
|
+
* Historical compatibility shim: callers used to receive a stash-relative
|
|
49
|
+
* file path like `.akm/runs/<runId>/improve-result.json`. With the state.db
|
|
50
|
+
* migration, no such file exists, but several callers still log "wrote to
|
|
51
|
+
* <path>" style messages. Returning a `state.db//improve_runs/<runId>`
|
|
52
|
+
* locator preserves the "the result is at <thing>" signature so existing
|
|
53
|
+
* log lines and error messages continue to make sense without rewriting
|
|
54
|
+
* every call site.
|
|
55
|
+
*/
|
|
56
|
+
export function relativeImproveResultPath(runId) {
|
|
57
|
+
return path.join("state.db", "improve_runs", runId);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Persist the full improve result into the `improve_runs` table of state.db.
|
|
61
|
+
*
|
|
62
|
+
* Backwards-compatible signature: the function name, argument list, and
|
|
63
|
+
* return type all match the pre-0.8.0 file-writing helper. The returned
|
|
64
|
+
* string is the `state.db//improve_runs/<runId>` locator (see
|
|
65
|
+
* {@link relativeImproveResultPath}), which is intended for log messages
|
|
66
|
+
* only — no caller should treat it as a filesystem path. Zero current
|
|
67
|
+
* readers existed for the previous file path, so this is a pure storage
|
|
68
|
+
* swap.
|
|
69
|
+
*
|
|
70
|
+
* The state.db row carries the scope and dry-run flag from `result.scope`
|
|
71
|
+
* and `result.dryRun`, plus the full result JSON for full fidelity. The
|
|
72
|
+
* dry-run column is indexed so productivity audits can filter cleanly
|
|
73
|
+
* (closes the dry-run/real-run artifact-trap recorded in MEMORY.md
|
|
74
|
+
* `feedback_akm_dryrun_artifact_trap`).
|
|
75
|
+
*/
|
|
76
|
+
export function writeImproveResultFile(stashDir, runId, result) {
|
|
77
|
+
const db = openStateDatabase();
|
|
78
|
+
try {
|
|
79
|
+
const startedAt = new Date().toISOString();
|
|
80
|
+
recordImproveRun(db, {
|
|
81
|
+
id: runId,
|
|
82
|
+
startedAt,
|
|
83
|
+
completedAt: startedAt,
|
|
84
|
+
stashDir,
|
|
85
|
+
dryRun: Boolean(result.dryRun),
|
|
86
|
+
profile: null,
|
|
87
|
+
scopeMode: result.scope?.mode ?? "all",
|
|
88
|
+
scopeValue: result.scope?.value ?? null,
|
|
89
|
+
guidance: result.guidance ?? null,
|
|
90
|
+
ok: Boolean(result.ok),
|
|
91
|
+
result,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
try {
|
|
96
|
+
db.close();
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// best-effort
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return relativeImproveResultPath(runId);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Persist an improve_runs row for a run that did NOT complete normally.
|
|
106
|
+
* 2026-05-26 incident: the cron's `timeout_ms: 1800000` SIGTERM'd an
|
|
107
|
+
* akm-improve invocation at 30:00 with 54 actionable refs in-flight. No
|
|
108
|
+
* `improve_runs` row was written because the writer only fired at successful
|
|
109
|
+
* end-of-run, so the run vanished from `akm health --detail per-run` even
|
|
110
|
+
* though it had consumed 30 min of LLM time and produced 29 ref-level
|
|
111
|
+
* proposals. This helper closes that gap: signal handlers and the CLI
|
|
112
|
+
* try/catch wrapper call it on the abnormal-exit paths so the row exists
|
|
113
|
+
* with `ok: false` and `metadata.terminated.reason` set.
|
|
114
|
+
*
|
|
115
|
+
* The persisted result envelope is minimal — we don't try to reconstruct
|
|
116
|
+
* the in-flight `actions[]` because that state lives inside `akmImprove`
|
|
117
|
+
* and is gone by the time the signal handler runs. The row captures
|
|
118
|
+
* enough to know: a run started, was scoped to X, did NOT complete, and
|
|
119
|
+
* why.
|
|
120
|
+
*/
|
|
121
|
+
export function recordTerminatedImproveRun(stashDir, runId, startedAt, reason, ctx) {
|
|
122
|
+
const completedAt = new Date().toISOString();
|
|
123
|
+
const minimalResult = {
|
|
124
|
+
schemaVersion: 1,
|
|
125
|
+
ok: false,
|
|
126
|
+
scope: { mode: ctx?.scopeMode ?? "all", ...(ctx?.scopeValue ? { value: ctx.scopeValue } : {}) },
|
|
127
|
+
dryRun: Boolean(ctx?.dryRun),
|
|
128
|
+
actions: [],
|
|
129
|
+
plannedRefs: [],
|
|
130
|
+
terminated: {
|
|
131
|
+
reason,
|
|
132
|
+
at: completedAt,
|
|
133
|
+
...(ctx?.errorMessage ? { errorMessage: ctx.errorMessage } : {}),
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
const db = openStateDatabase();
|
|
137
|
+
try {
|
|
138
|
+
recordImproveRun(db, {
|
|
139
|
+
id: runId,
|
|
140
|
+
startedAt,
|
|
141
|
+
completedAt,
|
|
142
|
+
stashDir,
|
|
143
|
+
dryRun: Boolean(ctx?.dryRun),
|
|
144
|
+
profile: ctx?.profile ?? null,
|
|
145
|
+
scopeMode: ctx?.scopeMode ?? "all",
|
|
146
|
+
scopeValue: ctx?.scopeValue ?? null,
|
|
147
|
+
guidance: null,
|
|
148
|
+
ok: false,
|
|
149
|
+
result: minimalResult,
|
|
150
|
+
metadata: {
|
|
151
|
+
terminated: {
|
|
152
|
+
reason,
|
|
153
|
+
at: completedAt,
|
|
154
|
+
...(ctx?.errorMessage ? { errorMessage: ctx.errorMessage } : {}),
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
try {
|
|
161
|
+
db.close();
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// best-effort
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|