akm-cli 0.9.0-beta.5 → 0.9.0-beta.51

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 (221) hide show
  1. package/CHANGELOG.md +711 -0
  2. package/README.md +12 -4
  3. package/dist/akm +38 -0
  4. package/dist/akm-migrate-storage +38 -0
  5. package/dist/assets/profiles/default.json +9 -4
  6. package/dist/assets/profiles/frequent.json +1 -1
  7. package/dist/assets/profiles/memory-focus.json +1 -1
  8. package/dist/assets/profiles/quick.json +1 -1
  9. package/dist/assets/profiles/synthesize.json +15 -0
  10. package/dist/assets/profiles/thorough.json +1 -1
  11. package/dist/assets/prompts/consolidate-system.md +23 -0
  12. package/dist/assets/prompts/contradiction-judge.md +33 -0
  13. package/dist/assets/prompts/distill-knowledge-system.md +22 -0
  14. package/dist/assets/prompts/distill-lesson-system.md +36 -0
  15. package/dist/assets/prompts/extract-session.md +6 -2
  16. package/dist/assets/prompts/graph-extract-system.md +1 -0
  17. package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
  18. package/dist/assets/prompts/memory-infer-system.md +1 -0
  19. package/dist/assets/prompts/memory-infer-user.md +5 -0
  20. package/dist/assets/prompts/metadata-enhance-system.md +1 -0
  21. package/dist/assets/prompts/procedural-system.md +44 -0
  22. package/dist/assets/prompts/recombine-system.md +40 -0
  23. package/dist/assets/prompts/staleness-detect-system.md +6 -0
  24. package/dist/assets/prompts/validate-summary-judge.md +1 -0
  25. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
  26. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
  28. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
  29. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
  34. package/dist/assets/templates/html/health.html +281 -111
  35. package/dist/assets/wiki/ingest-workflow-template.md +38 -10
  36. package/dist/cli/parse-args.js +46 -1
  37. package/dist/cli/shared.js +28 -0
  38. package/dist/cli.js +27 -11
  39. package/dist/commands/agent/agent-dispatch.js +2 -2
  40. package/dist/commands/agent/agent-support.js +0 -7
  41. package/dist/commands/agent/contribute-cli.js +17 -4
  42. package/dist/commands/config-cli.js +18 -2
  43. package/dist/commands/env/child-env.js +47 -0
  44. package/dist/commands/env/env-cli.js +33 -26
  45. package/dist/commands/env/secret-cli.js +36 -22
  46. package/dist/commands/feedback-cli.js +15 -6
  47. package/dist/commands/graph/graph-cli.js +5 -13
  48. package/dist/commands/graph/graph.js +76 -72
  49. package/dist/commands/health/checks.js +49 -1
  50. package/dist/commands/health/html-report.js +422 -80
  51. package/dist/commands/health.js +386 -9
  52. package/dist/commands/improve/calibration.js +161 -0
  53. package/dist/commands/improve/consolidate/chunking.js +141 -0
  54. package/dist/commands/improve/consolidate/eligibility.js +81 -0
  55. package/dist/commands/improve/consolidate/merge.js +145 -0
  56. package/dist/commands/improve/consolidate/sanitize.js +231 -0
  57. package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
  58. package/dist/commands/improve/consolidate.js +635 -660
  59. package/dist/commands/improve/dedup.js +482 -0
  60. package/dist/commands/improve/distill.js +159 -69
  61. package/dist/commands/improve/eligibility.js +434 -0
  62. package/dist/commands/improve/encoding-salience.js +205 -0
  63. package/dist/commands/improve/extract-cli.js +124 -2
  64. package/dist/commands/improve/extract-prompt.js +39 -2
  65. package/dist/commands/improve/extract-watch.js +140 -0
  66. package/dist/commands/improve/extract.js +389 -40
  67. package/dist/commands/improve/feedback-valence.js +54 -0
  68. package/dist/commands/improve/homeostatic.js +467 -0
  69. package/dist/commands/improve/improve-auto-accept.js +138 -7
  70. package/dist/commands/improve/improve-cli.js +36 -61
  71. package/dist/commands/improve/improve-profiles.js +14 -0
  72. package/dist/commands/improve/improve-result-file.js +14 -25
  73. package/dist/commands/improve/improve-session.js +58 -0
  74. package/dist/commands/improve/improve.js +485 -2498
  75. package/dist/commands/improve/locks.js +154 -0
  76. package/dist/commands/improve/loop-stages.js +1083 -0
  77. package/dist/commands/improve/memory/memory-contradiction-detect.js +23 -28
  78. package/dist/commands/improve/outcome-loop.js +256 -0
  79. package/dist/commands/improve/preparation.js +1966 -0
  80. package/dist/commands/improve/proactive-maintenance.js +115 -0
  81. package/dist/commands/improve/procedural.js +418 -0
  82. package/dist/commands/improve/recombine.js +850 -0
  83. package/dist/commands/improve/reflect-noise.js +0 -0
  84. package/dist/commands/improve/reflect.js +183 -40
  85. package/dist/commands/improve/salience.js +438 -0
  86. package/dist/commands/improve/triage.js +93 -0
  87. package/dist/commands/lint/agent-linter.js +19 -24
  88. package/dist/commands/lint/base-linter.js +173 -60
  89. package/dist/commands/lint/command-linter.js +19 -24
  90. package/dist/commands/lint/env-key-rules.js +38 -1
  91. package/dist/commands/lint/fact-linter.js +39 -0
  92. package/dist/commands/lint/index.js +31 -13
  93. package/dist/commands/lint/memory-linter.js +1 -1
  94. package/dist/commands/lint/registry.js +7 -2
  95. package/dist/commands/lint/task-linter.js +3 -3
  96. package/dist/commands/lint/workflow-linter.js +26 -1
  97. package/dist/commands/proposal/drain-policies.js +5 -0
  98. package/dist/commands/proposal/drain.js +43 -50
  99. package/dist/commands/proposal/proposal-cli.js +21 -31
  100. package/dist/commands/proposal/proposal.js +5 -0
  101. package/dist/commands/proposal/propose.js +7 -2
  102. package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
  103. package/dist/commands/proposal/validators/proposals.js +189 -63
  104. package/dist/commands/read/curate.js +414 -94
  105. package/dist/commands/read/knowledge.js +6 -3
  106. package/dist/commands/read/search-cli.js +9 -4
  107. package/dist/commands/read/search.js +10 -6
  108. package/dist/commands/read/show.js +86 -7
  109. package/dist/commands/sources/init.js +49 -17
  110. package/dist/commands/sources/installed-stashes.js +11 -3
  111. package/dist/commands/sources/schema-repair.js +43 -45
  112. package/dist/commands/sources/self-update.js +2 -2
  113. package/dist/commands/sources/source-add.js +7 -3
  114. package/dist/commands/sources/stash-cli.js +28 -40
  115. package/dist/commands/sources/stash-skeleton.js +23 -8
  116. package/dist/commands/tasks/tasks-cli.js +19 -27
  117. package/dist/commands/tasks/tasks.js +39 -11
  118. package/dist/commands/wiki-cli.js +21 -35
  119. package/dist/core/asset/asset-registry.js +3 -1
  120. package/dist/core/asset/asset-spec.js +18 -2
  121. package/dist/core/asset/frontmatter.js +166 -167
  122. package/dist/core/asset/markdown.js +8 -0
  123. package/dist/core/authoring-rules.js +92 -0
  124. package/dist/core/common.js +0 -5
  125. package/dist/core/config/config-migration.js +12 -11
  126. package/dist/core/config/config-schema.js +340 -56
  127. package/dist/core/config/config-types.js +3 -3
  128. package/dist/core/config/config.js +28 -7
  129. package/dist/core/events.js +3 -7
  130. package/dist/core/improve-types.js +11 -8
  131. package/dist/core/logs-db.js +10 -66
  132. package/dist/core/parse.js +36 -16
  133. package/dist/core/paths.js +3 -0
  134. package/dist/core/standards/resolve-standards-context.js +87 -0
  135. package/dist/core/standards/resolve-stash-standards.js +99 -0
  136. package/dist/core/standards/resolve-type-conventions.js +66 -0
  137. package/dist/core/state/migrations.js +714 -0
  138. package/dist/core/state-db.js +525 -474
  139. package/dist/indexer/db/db.js +439 -247
  140. package/dist/indexer/db/graph-db.js +129 -86
  141. package/dist/indexer/ensure-index.js +152 -17
  142. package/dist/indexer/graph/graph-boost.js +51 -41
  143. package/dist/indexer/graph/graph-extraction.js +218 -4
  144. package/dist/indexer/index-writer-lock.js +99 -0
  145. package/dist/indexer/indexer.js +123 -221
  146. package/dist/indexer/passes/dir-staleness.js +114 -0
  147. package/dist/indexer/passes/memory-inference.js +13 -5
  148. package/dist/indexer/passes/staleness-detect.js +2 -5
  149. package/dist/indexer/search/db-search.js +19 -6
  150. package/dist/indexer/search/ranking-contributors.js +22 -0
  151. package/dist/indexer/search/ranking.js +4 -0
  152. package/dist/indexer/search/search-source.js +17 -18
  153. package/dist/indexer/search/semantic-status.js +4 -0
  154. package/dist/indexer/walk/matchers.js +9 -0
  155. package/dist/integrations/agent/config.js +6 -53
  156. package/dist/integrations/agent/index.js +2 -18
  157. package/dist/integrations/agent/prompts.js +75 -9
  158. package/dist/integrations/agent/runner-dispatch.js +59 -0
  159. package/dist/integrations/harnesses/claude/session-log.js +11 -1
  160. package/dist/integrations/harnesses/index.js +2 -3
  161. package/dist/integrations/harnesses/opencode/session-log.js +173 -3
  162. package/dist/integrations/harnesses/opencode-sdk/index.js +2 -2
  163. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +0 -2
  164. package/dist/integrations/session-logs/index.js +16 -0
  165. package/dist/llm/client.js +45 -15
  166. package/dist/llm/embedder.js +42 -3
  167. package/dist/llm/embedders/deterministic.js +66 -0
  168. package/dist/llm/embedders/local.js +66 -2
  169. package/dist/llm/feature-gate.js +8 -4
  170. package/dist/llm/graph-extract.js +67 -44
  171. package/dist/llm/memory-infer-impl.js +138 -0
  172. package/dist/llm/memory-infer.js +1 -127
  173. package/dist/llm/metadata-enhance.js +44 -31
  174. package/dist/llm/structured-call.js +49 -0
  175. package/dist/migrate-storage-node.mjs +8 -0
  176. package/dist/output/context.js +5 -5
  177. package/dist/output/renderers.js +74 -2
  178. package/dist/output/shapes/curate.js +14 -2
  179. package/dist/output/shapes/passthrough.js +0 -1
  180. package/dist/output/text/helpers.js +16 -1
  181. package/dist/registry/providers/skills-sh.js +21 -147
  182. package/dist/registry/providers/static-index.js +15 -157
  183. package/dist/registry/resolve.js +22 -9
  184. package/dist/runtime.js +25 -1
  185. package/dist/scripts/migrate-storage.js +2617 -1961
  186. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +759 -510
  187. package/dist/setup/setup.js +29 -8
  188. package/dist/sources/include.js +6 -2
  189. package/dist/sources/providers/filesystem.js +0 -1
  190. package/dist/sources/providers/git-install.js +210 -0
  191. package/dist/sources/providers/git-provider.js +234 -0
  192. package/dist/sources/providers/git-stash.js +248 -0
  193. package/dist/sources/providers/git.js +10 -661
  194. package/dist/sources/providers/npm.js +2 -6
  195. package/dist/sources/providers/provider-utils.js +13 -7
  196. package/dist/sources/providers/sync-from-ref.js +9 -1
  197. package/dist/sources/providers/tar-utils.js +16 -8
  198. package/dist/sources/providers/website.js +9 -5
  199. package/dist/sources/website-ingest.js +187 -29
  200. package/dist/sources/wiki-fetchers/registry.js +53 -0
  201. package/dist/sources/wiki-fetchers/youtube.js +239 -0
  202. package/dist/storage/database.js +45 -10
  203. package/dist/storage/managed-db.js +82 -0
  204. package/dist/storage/repositories/registry-cache.js +92 -0
  205. package/dist/storage/sqlite-pragmas.js +146 -0
  206. package/dist/tasks/backends/cron.js +1 -1
  207. package/dist/tasks/backends/launchd.js +1 -1
  208. package/dist/tasks/backends/schtasks.js +1 -1
  209. package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
  210. package/dist/tasks/runner.js +5 -13
  211. package/dist/text-import-hook.mjs +0 -0
  212. package/dist/wiki/wiki.js +37 -0
  213. package/dist/workflows/db.js +3 -4
  214. package/dist/workflows/runtime/runs.js +1 -117
  215. package/dist/workflows/runtime/workflow-asset-loader.js +125 -0
  216. package/dist/workflows/validate-summary.js +2 -7
  217. package/docs/data-and-telemetry.md +3 -2
  218. package/docs/migration/release-notes/0.9.0.md +39 -0
  219. package/package.json +13 -11
  220. package/dist/commands/db-cli.js +0 -23
  221. package/dist/indexer/db/db-backup.js +0 -376
