akm-cli 0.9.0-beta.44 → 0.9.0-beta.46

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.
Files changed (80) hide show
  1. package/dist/cli/shared.js +28 -0
  2. package/dist/cli.js +1 -2
  3. package/dist/commands/env/env-cli.js +16 -24
  4. package/dist/commands/env/secret-cli.js +12 -20
  5. package/dist/commands/graph/graph-cli.js +5 -13
  6. package/dist/commands/graph/graph.js +3 -3
  7. package/dist/commands/health.js +5 -0
  8. package/dist/commands/improve/consolidate/chunking.js +141 -0
  9. package/dist/commands/improve/consolidate/eligibility.js +64 -0
  10. package/dist/commands/improve/consolidate/merge.js +145 -0
  11. package/dist/commands/improve/consolidate/sanitize.js +231 -0
  12. package/dist/commands/improve/consolidate/types.js +4 -0
  13. package/dist/commands/improve/consolidate.js +20 -571
  14. package/dist/commands/improve/distill.js +5 -9
  15. package/dist/commands/improve/eligibility.js +434 -0
  16. package/dist/commands/improve/extract-cli.js +9 -1
  17. package/dist/commands/improve/extract.js +5 -19
  18. package/dist/commands/improve/improve-auto-accept.js +4 -8
  19. package/dist/commands/improve/improve-cli.js +35 -60
  20. package/dist/commands/improve/improve-result-file.js +5 -23
  21. package/dist/commands/improve/improve-session.js +58 -0
  22. package/dist/commands/improve/improve.js +107 -3606
  23. package/dist/commands/improve/locks.js +154 -0
  24. package/dist/commands/improve/loop-stages.js +1079 -0
  25. package/dist/commands/improve/preparation.js +1963 -0
  26. package/dist/commands/improve/recombine.js +6 -12
  27. package/dist/commands/improve/reflect.js +29 -34
  28. package/dist/commands/proposal/drain.js +25 -48
  29. package/dist/commands/proposal/proposal-cli.js +21 -31
  30. package/dist/commands/proposal/validators/proposals.js +3 -7
  31. package/dist/commands/read/curate.js +70 -14
  32. package/dist/commands/read/knowledge.js +2 -2
  33. package/dist/commands/sources/self-update.js +2 -2
  34. package/dist/commands/sources/stash-cli.js +9 -37
  35. package/dist/commands/tasks/tasks-cli.js +19 -27
  36. package/dist/commands/wiki-cli.js +21 -35
  37. package/dist/core/config/config.js +18 -2
  38. package/dist/core/events.js +3 -7
  39. package/dist/core/logs-db.js +6 -63
  40. package/dist/core/parse.js +36 -16
  41. package/dist/core/state/migrations.js +714 -0
  42. package/dist/core/state-db.js +28 -779
  43. package/dist/indexer/db/db.js +82 -216
  44. package/dist/indexer/graph/graph-extraction.js +2 -0
  45. package/dist/indexer/indexer.js +11 -112
  46. package/dist/indexer/passes/dir-staleness.js +114 -0
  47. package/dist/indexer/search/search-source.js +10 -24
  48. package/dist/integrations/agent/runner-dispatch.js +59 -0
  49. package/dist/llm/client.js +22 -11
  50. package/dist/llm/graph-extract.js +58 -42
  51. package/dist/llm/memory-infer.js +34 -22
  52. package/dist/llm/metadata-enhance.js +35 -30
  53. package/dist/llm/structured-call.js +49 -0
  54. package/dist/output/shapes/passthrough.js +0 -1
  55. package/dist/registry/providers/skills-sh.js +21 -147
  56. package/dist/registry/providers/static-index.js +15 -157
  57. package/dist/registry/resolve.js +22 -9
  58. package/dist/scripts/migrate-storage.js +892 -1186
  59. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +214 -179
  60. package/dist/setup/setup.js +26 -5
  61. package/dist/sources/providers/filesystem.js +0 -1
  62. package/dist/sources/providers/git-install.js +206 -0
  63. package/dist/sources/providers/git-provider.js +234 -0
  64. package/dist/sources/providers/git-stash.js +248 -0
  65. package/dist/sources/providers/git.js +10 -671
  66. package/dist/sources/providers/npm.js +2 -6
  67. package/dist/sources/providers/sync-from-ref.js +9 -1
  68. package/dist/sources/providers/website.js +2 -3
  69. package/dist/sources/website-ingest.js +51 -9
  70. package/dist/sources/wiki-fetchers/registry.js +53 -0
  71. package/dist/sources/wiki-fetchers/youtube.js +181 -0
  72. package/dist/storage/database.js +45 -10
  73. package/dist/storage/managed-db.js +82 -0
  74. package/dist/storage/repositories/registry-cache.js +92 -0
  75. package/dist/tasks/runner.js +5 -13
  76. package/dist/workflows/runtime/runs.js +1 -117
  77. package/dist/workflows/runtime/workflow-asset-loader.js +125 -0
  78. package/package.json +5 -5
  79. package/dist/commands/db-cli.js +0 -23
  80. package/dist/indexer/db/db-backup.js +0 -376
