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,154 @@
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 `website-snapshot` adapter — akm 0.9.0 format-family work item (#46).
6
+ *
7
+ * A READ-ONLY (Mode A) view over a materialized crawl snapshot written by
8
+ * `src/sources/snapshot-fetchers/website-ingest.ts` (spec §6/§7). The on-disk
9
+ * pages are KNOWLEDGE-shaped markdown under `stash/knowledge/**` with no `type:`
10
+ * field; this adapter RE-TYPES them to the open `type: website`. Per
11
+ * open-question-3 (RESOLVED, maintainer 2026-07) the re-type is GATED — it
12
+ * applies only to a page carrying the `website` tag / a `sourceUrl` (a page
13
+ * lacking both is not re-typed); the document KEEPS its `sourceUrl` (surfaced as
14
+ * `sourceRef` on `documentJson`); and the conceptId STRIPS the
15
+ * `stash/knowledge/` prefix. `manifest.json` is snapshot PROVENANCE
16
+ * (`{url, fetchedAt}`), read by the probe but never indexed as a concept.
17
+ *
18
+ * Read-only ⇒ NO `placeNew` (Mode B export routes content through the
19
+ * DESTINATION adapter, which owns placement). `validate` runs base checks only
20
+ * (a mirror the adapter does not author has no native validators); `updated`
21
+ * never appears on a snapshot page, so `missing-updated` is filtered out.
22
+ *
23
+ * Conformance oracle (authored, DO NOT modify): fixture
24
+ * `tests/fixtures/bundles/website-snapshot/` + goldens
25
+ * `tests/fixtures/format-family-goldens/website-snapshot/{recognition,placement,lint,renderer}.json`.
26
+ */
27
+ import fs from "node:fs";
28
+ import path from "node:path";
29
+ import { parse as parseYaml } from "yaml";
30
+ import { parseFrontmatter, parseFrontmatterBlock } from "../../asset/frontmatter.js";
31
+ import { hashContent, nonEmptyString, runBaseValidateChecks } from "./shared.js";
32
+ /** A snapshot bundle is single-component; its one component is `main`. */
33
+ const COMPONENT_ID = "main";
34
+ /** The crawl page root the snapshot writer materializes pages under. */
35
+ const PAGES_PREFIX = "stash/knowledge/";
36
+ /** The provenance manifest basename (probe marker only, never indexed). */
37
+ const MANIFEST_FILE = "manifest.json";
38
+ /** The tag the snapshot writer stamps on every crawled page. */
39
+ const WEBSITE_TAG = "website";
40
+ /** Upper bound on the bounded `content` FTS field (mirrors okf-adapter). */
41
+ const MAX_CONTENT_CHARS = 100_000;
42
+ function toPosix(p) {
43
+ return p.replace(/\\/g, "/");
44
+ }
45
+ function parseSnapshotFrontmatter(raw) {
46
+ const out = { tags: [] };
47
+ const block = parseFrontmatterBlock(raw);
48
+ if (!block)
49
+ return out;
50
+ let data = {};
51
+ try {
52
+ const value = parseYaml(block.frontmatter);
53
+ if (value && typeof value === "object" && !Array.isArray(value))
54
+ data = value;
55
+ }
56
+ catch {
57
+ return out;
58
+ }
59
+ out.title = nonEmptyString(data.title);
60
+ out.description = nonEmptyString(data.description);
61
+ out.sourceUrl = nonEmptyString(data.sourceUrl);
62
+ if (Array.isArray(data.tags)) {
63
+ out.tags = data.tags.filter((t) => typeof t === "string" && t.trim().length > 0).map((t) => t.trim());
64
+ }
65
+ return out;
66
+ }
67
+ /** True when a page is a crawl snapshot page under `stash/knowledge/**`. */
68
+ function isSnapshotPage(relPath) {
69
+ const posix = toPosix(relPath);
70
+ return posix.startsWith(PAGES_PREFIX) && posix.toLowerCase().endsWith(".md");
71
+ }
72
+ /** The GATED re-type predicate (open-question-3): the page carries the `website` tag OR a `sourceUrl`. */
73
+ function isReTypeGated(fm) {
74
+ return fm.sourceUrl !== undefined || fm.tags.includes(WEBSITE_TAG);
75
+ }
76
+ /** conceptId = page path − `stash/knowledge/` prefix − `.md`. */
77
+ function conceptIdOf(relPath) {
78
+ return toPosix(relPath).slice(PAGES_PREFIX.length).replace(/\.md$/i, "");
79
+ }
80
+ function recognize(c, file) {
81
+ if (file.ext !== ".md" || !isSnapshotPage(file.relPath))
82
+ return null;
83
+ const raw = file.content();
84
+ const fm = parseSnapshotFrontmatter(raw);
85
+ if (!isReTypeGated(fm))
86
+ return null; // not a re-typed website page
87
+ const conceptId = conceptIdOf(file.relPath);
88
+ const name = fm.title ?? conceptId.split("/").pop() ?? conceptId;
89
+ const body = parseFrontmatter(raw).content;
90
+ const doc = {
91
+ ref: `${c.id}//${conceptId}`,
92
+ bundle: c.id,
93
+ component: COMPONENT_ID,
94
+ conceptId,
95
+ path: file.absPath,
96
+ hash: hashContent(raw),
97
+ adapterId: "website-snapshot",
98
+ type: "website",
99
+ name,
100
+ content: body.length > MAX_CONTENT_CHARS ? body.slice(0, MAX_CONTENT_CHARS) : body,
101
+ };
102
+ if (fm.description !== undefined)
103
+ doc.description = fm.description;
104
+ if (fm.sourceUrl !== undefined)
105
+ doc.documentJson = { sourceRef: fm.sourceUrl };
106
+ return doc;
107
+ }
108
+ async function validate(c, changes, ctx) {
109
+ const diagnostics = [];
110
+ for (const change of changes) {
111
+ if (change.op === "delete")
112
+ continue;
113
+ const raw = change.after ?? (await ctx.readFile(change.path));
114
+ if (typeof raw !== "string")
115
+ continue;
116
+ if (!isSnapshotPage(change.path))
117
+ continue;
118
+ const base = await runBaseValidateChecks(toPosix(change.path), parseFrontmatter(raw), c.root, ctx);
119
+ // A read-only crawl mirror carries `fetchedAt` provenance, never an `updated`
120
+ // field — so `missing-updated` is not a defect on a snapshot page.
121
+ diagnostics.push(...base.filter((d) => d.issue !== "missing-updated"));
122
+ }
123
+ return diagnostics;
124
+ }
125
+ export const websiteSnapshotAdapter = {
126
+ id: "website-snapshot",
127
+ version: "0.9.0",
128
+ extensions: [".md"],
129
+ recognize,
130
+ validate,
131
+ // No placeNew: the snapshot is READ-ONLY (Mode A). Export (Mode B) routes
132
+ // content through the DESTINATION adapter, which owns placement.
133
+ /**
134
+ * Install-time probe (§1.2): a root carrying the snapshot provenance
135
+ * `manifest.json` (`{url, fetchedAt}`). No other bundle root carries this
136
+ * exact marker, so the probe is unambiguous.
137
+ */
138
+ looksLikeRoot(root) {
139
+ let raw;
140
+ try {
141
+ raw = fs.readFileSync(path.join(root, MANIFEST_FILE), "utf8");
142
+ }
143
+ catch {
144
+ return false;
145
+ }
146
+ try {
147
+ const manifest = JSON.parse(raw);
148
+ return typeof manifest.url === "string" && typeof manifest.fetchedAt === "string";
149
+ }
150
+ catch {
151
+ return false;
152
+ }
153
+ },
154
+ };
@@ -0,0 +1,4 @@
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
+ export {};
@@ -0,0 +1,42 @@
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 { directoryMatcher, extensionMatcher, parentDirHintMatcher, smartMdMatcher, workflowProgramMatcher, } from "../../indexer/walk/matchers.js";
5
+ /**
6
+ * The five builtin matchers, in registration order. The array index IS the
7
+ * registration index `runMatchers` uses for tie-breaking. (The `wiki` matcher
8
+ * was removed in chunk 4 — the wiki asset-type is retired; LLM Wiki content is
9
+ * served by the first-class `llm-wiki` adapter, not the akm adapter.)
10
+ */
11
+ const AKM_MATCHERS = [
12
+ extensionMatcher,
13
+ directoryMatcher,
14
+ parentDirHintMatcher,
15
+ smartMdMatcher,
16
+ workflowProgramMatcher,
17
+ ];
18
+ /**
19
+ * Synchronous reproduction of `file-context.ts#runMatchers`'s arbitration
20
+ * (`:242-265`), minus its `ensureBuiltinsRegistered()` dynamic import. Runs
21
+ * every builtin matcher in registration order, collects the non-null
22
+ * `MatchResult`s, and returns the highest-specificity one (ties broken by the
23
+ * later-registered matcher — higher index — winning). Returns null when no
24
+ * matcher claims the file.
25
+ */
26
+ export function recognizeMatch(file) {
27
+ const hits = [];
28
+ for (let i = 0; i < AKM_MATCHERS.length; i++) {
29
+ const result = AKM_MATCHERS[i](file);
30
+ if (result !== null)
31
+ hits.push({ result, index: i });
32
+ }
33
+ if (hits.length === 0)
34
+ return null;
35
+ hits.sort((a, b) => {
36
+ const specDiff = b.result.specificity - a.result.specificity;
37
+ if (specDiff !== 0)
38
+ return specDiff;
39
+ return b.index - a.index;
40
+ });
41
+ return hits[0].result;
42
+ }
@@ -0,0 +1,56 @@
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 format-family adapter registry — akm 0.9.0 (§4 / normative §12.6).
6
+ *
7
+ * A STATIC, FROZEN registry per normative §12.6: the ordered built-in adapter
8
+ * list ({@link BUILTIN_ADAPTERS}) is defined in the built-in barrel
9
+ * (`./adapters`) and this module exposes read-only lookups over it. There is NO
10
+ * mutable registration step and NO load-order dependency — `getAdapters()` and
11
+ * `adapterForId()` are populated at MODULE LOAD, so every production call site
12
+ * sees the full set without anyone first calling a registration function. This
13
+ * replaces the earlier mutable module-level singleton, whose "someone must
14
+ * register the built-ins first" contract left the registry empty in production
15
+ * (every source then fell back to `akm`).
16
+ *
17
+ * PRODUCTION CONSUMERS (all install/index-time, never query-time): the ordered
18
+ * `looksLikeRoot` probe in `installations.ts#detectAdapterId`, and the
19
+ * bundle-root probe in `provider-utils.ts#detectStashRoot`.
20
+ *
21
+ * KEYED BY `adapter.id` ONLY. Adapters are FORMAT FAMILIES (§0.2): one adapter
22
+ * per component root, and `recognize()` is the single source of truth for what
23
+ * a file IS. The open OKF `type` lives on the emitted `IndexDocument`, never on
24
+ * the adapter — so there is deliberately NO per-`type` → adapter mapping here.
25
+ *
26
+ * QUERY-TIME SAFETY (normative §14.3 / D11 — "adapters/registry never run at
27
+ * query time"): this module is imported only from install/index-time modules;
28
+ * the search path (`indexer/search/**`) does not import it, and importing the
29
+ * frozen list pulls the concrete adapters into no query-time graph.
30
+ */
31
+ import { BUILTIN_ADAPTERS } from "./adapters/index.js";
32
+ export { BUILTIN_ADAPTERS } from "./adapters/index.js";
33
+ /** `adapter.id -> adapter`, frozen at module load from the static built-in list. */
34
+ const BY_ID = new Map(BUILTIN_ADAPTERS.map((a) => [a.id, a]));
35
+ /**
36
+ * Every built-in adapter, in the §1.2 install-time probe order (array order ==
37
+ * probe precedence; see `./adapters` for the ordering rationale). Returns a
38
+ * fresh array each call so callers may sort/filter it without disturbing the
39
+ * frozen registry.
40
+ */
41
+ export function getAdapters() {
42
+ return [...BUILTIN_ADAPTERS];
43
+ }
44
+ /** Look up an adapter by its own `id` (matches `BundleComponent.adapter`); `undefined` for an unknown id (spec §4 — caller skips + warns). */
45
+ export function adapterForId(id) {
46
+ return BY_ID.get(id);
47
+ }
48
+ /**
49
+ * DEPRECATED no-op retained for test back-compat only. The registry is a static
50
+ * frozen map (normative §12.6) populated at module load, so there is nothing to
51
+ * reset — `getAdapters()` / `adapterForId()` are always the full built-in set.
52
+ * New code MUST NOT depend on this.
53
+ */
54
+ export function resetAdapterRegistryForTests() {
55
+ // intentionally empty — the registry is static; see the doc comment above.
56
+ }
@@ -0,0 +1,4 @@
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
+ export {};
@@ -0,0 +1,229 @@
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
+ * Pure recognition/placement layer for the built-in akm asset types — akm
6
+ * 0.9.0 chunk-3 (the taxonomy-cutover leaf).
7
+ *
8
+ * This module is the SINGLE SOURCE OF TRUTH for the `AssetSpec` filesystem
9
+ * surface (`stashDir`/`isRelevantFile`/`toCanonicalName`/`toAssetPath`), the
10
+ * per-type stash-subdir map, and the derive/resolve helpers built on them.
11
+ * Chunk-3 deleted the mutable taxonomy globals that used to expose this data
12
+ * as ambient registries; the surface is now reached through the small typed
13
+ * accessors below (`stashDirFor`/`stashDirNames`/`placementTypes`/
14
+ * `assetPathForName`/`placementSpecFor`), which the `akm` bundle adapter
15
+ * (`adapter/adapters/akm-adapter.ts`) consumes for placement.
16
+ *
17
+ * ── Cycle-safety ──
18
+ *
19
+ * This leaf imports only Node builtins and the `core/recognition-util` pure
20
+ * sink, so it is NOT an import-cycle (SCC) participant. Depending on it from
21
+ * the `akm` adapter keeps the adapter a leaf. Renderer NAMES and action
22
+ * builders for the built-in types live in the static `type-presentation.ts`
23
+ * table (`TYPE_PRESENTATION`); they are intentionally absent here — placement
24
+ * is a filesystem concern, presentation is a rendering concern.
25
+ */
26
+ import fs from "node:fs";
27
+ import path from "node:path";
28
+ import { SCRIPT_EXTENSIONS, WORKFLOW_EXTENSIONS } from "../recognition-util.js";
29
+ function toPosix(input) {
30
+ return input.replace(/\\/g, "/");
31
+ }
32
+ const workflowSpec = {
33
+ isRelevantFile: (fileName) => WORKFLOW_EXTENSIONS.includes(path.extname(fileName).toLowerCase()),
34
+ toCanonicalName: (typeRoot, filePath) => {
35
+ const rel = toPosix(path.relative(typeRoot, filePath));
36
+ for (const ext of WORKFLOW_EXTENSIONS) {
37
+ if (rel.toLowerCase().endsWith(ext))
38
+ return rel.slice(0, -ext.length);
39
+ }
40
+ return rel;
41
+ },
42
+ toAssetPath: (typeRoot, name) => {
43
+ // Explicit extension wins (accepts refs like "release/ship.yaml").
44
+ const lower = name.toLowerCase();
45
+ for (const ext of WORKFLOW_EXTENSIONS) {
46
+ if (lower.endsWith(ext))
47
+ return path.join(typeRoot, name);
48
+ }
49
+ // Probe in priority order — `.md` first for back-compat — and fall back
50
+ // to the markdown path so error messages keep naming the canonical file.
51
+ for (const ext of WORKFLOW_EXTENSIONS) {
52
+ const candidate = path.join(typeRoot, `${name}${ext}`);
53
+ if (fs.existsSync(candidate))
54
+ return candidate;
55
+ }
56
+ return path.join(typeRoot, `${name}.md`);
57
+ },
58
+ };
59
+ const markdownSpec = {
60
+ isRelevantFile: (fileName) => path.extname(fileName).toLowerCase() === ".md",
61
+ toCanonicalName: (typeRoot, filePath) => {
62
+ const rel = toPosix(path.relative(typeRoot, filePath));
63
+ // Strip .md extension from canonical names (agent:code-reviewer, not agent:code-reviewer.md)
64
+ return rel.endsWith(".md") ? rel.slice(0, -3) : rel;
65
+ },
66
+ toAssetPath: (typeRoot, name) => {
67
+ // Accept both with and without .md extension
68
+ const withExt = name.endsWith(".md") ? name : `${name}.md`;
69
+ return path.join(typeRoot, withExt);
70
+ },
71
+ };
72
+ const scriptSpec = {
73
+ isRelevantFile: (fileName) => SCRIPT_EXTENSIONS.has(path.extname(fileName).toLowerCase()),
74
+ toCanonicalName: (typeRoot, filePath) => toPosix(path.relative(typeRoot, filePath)),
75
+ toAssetPath: (typeRoot, name) => path.join(typeRoot, name),
76
+ };
77
+ const PLACEMENT_SPECS = {
78
+ skill: {
79
+ stashDir: "skills",
80
+ isRelevantFile: (fileName) => fileName === "SKILL.md",
81
+ toCanonicalName: (typeRoot, filePath) => {
82
+ const relDir = toPosix(path.dirname(path.relative(typeRoot, filePath)));
83
+ if (!relDir || relDir === ".")
84
+ return undefined;
85
+ return relDir;
86
+ },
87
+ toAssetPath: (typeRoot, name) => path.join(typeRoot, name, "SKILL.md"),
88
+ },
89
+ command: { stashDir: "commands", ...markdownSpec },
90
+ agent: { stashDir: "agents", ...markdownSpec },
91
+ knowledge: { stashDir: "knowledge", ...markdownSpec },
92
+ workflow: { stashDir: "workflows", ...workflowSpec },
93
+ script: { stashDir: "scripts", ...scriptSpec },
94
+ memory: { stashDir: "memories", ...markdownSpec },
95
+ // Environment assets — whole `.env` files sourced/injected wholesale. Replaced
96
+ // the deprecated `vault` type (removed in 0.9.0). Only key NAMES are surfaced
97
+ // as metadata; values and comment text are never read for indexing (comments
98
+ // routinely contain commented-out credentials).
99
+ env: {
100
+ stashDir: "env",
101
+ isRelevantFile: (fileName) => fileName === ".env" || fileName.endsWith(".env"),
102
+ toCanonicalName: (typeRoot, filePath) => {
103
+ const rel = toPosix(path.relative(typeRoot, filePath));
104
+ const fileName = path.basename(rel);
105
+ // Treat ".env" as the "default" env; "<name>.env" → "<name>"
106
+ if (fileName === ".env") {
107
+ const dir = path.dirname(rel);
108
+ return dir === "." || dir === "" ? "default" : `${dir}/default`;
109
+ }
110
+ const stripped = rel.endsWith(".env") ? rel.slice(0, -4) : rel;
111
+ return stripped;
112
+ },
113
+ toAssetPath: (typeRoot, name) => {
114
+ if (name === "default")
115
+ return path.join(typeRoot, ".env");
116
+ return path.join(typeRoot, name.endsWith(".env") ? name : `${name}.env`);
117
+ },
118
+ },
119
+ // Secrets — a single sensitive value used on its own for authentication (a
120
+ // PEM key, API token, TLS cert). Unlike `env` (a group of related .env
121
+ // configuration), the ENTIRE file is the one secret value — there is no safe
122
+ // region to parse, so only the filename is ever surfaced as metadata. A
123
+ // secret is any regular file under `secrets/` except `.lock`/`.sensitive`
124
+ // sidecars; the canonical name preserves the natural filename.
125
+ secret: {
126
+ stashDir: "secrets",
127
+ isRelevantFile: (fileName) => !fileName.endsWith(".lock") && !fileName.endsWith(".sensitive"),
128
+ toCanonicalName: (typeRoot, filePath) => toPosix(path.relative(typeRoot, filePath)),
129
+ toAssetPath: (typeRoot, name) => path.join(typeRoot, name),
130
+ },
131
+ // v1 spec §13 — `lesson` asset type. Required frontmatter fields are
132
+ // `description` and `when_to_use`; lint enforces both.
133
+ lesson: { stashDir: "lessons", ...markdownSpec },
134
+ // Scheduled tasks. A task file pairs a cron-style schedule with a target
135
+ // (workflow ref, prompt, or command). Stored as pure YAML under
136
+ // <stash>/tasks/<id>.yml.
137
+ task: {
138
+ stashDir: "tasks",
139
+ isRelevantFile: (fileName) => path.extname(fileName).toLowerCase() === ".yml",
140
+ toCanonicalName: (typeRoot, filePath) => {
141
+ const rel = toPosix(path.relative(typeRoot, filePath));
142
+ return rel.endsWith(".yml") ? rel.slice(0, -4) : rel;
143
+ },
144
+ toAssetPath: (typeRoot, name) => {
145
+ const withExt = name.endsWith(".yml") ? name : `${name}.yml`;
146
+ return path.join(typeRoot, withExt);
147
+ },
148
+ },
149
+ // #561 — agent sessions indexed as a first-class searchable asset type.
150
+ // Generated markdown written by the `extract` pass to
151
+ // `sessions/<harness>/<session-id>.md`.
152
+ session: { stashDir: "sessions", ...markdownSpec },
153
+ // Durable stash-level semantic knowledge — facts about the user, team, or
154
+ // project. A plain markdown spec; see docs/architecture/specs/fact-asset-type.md.
155
+ fact: { stashDir: "facts", ...markdownSpec },
156
+ };
157
+ /** Live placement spec for a type, or `undefined` for an unknown type. */
158
+ export function placementSpecFor(type) {
159
+ return PLACEMENT_SPECS[type];
160
+ }
161
+ /** Every registered placement spec (for whole-registry sweeps). */
162
+ export function placementSpecList() {
163
+ return Object.values(PLACEMENT_SPECS);
164
+ }
165
+ /** Every registered placement type key (the set of types that have a stash subdir). */
166
+ export function placementTypes() {
167
+ return Object.keys(PLACEMENT_SPECS);
168
+ }
169
+ /** The stash subdir a type places into, or `undefined` for an unknown type. */
170
+ export function stashDirFor(type) {
171
+ return PLACEMENT_SPECS[type]?.stashDir;
172
+ }
173
+ /**
174
+ * Reverse of {@link stashDirFor}: the placement type owning a stash subdir, or
175
+ * `undefined` when no registered type places into it. The type→subdir map is a
176
+ * bijection over the built-in types (each type has a distinct subdir), so this
177
+ * is the well-defined inverse. Used by the Chunk-5 dual-grammar shim to reverse
178
+ * a D-R2 qualified conceptId (`<stash-subdir>/<name>`) back to a legacy
179
+ * `type:name` predicate so NULL-`item_ref` rows stay findable by new refs.
180
+ */
181
+ export function typeForStashDir(stashDir) {
182
+ for (const [type, spec] of Object.entries(PLACEMENT_SPECS)) {
183
+ if (spec.stashDir === stashDir)
184
+ return type;
185
+ }
186
+ return undefined;
187
+ }
188
+ /** All stash subdir names across the registered types. */
189
+ export function stashDirNames() {
190
+ return Object.values(PLACEMENT_SPECS).map((spec) => spec.stashDir);
191
+ }
192
+ /**
193
+ * Mutate the placement registry to add/replace a type's spec. Used by the
194
+ * custom-asset-type registration surface (extension types); built-ins are
195
+ * baked into {@link PLACEMENT_SPECS} above.
196
+ */
197
+ export function registerAssetSpec(type, spec) {
198
+ PLACEMENT_SPECS[type] = spec;
199
+ }
200
+ /** Remove a previously-registered type's spec. */
201
+ export function deregisterAssetSpec(type) {
202
+ delete PLACEMENT_SPECS[type];
203
+ }
204
+ export function isRelevantAssetFile(assetType, fileName) {
205
+ return PLACEMENT_SPECS[assetType]?.isRelevantFile(fileName) ?? false;
206
+ }
207
+ export function deriveCanonicalAssetName(assetType, typeRoot, filePath) {
208
+ return PLACEMENT_SPECS[assetType]?.toCanonicalName(typeRoot, filePath);
209
+ }
210
+ export function deriveCanonicalAssetNameFromStashRoot(assetType, stashRoot, filePath) {
211
+ const relPath = toPosix(path.relative(stashRoot, filePath));
212
+ const segments = relPath.split("/").filter(Boolean);
213
+ const firstSegment = segments[0];
214
+ // When the first segment matches the canonical type dir (e.g. "agents"),
215
+ // use it as the type root so canonical names are relative to it.
216
+ // Otherwise fall back to stashRoot — this preserves the full relative path
217
+ // as the canonical name, which is correct for installed stashes that live
218
+ // under custom directories (e.g. "tools/agents/svelte-file-editor").
219
+ const typeRoot = firstSegment !== undefined && firstSegment === stashDirFor(assetType)
220
+ ? path.join(stashRoot, firstSegment)
221
+ : stashRoot;
222
+ return deriveCanonicalAssetName(assetType, typeRoot, filePath);
223
+ }
224
+ export function assetPathForName(assetType, typeRoot, name) {
225
+ const spec = PLACEMENT_SPECS[assetType];
226
+ if (!spec)
227
+ throw new Error(`Unknown asset type: "${assetType}"`);
228
+ return spec.toAssetPath(typeRoot, name);
229
+ }