@@ -33,7 +33,7 @@ import { loadConfig } from "../core/config/config.js";
33
33
  import { NotFoundError, rethrowIfTestIsolationError } from "../core/errors.js";
34
34
  import { buildTaskRunId, insertTaskLogLines, openLogsDatabase, } from "../core/logs-db.js";
35
35
  import { getTaskLogDir } from "../core/paths.js";
36
- import { getTaskHistory, openStateDatabase, queryTaskHistory, upsertTaskHistory } from "../core/state-db.js";
36
+ import { getTaskHistory, queryTaskHistory, upsertTaskHistory, withStateDb } from "../core/state-db.js";
37
37
  import { error } from "../core/warn.js";
38
38
  import { requireAgentProfile, runAgent } from "../integrations/agent/index.js";
39
39
  import { resolveProcessAgentProfile } from "../integrations/agent/config.js";
@@ -460,8 +460,7 @@ function persistRunLog(input) {
460
460
  // ── history ─────────────────────────────────────────────────────────────────
461
461
  function appendHistory(result) {
462
462
  try {
463
- const db = openStateDatabase();
464
- try {
463
+ withStateDb((db) => {
465
464
  upsertTaskHistory(db, {
466
465
  task_id: result.id,
467
466
  status: result.status,
@@ -477,10 +476,7 @@ function appendHistory(result) {
477
476
  profile: result.target.kind === "prompt" ? result.target.profile : undefined,
478
477
  }),
479
478
  });
480
- }
481
- finally {
482
- db.close();
483
- }
479
+ });
484
480
  }
485
481
  catch (err) {
486
482
  rethrowIfTestIsolationError(err);
@@ -488,8 +484,7 @@ function appendHistory(result) {
488
484
  }
489
485
  }
490
486
  export function readTaskHistory(options = {}) {
491
- const db = openStateDatabase();
492
- try {
487
+ return withStateDb((db) => {
493
488
  let rows;
494
489
  if (options.id) {
495
490
  const row = getTaskHistory(db, options.id);
@@ -503,10 +498,7 @@ export function readTaskHistory(options = {}) {
503
498
  return rows.slice(0, options.limit);
504
499
  }
505
500
  return rows;
506
- }
507
- finally {
508
- db.close();
509
- }
501
+ });
510
502
  }
511
503
  /**
512
504
  * Convert a `TaskHistoryRow` from state.db back to a `TaskRunResult` shape
File without changes
package/dist/wiki/wiki.js CHANGED
@@ -224,6 +224,43 @@ function readSchemaDescription(wikiDir) {
224
224
  return undefined;
225
225
  }
226
226
  }
227
+ /**
228
+ * Load a wiki's `schema.md` body and frontmatter.
229
+ *
230
+ * Unlike {@link readSchemaDescription} (which returns only the frontmatter
231
+ * `description` for `listWikis` summaries), this returns the markdown **body**
232
+ * — everything after the closing `---` of the frontmatter — which is where the
233
+ * page contract, operations, and hard rules live. The body is the rulebook
234
+ * injected into the write-time prompt for wiki-page edits.
235
+ *
236
+ * Swallow-and-degrade like the existing reader: a missing file, an unresolvable
237
+ * wiki dir, or malformed content yields `{ body: "", frontmatter: {} }`. Never
238
+ * throws.
239
+ */
240
+ export function loadWikiSchema(stashRoot, name) {
241
+ const empty = { body: "", frontmatter: {} };
242
+ let wikiDir;
243
+ try {
244
+ wikiDir = resolveWikiDir(stashRoot, name);
245
+ }
246
+ catch {
247
+ return empty;
248
+ }
249
+ let raw;
250
+ try {
251
+ raw = fs.readFileSync(path.join(wikiDir, SCHEMA_MD), "utf8");
252
+ }
253
+ catch {
254
+ return empty;
255
+ }
256
+ try {
257
+ const parsed = parseFrontmatter(raw);
258
+ return { body: parsed.content, frontmatter: parsed.data };
259
+ }
260
+ catch {
261
+ return empty;
262
+ }
263
+ }
227
264
  function toIsoDate(ms) {
228
265
  return new Date(ms).toISOString();
229
266
  }
@@ -6,6 +6,7 @@ import path from "node:path";
6
6
  import { getWorkflowDbPath } from "../core/paths.js";
7
7
  import { openDatabase } from "../storage/database.js";
8
8
  import { runMigrations as runSqliteMigrations } from "../storage/engines/sqlite-migrations.js";
9
+ import { applyStandardPragmas } from "../storage/sqlite-pragmas.js";
9
10
  /**
10
11
  * workflow.db — Durable SQLite database for workflow run state.
11
12
  *
@@ -46,12 +47,10 @@ export function openWorkflowDatabase(dbPath = getWorkflowDbPath()) {
46
47
  fs.mkdirSync(dir, { recursive: true });
47
48
  }
48
49
  const db = openDatabase(dbPath);
49
- db.exec("PRAGMA journal_mode = WAL");
50
50
  // #589: 30 s busy timeout, matching index.db / state.db. Without it the
51
51
  // default is 0 ms, so any concurrent writer fails immediately with
52
- // SQLITE_BUSY.
53
- db.exec("PRAGMA busy_timeout = 30000");
54
- db.exec("PRAGMA foreign_keys = ON");
52
+ // SQLITE_BUSY. #628: journal_mode is configurable via AKM_SQLITE_JOURNAL_MODE.
53
+ applyStandardPragmas(db, { dataDir: dir });
55
54
  ensureBaseSchema(db);
56
55
  runMigrations(db);
57
56
  return db;
@@ -2,23 +2,16 @@
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 { randomUUID } from "node:crypto";
5
- import fs from "node:fs";
6
5
  import { parseAssetRef } from "../../core/asset/asset-ref.js";
7
6
  import { loadConfig } from "../../core/config/config.js";
8
7
  import { NotFoundError, UsageError } from "../../core/errors.js";
9
8
  import { appendEvent } from "../../core/events.js";
10
- import { getDbPath } from "../../core/paths.js";
11
- import { closeDatabase, openExistingDatabase } from "../../indexer/db/db.js";
12
- import { resolveSourceEntries } from "../../indexer/search/search-source.js";
13
- import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
14
- import { resolveAssetPath } from "../../sources/resolve.js";
15
9
  import { withWorkflowRunsRepo, } from "../../storage/repositories/workflow-runs-repository.js";
16
- import { formatWorkflowErrors } from "../authoring/authoring.js";
17
10
  import { getCurrentWorkflowScopeKey } from "../authoring/scope-key.js";
18
- import { parseWorkflow } from "../parser.js";
19
11
  import { validateStepSummary } from "../validate-summary.js";
20
12
  import { resolveAgentIdentity } from "./agent-identity.js";
21
13
  import { evaluateCheckin } from "./checkin.js";
14
+ import { loadWorkflowAsset, resolveWorkflowEntryId } from "./workflow-asset-loader.js";
22
15
  export async function startWorkflowRun(ref, params = {}, options) {
23
16
  const asset = await loadWorkflowAsset(ref);
24
17
  return withWorkflowRunsRepo(async (repo) => {
@@ -299,115 +292,6 @@ async function resolveRunSpecifier(repo, specifier, params) {
299
292
  const started = await startWorkflowRun(ref, params ?? {});
300
293
  return { run: readWorkflowRun(repo, started.run.id), autoStarted: true };
301
294
  }
302
- async function loadWorkflowAsset(ref) {
303
- const parsed = parseAssetRef(ref);
304
- if (parsed.type !== "workflow") {
305
- throw new UsageError(`Expected a workflow ref (workflow:<name>), got "${ref}".`);
306
- }
307
- const config = loadConfig();
308
- const allSources = resolveSourceEntries(undefined, config);
309
- const searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
310
- let assetPath;
311
- let sourcePath;
312
- for (const source of searchSources) {
313
- try {
314
- assetPath = await resolveAssetPath(source.path, "workflow", parsed.name);
315
- sourcePath = source.path;
316
- break;
317
- }
318
- catch {
319
- /* continue */
320
- }
321
- }
322
- if (!assetPath) {
323
- throw new NotFoundError(`Workflow not found for ref: workflow:${parsed.name}`);
324
- }
325
- const resolvedSourcePath = sourcePath ?? config.stashDir ?? assetPath;
326
- const fullRef = `${parsed.origin ? `${parsed.origin}//` : ""}workflow:${parsed.name}`;
327
- const cached = readWorkflowDocumentFromIndex(resolvedSourcePath, fullRef);
328
- const document = cached ?? loadWorkflowDocumentFromDisk(assetPath);
329
- return projectAsset(document, fullRef, assetPath, resolvedSourcePath);
330
- }
331
- function loadWorkflowDocumentFromDisk(assetPath) {
332
- const content = fs.readFileSync(assetPath, "utf8");
333
- const result = parseWorkflow(content, { path: assetPath });
334
- if (!result.ok) {
335
- throw new UsageError(formatWorkflowErrors(assetPath, result.errors));
336
- }
337
- return result.document;
338
- }
339
- function readWorkflowDocumentFromIndex(sourcePath, ref) {
340
- const dbPath = getDbPath();
341
- if (!fs.existsSync(dbPath))
342
- return null;
343
- const db = openExistingDatabase(dbPath);
344
- try {
345
- const parsed = parseAssetRef(ref);
346
- const entryKey = `${sourcePath}:${parsed.type}:${parsed.name}`;
347
- const row = db
348
- .prepare(`SELECT wd.document_json AS document_json
349
- FROM workflow_documents wd
350
- JOIN entries e ON e.id = wd.entry_id
351
- WHERE e.entry_type = 'workflow' AND e.entry_key = ?
352
- LIMIT 1`)
353
- .get(entryKey);
354
- if (!row)
355
- return null;
356
- try {
357
- return JSON.parse(row.document_json);
358
- }
359
- catch {
360
- return null;
361
- }
362
- }
363
- finally {
364
- closeDatabase(db);
365
- }
366
- }
367
- function projectAsset(doc, ref, assetPath, sourcePath) {
368
- return {
369
- ref,
370
- path: assetPath,
371
- sourcePath,
372
- title: doc.title,
373
- ...(doc.parameters
374
- ? {
375
- parameters: doc.parameters.map((p) => ({
376
- name: p.name,
377
- ...(p.description ? { description: p.description } : {}),
378
- })),
379
- }
380
- : {}),
381
- steps: doc.steps.map((s) => ({
382
- id: s.id,
383
- title: s.title,
384
- instructions: s.instructions.text,
385
- ...(s.completionCriteria ? { completionCriteria: s.completionCriteria.map((c) => c.text) } : {}),
386
- sequenceIndex: s.sequenceIndex,
387
- })),
388
- };
389
- }
390
- function resolveWorkflowEntryId(sourcePath, ref) {
391
- const dbPath = getDbPath();
392
- if (!fs.existsSync(dbPath))
393
- return null;
394
- const db = openExistingDatabase(dbPath);
395
- try {
396
- const parsed = parseAssetRef(ref);
397
- const entryKey = `${sourcePath}:${parsed.type}:${parsed.name}`;
398
- const row = db
399
- .prepare(`SELECT id
400
- FROM entries
401
- WHERE entry_type = 'workflow'
402
- AND entry_key = ?
403
- LIMIT 1`)
404
- .get(entryKey);
405
- return row?.id ?? null;
406
- }
407
- finally {
408
- closeDatabase(db);
409
- }
410
- }
411
295
  function readWorkflowRun(repo, runId) {
412
296
  const run = repo.getRunById(runId);
413
297
  if (!run) {
@@ -0,0 +1,125 @@
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 fs from "node:fs";
5
+ import { parseAssetRef } from "../../core/asset/asset-ref.js";
6
+ import { loadConfig } from "../../core/config/config.js";
7
+ import { NotFoundError, UsageError } from "../../core/errors.js";
8
+ import { getDbPath } from "../../core/paths.js";
9
+ import { resolveSourceEntries } from "../../indexer/search/search-source.js";
10
+ import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
11
+ import { resolveAssetPath } from "../../sources/resolve.js";
12
+ import { withIndexDb } from "../../storage/repositories/index-db.js";
13
+ import { formatWorkflowErrors } from "../authoring/authoring.js";
14
+ import { parseWorkflow } from "../parser.js";
15
+ /**
16
+ * Resolve a `workflow:<name>` ref to a fully-projected {@link WorkflowAsset}.
17
+ *
18
+ * Prefers the parsed document cached in `index.db` (fast path) and falls back to
19
+ * reading + parsing the source file from disk. Pure loading/parsing concern —
20
+ * extracted from the run repository so run orchestration no longer owns asset
21
+ * resolution.
22
+ */
23
+ export async function loadWorkflowAsset(ref) {
24
+ const parsed = parseAssetRef(ref);
25
+ if (parsed.type !== "workflow") {
26
+ throw new UsageError(`Expected a workflow ref (workflow:<name>), got "${ref}".`);
27
+ }
28
+ const config = loadConfig();
29
+ const allSources = resolveSourceEntries(undefined, config);
30
+ const searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
31
+ let assetPath;
32
+ let sourcePath;
33
+ for (const source of searchSources) {
34
+ try {
35
+ assetPath = await resolveAssetPath(source.path, "workflow", parsed.name);
36
+ sourcePath = source.path;
37
+ break;
38
+ }
39
+ catch {
40
+ /* continue */
41
+ }
42
+ }
43
+ if (!assetPath) {
44
+ throw new NotFoundError(`Workflow not found for ref: workflow:${parsed.name}`);
45
+ }
46
+ const resolvedSourcePath = sourcePath ?? config.stashDir ?? assetPath;
47
+ const fullRef = `${parsed.origin ? `${parsed.origin}//` : ""}workflow:${parsed.name}`;
48
+ const cached = readWorkflowDocumentFromIndex(resolvedSourcePath, fullRef);
49
+ const document = cached ?? loadWorkflowDocumentFromDisk(assetPath);
50
+ return projectAsset(document, fullRef, assetPath, resolvedSourcePath);
51
+ }
52
+ /**
53
+ * Resolve the `entries.id` for an indexed workflow, or null when the index
54
+ * database does not yet exist or has no matching entry.
55
+ */
56
+ export function resolveWorkflowEntryId(sourcePath, ref) {
57
+ if (!fs.existsSync(getDbPath()))
58
+ return null;
59
+ const parsed = parseAssetRef(ref);
60
+ const entryKey = `${sourcePath}:${parsed.type}:${parsed.name}`;
61
+ return withIndexDb((db) => {
62
+ const row = db
63
+ .prepare(`SELECT id
64
+ FROM entries
65
+ WHERE entry_type = 'workflow'
66
+ AND entry_key = ?
67
+ LIMIT 1`)
68
+ .get(entryKey);
69
+ return row?.id ?? null;
70
+ });
71
+ }
72
+ function loadWorkflowDocumentFromDisk(assetPath) {
73
+ const content = fs.readFileSync(assetPath, "utf8");
74
+ const result = parseWorkflow(content, { path: assetPath });
75
+ if (!result.ok) {
76
+ throw new UsageError(formatWorkflowErrors(assetPath, result.errors));
77
+ }
78
+ return result.document;
79
+ }
80
+ function readWorkflowDocumentFromIndex(sourcePath, ref) {
81
+ if (!fs.existsSync(getDbPath()))
82
+ return null;
83
+ const parsed = parseAssetRef(ref);
84
+ const entryKey = `${sourcePath}:${parsed.type}:${parsed.name}`;
85
+ return withIndexDb((db) => {
86
+ const row = db
87
+ .prepare(`SELECT wd.document_json AS document_json
88
+ FROM workflow_documents wd
89
+ JOIN entries e ON e.id = wd.entry_id
90
+ WHERE e.entry_type = 'workflow' AND e.entry_key = ?
91
+ LIMIT 1`)
92
+ .get(entryKey);
93
+ if (!row)
94
+ return null;
95
+ try {
96
+ return JSON.parse(row.document_json);
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ });
102
+ }
103
+ function projectAsset(doc, ref, assetPath, sourcePath) {
104
+ return {
105
+ ref,
106
+ path: assetPath,
107
+ sourcePath,
108
+ title: doc.title,
109
+ ...(doc.parameters
110
+ ? {
111
+ parameters: doc.parameters.map((p) => ({
112
+ name: p.name,
113
+ ...(p.description ? { description: p.description } : {}),
114
+ })),
115
+ }
116
+ : {}),
117
+ steps: doc.steps.map((s) => ({
118
+ id: s.id,
119
+ title: s.title,
120
+ instructions: s.instructions.text,
121
+ ...(s.completionCriteria ? { completionCriteria: s.completionCriteria.map((c) => c.text) } : {}),
122
+ sequenceIndex: s.sequenceIndex,
123
+ })),
124
+ };
125
+ }
@@ -16,14 +16,9 @@
16
16
  *
17
17
  * @module workflows/validate-summary
18
18
  */
19
+ import validateSummaryJudgePrompt from "../assets/prompts/validate-summary-judge.md" with { type: "text" };
19
20
  import { parseJsonResponse } from "../core/parse.js";
20
- const JUDGE_SYSTEM = "You are a strict completion auditor for a software workflow engine. " +
21
- "Given a step's completion criteria and a summary of the work an agent claims to have done, " +
22
- "judge whether the summary provides concrete evidence that EVERY criterion is satisfied. " +
23
- "Be skeptical: vague, hand-wavy, or unsubstantiated claims do NOT satisfy a criterion. " +
24
- 'Respond with ONLY a JSON object: {"complete": boolean, "missing": string[], "feedback": string}. ' +
25
- '"missing" lists the exact criteria that are not yet satisfied; "feedback" is a short directive ' +
26
- "telling the agent what to finish or fix. No prose, no markdown fences.";
21
+ const JUDGE_SYSTEM = validateSummaryJudgePrompt;
27
22
  function buildUserPrompt(input) {
28
23
  const criteria = input.completionCriteria.map((c, i) => `${i + 1}. ${c}`).join("\n");
29
24
  return [
@@ -63,7 +63,7 @@ Override: set `AKM_CACHE_DIR` or `XDG_CACHE_HOME`.
63
63
 
64
64
  | Path | Contents | Safe to delete? |
65
65
  |---|---|---|
66
- | `<stash>/` | All your asset files: agents, skills, commands, knowledge, workflows, memories, vaults, wikis, lessons | **No** — this is YOUR data |
66
+ | `<stash>/` | All your asset files: agents, skills, commands, knowledge, workflows, memories, env files, secrets, wikis, lessons, facts | **No** — this is YOUR data |
67
67
  | `<stash>/.akm/` | Hidden AKM metadata (v0.7 proposals, legacy runs) | Caution — check for pending proposals first |
68
68
 
69
69
  Override: set `AKM_STASH_DIR` (or configure `stashDir` in `config.json`).
@@ -130,7 +130,7 @@ An append-only log of every mutating action you perform with AKM. Events are sto
130
130
 
131
131
  ### 2. Proposals Table
132
132
 
133
- The proposal queue: pending, accepted, and rejected improvement proposals for your stash assets. Generated by `akm reflect` and the improve loop.
133
+ The proposal queue: pending, accepted, and rejected improvement proposals for your stash assets. Generated by `akm improve`, `akm propose`, and related proposal-producing flows.
134
134
 
135
135
  Contents:
136
136
  - Proposal UUID (primary key)
@@ -216,6 +216,7 @@ You can redirect any AKM directory to a custom path:
216
216
  |---|---|
217
217
  | `AKM_CONFIG_DIR` | Config directory (`~/.config/akm/`) |
218
218
  | `AKM_DATA_DIR` | Data directory (`~/.local/share/akm/`) |
219
+ | `AKM_SQLITE_JOURNAL_MODE` | SQLite journal mode: `WAL` (default), `DELETE`, or `TRUNCATE`. Use `DELETE`/`TRUNCATE` on network filesystems (NFS/SMB) where WAL is impossible. When left at the `WAL` default, akm auto-detects a network FS for the data dir and falls back to `DELETE`. |
219
220
  | `AKM_STATE_DIR` | State directory (`~/.local/state/akm/`) |
220
221
  | `AKM_CACHE_DIR` | Cache directory (`~/.cache/akm/`) |
221
222
  | `AKM_STASH_DIR` | Default stash directory (`~/akm/`) |
@@ -0,0 +1,39 @@
1
+ Migration notes for akm v0.9.0
2
+
3
+ This is the final 0.9.0 cut. If you were already running a 0.9.0 beta, the
4
+ main upgrade work is to align scripts, prompts, and stash layout with the
5
+ released command surface.
6
+
7
+ Key operator-facing changes:
8
+
9
+ - Node.js is supported again for the published CLI. Install with Bun, Node.js
10
+ >= 20.12, or the prebuilt binary.
11
+ - The legacy `vault` asset type and `akm vault ...` command family are gone.
12
+ Use `env:` for whole `.env` groups and `secret:` for a single sensitive
13
+ value.
14
+ - `akm-migrate-storage` still ships and still performs the non-destructive
15
+ `vaults/` -> `env/` copy for older stashes. Run it before indexing if you are
16
+ upgrading from a stash that still stores `.env` files only under `vaults/`.
17
+ - Proposal workflow is fully consolidated around `akm improve`, `akm propose`,
18
+ and `akm proposal ...`. Update any old `akm reflect`, `akm distill`,
19
+ `akm accept`, `akm reject`, or `akm proposals` usage.
20
+
21
+ Primary public command family for 0.9.0:
22
+
23
+ - `akm improve <ref> [--task "..."]`
24
+ - `akm propose <type> <name> (--task "..." | --file <path>)`
25
+ - `akm proposal list`
26
+ - `akm proposal show <id>`
27
+ - `akm proposal diff <id>`
28
+ - `akm proposal accept <id>`
29
+ - `akm proposal reject <id> --reason "..."`
30
+
31
+ Recommended post-upgrade checks:
32
+
33
+ - Run `akm help migrate 0.9.0` on every machine where the CLI is installed.
34
+ - Run `akm-migrate-storage --yes` once if the stash ever used `vaults/`.
35
+ - Rebuild the index with `akm index`.
36
+ - Review agent instructions and docs for old `vault`, `reflect`, and `distill`
37
+ examples.
38
+
39
+ Full changelog: https://github.com/itlackey/akm/blob/main/CHANGELOG.md
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-cli",
3
- "version": "0.9.0-beta.5",
3
+ "version": "0.9.0-beta.51",
4
4
  "type": "module",
5
5
  "description": "akm (Agent Knowledge Management) — A package manager for AI agent skills, commands, tools, and knowledge. Works with Claude Code, OpenCode, Cursor, and any AI coding assistant.",
6
6
  "keywords": [
@@ -46,28 +46,30 @@
46
46
  "docs/data-and-telemetry.md"
47
47
  ],
48
48
  "bin": {
49
- "akm": "dist/cli.js",
50
- "akm-migrate-storage": "dist/scripts/migrate-storage.js"
49
+ "akm": "dist/akm",
50
+ "akm-migrate-storage": "dist/akm-migrate-storage"
51
51
  },
52
52
  "scripts": {
53
- "preinstall": "node -e \"var ua=process.env.npm_config_user_agent||'';var major=parseInt((process.versions.node||'0').split('.')[0],10);if(process.versions.bun||ua.startsWith('bun/')||process.env.BUN_INSTALL||major>=20){process.exit(0)}console.error('\\n ERROR: akm-cli requires the Bun runtime (https://bun.sh), Node.js >= 20, or the prebuilt binary.\\n Install options:\\n 1. Bun: curl -fsSL https://bun.sh/install | bash && bun install -g akm-cli\\n 2. Binary: curl -fsSL https://github.com/itlackey/akm/releases/latest/download/install.sh | bash\\n');process.exit(1)\"",
54
- "build": "rm -rf dist && bun run tsc --project ./tsconfig.build.json && bun scripts/copy-assets.ts && bun scripts/fix-esm-extensions.ts",
53
+ "preinstall": "node -e \"var ua=process.env.npm_config_user_agent||'';var v=(process.versions.node||'0').split('.').map(function(n){return parseInt(n,10)||0});var ok=v[0]>20||(v[0]===20&&(v[1]>12||(v[1]===12&&v[2]>=0)));if(process.versions.bun||ua.startsWith('bun/')||process.env.BUN_INSTALL||ok){process.exit(0)}console.error('\\n ERROR: akm-cli requires the Bun runtime (https://bun.sh), Node.js >= 20.12, or the prebuilt binary.\\n Install options:\\n 1. Bun: curl -fsSL https://bun.sh/install | bash && bun install -g akm-cli\\n 2. Node: upgrade to Node.js 20.12 or newer (https://nodejs.org)\\n 3. Binary: curl -fsSL https://github.com/itlackey/akm/releases/latest/download/install.sh | bash\\n');process.exit(1)\"",
54
+ "build": "rm -rf dist && bun scripts/gen-config-schema.ts &&bun run tsc --project ./tsconfig.build.json && bun scripts/copy-assets.ts && bun scripts/fix-esm-extensions.ts",
55
55
  "check": "bun run lint && bunx tsc --noEmit && bun run test:unit && bun run test:integration",
56
56
  "check:fast": "bun run lint && bunx tsc --noEmit && bun run test:unit",
57
57
  "check:changed": "bun test tests/output-baseline.test.ts tests/integration/e2e.test.ts tests/stash-search.test.ts && bun run lint && bunx tsc --noEmit",
58
- "test": "bun test --parallel=${TEST_PARALLEL:-12} --timeout=30000 ./tests --path-ignore-patterns=tests/integration",
59
- "test:unit": "bun test --parallel=${TEST_PARALLEL:-12} --timeout=30000 ./tests --path-ignore-patterns=tests/integration",
60
- "test:integration": "bun test --parallel=${TEST_PARALLEL:-12} --timeout=30000 ./tests/integration ./tests/commands ./tests/workflows",
58
+ "sweep:tmp": "bun scripts/sweep-test-tmp.ts",
59
+ "test": "bash scripts/test-unit.sh",
60
+ "test:unit": "bash scripts/test-unit.sh",
61
+ "test:integration": "bun run sweep:tmp && bun test --isolate --timeout=30000 ./tests/integration ./tests/commands ./tests/workflows",
62
+ "test:unit:shard": "bun run sweep:tmp && bun test --isolate --timeout=30000 ./tests --path-ignore-patterns=tests/integration --shard=${SHARD:?set SHARD=k/N}",
63
+ "test:integration:shard": "bun run sweep:tmp && bun test --isolate --timeout=30000 ./tests/integration ./tests/commands ./tests/workflows --shard=${SHARD:?set SHARD=k/N}",
61
64
  "test:node-smoke": "bun scripts/node-smoke.ts",
62
65
  "test:node-compat": "AKM_NODE_COMPAT_TESTS=1 bun test --timeout=120000 tests/integration/node-compat.test.ts",
63
- "test:sharded": "bun test ./tests --shard=1/4 & bun test ./tests --shard=2/4 & bun test ./tests --shard=3/4 & bun test ./tests --shard=4/4 & wait",
64
66
  "test:time": "bun scripts/test-timing-report.ts",
65
67
  "lint:isolation": "bun scripts/lint-tests-isolation.ts",
66
68
  "lint:devto-posts": "bun scripts/lint-devto-posts.ts",
67
69
  "lint:devto-posts:fix": "bun scripts/lint-devto-posts.ts --fix",
68
70
  "publish:devto": "npx -y @sinedied/devto-cli push \"docs/posts/**/*.md\" --token \"$DEVTO_TOKEN\" --repo \"$GITHUB_REPOSITORY\" --branch \"${GITHUB_REF_NAME:-main}\" --reconcile",
69
71
  "release:check": "./tests/release-check.sh",
70
- "lint": "bunx biome check src/ tests/ && bun scripts/lint-tests-isolation.ts && bun scripts/lint-license-headers.ts && bun scripts/lint-runtime-boundary.ts",
72
+ "lint": "bunx biome check src/ tests/ && bun scripts/lint-tests-isolation.ts && bun scripts/lint-license-headers.ts && bun scripts/lint-runtime-boundary.ts && bun scripts/lint-repository-sql.ts && bun scripts/gen-config-schema.ts --check",
71
73
  "lint:runtime-boundary": "bun scripts/lint-runtime-boundary.ts",
72
74
  "lint:tests-isolation": "bun scripts/lint-tests-isolation.ts",
73
75
  "lint:fix": "bunx biome check --write src/ tests/",
@@ -93,7 +95,7 @@
93
95
  },
94
96
  "engines": {
95
97
  "bun": ">=1.0.0",
96
- "node": ">=20.0.0"
98
+ "node": ">=20.12.0"
97
99
  },
98
100
  "dependencies": {
99
101
  "@clack/prompts": "^1.3.0",
@@ -1,23 +0,0 @@
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
- * CLI command surface for `akm db ...`.
6
- *
7
- * MVP scope: only `akm db backups` is exposed. It lists the pre-upgrade
8
- * snapshots written by `backupDataDir()` under `<dataDir>/backups/`.
9
- *
10
- * Restoration is intentionally NOT a CLI subcommand for MVP — operators are
11
- * expected to stop akm and use `scripts/migrations/restore-data-dir.sh` (or a
12
- * plain `mv`/`cp`) to recover. Keeping the surface narrow lets us evolve the
13
- * backup format under the hood without locking in an API.
14
- */
15
- import { getDataDir } from "../core/paths.js";
16
- import { listBackups } from "../indexer/db/db-backup.js";
17
- export function akmDbBackups() {
18
- const dataDir = getDataDir();
19
- return {
20
- dataDir,
21
- backups: listBackups(dataDir),
22
- };
23
- }