@@ -13,6 +13,7 @@ import { resolveSourceEntries } from "../../indexer/search/search-source.js";
13
13
  import { getHyphenatedArg, getHyphenatedBoolean, parseFlagValue } from "../../output/context.js";
14
14
  import { akmImprove } from "./improve.js";
15
15
  import { buildImproveRunId, recordTerminatedImproveRun, relativeImproveResultPath, writeImproveResultFile, } from "./improve-result-file.js";
16
+ import { runImproveSession } from "./improve-session.js";
16
17
  export const improveCommand = defineCommand({
17
18
  meta: {
18
19
  name: "improve",
@@ -144,67 +145,44 @@ export const improveCommand = defineCommand({
144
145
  process.stderr.write(`warning: failed to persist terminated improve run ${runId}: ${err instanceof Error ? err.message : String(err)}\n`);
145
146
  }
146
147
  };
147
- // M5 (code-health round 2): signal -> {exit code, reason, ack message}
148
- // as an explicit table instead of three near-identical handlers. The
149
- // persist of the terminated-run row MUST complete before process.exit so
150
- // a SIGTERM'd run (e.g. cron timeout) always leaves a row in
151
- // improve_runs. recordTerminatedImproveRun is fully synchronous
152
- // (bun:sqlite writes are sync), so the in-line call below blocks until
153
- // the row is flushed before we exit.
154
- const SIGNAL_TABLE = {
155
- SIGTERM: { code: 143, reason: "SIGTERM", ack: true },
156
- SIGINT: { code: 130, reason: "SIGINT", ack: true },
157
- SIGHUP: { code: 129, reason: "SIGHUP", ack: false },
158
- };
159
- const makeSignalHandler = (sig) => () => {
160
- const { code, reason, ack } = SIGNAL_TABLE[sig];
161
- // Hard-exit fallback: if the synchronous persist ever hangs (e.g. a
162
- // stuck sqlite lock under contention), the watchdog still exits with
163
- // the correct code instead of leaving a zombie process. .unref() keeps
164
- // the timer from holding the loop open on the normal (fast) path.
165
- const watchdog = setTimeout(() => process.exit(code), 2000);
166
- if (typeof watchdog.unref === "function")
167
- watchdog.unref();
168
- try {
169
- persistTerminated(reason);
170
- }
171
- finally {
172
- clearTimeout(watchdog);
173
- }
174
- if (ack) {
175
- process.stderr.write(`[improve] received ${sig}; recorded terminated run ${runId}\n`);
176
- }
177
- process.exit(code);
178
- };
179
- const sigtermHandler = makeSignalHandler("SIGTERM");
180
- const sigintHandler = makeSignalHandler("SIGINT");
181
- const sighupHandler = makeSignalHandler("SIGHUP");
182
- process.once("SIGTERM", sigtermHandler);
183
- process.once("SIGINT", sigintHandler);
184
- process.once("SIGHUP", sighupHandler);
148
+ // R8: the signal table / handlers / watchdog / persist-before-exit
149
+ // choreography lives in `runImproveSession`. It registers the
150
+ // SIGTERM/SIGINT/SIGHUP handlers (each persists the terminated-run row
151
+ // BEFORE process.exit so a SIGTERM'd run e.g. cron timeout always
152
+ // leaves a row in improve_runs), awaits the work, then removes the
153
+ // handlers on the way out. `onTerminate` persists synchronously
154
+ // (recordTerminatedImproveRun -> bun:sqlite writes are sync), and the
155
+ // 2000ms watchdog inside the session force-exits if that ever hangs.
185
156
  let improveResult;
186
157
  try {
187
- improveResult = await akmImprove({
188
- scope: scopeArg,
189
- task: taskArg,
190
- dryRun,
191
- target: targetArg,
192
- autoAccept,
193
- ...(runId !== undefined ? { runId } : {}),
194
- ...(limitRaw !== undefined ? { limit: limitRaw } : {}),
195
- ...(timeoutMs !== undefined ? { timeoutMs } : {}),
196
- ...(minRetrievalCount !== undefined ? { minRetrievalCount } : {}),
197
- ...(requireFeedbackSignal ? { requireFeedbackSignal } : {}),
198
- ...(skipIfLocked ? { skipIfLocked } : {}),
199
- ...(profileArg !== undefined ? { profile: profileArg } : {}),
200
- ...(Object.keys(syncOverride).length > 0 ? { sync: syncOverride } : {}),
201
- consolidateOptions: {
202
- target: targetArg,
158
+ improveResult = await runImproveSession({
159
+ runWork: () => akmImprove({
160
+ scope: scopeArg,
161
+ task: taskArg,
203
162
  dryRun,
163
+ target: targetArg,
204
164
  autoAccept,
205
- task: taskArg,
206
- ...(consolidateRecovery !== undefined ? { recoveryMode: consolidateRecovery } : {}),
207
- },
165
+ ...(runId !== undefined ? { runId } : {}),
166
+ ...(limitRaw !== undefined ? { limit: limitRaw } : {}),
167
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
168
+ ...(minRetrievalCount !== undefined ? { minRetrievalCount } : {}),
169
+ ...(requireFeedbackSignal ? { requireFeedbackSignal } : {}),
170
+ ...(skipIfLocked ? { skipIfLocked } : {}),
171
+ ...(profileArg !== undefined ? { profile: profileArg } : {}),
172
+ ...(Object.keys(syncOverride).length > 0 ? { sync: syncOverride } : {}),
173
+ consolidateOptions: {
174
+ target: targetArg,
175
+ dryRun,
176
+ autoAccept,
177
+ task: taskArg,
178
+ ...(consolidateRecovery !== undefined ? { recoveryMode: consolidateRecovery } : {}),
179
+ },
180
+ }),
181
+ }, {
182
+ signalSource: process,
183
+ exit: process.exit,
184
+ onTerminate: (reason) => persistTerminated(reason),
185
+ ack: (message) => process.stderr.write(`[improve] ${message}; recorded terminated run ${runId}\n`),
208
186
  });
209
187
  }
210
188
  catch (err) {
@@ -216,9 +194,6 @@ export const improveCommand = defineCommand({
216
194
  throw err;
217
195
  }
218
196
  finally {
219
- process.removeListener("SIGTERM", sigtermHandler);
220
- process.removeListener("SIGINT", sigintHandler);
221
- process.removeListener("SIGHUP", sighupHandler);
222
197
  clearLogFile();
223
198
  }
224
199
  const durationMs = Date.now() - startedAtMs;
@@ -27,7 +27,7 @@
27
27
  */
28
28
  import crypto from "node:crypto";
29
29
  import path from "node:path";
30
- import { openStateDatabase, recordImproveRun } from "../../core/state-db.js";
30
+ import { recordImproveRun, withStateDb } from "../../core/state-db.js";
31
31
  /**
32
32
  * Build a stable run-id for a single improve invocation.
33
33
  *
@@ -74,8 +74,7 @@ export function relativeImproveResultPath(runId) {
74
74
  * `feedback_akm_dryrun_artifact_trap`).
75
75
  */
76
76
  export function writeImproveResultFile(stashDir, runId, result, startedAt) {
77
- const db = openStateDatabase();
78
- try {
77
+ withStateDb((db) => {
79
78
  const completedAt = new Date().toISOString();
80
79
  // startedAt is the ISO timestamp captured at process launch (passed from the
81
80
  // CLI entry point). If omitted, fall back to the run-id's embedded timestamp
@@ -95,15 +94,7 @@ export function writeImproveResultFile(stashDir, runId, result, startedAt) {
95
94
  ok: Boolean(result.ok),
96
95
  result,
97
96
  });
98
- }
99
- finally {
100
- try {
101
- db.close();
102
- }
103
- catch {
104
- // best-effort
105
- }
106
- }
97
+ });
107
98
  return relativeImproveResultPath(runId);
108
99
  }
109
100
  /**
@@ -138,8 +129,7 @@ export function recordTerminatedImproveRun(stashDir, runId, startedAt, reason, c
138
129
  ...(ctx?.errorMessage ? { errorMessage: ctx.errorMessage } : {}),
139
130
  },
140
131
  };
141
- const db = openStateDatabase();
142
- try {
132
+ withStateDb((db) => {
143
133
  recordImproveRun(db, {
144
134
  id: runId,
145
135
  startedAt,
@@ -160,13 +150,5 @@ export function recordTerminatedImproveRun(stashDir, runId, startedAt, reason, c
160
150
  },
161
151
  },
162
152
  });
163
- }
164
- finally {
165
- try {
166
- db.close();
167
- }
168
- catch {
169
- // best-effort
170
- }
171
- }
153
+ });
172
154
  }
@@ -0,0 +1,58 @@
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
+ /** Signal -> {exit code, reason, ack message}. */
5
+ export const SIGNAL_TABLE = {
6
+ SIGTERM: { code: 143, reason: "SIGTERM", ack: true },
7
+ SIGINT: { code: 130, reason: "SIGINT", ack: true },
8
+ SIGHUP: { code: 129, reason: "SIGHUP", ack: false },
9
+ };
10
+ /**
11
+ * Drive the improve-run lifecycle: register signal handlers, await `runWork`,
12
+ * and on clean completion remove the handlers and resolve with the result. The
13
+ * caller (improve-cli.ts) owns success-path result persistence + the final
14
+ * `exit(0)`; this function returns the work result so that choreography stays
15
+ * in the CLI exactly as before.
16
+ *
17
+ * Abnormal paths:
18
+ * - A registered signal fires -> persist terminated row (watchdog-guarded) ->
19
+ * optional ack -> `exit(code)`.
20
+ * - `runWork` rejects -> handlers are removed and the rejection propagates so
21
+ * the CLI's existing catch can persist `"exception"` and rethrow.
22
+ */
23
+ export async function runImproveSession(opts, deps) {
24
+ const { signalSource, exit, onTerminate, ack } = deps;
25
+ const makeSignalHandler = (sig) => () => {
26
+ const { code, reason, ack: shouldAck } = SIGNAL_TABLE[sig];
27
+ // Hard-exit fallback: if the synchronous persist ever hangs (e.g. a stuck
28
+ // sqlite lock under contention), the watchdog still exits with the correct
29
+ // code instead of leaving a zombie process. .unref() keeps the timer from
30
+ // holding the loop open on the normal (fast) path.
31
+ const watchdog = setTimeout(() => exit(code), 2000);
32
+ if (typeof watchdog.unref === "function")
33
+ watchdog.unref();
34
+ try {
35
+ onTerminate(reason);
36
+ }
37
+ finally {
38
+ clearTimeout(watchdog);
39
+ }
40
+ if (shouldAck)
41
+ ack?.(`received ${sig}`);
42
+ exit(code);
43
+ };
44
+ const sigtermHandler = makeSignalHandler("SIGTERM");
45
+ const sigintHandler = makeSignalHandler("SIGINT");
46
+ const sighupHandler = makeSignalHandler("SIGHUP");
47
+ signalSource.once("SIGTERM", sigtermHandler);
48
+ signalSource.once("SIGINT", sigintHandler);
49
+ signalSource.once("SIGHUP", sighupHandler);
50
+ try {
51
+ return await opts.runWork();
52
+ }
53
+ finally {
54
+ signalSource.removeListener("SIGTERM", sigtermHandler);
55
+ signalSource.removeListener("SIGINT", sigintHandler);
56
+ signalSource.removeListener("SIGHUP", sighupHandler);
57
+ }
58
+ }