akm-cli 0.7.5 → 0.8.0-rc.11

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 (300) hide show
  1. package/{.github/CHANGELOG.md → CHANGELOG.md} +192 -2
  2. package/README.md +22 -6
  3. package/SECURITY.md +93 -0
  4. package/dist/cli/config-migrate.js +144 -0
  5. package/dist/cli/config-validate.js +39 -0
  6. package/dist/cli/confirm.js +73 -0
  7. package/dist/cli/parse-args.js +133 -0
  8. package/dist/cli/shared.js +129 -0
  9. package/dist/cli.js +2569 -1449
  10. package/dist/commands/add-cli.js +279 -0
  11. package/dist/commands/agent-dispatch.js +110 -0
  12. package/dist/commands/agent-support.js +68 -0
  13. package/dist/commands/completions.js +3 -0
  14. package/dist/commands/config-cli.js +130 -534
  15. package/dist/commands/consolidate.js +2122 -0
  16. package/dist/commands/curate.js +44 -3
  17. package/dist/commands/db-cli.js +23 -0
  18. package/dist/commands/distill-promotion-policy.js +660 -0
  19. package/dist/commands/distill.js +1075 -77
  20. package/dist/commands/env.js +213 -0
  21. package/dist/commands/eval-cases.js +43 -0
  22. package/dist/commands/events.js +5 -23
  23. package/dist/commands/extract-cli.js +127 -0
  24. package/dist/commands/extract-prompt.js +204 -0
  25. package/dist/commands/extract.js +477 -0
  26. package/dist/commands/feedback-cli.js +331 -0
  27. package/dist/commands/graph.js +477 -0
  28. package/dist/commands/health.js +1302 -0
  29. package/dist/commands/help/help-accept.md +12 -0
  30. package/dist/commands/help/help-improve.md +69 -0
  31. package/dist/commands/help/help-proposals.md +18 -0
  32. package/dist/commands/help/help-propose.md +17 -0
  33. package/dist/commands/help/help-reject.md +11 -0
  34. package/dist/commands/history.js +54 -46
  35. package/dist/commands/improve-auto-accept.js +97 -0
  36. package/dist/commands/improve-cli.js +217 -0
  37. package/dist/commands/improve-profiles.js +166 -0
  38. package/dist/commands/improve-result-file.js +167 -0
  39. package/dist/commands/improve.js +2373 -0
  40. package/dist/commands/info.js +5 -2
  41. package/dist/commands/init.js +50 -2
  42. package/dist/commands/installed-stashes.js +102 -139
  43. package/dist/commands/knowledge.js +136 -0
  44. package/dist/commands/lint/agent-linter.js +49 -0
  45. package/dist/commands/lint/base-linter.js +479 -0
  46. package/dist/commands/lint/command-linter.js +49 -0
  47. package/dist/commands/lint/default-linter.js +16 -0
  48. package/dist/commands/lint/env-key-rules.js +154 -0
  49. package/dist/commands/lint/index.js +196 -0
  50. package/dist/commands/lint/knowledge-linter.js +16 -0
  51. package/dist/commands/lint/markdown-insertion.js +343 -0
  52. package/dist/commands/lint/memory-linter.js +61 -0
  53. package/dist/commands/lint/registry.js +36 -0
  54. package/dist/commands/lint/skill-linter.js +45 -0
  55. package/dist/commands/lint/task-linter.js +50 -0
  56. package/dist/commands/lint/types.js +4 -0
  57. package/dist/commands/lint/workflow-linter.js +56 -0
  58. package/dist/commands/lint.js +4 -0
  59. package/dist/commands/migration-help.js +5 -2
  60. package/dist/commands/proposal.js +67 -12
  61. package/dist/commands/propose.js +86 -31
  62. package/dist/commands/reflect.js +1091 -73
  63. package/dist/commands/registry-cli.js +150 -0
  64. package/dist/commands/registry-search.js +5 -2
  65. package/dist/commands/remember-cli.js +257 -0
  66. package/dist/commands/remember.js +69 -6
  67. package/dist/commands/schema-repair.js +203 -0
  68. package/dist/commands/search.js +115 -14
  69. package/dist/commands/secret.js +173 -0
  70. package/dist/commands/self-update.js +3 -0
  71. package/dist/commands/show.js +148 -25
  72. package/dist/commands/source-add.js +17 -45
  73. package/dist/commands/source-clone.js +3 -0
  74. package/dist/commands/source-manage.js +14 -19
  75. package/dist/commands/tasks.js +437 -0
  76. package/dist/commands/url-checker.js +42 -0
  77. package/dist/core/action-contributors.js +28 -0
  78. package/dist/core/asset-ref.js +17 -2
  79. package/dist/core/asset-registry.js +12 -17
  80. package/dist/core/asset-serialize.js +88 -0
  81. package/dist/core/asset-spec.js +67 -1
  82. package/dist/core/common.js +182 -0
  83. package/dist/core/concurrent.js +25 -0
  84. package/dist/core/config-io.js +347 -0
  85. package/dist/core/config-migration.js +622 -0
  86. package/dist/core/config-schema.js +534 -0
  87. package/dist/core/config-sources.js +108 -0
  88. package/dist/core/config-types.js +4 -0
  89. package/dist/core/config-walker.js +337 -0
  90. package/dist/core/config.js +364 -981
  91. package/dist/core/errors.js +42 -20
  92. package/dist/core/events.js +91 -138
  93. package/dist/core/file-lock.js +104 -0
  94. package/dist/core/frontmatter.js +75 -8
  95. package/dist/core/lesson-lint.js +3 -0
  96. package/dist/core/markdown.js +20 -0
  97. package/dist/core/memory-belief.js +62 -0
  98. package/dist/core/memory-contradiction-detect.js +274 -0
  99. package/dist/core/memory-improve.js +806 -0
  100. package/dist/core/parse.js +158 -0
  101. package/dist/core/paths.js +280 -14
  102. package/dist/core/proposal-quality-validators.js +380 -0
  103. package/dist/core/proposal-validators.js +69 -0
  104. package/dist/core/proposals.js +512 -42
  105. package/dist/core/state-db.js +1068 -0
  106. package/dist/core/text-truncation.js +107 -0
  107. package/dist/core/time.js +54 -0
  108. package/dist/core/tty.js +59 -0
  109. package/dist/core/warn.js +64 -1
  110. package/dist/core/write-source.js +3 -0
  111. package/dist/indexer/db-backup.js +391 -0
  112. package/dist/indexer/db-search.js +178 -256
  113. package/dist/indexer/db.js +975 -103
  114. package/dist/indexer/ensure-index.js +64 -0
  115. package/dist/indexer/file-context.js +3 -0
  116. package/dist/indexer/graph-boost.js +376 -101
  117. package/dist/indexer/graph-db.js +391 -0
  118. package/dist/indexer/graph-dedup.js +95 -0
  119. package/dist/indexer/graph-extraction.js +550 -124
  120. package/dist/indexer/index-context.js +4 -0
  121. package/dist/indexer/indexer.js +523 -301
  122. package/dist/indexer/llm-cache.js +52 -0
  123. package/dist/indexer/manifest.js +3 -0
  124. package/dist/indexer/matchers.js +167 -160
  125. package/dist/indexer/memory-inference.js +152 -74
  126. package/dist/indexer/metadata-contributors.js +29 -0
  127. package/dist/indexer/metadata.js +275 -196
  128. package/dist/indexer/path-resolver.js +92 -0
  129. package/dist/indexer/project-context.js +192 -0
  130. package/dist/indexer/ranking-contributors.js +331 -0
  131. package/dist/indexer/ranking.js +81 -0
  132. package/dist/indexer/search-fields.js +5 -9
  133. package/dist/indexer/search-hit-enrichers.js +111 -0
  134. package/dist/indexer/search-source.js +44 -10
  135. package/dist/indexer/semantic-status.js +6 -17
  136. package/dist/indexer/staleness-detect.js +447 -0
  137. package/dist/indexer/usage-events.js +12 -9
  138. package/dist/indexer/walker.js +28 -0
  139. package/dist/integrations/agent/builders.js +135 -0
  140. package/dist/integrations/agent/config.js +122 -230
  141. package/dist/integrations/agent/detect.js +3 -0
  142. package/dist/integrations/agent/index.js +7 -13
  143. package/dist/integrations/agent/model-aliases.js +55 -0
  144. package/dist/integrations/agent/profiles.js +70 -5
  145. package/dist/integrations/agent/prompts.js +214 -80
  146. package/dist/integrations/agent/runner.js +151 -0
  147. package/dist/integrations/agent/sdk-runner.js +126 -0
  148. package/dist/integrations/agent/spawn.js +118 -23
  149. package/dist/integrations/github.js +3 -0
  150. package/dist/integrations/lockfile.js +32 -69
  151. package/dist/integrations/session-logs/index.js +69 -0
  152. package/dist/integrations/session-logs/inline-refs.js +35 -0
  153. package/dist/integrations/session-logs/pre-filter.js +152 -0
  154. package/dist/integrations/session-logs/providers/claude-code.js +282 -0
  155. package/dist/integrations/session-logs/providers/opencode.js +258 -0
  156. package/dist/integrations/session-logs/types.js +4 -0
  157. package/dist/llm/call-ai.js +62 -0
  158. package/dist/llm/client.js +77 -124
  159. package/dist/llm/embedder.js +20 -29
  160. package/dist/llm/embedders/cache.js +3 -7
  161. package/dist/llm/embedders/local.js +42 -1
  162. package/dist/llm/embedders/remote.js +20 -8
  163. package/dist/llm/embedders/types.js +3 -7
  164. package/dist/llm/feature-gate.js +95 -48
  165. package/dist/llm/graph-extract.js +676 -70
  166. package/dist/llm/index-passes.js +44 -29
  167. package/dist/llm/memory-infer.js +77 -71
  168. package/dist/llm/metadata-enhance.js +42 -29
  169. package/dist/llm/prompts/extract-session.md +80 -0
  170. package/dist/llm/prompts/graph-extract-user-prompt.md +35 -0
  171. package/dist/output/cli-hints-full.md +292 -0
  172. package/dist/output/cli-hints-short.md +66 -0
  173. package/dist/output/cli-hints.js +7 -320
  174. package/dist/output/context.js +60 -8
  175. package/dist/output/renderers.js +300 -257
  176. package/dist/output/shapes/curate.js +56 -0
  177. package/dist/output/shapes/distill.js +10 -0
  178. package/dist/output/shapes/env-list.js +19 -0
  179. package/dist/output/shapes/events.js +11 -0
  180. package/dist/output/shapes/helpers.js +424 -0
  181. package/dist/output/shapes/history.js +7 -0
  182. package/dist/output/shapes/passthrough.js +102 -0
  183. package/dist/output/shapes/proposal-accept.js +7 -0
  184. package/dist/output/shapes/proposal-diff.js +7 -0
  185. package/dist/output/shapes/proposal-list.js +7 -0
  186. package/dist/output/shapes/proposal-producer.js +11 -0
  187. package/dist/output/shapes/proposal-reject.js +7 -0
  188. package/dist/output/shapes/proposal-show.js +7 -0
  189. package/dist/output/shapes/registry-search.js +6 -0
  190. package/dist/output/shapes/registry.js +30 -0
  191. package/dist/output/shapes/search.js +6 -0
  192. package/dist/output/shapes/secret-list.js +19 -0
  193. package/dist/output/shapes/show.js +6 -0
  194. package/dist/output/shapes/vault-list.js +19 -0
  195. package/dist/output/shapes.js +51 -516
  196. package/dist/output/text/add.js +6 -0
  197. package/dist/output/text/clone.js +6 -0
  198. package/dist/output/text/config.js +6 -0
  199. package/dist/output/text/curate.js +6 -0
  200. package/dist/output/text/distill.js +7 -0
  201. package/dist/output/text/enable-disable.js +7 -0
  202. package/dist/output/text/events.js +10 -0
  203. package/dist/output/text/feedback.js +6 -0
  204. package/dist/output/text/helpers.js +1039 -0
  205. package/dist/output/text/history.js +7 -0
  206. package/dist/output/text/import.js +6 -0
  207. package/dist/output/text/index.js +6 -0
  208. package/dist/output/text/info.js +6 -0
  209. package/dist/output/text/init.js +6 -0
  210. package/dist/output/text/list.js +6 -0
  211. package/dist/output/text/proposal-producer.js +8 -0
  212. package/dist/output/text/proposal.js +11 -0
  213. package/dist/output/text/registry-commands.js +11 -0
  214. package/dist/output/text/registry.js +30 -0
  215. package/dist/output/text/remember.js +6 -0
  216. package/dist/output/text/remove.js +6 -0
  217. package/dist/output/text/save.js +6 -0
  218. package/dist/output/text/search.js +6 -0
  219. package/dist/output/text/show.js +6 -0
  220. package/dist/output/text/update.js +6 -0
  221. package/dist/output/text/upgrade.js +6 -0
  222. package/dist/output/text/vault.js +16 -0
  223. package/dist/output/text/wiki.js +15 -0
  224. package/dist/output/text/workflow.js +14 -0
  225. package/dist/output/text.js +44 -1092
  226. package/dist/registry/build-index.js +3 -0
  227. package/dist/registry/create-provider-registry.js +3 -0
  228. package/dist/registry/factory.js +4 -1
  229. package/dist/registry/origin-resolve.js +3 -0
  230. package/dist/registry/providers/index.js +3 -0
  231. package/dist/registry/providers/skills-sh.js +71 -50
  232. package/dist/registry/providers/static-index.js +53 -48
  233. package/dist/registry/providers/types.js +3 -24
  234. package/dist/registry/resolve.js +11 -16
  235. package/dist/registry/types.js +3 -0
  236. package/dist/scripts/migrate-storage.js +17750 -0
  237. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +9031 -0
  238. package/dist/scripts/migrations/v16-to-v17.js +141 -0
  239. package/dist/setup/detect.js +3 -0
  240. package/dist/setup/ripgrep-install.js +3 -0
  241. package/dist/setup/ripgrep-resolve.js +3 -0
  242. package/dist/setup/setup.js +775 -37
  243. package/dist/setup/steps.js +3 -15
  244. package/dist/sources/include.js +3 -0
  245. package/dist/sources/provider-factory.js +5 -12
  246. package/dist/sources/provider.js +3 -20
  247. package/dist/sources/providers/filesystem.js +19 -23
  248. package/dist/sources/providers/git.js +138 -21
  249. package/dist/sources/providers/index.js +3 -0
  250. package/dist/sources/providers/install-types.js +3 -13
  251. package/dist/sources/providers/npm.js +3 -4
  252. package/dist/sources/providers/provider-utils.js +3 -0
  253. package/dist/sources/providers/sync-from-ref.js +3 -11
  254. package/dist/sources/providers/tar-utils.js +3 -0
  255. package/dist/sources/providers/website.js +18 -22
  256. package/dist/sources/resolve.js +3 -0
  257. package/dist/sources/types.js +3 -0
  258. package/dist/sources/website-ingest.js +7 -0
  259. package/dist/tasks/backends/cron.js +203 -0
  260. package/dist/tasks/backends/exec-utils.js +28 -0
  261. package/dist/tasks/backends/index.js +24 -0
  262. package/dist/tasks/backends/launchd-template.xml +19 -0
  263. package/dist/tasks/backends/launchd.js +187 -0
  264. package/dist/tasks/backends/schtasks-template.xml +29 -0
  265. package/dist/tasks/backends/schtasks.js +215 -0
  266. package/dist/tasks/parser.js +211 -0
  267. package/dist/tasks/resolveAkmBin.js +87 -0
  268. package/dist/tasks/runner.js +458 -0
  269. package/dist/tasks/schedule.js +227 -0
  270. package/dist/tasks/schema.js +15 -0
  271. package/dist/tasks/validator.js +62 -0
  272. package/dist/version.js +3 -0
  273. package/dist/wiki/index-template.md +12 -0
  274. package/dist/wiki/ingest-workflow-template.md +54 -0
  275. package/dist/wiki/log-template.md +8 -0
  276. package/dist/wiki/schema-template.md +61 -0
  277. package/dist/wiki/wiki-templates.js +15 -0
  278. package/dist/wiki/wiki.js +13 -61
  279. package/dist/workflows/authoring.js +8 -25
  280. package/dist/workflows/cli.js +3 -0
  281. package/dist/workflows/db.js +140 -10
  282. package/dist/workflows/document-cache.js +3 -10
  283. package/dist/workflows/parser.js +3 -0
  284. package/dist/workflows/renderer.js +11 -3
  285. package/dist/workflows/runs.js +77 -92
  286. package/dist/workflows/schema.js +3 -0
  287. package/dist/workflows/scope-key.js +3 -0
  288. package/dist/workflows/validator.js +4 -8
  289. package/dist/workflows/workflow-template.md +24 -0
  290. package/docs/README.md +10 -2
  291. package/docs/data-and-telemetry.md +225 -0
  292. package/docs/migration/release-notes/0.7.0.md +1 -1
  293. package/docs/migration/release-notes/0.7.5.md +2 -2
  294. package/docs/migration/release-notes/0.8.0.md +48 -0
  295. package/docs/migration/v0.7-to-v0.8.md +1307 -0
  296. package/package.json +30 -12
  297. package/.github/LICENSE +0 -374
  298. package/dist/commands/install-audit.js +0 -381
  299. package/dist/commands/vault.js +0 -328
  300. package/dist/templates/wiki-templates.js +0 -100
