akm-cli 0.9.0-beta.9 → 0.9.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (325) hide show
  1. package/CHANGELOG.md +592 -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/help/help-improve.md +9 -6
  6. package/dist/assets/hints/cli-hints-full.md +6 -5
  7. package/dist/assets/profiles/default.json +9 -4
  8. package/dist/assets/profiles/frequent.json +1 -1
  9. package/dist/assets/profiles/memory-focus.json +1 -1
  10. package/dist/assets/profiles/proactive-maintenance.json +25 -0
  11. package/dist/assets/profiles/quick.json +1 -1
  12. package/dist/assets/profiles/recombine-only.json +21 -0
  13. package/dist/assets/profiles/reflect-distill.json +30 -0
  14. package/dist/assets/profiles/synthesize.json +15 -0
  15. package/dist/assets/profiles/thorough.json +1 -1
  16. package/dist/assets/prompts/consolidate-system.md +23 -0
  17. package/dist/assets/prompts/contradiction-judge.md +33 -0
  18. package/dist/assets/prompts/distill-knowledge-system.md +22 -0
  19. package/dist/assets/prompts/distill-lesson-system.md +36 -0
  20. package/dist/assets/prompts/extract-session.md +11 -3
  21. package/dist/assets/prompts/graph-extract-system.md +1 -0
  22. package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
  23. package/dist/assets/prompts/memory-infer-system.md +1 -0
  24. package/dist/assets/prompts/memory-infer-user.md +5 -0
  25. package/dist/assets/prompts/metadata-enhance-system.md +1 -0
  26. package/dist/assets/prompts/procedural-system.md +44 -0
  27. package/dist/assets/prompts/recombine-system.md +40 -0
  28. package/dist/assets/prompts/staleness-detect-system.md +6 -0
  29. package/dist/assets/prompts/validate-summary-judge.md +1 -0
  30. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
  31. package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
  32. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
  33. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
  34. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
  35. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
  36. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
  37. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
  38. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
  39. package/dist/assets/templates/html/health.html +281 -111
  40. package/dist/assets/wiki/ingest-workflow-template.md +45 -16
  41. package/dist/assets/wiki/schema-template.md +4 -4
  42. package/dist/cli/clack.js +56 -0
  43. package/dist/cli/config-migrate.js +7 -1
  44. package/dist/cli/confirm.js +1 -1
  45. package/dist/cli/parse-args.js +46 -1
  46. package/dist/cli/shared.js +28 -0
  47. package/dist/cli.js +25 -21
  48. package/dist/commands/agent/agent-dispatch.js +3 -2
  49. package/dist/commands/agent/agent-support.js +0 -7
  50. package/dist/commands/agent/contribute-cli.js +26 -7
  51. package/dist/commands/config-cli.js +26 -13
  52. package/dist/commands/env/child-env.js +47 -0
  53. package/dist/commands/env/env-cli.js +220 -227
  54. package/dist/commands/env/env.js +14 -67
  55. package/dist/commands/env/secret-cli.js +140 -138
  56. package/dist/commands/feedback-cli.js +156 -155
  57. package/dist/commands/graph/graph-cli.js +5 -13
  58. package/dist/commands/graph/graph.js +3 -3
  59. package/dist/commands/health/advisories.js +151 -0
  60. package/dist/commands/health/checks.js +103 -16
  61. package/dist/commands/health/html-report.js +447 -81
  62. package/dist/commands/health/improve-metrics.js +771 -0
  63. package/dist/commands/health/llm-usage.js +65 -0
  64. package/dist/commands/health/md-report.js +103 -0
  65. package/dist/commands/health/metrics.js +278 -0
  66. package/dist/commands/health/stash-exposure.js +46 -0
  67. package/dist/commands/health/surfaces.js +216 -0
  68. package/dist/commands/health/task-runs.js +135 -0
  69. package/dist/commands/health/types.js +26 -0
  70. package/dist/commands/health/windows.js +195 -0
  71. package/dist/commands/health.js +91 -1091
  72. package/dist/commands/improve/anti-collapse.js +170 -0
  73. package/dist/commands/improve/calibration.js +161 -0
  74. package/dist/commands/improve/collapse-detector.js +421 -0
  75. package/dist/commands/improve/consolidate/chunking.js +141 -0
  76. package/dist/commands/improve/consolidate/eligibility.js +64 -0
  77. package/dist/commands/improve/consolidate/merge.js +145 -0
  78. package/dist/commands/improve/consolidate/sanitize.js +231 -0
  79. package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
  80. package/dist/commands/improve/consolidate.js +1295 -1277
  81. package/dist/commands/improve/dedup.js +482 -0
  82. package/dist/commands/improve/distill/content-repair.js +202 -0
  83. package/dist/commands/improve/distill/promote-memory.js +229 -0
  84. package/dist/commands/improve/distill/quality-gate.js +236 -0
  85. package/dist/commands/improve/distill-guards.js +127 -0
  86. package/dist/commands/improve/distill-promotion-policy.js +826 -167
  87. package/dist/commands/improve/distill.js +228 -605
  88. package/dist/commands/improve/eligibility.js +434 -0
  89. package/dist/commands/improve/encoding-salience.js +205 -0
  90. package/dist/commands/improve/extract-cli.js +179 -59
  91. package/dist/commands/improve/extract-prompt.js +54 -3
  92. package/dist/commands/improve/extract-watch.js +140 -0
  93. package/dist/commands/improve/extract.js +409 -43
  94. package/dist/commands/improve/feedback-valence.js +54 -0
  95. package/dist/commands/improve/hot-probation.js +45 -0
  96. package/dist/commands/improve/improve-auto-accept.js +157 -10
  97. package/dist/commands/improve/improve-cli.js +115 -73
  98. package/dist/commands/improve/improve-profiles.js +28 -8
  99. package/dist/commands/improve/improve-result-file.js +15 -25
  100. package/dist/commands/improve/improve-session.js +58 -0
  101. package/dist/commands/improve/improve.js +485 -2764
  102. package/dist/commands/improve/locks.js +154 -0
  103. package/dist/commands/improve/loop-stages.js +1100 -0
  104. package/dist/commands/improve/memory/memory-belief.js +14 -15
  105. package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
  106. package/dist/commands/improve/memory/memory-improve.js +27 -27
  107. package/dist/commands/improve/outcome-loop.js +270 -0
  108. package/dist/commands/improve/preparation.js +2002 -0
  109. package/dist/commands/improve/proactive-maintenance.js +37 -35
  110. package/dist/commands/improve/procedural.js +398 -0
  111. package/dist/commands/improve/recombine.js +818 -0
  112. package/dist/commands/improve/reflect-noise.js +0 -0
  113. package/dist/commands/improve/reflect.js +206 -45
  114. package/dist/commands/improve/salience.js +455 -0
  115. package/dist/commands/improve/schema-similarity-gate.js +168 -0
  116. package/dist/commands/improve/shared.js +51 -0
  117. package/dist/commands/improve/triage.js +93 -0
  118. package/dist/commands/lint/agent-linter.js +19 -24
  119. package/dist/commands/lint/base-linter.js +173 -60
  120. package/dist/commands/lint/command-linter.js +19 -24
  121. package/dist/commands/lint/env-key-rules.js +38 -1
  122. package/dist/commands/lint/fact-linter.js +39 -0
  123. package/dist/commands/lint/index.js +31 -13
  124. package/dist/commands/lint/memory-linter.js +1 -1
  125. package/dist/commands/lint/registry.js +7 -2
  126. package/dist/commands/lint/task-linter.js +3 -3
  127. package/dist/commands/lint/workflow-linter.js +26 -1
  128. package/dist/commands/observability-cli.js +4 -4
  129. package/dist/commands/proposal/drain-policies.js +13 -4
  130. package/dist/commands/proposal/drain.js +45 -51
  131. package/dist/commands/proposal/legacy-import.js +115 -0
  132. package/dist/commands/proposal/proposal-cli.js +24 -34
  133. package/dist/commands/proposal/proposal.js +2 -1
  134. package/dist/commands/proposal/propose.js +8 -3
  135. package/dist/commands/proposal/repository.js +829 -0
  136. package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
  137. package/dist/commands/proposal/validators/proposals.js +93 -895
  138. package/dist/commands/read/curate.js +410 -111
  139. package/dist/commands/read/knowledge.js +10 -3
  140. package/dist/commands/read/remember-cli.js +133 -138
  141. package/dist/commands/read/search-cli.js +15 -8
  142. package/dist/commands/read/search.js +22 -11
  143. package/dist/commands/read/show.js +106 -14
  144. package/dist/commands/registry-cli.js +76 -87
  145. package/dist/commands/remember.js +11 -12
  146. package/dist/commands/sources/add-cli.js +91 -95
  147. package/dist/commands/sources/history.js +1 -1
  148. package/dist/commands/sources/init.js +66 -18
  149. package/dist/commands/sources/installed-stashes.js +11 -3
  150. package/dist/commands/sources/schema-repair.js +44 -46
  151. package/dist/commands/sources/self-update.js +2 -2
  152. package/dist/commands/sources/source-add.js +7 -3
  153. package/dist/commands/sources/sources-cli.js +3 -3
  154. package/dist/commands/sources/stash-cli.js +19 -39
  155. package/dist/commands/sources/stash-skeleton.js +57 -8
  156. package/dist/commands/tasks/default-tasks.js +15 -2
  157. package/dist/commands/tasks/tasks-cli.js +20 -29
  158. package/dist/commands/tasks/tasks.js +39 -11
  159. package/dist/commands/wiki-cli.js +23 -38
  160. package/dist/commands/workflow-cli.js +15 -1
  161. package/dist/core/asset/asset-registry.js +3 -1
  162. package/dist/core/asset/asset-spec.js +21 -4
  163. package/dist/core/asset/frontmatter.js +188 -167
  164. package/dist/core/asset/markdown.js +8 -0
  165. package/dist/core/authoring-rules.js +92 -0
  166. package/dist/core/common.js +4 -23
  167. package/dist/core/concurrent.js +10 -1
  168. package/dist/core/config/config-io.js +10 -1
  169. package/dist/core/config/config-migration.js +18 -40
  170. package/dist/core/config/config-schema.js +382 -62
  171. package/dist/core/config/config-types.js +3 -3
  172. package/dist/core/config/config.js +67 -22
  173. package/dist/core/deep-merge.js +38 -0
  174. package/dist/core/errors.js +1 -0
  175. package/dist/core/eval/rank-metrics.js +113 -0
  176. package/dist/core/events.js +4 -7
  177. package/dist/core/improve-types.js +47 -8
  178. package/dist/core/logs-db.js +14 -75
  179. package/dist/core/parse.js +36 -16
  180. package/dist/core/paths.js +18 -18
  181. package/dist/core/standards/resolve-standards-context.js +87 -0
  182. package/dist/core/standards/resolve-stash-standards.js +99 -0
  183. package/dist/core/standards/resolve-type-conventions.js +66 -0
  184. package/dist/core/state/migrations.js +770 -0
  185. package/dist/core/state-db.js +132 -1126
  186. package/dist/core/structured.js +69 -0
  187. package/dist/core/time.js +53 -0
  188. package/dist/core/warn.js +21 -0
  189. package/dist/core/write-source.js +37 -0
  190. package/dist/indexer/db/db.js +259 -769
  191. package/dist/indexer/db/entry-mapper.js +41 -0
  192. package/dist/indexer/db/graph-db.js +129 -86
  193. package/dist/indexer/db/llm-cache.js +2 -2
  194. package/dist/indexer/db/schema.js +516 -0
  195. package/dist/indexer/ensure-index.js +36 -92
  196. package/dist/indexer/feedback/utility-policy.js +75 -0
  197. package/dist/indexer/graph/graph-boost.js +51 -41
  198. package/dist/indexer/graph/graph-extraction.js +207 -4
  199. package/dist/indexer/index-writer-lock.js +18 -11
  200. package/dist/indexer/index-written-assets.js +105 -0
  201. package/dist/indexer/indexer.js +182 -204
  202. package/dist/indexer/passes/dir-staleness.js +114 -0
  203. package/dist/indexer/passes/memory-inference.js +13 -5
  204. package/dist/indexer/passes/metadata.js +20 -0
  205. package/dist/indexer/read-preflight.js +23 -0
  206. package/dist/indexer/search/db-search.js +89 -13
  207. package/dist/indexer/search/fts-query.js +51 -0
  208. package/dist/indexer/search/ranking-contributors.js +95 -9
  209. package/dist/indexer/search/ranking.js +79 -3
  210. package/dist/indexer/search/search-fields.js +6 -0
  211. package/dist/indexer/search/search-source.js +32 -21
  212. package/dist/indexer/search/semantic-status.js +4 -0
  213. package/dist/indexer/walk/matchers.js +9 -0
  214. package/dist/indexer/walk/walker.js +21 -13
  215. package/dist/integrations/agent/builders.js +39 -13
  216. package/dist/integrations/agent/config.js +20 -59
  217. package/dist/integrations/agent/detect.js +9 -0
  218. package/dist/integrations/agent/index.js +3 -19
  219. package/dist/integrations/agent/model-aliases.js +7 -2
  220. package/dist/integrations/agent/profiles.js +7 -1
  221. package/dist/integrations/agent/prompts.js +75 -9
  222. package/dist/integrations/agent/runner-dispatch.js +59 -0
  223. package/dist/integrations/agent/runner.js +13 -9
  224. package/dist/integrations/agent/spawn.js +69 -67
  225. package/dist/integrations/harnesses/claude/agent-builder.js +1 -1
  226. package/dist/integrations/harnesses/claude/index.js +2 -0
  227. package/dist/integrations/harnesses/claude/session-log.js +10 -0
  228. package/dist/integrations/harnesses/index.js +2 -3
  229. package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
  230. package/dist/integrations/harnesses/opencode/index.js +2 -0
  231. package/dist/integrations/harnesses/opencode/session-log.js +173 -3
  232. package/dist/integrations/harnesses/opencode-sdk/index.js +2 -2
  233. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +98 -17
  234. package/dist/integrations/harnesses/types.js +1 -0
  235. package/dist/integrations/session-logs/index.js +16 -0
  236. package/dist/llm/call-ai.js +2 -2
  237. package/dist/llm/client.js +34 -11
  238. package/dist/llm/embedder.js +67 -4
  239. package/dist/llm/embedders/cache.js +3 -1
  240. package/dist/llm/embedders/deterministic.js +66 -0
  241. package/dist/llm/embedders/local.js +73 -3
  242. package/dist/llm/feature-gate.js +16 -15
  243. package/dist/llm/graph-extract.js +67 -44
  244. package/dist/llm/memory-infer-impl.js +138 -0
  245. package/dist/llm/memory-infer.js +1 -127
  246. package/dist/llm/metadata-enhance.js +44 -31
  247. package/dist/llm/structured-call.js +49 -0
  248. package/dist/migrate-storage-node.mjs +8 -0
  249. package/dist/output/context.js +5 -5
  250. package/dist/output/renderers.js +85 -14
  251. package/dist/output/shapes/curate.js +14 -2
  252. package/dist/output/shapes/helpers.js +0 -3
  253. package/dist/output/shapes/passthrough.js +2 -1
  254. package/dist/output/text/helpers.js +29 -1
  255. package/dist/output/text/workflow.js +1 -0
  256. package/dist/registry/providers/skills-sh.js +21 -147
  257. package/dist/registry/providers/static-index.js +15 -157
  258. package/dist/registry/resolve.js +27 -9
  259. package/dist/runtime.js +25 -1
  260. package/dist/scripts/migrate-storage.js +2661 -2369
  261. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +883 -596
  262. package/dist/setup/detect.js +9 -0
  263. package/dist/setup/legacy-config.js +106 -0
  264. package/dist/setup/prompt.js +57 -0
  265. package/dist/setup/providers.js +14 -0
  266. package/dist/setup/registry-stash-loader.js +12 -0
  267. package/dist/setup/semantic-assets.js +124 -0
  268. package/dist/setup/setup.js +52 -1614
  269. package/dist/setup/steps/connection.js +734 -0
  270. package/dist/setup/steps/output.js +31 -0
  271. package/dist/setup/steps/platforms.js +124 -0
  272. package/dist/setup/steps/semantic.js +27 -0
  273. package/dist/setup/steps/sources.js +222 -0
  274. package/dist/setup/steps/stashdir.js +42 -0
  275. package/dist/setup/steps/tasks.js +152 -0
  276. package/dist/sources/include.js +6 -2
  277. package/dist/sources/providers/filesystem.js +0 -1
  278. package/dist/sources/providers/git-install.js +210 -0
  279. package/dist/sources/providers/git-provider.js +234 -0
  280. package/dist/sources/providers/git-stash.js +248 -0
  281. package/dist/sources/providers/git.js +10 -661
  282. package/dist/sources/providers/npm.js +2 -6
  283. package/dist/sources/providers/provider-utils.js +13 -7
  284. package/dist/sources/providers/sync-from-ref.js +9 -1
  285. package/dist/sources/providers/website.js +9 -5
  286. package/dist/sources/website-ingest.js +187 -29
  287. package/dist/sources/wiki-fetchers/registry.js +53 -0
  288. package/dist/sources/wiki-fetchers/youtube.js +239 -0
  289. package/dist/storage/database.js +45 -10
  290. package/dist/storage/managed-db.js +82 -0
  291. package/dist/storage/repositories/canaries-repository.js +107 -0
  292. package/dist/storage/repositories/consolidation-repository.js +38 -0
  293. package/dist/storage/repositories/embeddings-repository.js +72 -0
  294. package/dist/storage/repositories/events-repository.js +187 -0
  295. package/dist/storage/repositories/extract-sessions-repository.js +96 -0
  296. package/dist/storage/repositories/improve-runs-repository.js +146 -0
  297. package/dist/storage/repositories/index-db.js +14 -8
  298. package/dist/storage/repositories/proposals-repository.js +220 -0
  299. package/dist/storage/repositories/recombine-repository.js +213 -0
  300. package/dist/storage/repositories/registry-cache.js +93 -0
  301. package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
  302. package/dist/storage/repositories/task-history-repository.js +93 -0
  303. package/dist/storage/sqlite-pragmas.js +146 -0
  304. package/dist/tasks/backends/cron.js +1 -1
  305. package/dist/tasks/backends/index.js +9 -0
  306. package/dist/tasks/backends/launchd.js +1 -1
  307. package/dist/tasks/backends/schtasks.js +1 -1
  308. package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
  309. package/dist/tasks/runner.js +15 -13
  310. package/dist/text-import-hook.mjs +0 -0
  311. package/dist/wiki/wiki.js +52 -11
  312. package/dist/workflows/cli.js +1 -0
  313. package/dist/workflows/db.js +3 -4
  314. package/dist/workflows/runtime/runs.js +43 -118
  315. package/dist/workflows/runtime/workflow-asset-loader.js +125 -0
  316. package/dist/workflows/validate-summary.js +2 -7
  317. package/docs/README.md +69 -18
  318. package/docs/data-and-telemetry.md +5 -4
  319. package/docs/migration/release-notes/0.7.0.md +1 -1
  320. package/docs/migration/release-notes/0.9.0.md +39 -0
  321. package/package.json +10 -10
  322. package/dist/assets/tasks/core/update-stashes.yml +0 -4
  323. package/dist/commands/db-cli.js +0 -23
  324. package/dist/indexer/db/db-backup.js +0 -376
  325. package/dist/indexer/passes/staleness-detect.js +0 -488
