akm-cli 0.9.0-beta.54 → 0.9.0-beta.55
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/dist/cli.js +5 -3
- package/dist/commands/agent/contribute-cli.js +2 -3
- package/dist/commands/env/env-cli.js +187 -202
- package/dist/commands/env/secret-cli.js +109 -121
- package/dist/commands/feedback-cli.js +152 -155
- package/dist/commands/health/advisories.js +151 -0
- package/dist/commands/health/improve-metrics.js +754 -0
- package/dist/commands/health/llm-usage.js +65 -0
- package/dist/commands/health/md-report.js +103 -0
- package/dist/commands/health/metrics.js +278 -0
- package/dist/commands/health/task-runs.js +135 -0
- package/dist/commands/health/types.js +18 -0
- package/dist/commands/health/windows.js +196 -0
- package/dist/commands/health.js +14 -1624
- package/dist/commands/improve/anti-collapse.js +170 -0
- package/dist/commands/improve/collapse-detector.js +3 -2
- package/dist/commands/improve/consolidate.js +636 -633
- package/dist/commands/improve/dedup.js +1 -1
- package/dist/commands/improve/distill/content-repair.js +202 -0
- package/dist/commands/improve/distill/promote-memory.js +228 -0
- package/dist/commands/improve/distill/quality-gate.js +233 -0
- package/dist/commands/improve/distill-guards.js +127 -0
- package/dist/commands/improve/distill.js +49 -575
- package/dist/commands/improve/extract-cli.js +74 -76
- package/dist/commands/improve/extract.js +6 -4
- package/dist/commands/improve/hot-probation.js +45 -0
- package/dist/commands/improve/improve-auto-accept.js +3 -2
- package/dist/commands/improve/improve-cli.js +14 -13
- package/dist/commands/improve/improve-result-file.js +2 -1
- package/dist/commands/improve/improve.js +6 -5
- package/dist/commands/improve/loop-stages.js +19 -21
- package/dist/commands/improve/preparation.js +4 -2
- package/dist/commands/improve/procedural.js +10 -31
- package/dist/commands/improve/recombine.js +19 -43
- package/dist/commands/improve/reflect.js +1 -1
- package/dist/commands/improve/schema-similarity-gate.js +168 -0
- package/dist/commands/improve/shared.js +48 -0
- package/dist/commands/observability-cli.js +4 -4
- package/dist/commands/proposal/drain-policies.js +2 -2
- package/dist/commands/proposal/drain.js +1 -1
- package/dist/commands/proposal/legacy-import.js +115 -0
- package/dist/commands/proposal/proposal-cli.js +3 -3
- package/dist/commands/proposal/proposal.js +2 -1
- package/dist/commands/proposal/propose.js +1 -1
- package/dist/commands/proposal/repository.js +829 -0
- package/dist/commands/proposal/validators/proposals.js +5 -920
- package/dist/commands/read/remember-cli.js +132 -137
- package/dist/commands/read/search-cli.js +1 -1
- package/dist/commands/registry-cli.js +76 -87
- package/dist/commands/sources/add-cli.js +90 -94
- package/dist/commands/sources/history.js +1 -1
- package/dist/commands/sources/schema-repair.js +1 -1
- package/dist/commands/sources/sources-cli.js +3 -3
- package/dist/commands/sources/stash-cli.js +1 -1
- package/dist/commands/tasks/tasks-cli.js +1 -2
- package/dist/commands/wiki-cli.js +2 -3
- package/dist/core/common.js +3 -3
- package/dist/core/config/config-schema.js +6 -0
- package/dist/core/deep-merge.js +38 -0
- package/dist/core/events.js +2 -1
- package/dist/core/logs-db.js +8 -13
- package/dist/core/paths.js +14 -14
- package/dist/core/state-db.js +13 -1140
- package/dist/indexer/db/db.js +66 -709
- package/dist/indexer/db/entry-mapper.js +41 -0
- package/dist/indexer/db/schema.js +516 -0
- package/dist/indexer/feedback/utility-policy.js +85 -0
- package/dist/indexer/graph/graph-extraction.js +2 -1
- package/dist/indexer/index-writer-lock.js +9 -0
- package/dist/indexer/indexer.js +78 -23
- package/dist/indexer/search/fts-query.js +51 -0
- package/dist/integrations/agent/spawn.js +15 -66
- package/dist/output/text/helpers.js +13 -0
- package/dist/scripts/migrate-storage.js +6891 -7436
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +44 -43
- package/dist/setup/legacy-config.js +106 -0
- package/dist/setup/prompt.js +57 -0
- package/dist/setup/providers.js +14 -0
- package/dist/setup/semantic-assets.js +124 -0
- package/dist/setup/setup.js +24 -1607
- package/dist/setup/steps/connection.js +734 -0
- package/dist/setup/steps/output.js +31 -0
- package/dist/setup/steps/platforms.js +124 -0
- package/dist/setup/steps/semantic.js +27 -0
- package/dist/setup/steps/sources.js +222 -0
- package/dist/setup/steps/stashdir.js +42 -0
- package/dist/setup/steps/tasks.js +152 -0
- package/dist/storage/repositories/canaries-repository.js +107 -0
- package/dist/storage/repositories/consolidation-repository.js +38 -0
- package/dist/storage/repositories/embeddings-repository.js +72 -0
- package/dist/storage/repositories/events-repository.js +187 -0
- package/dist/storage/repositories/extract-sessions-repository.js +96 -0
- package/dist/storage/repositories/improve-runs-repository.js +130 -0
- package/dist/storage/repositories/index-db.js +4 -7
- package/dist/storage/repositories/proposals-repository.js +220 -0
- package/dist/storage/repositories/recombine-repository.js +213 -0
- package/dist/storage/repositories/task-history-repository.js +93 -0
- package/dist/storage/sqlite-pragmas.js +3 -3
- package/dist/tasks/runner.js +2 -1
- package/package.json +1 -1
- package/dist/commands/improve/homeostatic.js +0 -497
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import fs from "node:fs";
|
|
18
18
|
import path from "node:path";
|
|
19
|
-
import {
|
|
20
|
-
import { EXIT_CODES, output
|
|
19
|
+
import { getStringArg } from "../../cli/parse-args.js";
|
|
20
|
+
import { defineJsonCommand, EXIT_CODES, output } from "../../cli/shared.js";
|
|
21
21
|
import { UsageError } from "../../core/errors.js";
|
|
22
22
|
import { getAvailableHarnesses, getWatchTargets } from "../../integrations/session-logs/index.js";
|
|
23
23
|
import { akmExtract } from "./extract.js";
|
|
24
24
|
import { akmExtractWatch } from "./extract-watch.js";
|
|
25
|
-
export const extractCommand =
|
|
25
|
+
export const extractCommand = defineJsonCommand({
|
|
26
26
|
meta: {
|
|
27
27
|
name: "extract",
|
|
28
28
|
description: "Extract durable insights from native session files (claude-code, opencode) and queue them as proposals. Replaces the legacy session-checkpoint hook.",
|
|
@@ -74,86 +74,84 @@ export const extractCommand = defineCommand({
|
|
|
74
74
|
},
|
|
75
75
|
},
|
|
76
76
|
async run({ args }) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (harnesses.length === 0) {
|
|
119
|
-
output("extract", {
|
|
120
|
-
schemaVersion: 1,
|
|
121
|
-
ok: false,
|
|
122
|
-
shape: "extract-auto-result",
|
|
123
|
-
warnings: ["no available harnesses found on this machine"],
|
|
124
|
-
results: [],
|
|
125
|
-
});
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
const results = [];
|
|
129
|
-
for (const h of harnesses) {
|
|
130
|
-
const result = await akmExtract({ type: h.name, ...commonOptions });
|
|
131
|
-
results.push(result);
|
|
132
|
-
}
|
|
133
|
-
const ok = results.every((r) => r.ok);
|
|
134
|
-
const totalProposals = results.reduce((sum, r) => sum + r.proposals.length, 0);
|
|
77
|
+
const type = getStringArg(args, "type") ?? "";
|
|
78
|
+
const sessionId = getStringArg(args, "session-id") ?? "";
|
|
79
|
+
const location = getStringArg(args, "location") ?? "";
|
|
80
|
+
const since = getStringArg(args, "since") ?? "";
|
|
81
|
+
const auto = args.auto === true;
|
|
82
|
+
const dryRun = args["dry-run"] === true;
|
|
83
|
+
const force = args.force === true;
|
|
84
|
+
const timeoutMs = typeof args["timeout-ms"] === "string" && args["timeout-ms"] !== ""
|
|
85
|
+
? Number.parseInt(args["timeout-ms"], 10)
|
|
86
|
+
: undefined;
|
|
87
|
+
if (timeoutMs !== undefined && (!Number.isFinite(timeoutMs) || timeoutMs <= 0)) {
|
|
88
|
+
throw new UsageError(`--timeout-ms must be a positive integer (got "${args["timeout-ms"]}").`, "INVALID_FLAG_VALUE");
|
|
89
|
+
}
|
|
90
|
+
const watch = args.watch === true;
|
|
91
|
+
const debounceMs = typeof args["debounce-ms"] === "string" && args["debounce-ms"] !== ""
|
|
92
|
+
? Number.parseInt(args["debounce-ms"], 10)
|
|
93
|
+
: 2000;
|
|
94
|
+
if (watch && (!Number.isFinite(debounceMs) || debounceMs <= 0)) {
|
|
95
|
+
throw new UsageError(`--debounce-ms must be a positive integer (got "${args["debounce-ms"]}").`, "INVALID_FLAG_VALUE");
|
|
96
|
+
}
|
|
97
|
+
if (watch) {
|
|
98
|
+
await runWatchMode({ debounceMs, dryRun, force, ...(since ? { since } : {}) });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (auto && type) {
|
|
102
|
+
throw new UsageError("--auto and --type are mutually exclusive. Pick one.", "INVALID_FLAG_VALUE");
|
|
103
|
+
}
|
|
104
|
+
if (!auto && !type) {
|
|
105
|
+
throw new UsageError("--type is required (or pass --auto to try every available harness).", "MISSING_REQUIRED_ARGUMENT");
|
|
106
|
+
}
|
|
107
|
+
const commonOptions = {
|
|
108
|
+
...(sessionId ? { sessionId } : {}),
|
|
109
|
+
...(location ? { location } : {}),
|
|
110
|
+
...(since ? { since } : {}),
|
|
111
|
+
dryRun,
|
|
112
|
+
force,
|
|
113
|
+
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
114
|
+
};
|
|
115
|
+
if (auto) {
|
|
116
|
+
const harnesses = getAvailableHarnesses();
|
|
117
|
+
if (harnesses.length === 0) {
|
|
135
118
|
output("extract", {
|
|
136
119
|
schemaVersion: 1,
|
|
137
|
-
ok,
|
|
120
|
+
ok: false,
|
|
138
121
|
shape: "extract-auto-result",
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
totalProposals,
|
|
142
|
-
results,
|
|
122
|
+
warnings: ["no available harnesses found on this machine"],
|
|
123
|
+
results: [],
|
|
143
124
|
});
|
|
144
|
-
// Signal failure to callers/cron when every harness failed. output()
|
|
145
|
-
// only renders; without this the */30 cron exits 0 on a total failure
|
|
146
|
-
// and the breakage is invisible to exit-code monitoring. process.exitCode
|
|
147
|
-
// (not process.exit) lets stdout flush and the watcher/timers settle.
|
|
148
|
-
if (!ok)
|
|
149
|
-
process.exitCode = EXIT_CODES.GENERAL;
|
|
150
125
|
return;
|
|
151
126
|
}
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
127
|
+
const results = [];
|
|
128
|
+
for (const h of harnesses) {
|
|
129
|
+
const result = await akmExtract({ type: h.name, ...commonOptions });
|
|
130
|
+
results.push(result);
|
|
131
|
+
}
|
|
132
|
+
const ok = results.every((r) => r.ok);
|
|
133
|
+
const totalProposals = results.reduce((sum, r) => sum + r.proposals.length, 0);
|
|
134
|
+
output("extract", {
|
|
135
|
+
schemaVersion: 1,
|
|
136
|
+
ok,
|
|
137
|
+
shape: "extract-auto-result",
|
|
138
|
+
dryRun,
|
|
139
|
+
harnessesProcessed: results.length,
|
|
140
|
+
totalProposals,
|
|
141
|
+
results,
|
|
142
|
+
});
|
|
143
|
+
// Signal failure to callers/cron when every harness failed. output()
|
|
144
|
+
// only renders; without this the */30 cron exits 0 on a total failure
|
|
145
|
+
// and the breakage is invisible to exit-code monitoring. process.exitCode
|
|
146
|
+
// (not process.exit) lets stdout flush and the watcher/timers settle.
|
|
147
|
+
if (!ok)
|
|
155
148
|
process.exitCode = EXIT_CODES.GENERAL;
|
|
156
|
-
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const result = await akmExtract({ type, ...commonOptions });
|
|
152
|
+
output("extract", result);
|
|
153
|
+
if (!result.ok)
|
|
154
|
+
process.exitCode = EXIT_CODES.GENERAL;
|
|
157
155
|
},
|
|
158
156
|
});
|
|
159
157
|
/**
|
|
@@ -32,7 +32,7 @@ import { ConfigError, UsageError } from "../../core/errors.js";
|
|
|
32
32
|
import { appendEvent } from "../../core/events.js";
|
|
33
33
|
import { probeLock, releaseLock, tryAcquireLockSync } from "../../core/file-lock.js";
|
|
34
34
|
import { resolveStashStandards } from "../../core/standards/resolve-stash-standards.js";
|
|
35
|
-
import {
|
|
35
|
+
import { getStateDbPath, openStateDatabase, withStateDb } from "../../core/state-db.js";
|
|
36
36
|
import { repairTruncatedDescription } from "../../core/text-truncation.js";
|
|
37
37
|
import { warn } from "../../core/warn.js";
|
|
38
38
|
import { indexWrittenAssets } from "../../indexer/index-written-assets.js";
|
|
@@ -44,10 +44,12 @@ import { chatCompletion } from "../../llm/client.js";
|
|
|
44
44
|
import { embed } from "../../llm/embedder.js";
|
|
45
45
|
import { tryLlmFeature } from "../../llm/feature-gate.js";
|
|
46
46
|
import { sha256Hex } from "../../runtime.js";
|
|
47
|
-
import {
|
|
47
|
+
import { getExtractedSessionsMap, getLastExtractRunAt, shouldSkipAlreadyExtractedSession, upsertExtractedSession, } from "../../storage/repositories/extract-sessions-repository.js";
|
|
48
|
+
import { createProposal, isProposalSkipped } from "../proposal/repository.js";
|
|
48
49
|
import { buildExtractPrompt, EXTRACT_JSON_SCHEMA, parseExtractPayload } from "./extract-prompt.js";
|
|
49
|
-
import {
|
|
50
|
+
import { buildHotProbationFrontmatter } from "./hot-probation.js";
|
|
50
51
|
import { resolveProcessEnabled } from "./improve-profiles.js";
|
|
52
|
+
import { applySchemaSimilarityPenalty, loadDerivedLayerEmbeddings, } from "./schema-similarity-gate.js";
|
|
51
53
|
import { buildSessionSummaryPrompt, parseSessionSummary, SESSION_SUMMARY_JSON_SCHEMA, sessionMeetsDurationGate, writeSessionAsset, } from "./session-asset.js";
|
|
52
54
|
import { resolveTriageConfig, scoreSessionTriage } from "./triage.js";
|
|
53
55
|
/** Default minimum session duration (minutes) for session indexing (#561). */
|
|
@@ -462,7 +464,7 @@ standardsContext) {
|
|
|
462
464
|
// existing derived-layer node, down-prioritize by multiplying confidence by
|
|
463
465
|
// the penalty. PARITY: schemaSimilarityCtx is null when the flag is off →
|
|
464
466
|
// applySchemaSimilarityPenalty returns the original confidence untouched and
|
|
465
|
-
// never embeds. (Logic lives in
|
|
467
|
+
// never embeds. (Logic lives in schema-similarity-gate.ts so it is unit-testable.)
|
|
466
468
|
const gateResult = await applySchemaSimilarityPenalty(candidate, schemaSimilarityCtx, (text) => schemaSimilarityCtx?.embedFn
|
|
467
469
|
? schemaSimilarityCtx.embedFn(text)
|
|
468
470
|
: embed(text, schemaSimilarityCtx?.embeddingConfig));
|
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
* WS-3b Step 0c — Hot-probation intake buffer (#604).
|
|
6
|
+
*
|
|
7
|
+
* New system-generated extractions enter `captureMode: hot-probation` and spend
|
|
8
|
+
* ONE consolidation cycle in probation before promotion to the main stash;
|
|
9
|
+
* dedup + quality second-pass runs against them. Stops noisy extractions from
|
|
10
|
+
* polluting the stash at the source. Reuses shared dedupHash + body_embeddings.
|
|
11
|
+
* Default OFF.
|
|
12
|
+
*
|
|
13
|
+
* @module hot-probation
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* captureMode value for system-generated extractions in probation.
|
|
17
|
+
* Automatic counterpart to the user-explicit `captureMode: hot`.
|
|
18
|
+
*/
|
|
19
|
+
export const CAPTURE_MODE_HOT_PROBATION = "hot-probation";
|
|
20
|
+
/**
|
|
21
|
+
* Returns true when an asset is in hot-probation (system-generated, not yet
|
|
22
|
+
* graduated from the intake dedup+quality pass).
|
|
23
|
+
*/
|
|
24
|
+
export function isHotProbation(captureModeValue) {
|
|
25
|
+
return captureModeValue === CAPTURE_MODE_HOT_PROBATION;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Returns true when an asset should be skipped by the consolidation LLM
|
|
29
|
+
* because it's still in hot-probation (hasn't completed the intake pass yet).
|
|
30
|
+
*
|
|
31
|
+
* Hot-probation assets are processed by the consolidation dedup pre-pass
|
|
32
|
+
* (runDeterministicDedup) but excluded from the LLM merge clustering, so
|
|
33
|
+
* noisy extractions can't pollute the LLM context.
|
|
34
|
+
*/
|
|
35
|
+
export function shouldSkipHotProbationInLlm(frontmatterData) {
|
|
36
|
+
return isHotProbation(frontmatterData.captureMode);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build frontmatter fields to inject when creating a hot-probation proposal.
|
|
40
|
+
* The proposal will carry `captureMode: hot-probation` so downstream logic
|
|
41
|
+
* knows to run the intake dedup pass before graduating it.
|
|
42
|
+
*/
|
|
43
|
+
export function buildHotProbationFrontmatter() {
|
|
44
|
+
return { captureMode: CAPTURE_MODE_HOT_PROBATION };
|
|
45
|
+
}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { loadConfig } from "../../core/config/config.js";
|
|
5
5
|
import { appendEvent } from "../../core/events.js";
|
|
6
|
-
import {
|
|
6
|
+
import { withStateDb } from "../../core/state-db.js";
|
|
7
7
|
import { info, warn } from "../../core/warn.js";
|
|
8
|
-
import {
|
|
8
|
+
import { getPhaseThreshold } from "../../storage/repositories/improve-runs-repository.js";
|
|
9
|
+
import { getProposal, promoteProposal, recordGateDecision } from "../proposal/repository.js";
|
|
9
10
|
async function sha256Hex(input) {
|
|
10
11
|
const data = new TextEncoder().encode(input);
|
|
11
12
|
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
@@ -8,11 +8,12 @@ import { output, runWithJsonErrors } from "../../cli/shared.js";
|
|
|
8
8
|
import { loadConfig } from "../../core/config/config.js";
|
|
9
9
|
import { UsageError } from "../../core/errors.js";
|
|
10
10
|
import { getCacheDir } from "../../core/paths.js";
|
|
11
|
-
import {
|
|
11
|
+
import { withStateDb } from "../../core/state-db.js";
|
|
12
12
|
import { clearLogFile, setLogFile } from "../../core/warn.js";
|
|
13
13
|
import { closeDatabase, openExistingDatabase } from "../../indexer/db/db.js";
|
|
14
14
|
import { resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
15
|
-
import {
|
|
15
|
+
import { parseFlagValue } from "../../output/context.js";
|
|
16
|
+
import { getActiveCanaries, queryRecentCycleMetrics } from "../../storage/repositories/canaries-repository.js";
|
|
16
17
|
import { refreshCanarySet } from "./collapse-detector.js";
|
|
17
18
|
import { akmImprove } from "./improve.js";
|
|
18
19
|
import { buildImproveRunId, recordTerminatedImproveRun, relativeImproveResultPath, writeImproveResultFile, } from "./improve-result-file.js";
|
|
@@ -137,7 +138,7 @@ export const improveCommand = defineCommand({
|
|
|
137
138
|
// contain ":"): dispatch to the detector inspection verb instead of an
|
|
138
139
|
// improve run.
|
|
139
140
|
if (args.scope === "canary") {
|
|
140
|
-
await runWithJsonErrors(() => runCanaryInspection(
|
|
141
|
+
await runWithJsonErrors(() => runCanaryInspection(args.refresh));
|
|
141
142
|
return;
|
|
142
143
|
}
|
|
143
144
|
await runWithJsonErrors(async () => {
|
|
@@ -146,31 +147,31 @@ export const improveCommand = defineCommand({
|
|
|
146
147
|
throw new UsageError(`akm improve does not accept --format. That flag controls output formatting for other commands (search, show, etc.).\n` +
|
|
147
148
|
`Did you mean: akm improve (no --format flag)?`, "INVALID_FLAG_VALUE");
|
|
148
149
|
}
|
|
149
|
-
const jsonToStdout =
|
|
150
|
-
const autoAcceptRaw =
|
|
150
|
+
const jsonToStdout = args["json-to-stdout"];
|
|
151
|
+
const autoAcceptRaw = args["auto-accept"];
|
|
151
152
|
const autoAccept = parseAutoAcceptFlag(autoAcceptRaw);
|
|
152
153
|
const targetArg = getStringArg(args, "target");
|
|
153
154
|
const taskArg = getStringArg(args, "task");
|
|
154
|
-
const dryRun =
|
|
155
|
+
const dryRun = args["dry-run"];
|
|
155
156
|
const limitRaw = parsePositiveIntFlag(args.limit ?? undefined);
|
|
156
|
-
const timeoutMs = parsePositiveIntFlag(
|
|
157
|
-
const consolidateRecoveryRaw =
|
|
157
|
+
const timeoutMs = parsePositiveIntFlag(args["timeout-ms"], "--timeout-ms");
|
|
158
|
+
const consolidateRecoveryRaw = args["consolidate-recovery"];
|
|
158
159
|
const consolidateRecovery = consolidateRecoveryRaw === undefined
|
|
159
160
|
? undefined
|
|
160
161
|
: consolidateRecoveryRaw.trim().toLowerCase();
|
|
161
162
|
if (consolidateRecovery !== undefined && consolidateRecovery !== "abort" && consolidateRecovery !== "clean") {
|
|
162
163
|
throw new UsageError(`Invalid --consolidate-recovery value: "${consolidateRecoveryRaw}". Must be one of: abort, clean.`, "INVALID_FLAG_VALUE");
|
|
163
164
|
}
|
|
164
|
-
const minRetrievalCountRaw =
|
|
165
|
+
const minRetrievalCountRaw = args["min-retrieval-count"];
|
|
165
166
|
const minRetrievalCount = parseNonNegativeIntFlag(minRetrievalCountRaw, "--min-retrieval-count");
|
|
166
|
-
const requireFeedbackSignal =
|
|
167
|
-
const skipIfLocked =
|
|
167
|
+
const requireFeedbackSignal = args["require-feedback-signal"];
|
|
168
|
+
const skipIfLocked = args["skip-if-locked"];
|
|
168
169
|
const profileArg = getStringArg(args, "profile");
|
|
169
170
|
// Only set the keys the user actually passed (citty leaves the flag
|
|
170
171
|
// undefined unless `--sync`/`--no-sync` / `--push`/`--no-push` appears),
|
|
171
172
|
// so the resolved profile `sync` block wins by default.
|
|
172
|
-
const syncFlag =
|
|
173
|
-
const pushFlag =
|
|
173
|
+
const syncFlag = args.sync;
|
|
174
|
+
const pushFlag = args.push;
|
|
174
175
|
const syncOverride = {};
|
|
175
176
|
if (syncFlag !== undefined)
|
|
176
177
|
syncOverride.enabled = syncFlag;
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
*/
|
|
28
28
|
import crypto from "node:crypto";
|
|
29
29
|
import path from "node:path";
|
|
30
|
-
import {
|
|
30
|
+
import { withStateDb } from "../../core/state-db.js";
|
|
31
|
+
import { recordImproveRun } from "../../storage/repositories/improve-runs-repository.js";
|
|
31
32
|
/**
|
|
32
33
|
* Build a stable run-id for a single improve invocation.
|
|
33
34
|
*
|
|
@@ -38,6 +38,7 @@ import { analyzeMemoryCleanup } from "./memory/memory-improve.js";
|
|
|
38
38
|
import { runImprovePreparationStage } from "./preparation.js";
|
|
39
39
|
import { DEFAULT_DUE_DAYS, filterProactiveDue } from "./proactive-maintenance.js";
|
|
40
40
|
import { akmReflect } from "./reflect.js";
|
|
41
|
+
import { errMessage } from "./shared.js";
|
|
41
42
|
export { resetHeldProcessLocks } from "./locks.js";
|
|
42
43
|
// Re-exported from ./loop-stages for test importers (improve-db-locking).
|
|
43
44
|
export { runImproveMaintenancePasses } from "./loop-stages.js";
|
|
@@ -202,7 +203,7 @@ export async function akmImprove(options = {}) {
|
|
|
202
203
|
await ensureIndexFn(primaryStashDir, { mode: "blocking" });
|
|
203
204
|
}
|
|
204
205
|
catch (err) {
|
|
205
|
-
preEnsureCleanupWarnings.push(`ensureIndex failed: ${
|
|
206
|
+
preEnsureCleanupWarnings.push(`ensureIndex failed: ${errMessage(err)}`);
|
|
206
207
|
}
|
|
207
208
|
// #339 loud-fail: if the index was empty pre-ensureIndex but is now
|
|
208
209
|
// populated, a version-upgrade-triggered rebuild just happened. Surface
|
|
@@ -241,7 +242,7 @@ export async function akmImprove(options = {}) {
|
|
|
241
242
|
}
|
|
242
243
|
catch (err) {
|
|
243
244
|
// Non-fatal: contradiction detection is a best-effort pass.
|
|
244
|
-
warn(`[improve] contradiction detection failed (non-fatal): ${
|
|
245
|
+
warn(`[improve] contradiction detection failed (non-fatal): ${errMessage(err)}`);
|
|
245
246
|
}
|
|
246
247
|
}
|
|
247
248
|
memoryCleanupPlan = shouldAnalyzeMemoryCleanup(scope, memorySummary.eligible, primaryStashDir)
|
|
@@ -302,7 +303,7 @@ export async function akmImprove(options = {}) {
|
|
|
302
303
|
});
|
|
303
304
|
}
|
|
304
305
|
catch (err) {
|
|
305
|
-
warn(`[improve] triage pre-pass failed (non-fatal): ${
|
|
306
|
+
warn(`[improve] triage pre-pass failed (non-fatal): ${errMessage(err)}`);
|
|
306
307
|
}
|
|
307
308
|
finally {
|
|
308
309
|
releaseProcessLock(triageLPath);
|
|
@@ -419,7 +420,7 @@ export async function akmImprove(options = {}) {
|
|
|
419
420
|
};
|
|
420
421
|
}
|
|
421
422
|
catch (syncErr) {
|
|
422
|
-
const reason =
|
|
423
|
+
const reason = errMessage(syncErr);
|
|
423
424
|
warn(`improve: stash sync failed (non-fatal): ${reason}`);
|
|
424
425
|
appendEvent({
|
|
425
426
|
eventType: "stash_synced",
|
|
@@ -821,7 +822,7 @@ export async function akmImprove(options = {}) {
|
|
|
821
822
|
eventType: "improve_failed",
|
|
822
823
|
ref: scope.mode === "ref" ? scope.value : `improve:${scope.mode}:${scope.value ?? "all"}`,
|
|
823
824
|
metadata: {
|
|
824
|
-
error:
|
|
825
|
+
error: errMessage(err),
|
|
825
826
|
durationMs: Date.now() - startMs,
|
|
826
827
|
},
|
|
827
828
|
}, eventsCtx);
|
|
@@ -9,7 +9,7 @@ import { UsageError } from "../../core/errors.js";
|
|
|
9
9
|
import { appendEvent } from "../../core/events.js";
|
|
10
10
|
import { openLogsDatabase, purgeOldTaskLogs } from "../../core/logs-db.js";
|
|
11
11
|
import { getDbPath } from "../../core/paths.js";
|
|
12
|
-
import {
|
|
12
|
+
import { withStateDb } from "../../core/state-db.js";
|
|
13
13
|
import { info, warn } from "../../core/warn.js";
|
|
14
14
|
import { closeDatabase, openIndexDatabase } from "../../indexer/db/db.js";
|
|
15
15
|
import { runGraphExtractionPass } from "../../indexer/graph/graph-extraction.js";
|
|
@@ -20,7 +20,10 @@ import { getWritableStashDirs, resolveSourceEntries } from "../../indexer/search
|
|
|
20
20
|
import { resolveImproveProcessRunnerFromProfile } from "../../integrations/agent/runner.js";
|
|
21
21
|
import { isProcessEnabled } from "../../llm/feature-gate.js";
|
|
22
22
|
import { withLlmStage } from "../../llm/usage-telemetry.js";
|
|
23
|
-
import {
|
|
23
|
+
import { purgeOldCycleMetrics } from "../../storage/repositories/canaries-repository.js";
|
|
24
|
+
import { purgeOldEvents } from "../../storage/repositories/events-repository.js";
|
|
25
|
+
import { purgeOldImproveRuns } from "../../storage/repositories/improve-runs-repository.js";
|
|
26
|
+
import { createProposal, expireStaleProposals, isProposalSkipped, listProposals, purgeOrphanProposals, } from "../proposal/repository.js";
|
|
24
27
|
import { checkDeadUrls } from "../url-checker.js";
|
|
25
28
|
import { DEFAULT_RETENTION_DAYS as CYCLE_METRICS_RETENTION_DAYS, runCollapseDetector } from "./collapse-detector.js";
|
|
26
29
|
import { deriveLessonRef } from "./distill.js";
|
|
@@ -35,6 +38,7 @@ import { maybeAutoTuneThreshold } from "./preparation.js";
|
|
|
35
38
|
import { akmProcedural } from "./procedural.js";
|
|
36
39
|
import { akmRecombine } from "./recombine.js";
|
|
37
40
|
import { recordNoOp, resetConsecutiveNoOps } from "./salience.js";
|
|
41
|
+
import { errMessage, refSlug } from "./shared.js";
|
|
38
42
|
// ── improve loop / post-loop / maintenance stages ───────────────────
|
|
39
43
|
// The cycle stages run by akmImprove, extracted from improve.ts.
|
|
40
44
|
export async function runImproveLoopStage(args) {
|
|
@@ -504,10 +508,7 @@ export async function runImproveLoopStage(args) {
|
|
|
504
508
|
}
|
|
505
509
|
}
|
|
506
510
|
if (distillResult.outcome === "quality_rejected" && primaryStashDir) {
|
|
507
|
-
const slug = planned.ref
|
|
508
|
-
.replace(/[^a-z0-9]/gi, "-")
|
|
509
|
-
.toLowerCase()
|
|
510
|
-
.slice(0, 60);
|
|
511
|
+
const slug = refSlug(planned.ref);
|
|
511
512
|
writeEvalCase(primaryStashDir, {
|
|
512
513
|
ref: planned.ref,
|
|
513
514
|
failureReason: distillResult.reason ?? "quality gate rejected",
|
|
@@ -520,10 +521,7 @@ export async function runImproveLoopStage(args) {
|
|
|
520
521
|
// D6: use pre-loaded map instead of per-iteration DB query
|
|
521
522
|
const rejectedProposalEvent = rejectedProposalsByRef.get(planned.ref);
|
|
522
523
|
if (rejectedProposalEvent && primaryStashDir) {
|
|
523
|
-
const slug = planned.ref
|
|
524
|
-
.replace(/[^a-z0-9]/gi, "-")
|
|
525
|
-
.toLowerCase()
|
|
526
|
-
.slice(0, 60);
|
|
524
|
+
const slug = refSlug(planned.ref);
|
|
527
525
|
writeEvalCase(primaryStashDir, {
|
|
528
526
|
ref: planned.ref,
|
|
529
527
|
failureReason: rejectedProposalEvent.metadata?.reason ?? "proposal rejected",
|
|
@@ -562,7 +560,7 @@ export async function runImproveLoopStage(args) {
|
|
|
562
560
|
actions.push({
|
|
563
561
|
ref: planned.ref,
|
|
564
562
|
mode: "error",
|
|
565
|
-
result: { ok: false, error:
|
|
563
|
+
result: { ok: false, error: errMessage(err) },
|
|
566
564
|
});
|
|
567
565
|
}
|
|
568
566
|
}
|
|
@@ -585,7 +583,7 @@ export async function runImproveLoopStage(args) {
|
|
|
585
583
|
maybeAutoTuneThreshold(phaseCfg.phaseThreshold ?? options.autoAccept, options.config ?? loadConfig(), stateDbPathForTune, undefined, phase);
|
|
586
584
|
}
|
|
587
585
|
catch (err) {
|
|
588
|
-
warn(`[improve] calibration auto-tune (${phase}) skipped: ${
|
|
586
|
+
warn(`[improve] calibration auto-tune (${phase}) skipped: ${errMessage(err)}`);
|
|
589
587
|
}
|
|
590
588
|
}
|
|
591
589
|
}
|
|
@@ -841,7 +839,7 @@ export async function runImproveMaintenancePasses(args) {
|
|
|
841
839
|
}
|
|
842
840
|
catch (err) {
|
|
843
841
|
memoryInferenceDurationMs = Date.now() - inferenceStart;
|
|
844
|
-
allWarnings.push(`memory inference failed: ${
|
|
842
|
+
allWarnings.push(`memory inference failed: ${errMessage(err)}`);
|
|
845
843
|
}
|
|
846
844
|
}
|
|
847
845
|
if (memoryInference && (memoryInference.splitParents > 0 || memoryInference.writtenFacts > 0)) {
|
|
@@ -852,7 +850,7 @@ export async function runImproveMaintenancePasses(args) {
|
|
|
852
850
|
info("[improve] reindex after memory inference complete");
|
|
853
851
|
}
|
|
854
852
|
catch (err) {
|
|
855
|
-
allWarnings.push(`reindex after memory inference failed: ${
|
|
853
|
+
allWarnings.push(`reindex after memory inference failed: ${errMessage(err)}`);
|
|
856
854
|
}
|
|
857
855
|
}
|
|
858
856
|
const graphEnabled = isProcessEnabled("index", "graph_extraction", config);
|
|
@@ -891,7 +889,7 @@ export async function runImproveMaintenancePasses(args) {
|
|
|
891
889
|
info("[improve] reindex after consolidation complete");
|
|
892
890
|
}
|
|
893
891
|
catch (err) {
|
|
894
|
-
allWarnings.push(`reindex after consolidation failed: ${
|
|
892
|
+
allWarnings.push(`reindex after consolidation failed: ${errMessage(err)}`);
|
|
895
893
|
}
|
|
896
894
|
}
|
|
897
895
|
// #584: no close/reopen needed here — reindexWithIndexDbReleased
|
|
@@ -930,7 +928,7 @@ export async function runImproveMaintenancePasses(args) {
|
|
|
930
928
|
}
|
|
931
929
|
catch (err) {
|
|
932
930
|
graphExtractionDurationMs = Date.now() - extractionStart;
|
|
933
|
-
allWarnings.push(`graph extraction failed: ${
|
|
931
|
+
allWarnings.push(`graph extraction failed: ${errMessage(err)}`);
|
|
934
932
|
}
|
|
935
933
|
}
|
|
936
934
|
else if (sources.length > 0 && !graphEnabled) {
|
|
@@ -959,7 +957,7 @@ export async function runImproveMaintenancePasses(args) {
|
|
|
959
957
|
}, eventsCtx);
|
|
960
958
|
}
|
|
961
959
|
catch (err) {
|
|
962
|
-
allWarnings.push(`orphan purge failed: ${
|
|
960
|
+
allWarnings.push(`orphan purge failed: ${errMessage(err)}`);
|
|
963
961
|
}
|
|
964
962
|
// Phase 6B (Advantage D6b): expire pending proposals that have aged past
|
|
965
963
|
// the retention window. Runs AFTER orphan purge so we never double-archive
|
|
@@ -986,7 +984,7 @@ export async function runImproveMaintenancePasses(args) {
|
|
|
986
984
|
}, eventsCtx);
|
|
987
985
|
}
|
|
988
986
|
catch (err) {
|
|
989
|
-
allWarnings.push(`proposal expiration failed: ${
|
|
987
|
+
allWarnings.push(`proposal expiration failed: ${errMessage(err)}`);
|
|
990
988
|
}
|
|
991
989
|
}
|
|
992
990
|
// Fix #2 (observability 0.8.0): trim the events table in state.db so it
|
|
@@ -1048,7 +1046,7 @@ export async function runImproveMaintenancePasses(args) {
|
|
|
1048
1046
|
}, { path: eventsCtx?.dbPath, borrowed: eventsCtx?.db });
|
|
1049
1047
|
}
|
|
1050
1048
|
catch (err) {
|
|
1051
|
-
allWarnings.push(`events purge failed: ${
|
|
1049
|
+
allWarnings.push(`events purge failed: ${errMessage(err)}`);
|
|
1052
1050
|
}
|
|
1053
1051
|
// task_logs in logs.db (#579) shares the same retention window as
|
|
1054
1052
|
// events/improve_runs — all three are observability data governed by
|
|
@@ -1069,7 +1067,7 @@ export async function runImproveMaintenancePasses(args) {
|
|
|
1069
1067
|
}, eventsCtx);
|
|
1070
1068
|
}
|
|
1071
1069
|
catch (err) {
|
|
1072
|
-
allWarnings.push(`task_logs purge failed: ${
|
|
1070
|
+
allWarnings.push(`task_logs purge failed: ${errMessage(err)}`);
|
|
1073
1071
|
}
|
|
1074
1072
|
finally {
|
|
1075
1073
|
if (logsDb) {
|
|
@@ -1099,7 +1097,7 @@ export async function runImproveMaintenancePasses(args) {
|
|
|
1099
1097
|
allWarnings.push(`[improve] staleness detection: ${w}`);
|
|
1100
1098
|
}
|
|
1101
1099
|
catch (err) {
|
|
1102
|
-
allWarnings.push(`staleness detection failed: ${
|
|
1100
|
+
allWarnings.push(`staleness detection failed: ${errMessage(err)}`);
|
|
1103
1101
|
}
|
|
1104
1102
|
}
|
|
1105
1103
|
}
|
|
@@ -9,14 +9,16 @@ import { daysToMs } from "../../core/common.js";
|
|
|
9
9
|
import { getDefaultLlmConfig, loadConfig } from "../../core/config/config.js";
|
|
10
10
|
import { rethrowIfTestIsolationError } from "../../core/errors.js";
|
|
11
11
|
import { appendEvent, readEvents } from "../../core/events.js";
|
|
12
|
-
import {
|
|
12
|
+
import { openStateDatabase, withStateDb } from "../../core/state-db.js";
|
|
13
13
|
import { info, warn } from "../../core/warn.js";
|
|
14
14
|
import { closeDatabase, getRetrievalCounts, getZeroResultSearches, openExistingDatabase } from "../../indexer/db/db.js";
|
|
15
15
|
import { countUsageEventsByType } from "../../indexer/usage/usage-events.js";
|
|
16
16
|
import { getAvailableHarnesses } from "../../integrations/session-logs/index.js";
|
|
17
17
|
import { withLlmStage } from "../../llm/usage-telemetry.js";
|
|
18
|
+
import { persistPhaseThreshold } from "../../storage/repositories/improve-runs-repository.js";
|
|
19
|
+
import { listProposalGateDecisions, listStateProposals } from "../../storage/repositories/proposals-repository.js";
|
|
18
20
|
import { akmLint } from "../lint/index.js";
|
|
19
|
-
import { getProposal, listProposals } from "../proposal/
|
|
21
|
+
import { getProposal, listProposals } from "../proposal/repository.js";
|
|
20
22
|
import { runSchemaRepairPass } from "../sources/schema-repair.js";
|
|
21
23
|
import { computeThresholdAutoTune, gateDecisionsToSamples, summarizeCalibration, } from "./calibration.js";
|
|
22
24
|
import { akmConsolidate, isSessionCaptureMemoryName } from "./consolidate.js";
|