@@ -1,3 +1,6 @@
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/.
1
4
  import { randomUUID } from "node:crypto";
2
5
  import fs from "node:fs";
3
6
  import { parseAssetRef } from "../core/asset-ref";
@@ -13,64 +16,72 @@ import { formatWorkflowErrors } from "./authoring";
13
16
  import { closeWorkflowDatabase, openWorkflowDatabase } from "./db";
14
17
  import { parseWorkflow } from "./parser";
15
18
  import { getCurrentWorkflowScopeKey } from "./scope-key";
16
- export async function startWorkflowRun(ref, params = {}) {
17
- const asset = await loadWorkflowAsset(ref);
18
- const workflowDb = openWorkflowDatabase();
19
+ async function withWorkflowDb(fn) {
20
+ const db = openWorkflowDatabase();
19
21
  try {
22
+ return await Promise.resolve(fn(db));
23
+ }
24
+ finally {
25
+ closeWorkflowDatabase(db);
26
+ }
27
+ }
28
+ export async function startWorkflowRun(ref, params = {}, options) {
29
+ const asset = await loadWorkflowAsset(ref);
30
+ return withWorkflowDb(async (db) => {
20
31
  const now = new Date().toISOString();
21
32
  const runId = randomUUID();
22
33
  const scopeKey = getCurrentWorkflowScopeKey();
23
34
  const currentStepId = asset.steps[0]?.id ?? null;
24
35
  const workflowEntryId = resolveWorkflowEntryId(asset.sourcePath, asset.ref);
25
- workflowDb.transaction(() => {
26
- workflowDb
27
- .prepare(`INSERT INTO workflow_runs (
36
+ // Concurrency guard (#485): if an active run already exists in this
37
+ // (workflow_ref, scope_key) pair, refuse to create a parallel run unless
38
+ // `force: true` is set. Previously every call inserted unconditionally,
39
+ // so two terminals running `akm workflow start <ref>` left two runs
40
+ // racing; `akm workflow next` then non-deterministically picked one.
41
+ if (!options?.force) {
42
+ const existing = db
43
+ .prepare("SELECT id, current_step_id FROM workflow_runs WHERE workflow_ref = ? AND scope_key = ? AND status = 'active' ORDER BY updated_at DESC LIMIT 1")
44
+ .get(asset.ref, scopeKey);
45
+ if (existing) {
46
+ throw new UsageError(`Workflow ${asset.ref} already has an active run in this scope (id=${existing.id}, step=${existing.current_step_id ?? "—"}). ` +
47
+ `Use 'akm workflow next ${asset.ref}' to resume it, 'akm workflow abandon ${existing.id}' to give up on it, or pass --force to start a parallel run.`, "RESOURCE_ALREADY_EXISTS");
48
+ }
49
+ }
50
+ db.transaction(() => {
51
+ db.prepare(`INSERT INTO workflow_runs (
28
52
  id, workflow_ref, scope_key, workflow_entry_id, workflow_title, status, params_json, current_step_id, created_at, updated_at
29
- ) VALUES (?, ?, ?, ?, ?, 'active', ?, ?, ?, ?)`)
30
- .run(runId, asset.ref, scopeKey, workflowEntryId, asset.title, JSON.stringify(params), currentStepId, now, now);
31
- const insertStep = workflowDb.prepare(`INSERT INTO workflow_run_steps (
53
+ ) VALUES (?, ?, ?, ?, ?, 'active', ?, ?, ?, ?)`).run(runId, asset.ref, scopeKey, workflowEntryId, asset.title, JSON.stringify(params), currentStepId, now, now);
54
+ const insertStep = db.prepare(`INSERT INTO workflow_run_steps (
32
55
  run_id, step_id, step_title, instructions, completion_json, sequence_index, status
33
56
  ) VALUES (?, ?, ?, ?, ?, ?, 'pending')`);
34
57
  for (const step of asset.steps) {
35
58
  insertStep.run(runId, step.id, step.title, step.instructions, step.completionCriteria ? JSON.stringify(step.completionCriteria) : null, step.sequenceIndex ?? 0);
36
59
  }
37
60
  })();
38
- const result = getWorkflowStatus(runId);
61
+ const result = await getWorkflowStatus(runId);
39
62
  appendEvent({
40
63
  eventType: "workflow_started",
41
64
  ref: ref,
42
65
  metadata: { runId: result.run.id, title: result.run.workflowTitle },
43
66
  });
44
67
  return result;
45
- }
46
- finally {
47
- closeWorkflowDatabase(workflowDb);
48
- }
68
+ });
49
69
  }
50
- export function getWorkflowStatus(runId) {
51
- const workflowDb = openWorkflowDatabase();
52
- try {
53
- const run = readWorkflowRun(workflowDb, runId);
54
- const steps = readWorkflowRunSteps(workflowDb, run.id);
70
+ export async function getWorkflowStatus(runId) {
71
+ return withWorkflowDb((db) => {
72
+ const run = readWorkflowRun(db, runId);
73
+ const steps = readWorkflowRunSteps(db, run.id);
55
74
  return buildWorkflowRunDetail(run, steps);
56
- }
57
- finally {
58
- closeWorkflowDatabase(workflowDb);
59
- }
75
+ });
60
76
  }
61
- export function hasWorkflowRun(runId) {
62
- const workflowDb = openWorkflowDatabase();
63
- try {
64
- const row = workflowDb.prepare("SELECT 1 FROM workflow_runs WHERE id = ? LIMIT 1").get(runId);
77
+ export async function hasWorkflowRun(runId) {
78
+ return withWorkflowDb((db) => {
79
+ const row = db.prepare("SELECT 1 FROM workflow_runs WHERE id = ? LIMIT 1").get(runId);
65
80
  return !!row;
66
- }
67
- finally {
68
- closeWorkflowDatabase(workflowDb);
69
- }
81
+ });
70
82
  }
71
- export function listWorkflowRuns(input) {
72
- const workflowDb = openWorkflowDatabase();
73
- try {
83
+ export async function listWorkflowRuns(input) {
84
+ return withWorkflowDb((db) => {
74
85
  const filters = [];
75
86
  const params = [];
76
87
  const scopeKey = getCurrentWorkflowScopeKey();
@@ -88,20 +99,16 @@ export function listWorkflowRuns(input) {
88
99
  filters.push("status IN ('active', 'blocked')");
89
100
  }
90
101
  const where = filters.length > 0 ? `WHERE ${filters.join(" AND ")}` : "";
91
- const rows = workflowDb
102
+ const rows = db
92
103
  .prepare(`SELECT * FROM workflow_runs ${where} ORDER BY updated_at DESC, created_at DESC`)
93
104
  .all(...params);
94
105
  return { runs: rows.map(toWorkflowRunSummary) };
95
- }
96
- finally {
97
- closeWorkflowDatabase(workflowDb);
98
- }
106
+ });
99
107
  }
100
108
  export async function getNextWorkflowStep(specifier, params) {
101
- const workflowDb = openWorkflowDatabase();
102
- try {
103
- const { run, autoStarted } = await resolveRunSpecifier(workflowDb, specifier, params);
104
- const steps = readWorkflowRunSteps(workflowDb, run.id);
109
+ return withWorkflowDb(async (db) => {
110
+ const { run, autoStarted } = await resolveRunSpecifier(db, specifier, params);
111
+ const steps = readWorkflowRunSteps(db, run.id);
105
112
  const currentStep = resolveCurrentStep(run, steps);
106
113
  const done = run.status === "completed" ? true : undefined;
107
114
  return {
@@ -115,54 +122,44 @@ export async function getNextWorkflowStep(specifier, params) {
115
122
  ...(done ? { done } : {}),
116
123
  ...(autoStarted ? { autoStarted } : {}),
117
124
  };
118
- }
119
- finally {
120
- closeWorkflowDatabase(workflowDb);
121
- }
125
+ });
122
126
  }
123
- export function resumeWorkflowRun(runId) {
124
- const workflowDb = openWorkflowDatabase();
125
- try {
126
- const run = readWorkflowRun(workflowDb, runId);
127
+ export async function resumeWorkflowRun(runId) {
128
+ return withWorkflowDb((db) => {
129
+ const run = readWorkflowRun(db, runId);
127
130
  if (run.status === "completed") {
128
131
  throw new UsageError(`Workflow run ${run.id} is already completed and cannot be resumed.`);
129
132
  }
130
133
  if (run.status === "active") {
131
- const steps = readWorkflowRunSteps(workflowDb, run.id);
134
+ const steps = readWorkflowRunSteps(db, run.id);
132
135
  return buildWorkflowRunDetail(run, steps);
133
136
  }
134
137
  // blocked or failed → flip back to active and re-open the current step so
135
138
  // it can be reclassified (completed, failed, skipped) after resuming.
136
139
  const now = new Date().toISOString();
137
- workflowDb.transaction(() => {
140
+ db.transaction(() => {
138
141
  if (run.current_step_id) {
139
- workflowDb
140
- .prepare(`UPDATE workflow_run_steps
142
+ db.prepare(`UPDATE workflow_run_steps
141
143
  SET status = 'pending', notes = NULL, evidence_json = NULL, completed_at = NULL
142
- WHERE run_id = ? AND step_id = ? AND status IN ('blocked', 'failed')`)
143
- .run(run.id, run.current_step_id);
144
+ WHERE run_id = ? AND step_id = ? AND status IN ('blocked', 'failed')`).run(run.id, run.current_step_id);
144
145
  }
145
- workflowDb.prepare("UPDATE workflow_runs SET status = 'active', updated_at = ? WHERE id = ?").run(now, run.id);
146
+ db.prepare("UPDATE workflow_runs SET status = 'active', updated_at = ? WHERE id = ?").run(now, run.id);
146
147
  })();
147
148
  const updated = { ...run, status: "active", updated_at: now };
148
- const steps = readWorkflowRunSteps(workflowDb, run.id);
149
+ const steps = readWorkflowRunSteps(db, run.id);
149
150
  return buildWorkflowRunDetail(updated, steps);
150
- }
151
- finally {
152
- closeWorkflowDatabase(workflowDb);
153
- }
151
+ });
154
152
  }
155
- export function completeWorkflowStep(input) {
156
- const workflowDb = openWorkflowDatabase();
157
- try {
153
+ export async function completeWorkflowStep(input) {
154
+ return withWorkflowDb((db) => {
158
155
  let updatedRun;
159
156
  let refreshedSteps = [];
160
- workflowDb.transaction(() => {
161
- const run = readWorkflowRun(workflowDb, input.runId);
157
+ db.transaction(() => {
158
+ const run = readWorkflowRun(db, input.runId);
162
159
  if (run.status !== "active") {
163
160
  throw new UsageError(`Workflow run ${run.id} is ${run.status} and cannot be updated.`);
164
161
  }
165
- const existing = workflowDb
162
+ const existing = db
166
163
  .prepare("SELECT * FROM workflow_run_steps WHERE run_id = ? AND step_id = ?")
167
164
  .get(run.id, input.stepId);
168
165
  if (!existing) {
@@ -175,18 +172,14 @@ export function completeWorkflowStep(input) {
175
172
  throw new UsageError(`Step "${input.stepId}" is not the current step for workflow run ${run.id}. Complete "${run.current_step_id}" first.`);
176
173
  }
177
174
  const completedAt = new Date().toISOString();
178
- workflowDb
179
- .prepare(`UPDATE workflow_run_steps
175
+ db.prepare(`UPDATE workflow_run_steps
180
176
  SET status = ?, notes = ?, evidence_json = ?, completed_at = ?
181
- WHERE run_id = ? AND step_id = ?`)
182
- .run(input.status, input.notes?.trim() || null, input.evidence ? JSON.stringify(input.evidence) : null, completedAt, run.id, input.stepId);
183
- refreshedSteps = readWorkflowRunSteps(workflowDb, run.id);
177
+ WHERE run_id = ? AND step_id = ?`).run(input.status, input.notes?.trim() || null, input.evidence ? JSON.stringify(input.evidence) : null, completedAt, run.id, input.stepId);
178
+ refreshedSteps = readWorkflowRunSteps(db, run.id);
184
179
  const state = deriveRunState(refreshedSteps);
185
- workflowDb
186
- .prepare(`UPDATE workflow_runs
180
+ db.prepare(`UPDATE workflow_runs
187
181
  SET status = ?, current_step_id = ?, updated_at = ?, completed_at = ?
188
- WHERE id = ?`)
189
- .run(state.status, state.currentStepId, completedAt, state.completedAt, run.id);
182
+ WHERE id = ?`).run(state.status, state.currentStepId, completedAt, state.completedAt, run.id);
190
183
  updatedRun = {
191
184
  ...run,
192
185
  status: state.status,
@@ -205,10 +198,7 @@ export function completeWorkflowStep(input) {
205
198
  appendEvent({ eventType: "workflow_finished", ref: detail.run.workflowRef, metadata: { runId: input.runId } });
206
199
  }
207
200
  return detail;
208
- }
209
- finally {
210
- closeWorkflowDatabase(workflowDb);
211
- }
201
+ });
212
202
  }
213
203
  async function resolveRunSpecifier(db, specifier, params) {
214
204
  const explicitRun = db.prepare("SELECT * FROM workflow_runs WHERE id = ?").get(specifier);
@@ -262,7 +252,7 @@ async function loadWorkflowAsset(ref) {
262
252
  if (!assetPath) {
263
253
  throw new NotFoundError(`Workflow not found for ref: workflow:${parsed.name}`);
264
254
  }
265
- const resolvedSourcePath = sourcePath ?? loadConfig().stashDir ?? assetPath;
255
+ const resolvedSourcePath = sourcePath ?? config.stashDir ?? assetPath;
266
256
  const fullRef = `${parsed.origin ? `${parsed.origin}//` : ""}workflow:${parsed.name}`;
267
257
  const cached = readWorkflowDocumentFromIndex(resolvedSourcePath, fullRef);
268
258
  const document = cached ?? loadWorkflowDocumentFromDisk(assetPath);
@@ -452,18 +442,13 @@ function parseJsonArray(value) {
452
442
  }
453
443
  return undefined;
454
444
  }
455
- export function getActiveWorkflowRun(scopeKey = getCurrentWorkflowScopeKey()) {
456
- try {
457
- const workflowDb = openWorkflowDatabase();
458
- const row = workflowDb
445
+ export async function getActiveWorkflowRun(scopeKey = getCurrentWorkflowScopeKey()) {
446
+ return withWorkflowDb((db) => {
447
+ const row = db
459
448
  .query("SELECT id, current_step_id, workflow_ref FROM workflow_runs WHERE scope_key = ? AND status IN ('active', 'blocked') ORDER BY updated_at DESC LIMIT 1")
460
449
  .get(scopeKey);
461
- closeWorkflowDatabase(workflowDb);
462
450
  if (!row)
463
451
  return null;
464
452
  return { runId: row.id, stepId: row.current_step_id, workflowRef: row.workflow_ref };
465
- }
466
- catch {
467
- return null; // fail-open: never crash show output due to DB error
468
- }
453
+ }).catch(() => null); // fail-open: never crash show output due to DB error
469
454
  }
@@ -1,3 +1,6 @@
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/.
1
4
  /**
2
5
  * Validated JSON shape for a workflow asset.
3
6
  *
@@ -1,3 +1,6 @@
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/.
1
4
  import { createHash } from "node:crypto";
2
5
  import fs from "node:fs";
3
6
  import path from "node:path";
@@ -1,12 +1,8 @@
1
- /**
2
- * Cross-cutting semantic checks over an assembled WorkflowDocument draft.
3
- *
4
- * The parser handles per-line shape checks; this module runs rules that need
5
- * the whole document or the raw frontmatter at once: duplicate step IDs,
6
- * step-id format, and the frontmatter key whitelist.
7
- */
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/.
8
4
  const STEP_ID_REGEX = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
9
- const ALLOWED_FRONTMATTER_KEYS = new Set(["description", "tags", "params"]);
5
+ const ALLOWED_FRONTMATTER_KEYS = new Set(["description", "tags", "params", "name", "updated"]);
10
6
  export function runSemanticChecks(draft, frontmatterData, frontmatterEndLine, errors) {
11
7
  checkFrontmatterKeys(frontmatterData, frontmatterEndLine, errors);
12
8
  checkStepIdFormat(draft, errors);
@@ -0,0 +1,24 @@
1
+ ---
2
+ description: Describe what this workflow accomplishes
3
+ tags:
4
+ - example
5
+ params:
6
+ example_param: Explain this parameter
7
+ ---
8
+
9
+ # Workflow: {{TITLE}}
10
+
11
+ ## Step: {{FIRST_STEP_TITLE}}
12
+ Step ID: {{FIRST_STEP_ID}}
13
+
14
+ ### Instructions
15
+ Describe what to do in this step.
16
+
17
+ ### Completion Criteria
18
+ - Confirm the first step is complete
19
+
20
+ ## Step: Second Step
21
+ Step ID: second-step
22
+
23
+ ### Instructions
24
+ Describe what happens next.
package/docs/README.md CHANGED
@@ -10,8 +10,9 @@
10
10
 
11
11
  ## Upgrading
12
12
 
13
+ - [Roadmap](roadmap.md) -- High-level focus for the 0.9 and 1.0 releases
13
14
  - [v1 migration guide](migration/v1.md) -- The path from 0.x to v1.0, including the `.stash.json` removal scheduled for v0.8.0
14
- - [Release notes (latest: 0.7.0)](migration/release-notes/0.7.0.md) -- Per-release notes drop into `migration/release-notes/`, including current pre-release removals
15
+ - [Release notes (latest: 0.8.0)](migration/release-notes/0.8.0.md) -- Per-release notes drop into `migration/release-notes/`, including current pre-release removals
15
16
  - [v0.5 → v0.6 migration guide](migration/v0.5-to-v0.6.md) -- Every breaking change with before/after code, publisher checklist, and troubleshooting
16
17
 
17
18
  ## Reference
@@ -28,17 +29,24 @@
28
29
  - [itlackey/akm-plugins](https://github.com/itlackey/akm-plugins) -- optional integrations for tools like OpenCode
29
30
  - [itlackey/akm-bench](https://github.com/itlackey/akm-bench) -- the standalone benchmark and evaluation repo for akm
30
31
 
32
+ ## Operations
33
+
34
+ - Analyzing `akm improve` runs -- use [`akm health`](../src/commands/health.ts) (0.8.0+): `--since`, `--detail per-run`, `--window-compare`, `--windows`. See [health-command-enhancements.md](technical/health-command-enhancements.md).
35
+
31
36
  ## Internals
32
37
 
33
38
  - [Search](technical/search.md) -- Hybrid search architecture and scoring
34
39
  - [Indexing](technical/indexing.md) -- How the search index is built
35
40
  - [Classification](technical/classification.md) -- Matcher and renderer behavior
41
+ - [Functional Contract Patterns](technical/functional-contract-patterns.md) -- Quick reference for contributor pipelines and small process contracts
42
+ - [Implementation Plan: Functional Contract Refactor](technical/implementation-plan-functional-contract-refactor.md) -- Phased plan to move behavior from type-centric switchboards to process-local contributors
43
+ - [Architecture Cleanup Checklist](technical/architecture-cleanup-checklist.md) -- Living checklist for executing the cleanup plan with parity gates, reviews, and git hygiene
36
44
  - [Show Response](technical/show-response.md) -- `akm show` output fields by asset type
37
45
  - [Testing Workflow](technical/testing-workflow.md) -- End-to-end, Docker, deployment, and upgrade validation
38
46
  - [Ref Format](technical/ref.md) -- Wire format for asset references
39
47
  - [Test Coverage Guide](technical/test-coverage-guide.md) -- High-value testing areas
40
48
  - [Core Principles](technical/akm-core-principles.md) -- Design principles and constraints
41
- - [akm-bench](technical/benchmark.md) -- Search-quality benchmark suite
49
+ - `technical/benchmark.md` (planned) -- Search-quality benchmark suite
42
50
 
43
51
  ## Posts
44
52
 
@@ -0,0 +1,225 @@
1
+ # AKM Data & Telemetry
2
+
3
+ AKM stores data locally on your machine. **It has no remote telemetry.** No data is sent to Anthropic, the AKM project, or any third party. This document describes exactly what AKM reads and writes on your machine.
4
+
5
+ ## No Remote Data Collection
6
+
7
+ AKM does not:
8
+ - Send usage data, events, or crash reports to any server
9
+ - Contact any AKM-operated endpoint at runtime (only your own configured LLM/embedding endpoints)
10
+ - Include any analytics SDK or beacon
11
+ - Collect email, name, or any personally-identifying information
12
+
13
+ The only network requests AKM makes are:
14
+ 1. Fetching registry metadata and stash packages from sources you explicitly configure (GitHub, npm, websites)
15
+ 2. Calls to your configured LLM/embedding endpoint (if you enabled those features)
16
+ 3. `akm upgrade` — fetches the latest release from GitHub releases
17
+ 4. `akm setup` — a single DNS lookup for `github.com` to decide whether to skip network-dependent steps (Ollama detection, remote embedding probes) when offline. No HTTP request is made by this probe; if it succeeds, akm proceeds with the network-dependent steps you already configured.
18
+
19
+ ---
20
+
21
+ ## Local On-Disk Surface
22
+
23
+ AKM writes to these locations on your machine. All paths follow [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/latest/) conventions on Linux/macOS and Windows conventions on Windows.
24
+
25
+ ### Config Directory (`$XDG_CONFIG_HOME/akm` or `~/.config/akm/`)
26
+
27
+ | Path | Contents | Safe to delete? |
28
+ |---|---|---|
29
+ | `config.json` | Your AKM configuration: LLM endpoints, stash paths, feature flags, profiles | **No** — deleting resets all settings |
30
+
31
+ Override: set `AKM_CONFIG_DIR` or `XDG_CONFIG_HOME`.
32
+
33
+ ### Data Directory (`$XDG_DATA_HOME/akm` or `~/.local/share/akm/`)
34
+
35
+ | Path | Contents | Safe to delete? |
36
+ |---|---|---|
37
+ | `index.db` | Search index for all your stash assets (FTS5 + metadata) | Yes — rebuilds via `akm index --full` |
38
+ | `workflow.db` | Workflow run state and history | Caution — deletes run history |
39
+ | `state.db` | Events, proposals, task history, improve run results | **No** — deletes event log, proposal queue, improve history |
40
+ | `akm.lock` | Inter-process write lock | Yes — recreated automatically |
41
+ | `akm.lock.lck` | Lock write sentinel | Yes — recreated automatically |
42
+
43
+ Override: set `AKM_DATA_DIR` or `XDG_DATA_HOME`.
44
+
45
+ ### Cache Directory (`$XDG_CACHE_HOME/akm` or `~/.cache/akm/`)
46
+
47
+ Everything in the cache is regenerable. It is safe to delete the entire cache directory; AKM will recreate what it needs on next use.
48
+
49
+ | Path | Contents | Safe to delete? |
50
+ |---|---|---|
51
+ | `config-backups/config-<timestamp>.json` | Pre-migration config snapshots (5 retained) | Yes |
52
+ | `config-backups/config.latest.json` | Latest backup alias | Yes |
53
+ | `registry/` | Downloaded registry tarballs (stash packages from npm, GitHub, etc.) | Yes — re-downloaded on next `akm add` or `akm update` |
54
+ | `registry-index/` | Legacy per-URL JSON cache (v0.7 artifact) | Yes — fully replaced by `index.db` in 0.8.0 |
55
+ | `semantic-status.json` | Semantic index build status marker | Yes |
56
+ | `bin/` | Downloaded AKM binary cache (used by `akm upgrade`) | Yes |
57
+ | `tasks/logs/` | Scheduled task log files | Yes — ephemeral logs |
58
+ | `tasks/history/` | Legacy task history JSONL (v0.7 migration artifact) | Yes |
59
+
60
+ Override: set `AKM_CACHE_DIR` or `XDG_CACHE_HOME`.
61
+
62
+ ### Stash Directory (`~/akm/` by default, or user-configured)
63
+
64
+ | Path | Contents | Safe to delete? |
65
+ |---|---|---|
66
+ | `<stash>/` | All your asset files: agents, skills, commands, knowledge, workflows, memories, vaults, wikis, lessons | **No** — this is YOUR data |
67
+ | `<stash>/.akm/` | Hidden AKM metadata (v0.7 proposals, legacy runs) | Caution — check for pending proposals first |
68
+
69
+ Override: set `AKM_STASH_DIR` (or configure `stashDir` in `config.json`).
70
+
71
+ ---
72
+
73
+ ## What Is Stored in `state.db`
74
+
75
+ `state.db` holds three categories of non-regenerable data:
76
+
77
+ ### 1. Events Table
78
+
79
+ An append-only log of every mutating action you perform with AKM. Events are stored locally for self-improvement (the improve loop uses them to surface usage patterns) and for inspection via `akm events`.
80
+
81
+ **What is recorded:**
82
+ - `event_type` — what action was taken (see full list below)
83
+ - `ts` — ISO-8601 UTC timestamp
84
+ - `ref` — the asset ref affected (e.g. `skill:code-review`), if applicable
85
+ - `metadata` — structured payload specific to the event type (e.g. query text for `search`, score for `feedback`)
86
+
87
+ **What is NOT recorded:**
88
+ - File contents
89
+ - LLM prompts or responses
90
+ - API keys or secrets (config is not stored in events)
91
+ - Personal information
92
+
93
+ **Retention:** Events older than 90 days are purged automatically when `akm improve` runs its maintenance pass. Purge is controlled by `purgeOldEvents()` with a 90-day default.
94
+
95
+ **Full event type list:**
96
+
97
+ | Event type | When emitted | Key metadata fields |
98
+ |---|---|---|
99
+ | `add` | `akm add <source>` | `ref`, `provider` |
100
+ | `remove` | `akm remove <source>` | `ref` |
101
+ | `update` | `akm update [source]` | `ref` |
102
+ | `remember` | `akm remember <text>` | `ref` |
103
+ | `import` | `akm import <file>` | `ref` |
104
+ | `save` | `akm save <ref>` | `ref` |
105
+ | `feedback` | `akm feedback <ref>` | `signal` (positive/negative) |
106
+ | `search` | `akm search <query>` | `query`, `source`, `signal` |
107
+ | `curate` | `akm curate <prompt>` | `query`, `source` |
108
+ | `show` | `akm show <ref>` | `ref`, `type`, `name` |
109
+ | `select` | `akm show` after a search returning the same ref | `ref`, `entryId` |
110
+ | `promoted` | `akm proposal accept <id>` | `ref` |
111
+ | `rejected` | `akm proposal reject <id>` | `ref` |
112
+ | `reflect_invoked` | Start of reflect phase in `akm improve` | `ref`, profile |
113
+ | `reflect_completed` | Reflect phase produced a proposal | `ref` |
114
+ | `improve_reflect_outcome` | Per-asset reflect result | `ref`, `ok`, `durationMs`, `reason` |
115
+ | `propose_invoked` | `akm propose` | `ref` |
116
+ | `distill_invoked` | `akm distill` | |
117
+ | `improve_skipped` | Asset skipped by cooldown or budget | `ref`, `reason` |
118
+ | `improve_completed` | `akm improve` run finished | run stats |
119
+ | `improve_failed` | `akm improve` run errored | error |
120
+ | `improve_lock_recovered` | Stale lock cleared at startup | |
121
+ | `proposal_orphan_purge` | Stale proposals pruned | `checked`, `rejected` |
122
+ | `proposal_creation_rejected` | `createProposal()` validation failed | `ref`, `reason`, `source` |
123
+ | `proposal_expired` | Proposal expired | `ref` |
124
+ | `events_purged` | Old events deleted by maintenance | `purgedCount`, `retentionDays` |
125
+ | `workflow_started` | `akm workflow start <ref>` | `ref`, `runId` |
126
+ | `workflow_step_completed` | `akm workflow next` | `ref`, `runId`, `stepId` |
127
+ | `workflow_finished` | `akm workflow complete` | `ref`, `runId` |
128
+ | `schema_repair_invoked` | `akm lint --repair` triggered schema repair | `ref` |
129
+ | `archive_cleanup` | Archive cleanup during consolidation | |
130
+
131
+ ### 2. Proposals Table
132
+
133
+ The proposal queue: pending, accepted, and rejected improvement proposals for your stash assets. Generated by `akm reflect` and the improve loop.
134
+
135
+ Contents:
136
+ - Proposal UUID (primary key)
137
+ - Target asset ref
138
+ - Status (pending/accepted/rejected)
139
+ - Source (which process generated it — e.g. `reflect`, `distill`)
140
+ - Full proposal content (Markdown text)
141
+ - Created/updated timestamps
142
+
143
+ ### 3. Task History Table
144
+
145
+ A record of scheduled task runs (from `akm tasks`):
146
+ - Task ID, status, start/end times
147
+ - Log file path (the log content stays in `$CACHE/tasks/logs/`)
148
+
149
+ ---
150
+
151
+ ## How to Inspect and Clear Local Data
152
+
153
+ ### Inspect events
154
+
155
+ ```sh
156
+ # List recent events
157
+ akm events list
158
+
159
+ # Stream live events (tail)
160
+ akm events tail
161
+
162
+ # Filter by type
163
+ akm events list --type search --limit 20
164
+
165
+ # Filter by asset ref
166
+ akm events list --ref skill:code-review
167
+ ```
168
+
169
+ ### Inspect proposals
170
+
171
+ ```sh
172
+ # List pending proposals
173
+ akm proposals
174
+
175
+ # Show a specific proposal
176
+ akm proposals show <id>
177
+ ```
178
+
179
+ ### Clear specific data
180
+
181
+ ```sh
182
+ # Delete the search index (safe — rebuilds with akm index --full)
183
+ rm ~/.local/share/akm/index.db
184
+
185
+ # Delete all cached registry downloads
186
+ rm -rf ~/.cache/akm/registry/
187
+
188
+ # Delete config backups
189
+ rm -rf ~/.cache/akm/config-backups/
190
+
191
+ # Delete the events log from state.db (non-reversible)
192
+ # There is no akm CLI command to do this directly in 0.8.0.
193
+ # Use SQLite directly:
194
+ sqlite3 ~/.local/share/akm/state.db "DELETE FROM events;"
195
+
196
+ # Delete all proposals
197
+ sqlite3 ~/.local/share/akm/state.db "DELETE FROM proposals;"
198
+ ```
199
+
200
+ ### Start completely fresh (nuclear reset)
201
+
202
+ ```sh
203
+ rm -f ~/.config/akm/config.json
204
+ rm -rf ~/.local/share/akm/
205
+ rm -rf ~/.cache/akm/
206
+ # Your stash files in ~/akm/ are NOT touched by the above.
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Environment Variable Overrides
212
+
213
+ You can redirect any AKM directory to a custom path:
214
+
215
+ | Variable | Overrides |
216
+ |---|---|
217
+ | `AKM_CONFIG_DIR` | Config directory (`~/.config/akm/`) |
218
+ | `AKM_DATA_DIR` | Data directory (`~/.local/share/akm/`) |
219
+ | `AKM_STATE_DIR` | State directory (`~/.local/state/akm/`) |
220
+ | `AKM_CACHE_DIR` | Cache directory (`~/.cache/akm/`) |
221
+ | `AKM_STASH_DIR` | Default stash directory (`~/akm/`) |
222
+ | `XDG_CONFIG_HOME` | XDG base — akm appends `/akm` |
223
+ | `XDG_DATA_HOME` | XDG base — akm appends `/akm` |
224
+ | `XDG_STATE_HOME` | XDG base — akm appends `/akm` |
225
+ | `XDG_CACHE_HOME` | XDG base — akm appends `/akm` |
@@ -90,7 +90,7 @@ until the user opts in. Seven keys ship in 0.7.0:
90
90
  | `feedback_distillation` | `akm distill <ref>` |
91
91
  | `embedding_fallback_score` | scorer fallback when embeddings unavailable |
92
92
  | `memory_inference` | indexer split of pending memories into atomic facts |
93
- | `graph_extraction` | indexer entity/relation extraction → `graph.json` |
93
+ | `graph_extraction` | indexer entity/relation extraction → SQLite graph tables |
94
94
 
95
95
  Every gated call site uses `tryLlmFeature(feature, config, fn, fallback)`
96
96
  from `src/llm/feature-gate.ts`. The wrapper guarantees:
@@ -15,6 +15,6 @@ No manual migration is required for most users, but note these operator-facing d
15
15
 
16
16
  1. If you were relying on ref-based workflow runs being globally shared across repos or directories, that behavior is gone. Use direct run IDs when you intentionally need to resume a specific run created elsewhere.
17
17
  2. Existing older workflow runs created before the new workspace scope key was introduced are still accessible by direct run ID, but ref-based commands now prefer runs created in the current scope.
18
- 3. `akm help migrate latest` now resolves to 0.7.5 and uses the published `.github/CHANGELOG.md` path.
18
+ 3. `akm help migrate latest` now resolves to 0.7.5 and uses the published `CHANGELOG.md` path.
19
19
 
20
- Full changelog: https://github.com/itlackey/akm/blob/main/.github/CHANGELOG.md
20
+ Full changelog: https://github.com/itlackey/akm/blob/main/CHANGELOG.md