@@ -33,13 +33,14 @@ 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 { 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";
40
40
  import { resolveRunner } from "../integrations/agent/runner.js";
41
41
  import { spawn } from "../runtime.js";
42
42
  import { resolveAssetPath } from "../sources/resolve.js";
43
+ import { getTaskHistory, queryTaskHistory, upsertTaskHistory } from "../storage/repositories/task-history-repository.js";
43
44
  import { startWorkflowRun } from "../workflows/runtime/runs.js";
44
45
  import { parseTaskDocument } from "./parser.js";
45
46
  export async function runTask(id, options = {}) {
@@ -131,6 +132,11 @@ async function runCommandTask(input) {
131
132
  stdout: "pipe",
132
133
  stderr: "pipe",
133
134
  cwd: process.env.HOME ?? "/tmp",
135
+ // Stamp task-runner provenance so any akm invocation in the command tree
136
+ // records usage events as machine traffic, not user demand (DRIFT-6).
137
+ // A more specific stamp already in the environment (e.g. improve's
138
+ // AKM_EVENT_SOURCE=improve on its child spawns) still wins in children.
139
+ env: { ...process.env, AKM_EVENT_SOURCE: process.env.AKM_EVENT_SOURCE ?? "task" },
134
140
  });
135
141
  let timer;
136
142
  let timedOut = false;
@@ -351,6 +357,10 @@ async function runPromptTask(input) {
351
357
  timeoutMs: agentTimeoutMs,
352
358
  cwd: stashDir,
353
359
  ...agentOptions,
360
+ // Stamp task-runner provenance for any akm invocation the agent makes
361
+ // (DRIFT-6: agent-task traffic must not be recorded as user demand).
362
+ // Caller-supplied env still wins on conflicts.
363
+ env: { AKM_EVENT_SOURCE: "task", ...agentOptions?.env },
354
364
  });
