akm-cli 0.9.0-rc.4 → 0.9.0-rc.6

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 (438) hide show
  1. package/CHANGELOG.md +122 -26
  2. package/README.md +7 -7
  3. package/SECURITY.md +11 -10
  4. package/dist/akm +2 -2
  5. package/dist/akm-migrate-storage +2 -2
  6. package/dist/assets/hints/cli-hints-full.md +60 -73
  7. package/dist/assets/hints/cli-hints-short.md +8 -12
  8. package/dist/assets/improve-strategies/default.json +5 -7
  9. package/dist/assets/improve-strategies/frequent.json +2 -2
  10. package/dist/assets/improve-strategies/proactive-maintenance.json +2 -2
  11. package/dist/assets/improve-strategies/quick.json +1 -1
  12. package/dist/assets/improve-strategies/reflect-distill.json +3 -3
  13. package/dist/assets/improve-strategies/thorough.json +1 -1
  14. package/dist/assets/prompts/consolidate-system.md +5 -5
  15. package/dist/assets/prompts/extract-session.md +2 -6
  16. package/dist/assets/prompts/reflect-llm-framed-contract.md +11 -0
  17. package/dist/assets/prompts/reflect-llm-schema-contract.md +3 -0
  18. package/dist/assets/prompts/reflect-output-repair.md +3 -0
  19. package/dist/assets/stash-skeleton/README.md +10 -11
  20. package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +1 -1
  21. package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +1 -1
  22. package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +1 -1
  23. package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -2
  24. package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -2
  25. package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +1 -1
  26. package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -2
  27. package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +1 -1
  28. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +18 -18
  29. package/dist/assets/stash-skeleton/facts/conventions/domains.md +8 -9
  30. package/dist/assets/stash-skeleton/facts/conventions/organization.md +13 -15
  31. package/dist/assets/tasks/core/extract.yml +2 -2
  32. package/dist/assets/tasks/core/improve.yml +1 -1
  33. package/dist/assets/templates/html/health.html +2 -3
  34. package/dist/cli/config-migrate.js +1328 -101
  35. package/dist/cli/invocation.js +255 -0
  36. package/dist/cli/parse-args.js +20 -83
  37. package/dist/cli/shared.js +15 -37
  38. package/dist/cli.js +18 -49
  39. package/dist/commands/agent/agent-dispatch.js +2 -2
  40. package/dist/commands/agent/contribute-cli.js +5 -4
  41. package/dist/commands/bundle/bundle-cli.js +68 -0
  42. package/dist/commands/bundle/bundle.js +219 -0
  43. package/dist/commands/completions.js +2 -2
  44. package/dist/commands/config-cli.js +6 -3
  45. package/dist/commands/env/env-binding.js +13 -9
  46. package/dist/commands/env/env-cli.js +49 -48
  47. package/dist/commands/env/secret-cli.js +24 -10
  48. package/dist/commands/events.js +2 -2
  49. package/dist/commands/feedback-cli.js +59 -33
  50. package/dist/commands/graph/graph.js +6 -4
  51. package/dist/commands/health/advisories.js +4 -4
  52. package/dist/commands/health/html-report.js +190 -593
  53. package/dist/commands/health/improve-metrics.js +240 -188
  54. package/dist/commands/health/metrics.js +9 -17
  55. package/dist/commands/health/report-view-model.js +509 -0
  56. package/dist/commands/health/surfaces.js +6 -3
  57. package/dist/commands/health/types-checks.js +4 -0
  58. package/dist/commands/health/types-improve.js +22 -0
  59. package/dist/commands/health/types-metrics.js +4 -0
  60. package/dist/commands/health/types-result.js +7 -0
  61. package/dist/commands/health/types-runs.js +4 -0
  62. package/dist/commands/health/types-session-log.js +4 -0
  63. package/dist/commands/health/types-windows.js +4 -0
  64. package/dist/commands/health/types.js +26 -21
  65. package/dist/commands/health/windows.js +1 -2
  66. package/dist/commands/health.js +219 -161
  67. package/dist/commands/improve/collapse-detector.js +25 -14
  68. package/dist/commands/improve/consolidate/chunking.js +7 -5
  69. package/dist/commands/improve/consolidate.js +640 -740
  70. package/dist/commands/improve/content-hash.js +39 -0
  71. package/dist/commands/improve/distill/content-repair.js +4 -10
  72. package/dist/commands/improve/distill/promote-memory.js +79 -49
  73. package/dist/commands/improve/distill/quality-gate.js +113 -35
  74. package/dist/commands/improve/distill-promotion-policy.js +24 -885
  75. package/dist/commands/improve/distill.js +565 -337
  76. package/dist/commands/improve/eligibility.js +75 -36
  77. package/dist/commands/improve/extract-cli.js +6 -6
  78. package/dist/commands/improve/extract-prompt.js +5 -34
  79. package/dist/commands/improve/extract.js +526 -357
  80. package/dist/commands/improve/feedback-valence.js +2 -12
  81. package/dist/commands/improve/improve-cli.js +11 -20
  82. package/dist/commands/improve/improve-result-file.js +7 -6
  83. package/dist/commands/improve/improve-run-types.js +4 -0
  84. package/dist/commands/improve/improve-strategies.js +3 -9
  85. package/dist/commands/improve/improve.js +822 -727
  86. package/dist/commands/improve/locks.js +27 -95
  87. package/dist/commands/improve/loop-stages.js +941 -963
  88. package/dist/commands/improve/memory/derived-ref.js +122 -0
  89. package/dist/commands/improve/memory/memory-contradiction-detect.js +35 -38
  90. package/dist/commands/improve/memory/memory-improve.js +24 -37
  91. package/dist/commands/improve/outcome-loop.js +13 -33
  92. package/dist/commands/improve/preparation.js +889 -691
  93. package/dist/commands/improve/proactive-maintenance.js +37 -9
  94. package/dist/commands/improve/proposal-envelope.js +31 -0
  95. package/dist/commands/improve/reflect.js +974 -588
  96. package/dist/commands/improve/run-context.js +119 -0
  97. package/dist/commands/improve/salience.js +8 -4
  98. package/dist/commands/improve/session-asset.js +7 -3
  99. package/dist/commands/improve/shared.js +14 -40
  100. package/dist/commands/improve/source-identity.js +39 -26
  101. package/dist/commands/improve/triage.js +20 -17
  102. package/dist/commands/lint/base-linter.js +288 -295
  103. package/dist/commands/lint/index.js +132 -19
  104. package/dist/commands/mv-cli.js +257 -234
  105. package/dist/commands/observability-cli.js +2 -1
  106. package/dist/commands/proposal/diff-format.js +50 -0
  107. package/dist/commands/proposal/drain-policies.js +0 -6
  108. package/dist/commands/proposal/drain.js +17 -16
  109. package/dist/commands/proposal/proposal-cli.js +40 -77
  110. package/dist/commands/proposal/proposal-types.js +56 -0
  111. package/dist/commands/proposal/proposal.js +39 -1
  112. package/dist/commands/proposal/propose.js +41 -19
  113. package/dist/commands/proposal/repository.js +566 -486
  114. package/dist/commands/proposal/validators/proposal-quality-validators.js +22 -6
  115. package/dist/commands/proposal/validators/proposal-validators.js +6 -5
  116. package/dist/commands/proposal/validators/proposals.js +5 -4
  117. package/dist/commands/read/curate.js +50 -28
  118. package/dist/commands/read/knowledge.js +25 -16
  119. package/dist/commands/read/remember-cli.js +12 -4
  120. package/dist/commands/read/search-cli.js +33 -33
  121. package/dist/commands/read/search.js +68 -55
  122. package/dist/commands/read/show.js +54 -135
  123. package/dist/commands/remember.js +7 -5
  124. package/dist/commands/sources/add-cli.js +10 -24
  125. package/dist/commands/sources/bundle-config-ops.js +58 -0
  126. package/dist/commands/sources/history.js +13 -8
  127. package/dist/commands/sources/info.js +10 -11
  128. package/dist/commands/sources/init.js +12 -21
  129. package/dist/commands/sources/installed-stashes.js +151 -138
  130. package/dist/commands/sources/schema-repair.js +5 -3
  131. package/dist/commands/sources/self-update.js +9 -7
  132. package/dist/commands/sources/source-add.js +116 -154
  133. package/dist/commands/sources/source-clone.js +33 -14
  134. package/dist/commands/sources/source-manage.js +43 -32
  135. package/dist/commands/sources/sources-cli.js +12 -7
  136. package/dist/commands/sources/stash-cli.js +12 -5
  137. package/dist/commands/sources/stash-skeleton.js +1 -1
  138. package/dist/commands/tasks/default-tasks.js +13 -13
  139. package/dist/commands/tasks/tasks-cli.js +3 -3
  140. package/dist/commands/tasks/tasks.js +71 -31
  141. package/dist/commands/workflow-cli.js +22 -26
  142. package/dist/core/action-contributors.js +1 -1
  143. package/dist/core/activation-policy.js +49 -0
  144. package/dist/core/adapter/adapters/agent-skills-adapter.js +181 -0
  145. package/dist/core/adapter/adapters/akm-adapter.js +509 -0
  146. package/dist/core/adapter/adapters/akm-lint.js +381 -0
  147. package/dist/core/adapter/adapters/akm-metadata.js +416 -0
  148. package/dist/core/adapter/adapters/akm-task-adapter.js +150 -0
  149. package/dist/core/adapter/adapters/akm-workflow-adapter.js +196 -0
  150. package/dist/core/adapter/adapters/claude-adapter.js +61 -0
  151. package/dist/core/adapter/adapters/dotenv-adapter.js +187 -0
  152. package/dist/core/adapter/adapters/generic-files-adapter.js +117 -0
  153. package/dist/core/adapter/adapters/index.js +80 -0
  154. package/dist/core/adapter/adapters/llm-wiki-adapter.js +413 -0
  155. package/dist/core/adapter/adapters/okf-adapter.js +223 -0
  156. package/dist/core/adapter/adapters/opencode-adapter.js +68 -0
  157. package/dist/core/adapter/adapters/shared.js +286 -0
  158. package/dist/core/adapter/adapters/tool-dir-shared.js +212 -0
  159. package/dist/core/adapter/adapters/website-snapshot-adapter.js +154 -0
  160. package/dist/core/adapter/bundle-adapter.js +4 -0
  161. package/dist/core/adapter/recognize-match.js +42 -0
  162. package/dist/core/adapter/registry.js +56 -0
  163. package/dist/core/adapter/types.js +4 -0
  164. package/dist/core/asset/asset-placement.js +229 -0
  165. package/dist/core/asset/asset-ref.js +107 -78
  166. package/dist/core/asset/asset-serialize.js +20 -0
  167. package/dist/core/asset/frontmatter.js +1 -1
  168. package/dist/core/asset/resolve-ref.js +223 -0
  169. package/dist/core/asset/stash-meta.js +1 -1
  170. package/dist/core/common.js +141 -49
  171. package/dist/core/config/config-io.js +0 -108
  172. package/dist/core/config/config-schema.js +94 -1039
  173. package/dist/core/config/config-sources.js +115 -36
  174. package/dist/core/config/config-types.js +16 -11
  175. package/dist/core/config/config-walker.js +4 -2
  176. package/dist/core/config/config.js +21 -26
  177. package/dist/core/config/engine-semantics.js +0 -4
  178. package/dist/core/config/schema/embedding.js +38 -0
  179. package/dist/core/config/schema/engines.js +116 -0
  180. package/dist/core/config/schema/feedback.js +31 -0
  181. package/dist/core/config/schema/improve-processes.js +395 -0
  182. package/dist/core/config/schema/improve.js +76 -0
  183. package/dist/core/config/schema/index-config.js +183 -0
  184. package/dist/core/config/schema/output.js +15 -0
  185. package/dist/core/config/schema/primitives.js +94 -0
  186. package/dist/core/config/schema/search.js +30 -0
  187. package/dist/core/config/schema/setup.js +27 -0
  188. package/dist/core/config/schema/sources-bundles.js +164 -0
  189. package/dist/core/config/schema/workflow.js +29 -0
  190. package/dist/core/env-secret-ref.js +113 -8
  191. package/dist/core/errors.js +1 -1
  192. package/dist/core/events-types.js +4 -0
  193. package/dist/core/extra-params.js +1 -0
  194. package/dist/core/file-change.js +16 -0
  195. package/dist/core/fs-txn.js +316 -0
  196. package/dist/core/git-message.js +59 -0
  197. package/dist/core/improve-result.js +9 -1
  198. package/dist/core/logs-db.js +1 -1
  199. package/dist/core/maintenance-barrier.js +16 -0
  200. package/dist/core/migration-backup.js +332 -160
  201. package/dist/core/paths.js +3 -6
  202. package/dist/core/platform.js +10 -0
  203. package/dist/core/recognition-util.js +130 -0
  204. package/dist/core/redaction.js +2 -2
  205. package/dist/core/standards/resolve-standards-context.js +47 -64
  206. package/dist/core/standards/resolve-type-conventions.js +3 -3
  207. package/dist/core/state/migrations.js +201 -8
  208. package/dist/core/state-db.js +38 -2
  209. package/dist/core/subprocess.js +303 -0
  210. package/dist/core/time.js +20 -0
  211. package/dist/core/type-presentation.js +130 -0
  212. package/dist/core/write-source.js +39 -67
  213. package/dist/indexer/bundle-identity-guard.js +91 -0
  214. package/dist/indexer/db/graph-db.js +1 -1
  215. package/dist/indexer/db/llm-cache.js +1 -1
  216. package/dist/indexer/ensure-index.js +29 -9
  217. package/dist/indexer/graph/graph-boost.js +28 -24
  218. package/dist/indexer/graph/graph-extraction.js +5 -6
  219. package/dist/indexer/graph/graph-types.js +4 -0
  220. package/dist/indexer/index-written-assets.js +44 -17
  221. package/dist/indexer/indexer.js +289 -153
  222. package/dist/indexer/init.js +18 -25
  223. package/dist/indexer/installations.js +224 -0
  224. package/dist/indexer/passes/dir-staleness.js +2 -1
  225. package/dist/indexer/passes/memory-inference.js +8 -4
  226. package/dist/indexer/passes/metadata.js +96 -243
  227. package/dist/indexer/scan/doc-to-entry.js +123 -0
  228. package/dist/indexer/scan/drain-dir.js +144 -0
  229. package/dist/indexer/search/db-search.js +171 -99
  230. package/dist/indexer/search/fts-query.js +1 -1
  231. package/dist/indexer/search/ranking-contributors.js +57 -7
  232. package/dist/indexer/search/ranking-types.js +4 -0
  233. package/dist/indexer/search/ranking.js +31 -6
  234. package/dist/indexer/search/search-attribution.js +67 -0
  235. package/dist/indexer/search/search-hit-enrichers.js +30 -40
  236. package/dist/indexer/search/search-source.js +109 -52
  237. package/dist/indexer/search/semantic-status.js +4 -1
  238. package/dist/indexer/usage/unmigrated-vaults-guard.js +2 -1
  239. package/dist/indexer/usage/usage-events.js +72 -9
  240. package/dist/indexer/walk/file-context.js +1 -44
  241. package/dist/indexer/walk/matchers.js +16 -32
  242. package/dist/indexer/walk/path-resolver.js +6 -5
  243. package/dist/indexer/walk/walker.js +4 -2
  244. package/dist/integrations/agent/engine-resolution.js +22 -0
  245. package/dist/integrations/agent/model-aliases.js +1 -1
  246. package/dist/integrations/agent/prompts.js +35 -11
  247. package/dist/integrations/agent/spawn.js +41 -270
  248. package/dist/integrations/harnesses/aider/agent-builder.js +2 -2
  249. package/dist/integrations/harnesses/aider/index.js +2 -11
  250. package/dist/integrations/harnesses/amazonq/agent-builder.js +1 -9
  251. package/dist/integrations/harnesses/amazonq/index.js +3 -16
  252. package/dist/integrations/harnesses/claude/config-import.js +1 -3
  253. package/dist/integrations/harnesses/claude/index.js +1 -12
  254. package/dist/integrations/harnesses/claude/session-log.js +27 -65
  255. package/dist/integrations/harnesses/codex/agent-builder.js +1 -2
  256. package/dist/integrations/harnesses/codex/index.js +2 -12
  257. package/dist/integrations/harnesses/copilot/agent-builder.js +2 -3
  258. package/dist/integrations/harnesses/copilot/index.js +1 -12
  259. package/dist/integrations/harnesses/gemini/agent-builder.js +1 -3
  260. package/dist/integrations/harnesses/gemini/index.js +1 -12
  261. package/dist/integrations/harnesses/ids.js +24 -0
  262. package/dist/integrations/harnesses/index.js +27 -2
  263. package/dist/integrations/harnesses/opencode/config-import.js +1 -3
  264. package/dist/integrations/harnesses/opencode/index.js +1 -12
  265. package/dist/integrations/harnesses/opencode/session-log.js +67 -110
  266. package/dist/integrations/harnesses/opencode-sdk/harness.js +2 -11
  267. package/dist/integrations/harnesses/openhands/agent-builder.js +3 -3
  268. package/dist/integrations/harnesses/openhands/index.js +2 -11
  269. package/dist/integrations/harnesses/pi/agent-builder.js +3 -11
  270. package/dist/integrations/harnesses/pi/index.js +3 -15
  271. package/dist/integrations/harnesses/shared.js +17 -0
  272. package/dist/integrations/harnesses/types.js +37 -2
  273. package/dist/integrations/lockfile.js +36 -0
  274. package/dist/integrations/session-logs/index.js +21 -12
  275. package/dist/integrations/session-logs/provider-base.js +113 -0
  276. package/dist/llm/client.js +7 -5
  277. package/dist/llm/embedders/deterministic.js +2 -2
  278. package/dist/llm/embedders/remote.js +8 -4
  279. package/dist/llm/graph-extract.js +7 -2
  280. package/dist/llm/metadata-enhance.js +43 -26
  281. package/dist/llm/structured-call.js +15 -7
  282. package/dist/migrate/legacy/config-source-migration.js +223 -0
  283. package/dist/migrate/legacy/content-migration.js +305 -0
  284. package/dist/migrate/legacy/legacy-layout.js +779 -0
  285. package/dist/migrate/legacy/legacy-paths.js +25 -0
  286. package/dist/migrate/legacy/legacy-stash-json.js +72 -0
  287. package/dist/migrate/legacy/proposal-fs-import.js +168 -0
  288. package/dist/migrate/legacy/task-target-ref-migration.js +272 -0
  289. package/dist/migrate/legacy/three-db-cutover.js +840 -0
  290. package/dist/migrate/legacy/workflow-migrations-bodies.js +52 -0
  291. package/dist/migrate/legacy/workflow-migrations-frozen.js +21 -0
  292. package/dist/migrate/legacy-ref-grammar.js +209 -0
  293. package/dist/output/command-registry.js +27 -0
  294. package/dist/output/html-render.js +11 -16
  295. package/dist/output/renderers.js +32 -276
  296. package/dist/output/shapes/passthrough.js +3 -9
  297. package/dist/output/shapes/registry.js +12 -6
  298. package/dist/output/text/command-format.js +547 -0
  299. package/dist/output/text/helpers.js +15 -1377
  300. package/dist/output/text/proposal-format.js +230 -0
  301. package/dist/output/text/registry.js +12 -6
  302. package/dist/output/text/show-directives.js +107 -0
  303. package/dist/output/text/show-format.js +103 -0
  304. package/dist/output/text/workflow-format.js +345 -0
  305. package/dist/output/text.js +1 -3
  306. package/dist/registry/build-index.js +13 -17
  307. package/dist/registry/providers/static-index.js +2 -2
  308. package/dist/registry/resolve.js +4 -90
  309. package/dist/registry/semver.js +93 -0
  310. package/dist/runtime.js +90 -0
  311. package/dist/schemas/akm-config.json +2956 -14890
  312. package/dist/schemas/akm-task.json +2 -2
  313. package/dist/schemas/akm-workflow.json +2 -2
  314. package/dist/scripts/migrate-storage.js +2312 -19642
  315. package/dist/setup/detect.js +5 -7
  316. package/dist/setup/engine-config.js +2 -1
  317. package/dist/setup/registry-stash-loader.js +1 -1
  318. package/dist/setup/semantic-assets.js +12 -9
  319. package/dist/setup/setup.js +109 -39
  320. package/dist/setup/steps/connection-shared.js +120 -0
  321. package/dist/setup/steps/connection.js +50 -274
  322. package/dist/setup/steps/platforms.js +1 -0
  323. package/dist/setup/steps/sources.js +13 -6
  324. package/dist/setup/steps/stashdir.js +5 -2
  325. package/dist/sources/freshness.js +39 -0
  326. package/dist/sources/providers/git-provider.js +29 -33
  327. package/dist/sources/providers/git-stash.js +10 -5
  328. package/dist/sources/providers/provider-utils.js +40 -18
  329. package/dist/sources/providers/website.js +1 -1
  330. package/dist/sources/resolve.js +5 -5
  331. package/dist/sources/snapshot-fetchers/types.js +4 -0
  332. package/dist/sources/{website-ingest.js → snapshot-fetchers/website-ingest.js} +105 -39
  333. package/dist/storage/database.js +47 -3
  334. package/dist/storage/engines/sqlite-migrations.js +34 -16
  335. package/dist/storage/locations.js +1 -2
  336. package/dist/storage/repositories/improve-runs-repository.js +0 -20
  337. package/dist/storage/repositories/index-connection.js +80 -0
  338. package/dist/storage/repositories/index-db.js +4 -3
  339. package/dist/storage/repositories/index-entries-repository.js +952 -0
  340. package/dist/{indexer/db/entry-mapper.js → storage/repositories/index-entry-mapper.js} +15 -2
  341. package/dist/storage/repositories/index-entry-types.js +4 -0
  342. package/dist/storage/repositories/index-fts-repository.js +164 -0
  343. package/dist/storage/repositories/index-llm-cache-repository.js +109 -0
  344. package/dist/storage/repositories/index-meta-repository.js +50 -0
  345. package/dist/{indexer/db/schema.js → storage/repositories/index-schema.js} +241 -100
  346. package/dist/storage/repositories/index-sql.js +12 -0
  347. package/dist/storage/repositories/index-utility-repository.js +369 -0
  348. package/dist/storage/repositories/index-vec-repository.js +245 -0
  349. package/dist/storage/repositories/proposals-repository.js +41 -50
  350. package/dist/storage/repositories/registry-cache.js +1 -1
  351. package/dist/storage/repositories/workflow-runs-repository.js +17 -11
  352. package/dist/tasks/backends/cron.js +5 -5
  353. package/dist/tasks/backends/exec-utils.js +21 -0
  354. package/dist/tasks/backends/index.js +6 -9
  355. package/dist/tasks/backends/launchd.js +16 -17
  356. package/dist/tasks/backends/schtasks.js +33 -41
  357. package/dist/tasks/backends/types.js +4 -0
  358. package/dist/tasks/parser.js +25 -5
  359. package/dist/tasks/runner.js +33 -39
  360. package/dist/tasks/validator.js +5 -6
  361. package/dist/workflows/authoring/authoring.js +8 -11
  362. package/dist/workflows/exec/brief.js +10 -7
  363. package/dist/workflows/exec/report.js +261 -156
  364. package/dist/workflows/exec/run-workflow.js +2 -1
  365. package/dist/workflows/exec/step-work.js +3 -9
  366. package/dist/workflows/program/parser.js +4 -60
  367. package/dist/workflows/renderer.js +11 -60
  368. package/dist/workflows/runtime/checkin.js +1 -1
  369. package/dist/workflows/runtime/plan-classifier.js +7 -4
  370. package/dist/workflows/runtime/runs.js +11 -10
  371. package/dist/workflows/runtime/unit-checkin.js +1 -1
  372. package/dist/workflows/runtime/unit-phases.js +20 -0
  373. package/dist/workflows/runtime/workflow-asset-loader.js +27 -16
  374. package/dist/workflows/validate-summary.js +2 -2
  375. package/dist/workflows/validator.js +18 -2
  376. package/docs/migration/release-notes/0.9.0.md +45 -3
  377. package/docs/migration/v0.8-to-v0.9.md +466 -262
  378. package/docs/{data-and-telemetry.md → reference/data-and-telemetry.md} +61 -17
  379. package/package.json +10 -9
  380. package/schemas/akm-config.json +2956 -14890
  381. package/schemas/akm-task.json +2 -2
  382. package/schemas/akm-workflow.json +2 -2
  383. package/dist/assets/help/help-accept.md +0 -12
  384. package/dist/assets/help/help-improve.md +0 -84
  385. package/dist/assets/help/help-proposals.md +0 -17
  386. package/dist/assets/help/help-propose.md +0 -17
  387. package/dist/assets/help/help-reject.md +0 -11
  388. package/dist/assets/improve-strategies/recombine-only.json +0 -23
  389. package/dist/assets/improve-strategies/synthesize.json +0 -17
  390. package/dist/assets/prompts/procedural-system.md +0 -44
  391. package/dist/assets/prompts/recombine-system.md +0 -40
  392. package/dist/assets/prompts/staleness-detect-system.md +0 -6
  393. package/dist/assets/templates/html/default.html +0 -78
  394. package/dist/assets/templates/html/vendor/echarts.min.js +0 -45
  395. package/dist/assets/wiki/index-template.md +0 -12
  396. package/dist/assets/wiki/ingest-workflow-template.md +0 -83
  397. package/dist/assets/wiki/log-template.md +0 -8
  398. package/dist/assets/wiki/schema-template.md +0 -61
  399. package/dist/commands/improve/calibration.js +0 -161
  400. package/dist/commands/improve/dedup.js +0 -482
  401. package/dist/commands/improve/hot-probation.js +0 -45
  402. package/dist/commands/improve/improve-auto-accept.js +0 -262
  403. package/dist/commands/improve/procedural.js +0 -403
  404. package/dist/commands/improve/recombine.js +0 -843
  405. package/dist/commands/improve/schema-similarity-gate.js +0 -168
  406. package/dist/commands/lint/agent-linter.js +0 -44
  407. package/dist/commands/lint/command-linter.js +0 -44
  408. package/dist/commands/lint/default-linter.js +0 -16
  409. package/dist/commands/lint/fact-linter.js +0 -39
  410. package/dist/commands/lint/knowledge-linter.js +0 -16
  411. package/dist/commands/lint/memory-linter.js +0 -61
  412. package/dist/commands/lint/registry.js +0 -41
  413. package/dist/commands/lint/skill-linter.js +0 -45
  414. package/dist/commands/lint/task-linter.js +0 -50
  415. package/dist/commands/lint/workflow-linter.js +0 -81
  416. package/dist/commands/proposal/legacy-import.js +0 -115
  417. package/dist/commands/wiki-cli.js +0 -291
  418. package/dist/core/asset/asset-registry.js +0 -76
  419. package/dist/core/asset/asset-spec.js +0 -316
  420. package/dist/core/eval/rank-metrics.js +0 -113
  421. package/dist/core/ripgrep/install.js +0 -163
  422. package/dist/core/ripgrep/resolve.js +0 -81
  423. package/dist/indexer/db/db.js +0 -1585
  424. package/dist/indexer/manifest.js +0 -170
  425. package/dist/indexer/passes/metadata-contributors.js +0 -31
  426. package/dist/integrations/harnesses/opencode-sdk/index.js +0 -25
  427. package/dist/output/text/wiki.js +0 -16
  428. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +0 -18228
  429. package/dist/scripts/migrations/v16-to-v17.js +0 -141
  430. package/dist/storage/repositories/consolidation-repository.js +0 -38
  431. package/dist/storage/repositories/recombine-repository.js +0 -213
  432. package/dist/wiki/wiki-templates.js +0 -15
  433. package/dist/wiki/wiki.js +0 -1013
  434. package/dist/workflows/db.js +0 -413
  435. package/docs/README.md +0 -103
  436. package/docs/migration/release-notes/0.9.0-beta.60.md +0 -19
  437. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/registry.js +0 -0
  438. /package/dist/sources/{wiki-fetchers → snapshot-fetchers}/youtube.js +0 -0