355
365
  const finishedAt = now();
356
366
  const log = renderPromptLog({ task, profileName: profile.name, result });
@@ -460,8 +470,7 @@ function persistRunLog(input) {
460
470
  // ── history ─────────────────────────────────────────────────────────────────
461
471
  function appendHistory(result) {
462
472
  try {
463
- const db = openStateDatabase();
464
- try {
473
+ withStateDb((db) => {
465
474
  upsertTaskHistory(db, {
466
475
  task_id: result.id,
467
476
  status: result.status,
@@ -477,10 +486,7 @@ function appendHistory(result) {
477
486
  profile: result.target.kind === "prompt" ? result.target.profile : undefined,
478
487
  }),
479
488
  });
480
- }
481
- finally {
482
- db.close();
483
- }
489
+ });
484
490
  }
485
491
  catch (err) {
486
492
  rethrowIfTestIsolationError(err);
@@ -488,8 +494,7 @@ function appendHistory(result) {
488
494
  }
489
495
  }
490
496
  export function readTaskHistory(options = {}) {
491
- const db = openStateDatabase();
492
- try {
497
+ return withStateDb((db) => {
493
498
  let rows;
494
499
  if (options.id) {
495
500
  const row = getTaskHistory(db, options.id);
@@ -503,10 +508,7 @@ export function readTaskHistory(options = {}) {
503
508
  return rows.slice(0, options.limit);
504
509
  }
505
510
  return rows;
506
- }
507
- finally {
508
- db.close();
509
- }
511
+ });
510
512
  }
511
513
  /**
512
514
  * Convert a `TaskHistoryRow` from state.db back to a `TaskRunResult` shape
File without changes
package/dist/wiki/wiki.js CHANGED
@@ -58,6 +58,8 @@ export const SCHEMA_MD = "schema.md";
58
58
  export const INDEX_MD = "index.md";
59
59
  export const LOG_MD = "log.md";
60
60
  export const RAW_SUBDIR = "raw";
61
+ /** Canonical location for agent-authored pages, mirroring RAW_SUBDIR. */
62
+ export const PAGES_SUBDIR = "pages";
61
63
  /** Files at a wiki root that are not pages. */
62
64
  const WIKI_SPECIAL_FILES = new Set([SCHEMA_MD, INDEX_MD, LOG_MD]);
63
65
  const WIKI_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
@@ -224,6 +226,43 @@ function readSchemaDescription(wikiDir) {
224
226
  return undefined;
225
227
  }
226
228
  }
229
+ /**
230
+ * Load a wiki's `schema.md` body and frontmatter.
231
+ *
232
+ * Unlike {@link readSchemaDescription} (which returns only the frontmatter
233
+ * `description` for `listWikis` summaries), this returns the markdown **body**
234
+ * — everything after the closing `---` of the frontmatter — which is where the
235
+ * page contract, operations, and hard rules live. The body is the rulebook
236
+ * injected into the write-time prompt for wiki-page edits.
237
+ *
238
+ * Swallow-and-degrade like the existing reader: a missing file, an unresolvable
239
+ * wiki dir, or malformed content yields `{ body: "", frontmatter: {} }`. Never
240
+ * throws.
241
+ */
242
+ export function loadWikiSchema(stashRoot, name) {
243
+ const empty = { body: "", frontmatter: {} };
244
+ let wikiDir;
245
+ try {
246
+ wikiDir = resolveWikiDir(stashRoot, name);
247
+ }
248
+ catch {
249
+ return empty;
250
+ }
251
+ let raw;
252
+ try {
253
+ raw = fs.readFileSync(path.join(wikiDir, SCHEMA_MD), "utf8");
254
+ }
255
+ catch {
256
+ return empty;
257
+ }
258
+ try {
259
+ const parsed = parseFrontmatter(raw);
260
+ return { body: parsed.content, frontmatter: parsed.data };
261
+ }
262
+ catch {
263
+ return empty;
264
+ }
265
+ }
227
266
  function toIsoDate(ms) {
228
267
  return new Date(ms).toISOString();
229
268
  }
@@ -369,18 +408,20 @@ export function createWiki(stashDir, name) {
369
408
  fs.writeFileSync(absPath, content, "utf8");
370
409
  created.push(absPath);
371
410
  }
372
- // Ensure raw/ exists with a .gitkeep so empty wikis survive clean clones.
373
- // Handle the dir-exists-but-no-.gitkeep case too (partial scaffolds,
411
+ // Ensure raw/ and pages/ exist with a .gitkeep so empty wikis survive clean
412
+ // clones. Handle the dir-exists-but-no-.gitkeep case too (partial scaffolds,
374
413
  // user-created directories) so the invariant always holds after `create`.
375
- const rawDir = path.join(wikiDir, RAW_SUBDIR);
376
- fs.mkdirSync(rawDir, { recursive: true });
377
- const gitkeepPath = path.join(rawDir, ".gitkeep");
378
- if (fs.existsSync(gitkeepPath)) {
379
- skipped.push(gitkeepPath);
380
- }
381
- else {
382
- fs.writeFileSync(gitkeepPath, "", "utf8");
383
- created.push(gitkeepPath);
414
+ for (const subdir of [RAW_SUBDIR, PAGES_SUBDIR]) {
415
+ const dir = path.join(wikiDir, subdir);
416
+ fs.mkdirSync(dir, { recursive: true });
417
+ const gitkeepPath = path.join(dir, ".gitkeep");
418
+ if (fs.existsSync(gitkeepPath)) {
419
+ skipped.push(gitkeepPath);
420
+ }
421
+ else {
422
+ fs.writeFileSync(gitkeepPath, "", "utf8");
423
+ created.push(gitkeepPath);
424
+ }
384
425
  }
385
426
  return { name, ref: `wiki:${name}`, path: wikiDir, created, skipped };
386
427
  }
@@ -17,6 +17,7 @@ export const WORKFLOW_SUBCOMMANDS = new Set([
17
17
  "create",
18
18
  "template",
19
19
  "resume",
20
+ "abandon",
20
21
  "validate",
21
22
  ]);
22
23
  export function parseWorkflowJsonObject(raw, flagName) {
@@ -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) => {
@@ -74,10 +67,15 @@ export async function startWorkflowRun(ref, params = {}, options) {
74
67
  })));
75
68
  });
76
69
  const result = await getWorkflowStatus(runId);
70
+ // 07 P1-B: emit only the run id + status — NOT the raw workflowTitle (which
71
+ // comes verbatim from the workflow asset's frontmatter and is therefore
72
+ // attacker-influenceable). Keeping raw titles out of the events stream
73
+ // shrinks the injectable footprint for any consumer that re-surfaces events
74
+ // into agent context.
77
75
  appendEvent({
78
76
  eventType: "workflow_started",
79
77
  ref: ref,
80
- metadata: { runId: result.run.id, title: result.run.workflowTitle },
78
+ metadata: { runId: result.run.id, status: result.run.status },
81
79
  });
82
80
  return result;
83
81
  });
@@ -164,6 +162,42 @@ export async function resumeWorkflowRun(runId) {
164
162
  return buildWorkflowRunDetail(updated, steps);
165
163
  });
166
164
  }
165
+ /**
166
+ * Give up on a run (08-F6): flip it to `failed` so it stops counting as
167
+ * active — the run-level verb the concurrency-guard message in
168
+ * {@link startWorkflowRun} advertises. Terminal-state runs are refused;
169
+ * {@link resumeWorkflowRun} can reopen an abandoned run if it was a mistake.
170
+ */
171
+ export async function abandonWorkflowRun(runId) {
172
+ return withWorkflowRunsRepo((repo) => {
173
+ const run = readWorkflowRun(repo, runId);
174
+ if (run.status === "completed" || run.status === "failed") {
175
+ throw new UsageError(`Workflow run ${run.id} is already ${run.status}.`);
176
+ }
177
+ const now = new Date().toISOString();
178
+ repo.updateRunState({
179
+ status: "failed",
180
+ currentStepId: run.current_step_id,
181
+ updatedAt: now,
182
+ completedAt: now,
183
+ checkinArmedAt: now,
184
+ runId: run.id,
185
+ });
186
+ const updated = {
187
+ ...run,
188
+ status: "failed",
189
+ updated_at: now,
190
+ completed_at: now,
191
+ checkin_armed_at: now,
192
+ };
193
+ const steps = readWorkflowRunSteps(repo, run.id);
194
+ const detail = buildWorkflowRunDetail(updated, steps);
195
+ // Same injectable-footprint rule as workflow_started (07 P1-B): ids and
196
+ // status only, never the frontmatter-derived title.
197
+ appendEvent({ eventType: "workflow_abandoned", ref: run.workflow_ref, metadata: { runId: run.id } });
198
+ return detail;
199
+ });
200
+ }
167
201
  export async function completeWorkflowStep(input) {
168
202
  // Read the step (read-only) up front so the LLM validation gate runs OUTSIDE
169
203
  // the write transaction — a slow/hung LLM must never hold a db write lock.
@@ -299,115 +333,6 @@ async function resolveRunSpecifier(repo, specifier, params) {
299
333
  const started = await startWorkflowRun(ref, params ?? {});
300
334
  return { run: readWorkflowRun(repo, started.run.id), autoStarted: true };
301
335
  }
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
336
  function readWorkflowRun(repo, runId) {
412
337
  const run = repo.getRunById(runId);
413
338
  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 [
package/docs/README.md CHANGED
@@ -4,50 +4,101 @@
4
4
 
5
5
  - [Concepts](concepts.md) -- Stashes, registries, asset types, and refs
6
6
  - [Getting Started](getting-started.md) -- Quick setup guide
7
+ - [Local Development](local-development.md) -- Dogfooding akm while editing its own source
7
8
  - [Agent Install Guide](agents/agent-install.md) -- Step-by-step automated install for agents
8
9
  - [Stash Maker's Guide](stash-makers.md) -- Build and share a stash on GitHub, npm, or a network directory
9
10
  - [Wikis](wikis.md) -- Multi-wiki knowledge bases (Karpathy-style)
10
11
 
12
+ ## Configuration & Data
13
+
14
+ - [Configuration](configuration.md) -- Providers, settings, and Ollama setup
15
+ - [Configuring Agent Profiles](configuration-agent-profiles.md) -- How akm runs a coding agent, CLI or API
16
+ - [Data & Telemetry](data-and-telemetry.md) -- Exactly what akm reads and writes on your machine (no remote telemetry)
17
+
18
+ ## Features
19
+
20
+ - [Workflows](features/workflows.md) -- Structured, resumable multi-step procedures
21
+ - [Search & Discovery](features/search-discovery.md) -- Finding assets without knowing their exact name
22
+ - [Knowledge Management](features/knowledge-management.md) -- Lessons, incidents, and research as first-class assets
23
+ - [Sources & Registries](features/sources-registries.md) -- Where assets come from and how to find more
24
+ - [Wiki Snapshot Fetchers](features/wiki-snapshot-fetchers.md) -- Pluggable fetchers for URL-based knowledge reads
25
+ - [Agent Integration](features/agent-integration.md) -- Wiring akm into any shell-capable coding agent
26
+ - [The Improvement Loop](features/improvement-loop.md) -- How the stash adapts from usage and feedback
27
+
11
28
  ## Upgrading
12
29
 
13
30
  - [Roadmap](roadmap.md) -- High-level focus for the 0.9 and 1.0 releases
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
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
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
31
+ - [v1 migration guide](migration/v1.md) -- The path from 0.x to v1.0
32
+ - [v0.8 -> v0.9 migration guide](migration/v0.8-to-v0.9.md) -- Current-cycle breaking changes
33
+ - [Release notes (latest: 0.9.0)](migration/release-notes/0.9.0.md) -- Per-release notes; see the [release-notes index](migration/release-notes/README.md) for every version
34
+ - [v0.5 -> v0.6 migration guide](migration/v0.5-to-v0.6.md) -- Every breaking change with before/after code, publisher checklist, and troubleshooting
17
35
 
18
36
  ## Reference
19
37
 
20
38
  - [CLI](cli.md) -- All `akm` commands and flags
21
39
  - [Registry](registry.md) -- Registries, search, hosting, and managing sources
22
- - [Configuration](configuration.md) -- Providers, settings, and Ollama setup
23
- - [Filesystem](technical/filesystem.md) -- Directory layout plus `.stash.json` deprecation and migration notes
40
+ - [akm-eval](akm-eval.md) -- Standalone toolkit for measuring whether `akm improve` is working
24
41
 
25
- ## Official Ecosystem Repositories
42
+ ## Agents
26
43
 
27
- - [itlackey/akm-stash](https://github.com/itlackey/akm-stash) -- the official onboarding stash with ready-made assets you can install with `akm add`
28
- - [itlackey/akm-registry](https://github.com/itlackey/akm-registry) -- the official registry index that powers built-in discovery
29
- - [itlackey/akm-plugins](https://github.com/itlackey/akm-plugins) -- optional integrations for tools like OpenCode
30
- - [itlackey/akm-bench](https://github.com/itlackey/akm-bench) -- the standalone benchmark and evaluation repo for akm
44
+ - [AGENTS.md](agents/AGENTS.md) -- The system-prompt reference agents load to use akm
45
+ - [Curate Workmap](agents/curate-workmap.md) -- Read before changing `akm curate` ranking or output
46
+
47
+ ## Architecture
48
+
49
+ - [Architecture](technical/architecture.md) -- How akm's sources, cache, index, and registries fit together
50
+ - [Runtime Boundary Design](architecture/runtime-boundary-design.md) -- Isolating `bun:sqlite`/`Bun.*` from the core
51
+ - [Brain Workflow (diagram)](architecture/brain-workflow.html) -- Visual map of the improve/self-learning loop
52
+
53
+ ## Example Stash
54
+
55
+ - [Example Stash](example-stash/README.md) -- A documentation-backed example stash showing how asset types fit together
56
+
57
+ ## Analysis
31
58
 
32
- ## Operations
59
+ - [Indexer Vertical Slice Refactor Plan](analysis/indexer-vertical-slice-refactor-plan.md)
60
+ - [Indexer Refactor Review (Expert Options)](analysis/indexer-refactor-expert-options.md)
33
61
 
34
- - Analyzing `akm improve` runs -- use [`akm health`](../src/commands/health.ts) (0.8.0+): `--since`, `--group-by run`, `--window-compare`, `--windows`. See [health-command-enhancements.md](technical/health-command-enhancements.md).
62
+ ## Design (unshipped work)
35
63
 
36
- ## Internals
64
+ - [Self-Improvement, Self-Learning & Memory Reference Index](design/self-improvement-learning-memory-reference-index.md) -- Master index for every unshipped improve/self-learning/memory design doc, with a subsystem-to-doc status table
37
65
 
66
+ Every doc under `docs/design/` must carry a `Status` / `Supersedes` / `Date` header (pre-existing docs are grandfathered until next touched). When a design ships, the shipping PR moves it to `docs/archive/` in the same PR.
67
+
68
+ ## Archive
69
+
70
+ - [Archive](archive/README.md) -- Design and implementation plans whose work has already shipped, retained as ADR-style records
71
+
72
+ ## Internals (technical/)
73
+
74
+ - [Filesystem](technical/filesystem.md) -- Directory layout plus `.stash.json` deprecation and migration notes
38
75
  - [Search](technical/search.md) -- Hybrid search architecture and scoring
39
76
  - [Indexing](technical/indexing.md) -- How the search index is built
40
77
  - [Classification](technical/classification.md) -- Matcher and renderer behavior
78
+ - [Storage Locations](technical/storage-locations.md) -- Authoritative inventory of every on-disk read/write path
79
+ - [Improve Workflow](technical/improve-workflow.md) -- `akm improve` command surface and pipeline reference
80
+ - [Health Advisories](technical/health-advisories.md) -- `akm health` advisory-to-action map for operators
81
+ - [Fresh-Host Rebuild Runbook](technical/fresh-host-rebuild-runbook.md) -- Rebuild an akm install on a new machine
82
+ - [Ranking Ablation & Saturation Analysis](technical/ranking-ablation-and-saturation-analysis.md) -- Reproducible contributor-ablation measurement and the score-saturation trap
41
83
  - [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
44
- - [Show Response](technical/show-response.md) -- `akm show` output fields by asset type
84
+ - [Test Coverage Guide](technical/test-coverage-guide.md) -- High-value testing areas
45
85
  - [Testing Workflow](technical/testing-workflow.md) -- End-to-end, Docker, deployment, and upgrade validation
46
86
  - [Ref Format](technical/ref.md) -- Wire format for asset references
47
- - [Test Coverage Guide](technical/test-coverage-guide.md) -- High-value testing areas
48
87
  - [Core Principles](technical/akm-core-principles.md) -- Design principles and constraints
49
- - `technical/benchmark.md` (planned) -- Search-quality benchmark suite
88
+ - [Claude Code workflows vs. akm workflows](technical/claude-code-vs-akm-workflows.md) -- Comparing the two things that share a name
89
+ - [Extending akm workflows into a harness-agnostic orchestration engine](technical/akm-workflows-orchestration-plan.md) -- Current formalized plan, supersedes part of the doc above
90
+
91
+ ## Official Ecosystem Repositories
92
+
93
+ - [itlackey/akm-stash](https://github.com/itlackey/akm-stash) -- the official onboarding stash with ready-made assets you can install with `akm add`
94
+ - [itlackey/akm-registry](https://github.com/itlackey/akm-registry) -- the official registry index that powers built-in discovery
95
+ - [itlackey/akm-plugins](https://github.com/itlackey/akm-plugins) -- optional integrations for tools like OpenCode
96
+ - [itlackey/akm-bench](https://github.com/itlackey/akm-bench) -- the standalone benchmark and evaluation repo for akm
50
97
 
51
98
  ## Posts
52
99
 
53
100
  - [Blog posts](posts/) -- Articles and posts about akm
101
+
102
+ ---
103
+
104
+ New docs, in five lines: keep one current-truth doc per subsystem, don't fork a second one. Unshipped designs live in `docs/design/` with a mandatory `Status` / `Supersedes` / `Date` header. The PR that ships the design moves its doc to `docs/archive/` in that same PR. Cite code by symbol and memories by search-terms -- not line numbers or exact refs, both rot. Nothing in `docs/` may reference `.plans/` (it's scratch -- promote the content or drop the link); no new improve-analysis docs until the 30-clean-day gate.