@@ -0,0 +1,509 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * The AKM workspace's own `akm` adapter — akm 0.9.0 chunk-2, WI-B.
6
+ *
7
+ * Implements `docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md` §5.1 (BINDING) +
8
+ * §6 + §7 (the `akm` row) EXACTLY: a BEHAVIOR-PRESERVING PORT that reproduces
9
+ * TODAY'S classification and placement VERBATIM by REUSING the existing matcher
10
+ * stack. It is NOT re-derived onto frontmatter `type` (that is the sibling
11
+ * `okf` adapter's job, §5), NOT split per-`type` (the 14 AKM formats are `type`
12
+ * VALUES the single `akm` adapter emits, §6/§0.2), and introduces NO new
13
+ * positional/directory heuristics of its own.
14
+ *
15
+ * ── recognize (§5.1): the sync `runMatchers` reproduction ──
16
+ *
17
+ * `file-context.ts#runMatchers` (`:242-265`) is async ONLY because of its lazy
18
+ * `ensureBuiltinsRegistered()` dynamic import; its ARBITRATION is pure and
19
+ * synchronous. We reproduce it here by importing the SAME five builtin matcher
20
+ * functions (`matchers.ts` `extensionMatcher` / `directoryMatcher` /
21
+ * `parentDirHintMatcher` / `smartMdMatcher` / `workflowProgramMatcher`) in the
22
+ * SAME order they are registered, collecting every non-null
23
+ * `MatchResult` and picking the winner by **specificity descending, ties broken
24
+ * by later-registered (higher index) winning** — byte-identical to
25
+ * `runMatchers`'s `b.specificity - a.specificity` then `b.index - a.index`.
26
+ * Because the matcher functions (which resolve renderer names via the static
27
+ * `TYPE_PRESENTATION` table in `type-presentation.ts`, all built-in types
28
+ * present at load) are the exact ones `runMatchers` uses, {@link recognizeMatch}
29
+ * agrees with the async `runMatchers` on `type` / `specificity` / `renderer` for
30
+ * every input. This is "use the existing matchers" literally — same functions,
31
+ * same arbitration.
32
+ *
33
+ * The winning `MatchResult.renderer` is carried on `documentJson.renderer` so
34
+ * WI-C can wire presentation via `TYPE_PRESENTATION` without a new
35
+ * `IndexDocument` field (WI-C owns presentation).
36
+ *
37
+ * ── conceptId (§5.1 + ref-grammar decision D-R2): the QUALIFIED spelling ──
38
+ *
39
+ * conceptId = `<stash-subdir>/<canonical-name>` — the placement stash-subdir
40
+ * (`stashDirFor(type)`) followed by the winning type's canonical name
41
+ * (`deriveCanonicalAssetNameFromStashRoot`: skill = its dir, script keeps its
42
+ * extension, markdown strips `.md`, env/task strip their ext, secret/session
43
+ * keep the natural path). For markdown types this IS the OKF concept ID
44
+ * (path − `.md`); it is the same spelling {@link placeNew} consumes, so
45
+ * recognize/place share one identity (D-R2 resolved the earlier split). The
46
+ * `type` is carried separately on `IndexDocument.type`, per §0.2 (type ≠
47
+ * identity), and `entry.name` keeps the BARE canonical name for FTS parity.
48
+ *
49
+ * ── placeNew / directoryList / looksLikeRoot: type-driven placement ──
50
+ *
51
+ * Placement is type-driven (`path-resolver.ts#buildDiskCandidates`: the primary
52
+ * candidate is `assetPathForName(ref.type, join(root, stashDirFor(ref.type)),
53
+ * ref.name)`). §5.1 removes `type` from the ref, so {@link placeNew} recovers
54
+ * it from the conceptId's LEADING path segment — the qualified `<stash-subdir>/
55
+ * <name>` form of §1.3 — reverse-mapping that segment against the placement
56
+ * stash-subdir map and then delegating to `assetPathForName`. See the method
57
+ * doc for the recognize/place conceptId-spelling note.
58
+ *
59
+ * ── validate: base checks only (WI-B) ──
60
+ *
61
+ * Base validate checks only for this WI (shared `validateChangesWithBaseChecks`
62
+ * — the ported unquoted-colon / missing-updated / stale-path / missing-ref).
63
+ * The per-type linters (SkillLinter/WorkflowLinter/TaskLinter/…) are WI-C.
64
+ *
65
+ * ── Cycle-safety (chunk-3 cutover, baseline 18) ──
66
+ *
67
+ * This module VALUE-imports `matchers.ts` (indexer/walk) for classification and
68
+ * `asset-placement.ts` (core/asset) for placement — delegating to the existing
69
+ * logic, not re-implementing it. Neither is a taxonomy import-cycle (SCC)
70
+ * participant: `matchers.ts` resolves renderers via `type-presentation.ts`, and
71
+ * `asset-placement.ts` is a pure leaf (only Node builtins + `recognition-util`).
72
+ * Nothing in `src/` imports this adapter back (only the test-only
73
+ * `adapters/index.ts` barrel does, and nothing in `src/` imports THAT), so the
74
+ * adapter is itself a leaf — verified: `bun scripts/lint-import-cycles.ts` stays
75
+ * within baseline and this module is NOT a participant.
76
+ */
77
+ import fs from "node:fs";
78
+ import path from "node:path";
79
+ import { parse as parseYaml } from "yaml";
80
+ import { applyPostContributorFields, applyPreContributorFields, extractPackageMetadata, } from "../../../indexer/passes/metadata.js";
81
+ import { assetPathForName, deriveCanonicalAssetNameFromStashRoot, placementTypes, stashDirFor, stashDirNames, } from "../../asset/asset-placement.js";
82
+ import { parseFrontmatter } from "../../asset/frontmatter.js";
83
+ import { recognizeMatch } from "../recognize-match.js";
84
+ import { perTypeValidateChecks, skillDirectoryDiagnostics } from "./akm-lint.js";
85
+ import { applyFoldedMetadata, foldRecognizedMetadata } from "./akm-metadata.js";
86
+ import { hashContent, runBaseValidateChecks } from "./shared.js";
87
+ // `recognizeMatch` + the builtin matcher list moved to the cycle-free leaf
88
+ // `../recognize-match` (Chunk 5 M-b) so both this adapter AND the indexer
89
+ // metadata pass import it without closing a metadata ↔ adapter cycle. Re-exported
90
+ // here so existing `akm-adapter` importers (tests, sibling modules) are
91
+ // unaffected.
92
+ export { recognizeMatch } from "../recognize-match.js";
93
+ /**
94
+ * OKF reserved structural files (ref-grammar decision D-R6, spec §5.1 /
95
+ * adapter-spec §5.1/§6): `index.md` (directory listing) and `log.md` (update
96
+ * history) are bundle structure at EVERY depth — never a concept document. The
97
+ * `okf` / `llm-wiki` adapters already exclude them (`okf-adapter.ts`
98
+ * `RESERVED_FILES`); this brings the `akm` adapter into conformance so a
99
+ * `knowledge/index.md` never classifies as a `knowledge` item. Case-insensitive,
100
+ * matched on the bare filename so the exclusion holds at any depth.
101
+ */
102
+ const RESERVED_FILES = new Set(["index.md", "log.md"]);
103
+ /** True when `name` (a bare file name) is an OKF reserved file, case-insensitively (D-R6). */
104
+ function isReservedFileName(name) {
105
+ return RESERVED_FILES.has(name.toLowerCase());
106
+ }
107
+ /** Wiki-directory infrastructure files excluded at a `wikis/<name>/` root (ported from the retired `shouldIndexStashFile`). */
108
+ const WIKI_INFRA_FILES = new Set(["schema.md", "index.md", "log.md"]);
109
+ /**
110
+ * AKM-stash indexing policy, moved here from the indexer's `shouldIndexStashFile`
111
+ * pre-filter (owner ruling 2026-07-21 — adapter-owned filtering). Each adapter
112
+ * abstains on its own bundle's files; the core walk keeps only universal hygiene.
113
+ *
114
+ * PATH/STAT-based ONLY — never reads `file.content()`, so the bytes-never-read
115
+ * invariant for sensitive env/secret files holds by construction. Returns `true`
116
+ * when the `akm` adapter must ABSTAIN (recognize → null):
117
+ * - an `env/…` `.env` file with a sibling `.sensitive` marker;
118
+ * - anything under the frozen legacy `vaults/` dir (the `vault` type is gone);
119
+ * - a `secrets/` `.sensitive`/`.lock` marker, or a secret with a sibling
120
+ * `<name>.sensitive` marker;
121
+ * - a `wikis/<name>/` root-level infra file (schema.md/index.md/log.md).
122
+ */
123
+ function akmStashAbstains(root, absPath) {
124
+ const relPath = path.relative(root, absPath);
125
+ if (!relPath || relPath.startsWith("..") || path.isAbsolute(relPath))
126
+ return false;
127
+ const segments = relPath.split(/[\\/]+/).filter(Boolean);
128
+ if (segments.length === 0)
129
+ return false;
130
+ // Skip env `.env` files that have a sibling `.sensitive` marker file.
131
+ if (segments[0] === "env" && (absPath.endsWith(".env") || path.basename(absPath) === ".env")) {
132
+ if (fs.existsSync(absPath.replace(/\.env$/, ".sensitive")))
133
+ return true;
134
+ }
135
+ // The legacy `vaults/` directory (frozen copy left by the 0.8 migration) is
136
+ // never indexed — the `vault` asset type was removed in 0.9.0.
137
+ if (segments[0] === "vaults")
138
+ return true;
139
+ // Skip secret files that are themselves a `.sensitive` marker, or that have a
140
+ // sibling `<name>.sensitive` marker. Secrets are otherwise indexed by name
141
+ // only (their bytes are never read for classification here).
142
+ if (segments[0] === "secrets") {
143
+ if (absPath.endsWith(".sensitive") || absPath.endsWith(".lock"))
144
+ return true;
145
+ if (fs.existsSync(`${absPath}.sensitive`))
146
+ return true;
147
+ }
148
+ // Inside a `wikis/<name>/` directory, the root-level infrastructure files
149
+ // schema.md / index.md / log.md are excluded.
150
+ const wikisIdx = segments.indexOf("wikis");
151
+ if (wikisIdx < 0 || wikisIdx + 1 >= segments.length)
152
+ return false;
153
+ const wikiRelativeSegments = segments.slice(wikisIdx + 2);
154
+ return wikiRelativeSegments.length === 1 && WIKI_INFRA_FILES.has(wikiRelativeSegments[0]);
155
+ }
156
+ /** Reverse the placement map (stash subdir → akm type). Built per call so a runtime-registered custom type is honored (live-delegation, not a snapshot). */
157
+ function stashDirToType(stashDir) {
158
+ for (const type of placementTypes()) {
159
+ if (stashDirFor(type) === stashDir)
160
+ return type;
161
+ }
162
+ return undefined;
163
+ }
164
+ /**
165
+ * The search-surface `IndexDocument` fields that have NO first-class `IndexDocument`
166
+ * home (spec §3) and therefore ride `documentJson` so the persist-time fold
167
+ * (`search-fields.ts:28-33`) can still reach them — the exact set
168
+ * `buildSearchFields` folds into the `hints`/`content` FTS columns beyond the
169
+ * first-class name/description/tags/aliases/searchHints, plus the provenance the
170
+ * WI-C tests read (renderer/source). Kept as a named list so the fold surface and
171
+ * the mapping stay in lockstep.
172
+ */
173
+ const DOCUMENT_JSON_CARRIED_FIELDS = [
174
+ "examples",
175
+ "usage",
176
+ "intent",
177
+ "xrefs",
178
+ "pageKind",
179
+ "whenToUse",
180
+ "toc",
181
+ "parameters",
182
+ "bodyOpening",
183
+ "source",
184
+ "category",
185
+ "supersededBy",
186
+ "contradictedBy",
187
+ "run",
188
+ "setup",
189
+ "cwd",
190
+ "wikiRole",
191
+ "sources",
192
+ "generation",
193
+ "sourceRefs",
194
+ "evidenceSources",
195
+ ];
196
+ /**
197
+ * Map the fully-assembled `IndexDocument` (produced by the shared metadata
198
+ * pipeline) onto an `IndexDocument` (spec §3). First-class ranking/embedding
199
+ * fields land on named IndexDocument fields; every other search-surface or
200
+ * signal field rides `documentJson` (opaque adapter extras) so nothing the
201
+ * ranking/embedding/filter inputs read is lost — the M-b shadow-parity gate.
202
+ * The winning renderer name is carried on `documentJson.renderer` (WI-C contract).
203
+ */
204
+ function indexDocumentFromEntry(entry, base, rendererName) {
205
+ const extras = { renderer: rendererName };
206
+ for (const field of DOCUMENT_JSON_CARRIED_FIELDS) {
207
+ const value = entry[field];
208
+ if (value !== undefined)
209
+ extras[field] = value;
210
+ }
211
+ const doc = {
212
+ ...base,
213
+ name: entry.name,
214
+ documentJson: extras,
215
+ };
216
+ // First-class search + signal fields (only when present).
217
+ if (entry.description !== undefined)
218
+ doc.description = entry.description;
219
+ if (entry.tags !== undefined)
220
+ doc.tags = entry.tags;
221
+ if (entry.aliases !== undefined)
222
+ doc.aliases = entry.aliases;
223
+ if (entry.searchHints !== undefined)
224
+ doc.searchHints = entry.searchHints;
225
+ if (entry.quality !== undefined)
226
+ doc.quality = entry.quality;
227
+ if (entry.confidence !== undefined)
228
+ doc.confidence = entry.confidence;
229
+ if (entry.beliefState !== undefined)
230
+ doc.beliefState = entry.beliefState;
231
+ if (entry.currentBeliefRefs !== undefined)
232
+ doc.currentBeliefRefs = entry.currentBeliefRefs;
233
+ if (entry.scope !== undefined)
234
+ doc.scope = entry.scope;
235
+ if (entry.captureMode !== undefined)
236
+ doc.captureMode = entry.captureMode;
237
+ if (entry.lessonStrength !== undefined)
238
+ doc.lessonStrength = entry.lessonStrength;
239
+ if (entry.derivedFrom !== undefined)
240
+ doc.derivedFrom = entry.derivedFrom;
241
+ return doc;
242
+ }
243
+ function recognize(c, file) {
244
+ // D-R6 (spec §5.1): `index.md` / `log.md` are OKF reserved structural files at
245
+ // every depth — never items. Excluded BEFORE classification so a directory
246
+ // listing or update log never becomes a `knowledge` (or other) concept.
247
+ if (isReservedFileName(file.fileName))
248
+ return null;
249
+ // Adapter-owned filtering (owner ruling 2026-07-21): AKM-stash policy that used
250
+ // to live in the indexer's `shouldIndexStashFile` pre-filter. Path/stat-based —
251
+ // `file.content()` is never read to reach this abstention.
252
+ if (akmStashAbstains(c.root, file.absPath))
253
+ return null;
254
+ const match = recognizeMatch(file);
255
+ if (match === null)
256
+ return null;
257
+ // canonical name = the winning type's per-type canonical name (§5.1:
258
+ // reproduce AssetSpec.toCanonicalName). Fall back to the BASENAME minus its
259
+ // extension only if the type's toCanonicalName abstains (e.g. a `skills/x.md`
260
+ // flat file, or a `SKILL.md` sitting directly at the skills/ root with no name
261
+ // dir). The basename fallback is byte-identical to the pre-0.9.0 flat-walk's
262
+ // `?? baseName` fallback (metadata.ts `generateMetadata`), so `entry.name`
263
+ // stays the BARE canonical name — never the stash-root-relative path, which
264
+ // would re-embed the `<stash-subdir>/` type prefix and double-prefix every
265
+ // downstream legacy `type:name` ref (e.g. `skill:skills/x`).
266
+ const derived = deriveCanonicalAssetNameFromStashRoot(match.type, c.root, file.absPath);
267
+ const canonicalName = derived ?? path.basename(file.absPath).replace(/\.[^./]+$/, "");
268
+ // conceptId = the QUALIFIED `<stash-subdir>/<canonical-name>` spelling
269
+ // (ref-grammar decision D-R2): the same form `placeNew` consumes, and for
270
+ // markdown types the OKF concept ID (path − .md). Both branches now feed a
271
+ // BARE canonicalName (the abstain fallback is the basename, above), so the
272
+ // stash-subdir is prefixed uniformly — a flat `skills/x.md` yields
273
+ // `skills/x`, never the un-prefixed `x` or the double-prefixed
274
+ // `skills/skills/x`. `entry.name` below keeps the BARE canonical name —
275
+ // identity ≠ search text.
276
+ const stashDir = stashDirFor(match.type);
277
+ const conceptId = stashDir !== undefined ? `${stashDir}/${canonicalName}` : canonicalName;
278
+ const dirPath = path.dirname(file.absPath);
279
+ // Chunk 5 M-b: recognize now carries the FULL index-time metadata surface
280
+ // (spec §2/§3), reproducing `buildEntryFromFile`'s flat-walk metadata
281
+ // output by SHARING its P1/P2/P4 assembly and substituting the synchronous
282
+ // `foldRecognizedMetadata` (+ `applyFoldedMetadata`, which replicates the
283
+ // in-place contributor precedence) for the async P3 renderer contributors.
284
+ // `entry.name` = the BARE canonical name (conceptId minus the D-R2 stash-subdir
285
+ // prefix) so the FTS `name` column
286
+ // matches the pre-0.9.0 indexer (search-behavior parity), NOT the frontmatter
287
+ // title. Parity is by construction — the two paths differ only in the P3 step,
288
+ // pinned equal by the akm-adapter fold-parity test.
289
+ const entry = {
290
+ name: canonicalName,
291
+ type: match.type,
292
+ quality: "generated",
293
+ confidence: 0.55,
294
+ source: "filename",
295
+ };
296
+ applyPreContributorFields(entry, file.absPath, file, extractPackageMetadata(dirPath));
297
+ applyFoldedMetadata(entry, foldRecognizedMetadata(match.renderer, file));
298
+ applyPostContributorFields(entry, file.absPath, canonicalName, dirPath);
299
+ return indexDocumentFromEntry(entry, {
300
+ ref: `${c.id}//${conceptId}`,
301
+ bundle: c.id,
302
+ component: c.id,
303
+ conceptId,
304
+ path: file.absPath,
305
+ // Hash over the full raw bytes (incrementality/fingerprints, `types.ts`
306
+ // hash doc comment) — an opaque digest, not indexed content.
307
+ hash: hashContent(file.content()),
308
+ adapterId: "akm",
309
+ type: match.type,
310
+ }, match.renderer);
311
+ }
312
+ /**
313
+ * A read-only {@link FileContext} backed by an OVERLAY string (a pending
314
+ * change's content) instead of the live filesystem — the `validate` contract
315
+ * ({@link BundleAdapter.validate} doc comment / adapter-spec §12.1) forbids
316
+ * reading the live FS. It mirrors `buildFileContext`'s eager path-field
317
+ * derivation exactly (so the matchers classify identically) and serves the
318
+ * overlay bytes from `content()`/`frontmatter()`. `stat()` throws: no matcher
319
+ * calls it, and there is no snapshot mtime to serve.
320
+ */
321
+ function buildOverlayContext(root, relPathInput, raw) {
322
+ const absPath = path.join(root, relPathInput);
323
+ const relPath = path.relative(root, absPath).replace(/\\/g, "/");
324
+ const ext = path.extname(absPath).toLowerCase();
325
+ const fileName = path.basename(absPath);
326
+ const parentDirAbs = path.dirname(absPath);
327
+ const parentDir = path.basename(parentDirAbs);
328
+ const relDir = path.dirname(relPath).replace(/\\/g, "/");
329
+ const ancestorDirs = relDir === "." ? [] : relDir.split("/").filter((seg) => seg.length > 0);
330
+ let cachedFrontmatter;
331
+ let frontmatterComputed = false;
332
+ return {
333
+ absPath,
334
+ relPath,
335
+ ext,
336
+ fileName,
337
+ parentDir,
338
+ parentDirAbs,
339
+ ancestorDirs,
340
+ stashRoot: root,
341
+ content: () => raw,
342
+ frontmatter: () => {
343
+ if (!frontmatterComputed) {
344
+ const parsed = parseFrontmatter(raw);
345
+ cachedFrontmatter = Object.keys(parsed.data).length > 0 ? parsed.data : null;
346
+ frontmatterComputed = true;
347
+ }
348
+ return cachedFrontmatter ?? null;
349
+ },
350
+ stat: () => {
351
+ throw new Error("stat() is unavailable in a validate overlay FileContext");
352
+ },
353
+ };
354
+ }
355
+ /**
356
+ * `validate` (spec §6) = shared base checks + the winning `type`'s per-type
357
+ * extra checks, reproducing today's `akmLint`/`getLinterForType` dispatch
358
+ * byte-for-byte (the FROZEN `lint/all-types.json` `perType` golden is the gate).
359
+ *
360
+ * Per change (non-delete, readable): the `type` is recovered by running the
361
+ * SAME sync matcher arbitration ({@link recognizeMatch}) over an OVERLAY
362
+ * FileContext ({@link buildOverlayContext}) — no live-FS read. `task` files are
363
+ * parsed as pure YAML (mirroring `lint/index.ts`'s `subdir === "tasks"` branch)
364
+ * so the TaskLinter's field checks see real data and `missing-updated` never
365
+ * fires (frontmatter is `null`); everything else parses via `parseFrontmatter`.
366
+ * Base checks (shared) then the per-type extra checks run; a `skills/` directory
367
+ * pass reproduces `SkillLinter.lintDirectory` across the change set.
368
+ */
369
+ async function validate(c, changes, ctx) {
370
+ const diagnostics = [];
371
+ const seenSkillDirs = new Set();
372
+ for (const change of changes) {
373
+ if (change.op === "delete")
374
+ continue;
375
+ const raw = change.after ?? (await ctx.readFile(change.path));
376
+ if (typeof raw !== "string")
377
+ continue;
378
+ const overlay = buildOverlayContext(c.root, change.path, raw);
379
+ const match = recognizeMatch(overlay);
380
+ const type = match?.type;
381
+ // Parse strategy per `lint/index.ts`: `task` → pure YAML (frontmatter null),
382
+ // everything else → `parseFrontmatter`.
383
+ let parsed;
384
+ if (type === "task") {
385
+ let data = {};
386
+ try {
387
+ const doc = parseYaml(raw);
388
+ if (doc && typeof doc === "object" && !Array.isArray(doc))
389
+ data = doc;
390
+ }
391
+ catch {
392
+ data = {};
393
+ }
394
+ parsed = { data, content: raw, frontmatter: null };
395
+ }
396
+ else {
397
+ const p = parseFrontmatter(raw);
398
+ parsed = { data: p.data, content: p.content, frontmatter: p.frontmatter };
399
+ }
400
+ diagnostics.push(...(await runBaseValidateChecks(change.path, parsed, c.root, ctx)));
401
+ diagnostics.push(...(await perTypeValidateChecks({
402
+ type,
403
+ relPath: change.path,
404
+ raw,
405
+ data: parsed.data,
406
+ frontmatter: parsed.frontmatter,
407
+ body: parsed.content,
408
+ ext: overlay.ext,
409
+ ctx,
410
+ })));
411
+ diagnostics.push(...(await skillDirectoryDiagnostics(change.path, seenSkillDirs, ctx)));
412
+ }
413
+ return diagnostics;
414
+ }
415
+ export const akmAdapter = {
416
+ id: "akm",
417
+ version: "0.9.0",
418
+ // Recognized-extension HINT, derived from what the matchers accept (§6):
419
+ // `.md` (markdown types + skill), `.yaml`/`.yml` (workflow programs,
420
+ // task YAML), `.env` (env files), and the 16 SCRIPT_EXTENSIONS. This is a
421
+ // NON-EXHAUSTIVE hint for the akm adapter: recognition is directory-driven
422
+ // via `recognize()` (e.g. a bare `secrets/<anything>` file with no extension
423
+ // is a `secret`), so `recognize()` — not this list — is the source of truth.
424
+ extensions: [
425
+ ".md",
426
+ ".yaml",
427
+ ".yml",
428
+ ".env",
429
+ ".sh",
430
+ ".ts",
431
+ ".js",
432
+ ".ps1",
433
+ ".cmd",
434
+ ".bat",
435
+ ".py",
436
+ ".rb",
437
+ ".go",
438
+ ".pl",
439
+ ".php",
440
+ ".lua",
441
+ ".r",
442
+ ".swift",
443
+ ".kt",
444
+ ".kts",
445
+ ],
446
+ recognize,
447
+ validate,
448
+ /**
449
+ * Type-driven placement (§5.1), reproducing `path-resolver.ts#buildDiskCandidates`:
450
+ * the primary candidate is
451
+ * `assetPathForName(type, join(root, stashDirFor(type)), name)`.
452
+ *
453
+ * §5.1 removes `type` from the ref, so the winning type is recovered from the
454
+ * conceptId's LEADING path segment — the §1.3 qualified `<stash-subdir>/<name>`
455
+ * form (e.g. `knowledge/http-caching`, `workflows/release`, `skills/<dir>`).
456
+ * The leading segment is reverse-mapped against the placement stash-subdir map;
457
+ * the remainder is the per-type name handed to `assetPathForName`. An
458
+ * unqualified conceptId (no recognized leading stash-subdir) falls back to a
459
+ * direct `<root>/<conceptId>.md` — the same `${name}.md` fallback
460
+ * `buildDiskCandidates` carries (`preserveDirectNameFallback`).
461
+ *
462
+ * `recognize()` emits the SAME qualified spelling (ref-grammar decision
463
+ * D-R2), so recognize/place share one canonical identity — the earlier
464
+ * bare-vs-qualified split is resolved.
465
+ */
466
+ placeNew(c, conceptId) {
467
+ const posix = conceptId.replace(/\\/g, "/");
468
+ const slash = posix.indexOf("/");
469
+ if (slash > 0) {
470
+ const head = posix.slice(0, slash);
471
+ const rest = posix.slice(slash + 1);
472
+ const type = stashDirToType(head);
473
+ if (type !== undefined && rest.length > 0) {
474
+ const typeDir = path.join(c.root, head);
475
+ return assetPathForName(type, typeDir, rest);
476
+ }
477
+ }
478
+ return path.join(c.root, `${posix}.md`);
479
+ },
480
+ /** The AKM workspace's owned stash subdirs (§7): the placement stash-subdir names, feeding git exact-path staging. */
481
+ directoryList(_c) {
482
+ return [...new Set(stashDirNames())];
483
+ },
484
+ /**
485
+ * Install-time probe (§1.2), reproducing today's stash-root detection
486
+ * (`provider-utils.ts#detectStashRoot`/`hasStashDirs`): a root is an AKM
487
+ * workspace root when it carries a `.stash` marker directory OR any immediate
488
+ * subdirectory named after a placement stash subdir. Pure stat/readdir; a
489
+ * missing/unreadable root is not a root.
490
+ */
491
+ looksLikeRoot(root) {
492
+ try {
493
+ if (fs.statSync(path.join(root, ".stash")).isDirectory())
494
+ return true;
495
+ }
496
+ catch {
497
+ // no .stash marker — fall through to the type-dir probe
498
+ }
499
+ const ownedDirNames = new Set(stashDirNames());
500
+ let entries;
501
+ try {
502
+ entries = fs.readdirSync(root, { withFileTypes: true });
503
+ }
504
+ catch {
505
+ return false;
506
+ }
507
+ return entries.some((entry) => entry.isDirectory() && ownedDirNames.has(entry.name));
508
+ },
509
+ };