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,416 @@
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
+ * Index-time metadata fold for the `akm` adapter's `recognize` — akm 0.9.0
6
+ * chunk-2, WI-C, implementing spec §2 ("the nine index-time metadata
7
+ * contributors move into recognize") + the 2 workflow contributors.
8
+ *
9
+ * This leaf reproduces the 11 `registerMetadataContributor` sites keyed on the
10
+ * winning RENDERER name (exactly how each contributor's `appliesTo({ rendererName })`
11
+ * selects):
12
+ *
13
+ * - `output/renderers.ts` (9): toc-metadata (knowledge-md),
14
+ * lesson-frontmatter-metadata, memory-frontmatter-metadata,
15
+ * script-comment-metadata, env-file-metadata, secret-file-metadata,
16
+ * task-yaml-metadata, session-md-metadata, fact-md-metadata;
17
+ * - `workflows/renderer.ts` (2): workflow-document-metadata (workflow-md),
18
+ * workflow-program-metadata (workflow-program-yaml).
19
+ *
20
+ * ── Cycle-safety (chunk-2 ratchet, baseline 18) ──
21
+ *
22
+ * Imported ONLY by `akm-adapter.ts` (itself imported by nothing in `src/` — see
23
+ * that file's header), so this leaf can never gain an inbound edge from a cycle
24
+ * participant and therefore can never JOIN a cycle. It VALUE-imports the pure
25
+ * parsers each contributor already uses so the fold cannot drift from them:
26
+ * `parseFrontmatter`, `parseMarkdownToc`, `parseWorkflow`, `parseWorkflowProgram`,
27
+ * `projectProgramParameters`/`programStepInstructions`, and `listKeys`
28
+ * (env key-names). `output/renderers.ts` / `workflows/renderer.ts` are the
29
+ * cycle-sensitive modules whose contributor bodies live in this port — their
30
+ * ONE non-importable helper (`metadata.ts#extractDescriptionFromComments`, a
31
+ * heavy cycle-participant module) is copied verbatim below as
32
+ * {@link extractDescriptionFromComments} rather than imported. Verified:
33
+ * `bun scripts/lint-import-cycles.ts` stays at 18.
34
+ *
35
+ * ── What is folded, and where it lands on the IndexDocument ──
36
+ *
37
+ * The contributors mutate a `IndexDocument`; {@link foldRecognizedMetadata} returns
38
+ * the same fields as a plain {@link FoldedMetadata}, which `recognize` maps onto
39
+ * `IndexDocument` first-class fields (`tags`/`searchHints`/`description`/
40
+ * `confidence`) and, for the fields without a first-class home
41
+ * (`toc`/`parameters`/`source`), onto `documentJson` (opaque adapter extras).
42
+ * The seed is a MINIMAL entry (name+type only): this isolates exactly what the
43
+ * contributors add, which is what the parity test compares against
44
+ * `applyMetadataContributors` run on the same minimal seed.
45
+ *
46
+ * ── Tolerance note ──
47
+ *
48
+ * Every contributor that reads/parses content is reproduced with the SAME
49
+ * try/catch tolerance it has today (toc/memory/session/fact/task swallow parse
50
+ * errors). The two workflow contributors throw-to-skip in today's pipeline (a
51
+ * broken workflow is dropped by the metadata drain); here the parse is wrapped
52
+ * so a broken workflow yields no folded metadata instead of throwing out of the
53
+ * synchronous `recognize` — the drop-the-entry behavior is an index-drain
54
+ * concern (Chunk 4/5), not recognition's. On the valid Chunk-0b fixture this
55
+ * distinction never triggers.
56
+ */
57
+ import fs from "node:fs";
58
+ import { parse as parseYaml } from "yaml";
59
+ import { listKeys } from "../../../commands/env/env.js";
60
+ import { parseWorkflow } from "../../../workflows/parser.js";
61
+ import { parseWorkflowProgram } from "../../../workflows/program/parser.js";
62
+ import { programStepInstructions, projectProgramParameters } from "../../../workflows/program/project.js";
63
+ import { parseFrontmatter } from "../../asset/frontmatter.js";
64
+ import { parseMarkdownToc } from "../../asset/markdown.js";
65
+ import { nonEmptyString } from "./shared.js";
66
+ /**
67
+ * Verbatim copy of `indexer/passes/metadata.ts#extractDescriptionFromComments`
68
+ * (`:1510-1552`) — `metadata.ts` is a heavy cycle-participant module, so the
69
+ * one non-importable helper `applyScriptMetadata` needs is copied here (the
70
+ * others are imported). Reads a leading JSDoc block or hash-comment run from the
71
+ * script file; returns `null` on read/parse miss.
72
+ */
73
+ function extractDescriptionFromComments(filePath) {
74
+ let content;
75
+ try {
76
+ content = fs.readFileSync(filePath, "utf8");
77
+ }
78
+ catch {
79
+ return null;
80
+ }
81
+ const lines = content.split(/\r?\n/).slice(0, 50);
82
+ const blockStart = lines.findIndex((l) => /^\s*\/\*\*/.test(l));
83
+ if (blockStart >= 0) {
84
+ const desc = [];
85
+ for (let i = blockStart; i < lines.length; i++) {
86
+ const line = lines[i];
87
+ if (i > blockStart && /\*\//.test(line))
88
+ break;
89
+ const cleaned = line
90
+ .replace(/^\s*\/?\*\*?\s?/, "")
91
+ .replace(/\*\/\s*$/, "")
92
+ .trim();
93
+ if (cleaned)
94
+ desc.push(cleaned);
95
+ }
96
+ if (desc.length > 0)
97
+ return desc.join(" ");
98
+ }
99
+ let start = 0;
100
+ if (lines[0]?.startsWith("#!"))
101
+ start = 1;
102
+ const hashLines = [];
103
+ for (let i = start; i < lines.length; i++) {
104
+ const line = lines[i].trim();
105
+ if (line.startsWith("#") && !line.startsWith("#!")) {
106
+ hashLines.push(line.replace(/^#+\s*/, "").trim());
107
+ }
108
+ else if (line === "") {
109
+ }
110
+ else {
111
+ break;
112
+ }
113
+ }
114
+ if (hashLines.length > 0)
115
+ return hashLines.join(" ");
116
+ return null;
117
+ }
118
+ /**
119
+ * Reproduce `applyFrontmatterDescriptionAndTags` (`output/renderers.ts:668-684`):
120
+ * set description/source/confidence from frontmatter (only when not already set)
121
+ * and merge frontmatter `tags:` onto the folded tags. Returns nothing — mutates
122
+ * `out`.
123
+ */
124
+ function applyFrontmatterDescriptionAndTags(fm, out) {
125
+ const desc = nonEmptyString(fm.description);
126
+ if (desc && !out.description) {
127
+ out.description = desc;
128
+ out.source = "frontmatter";
129
+ out.confidence = 0.9;
130
+ }
131
+ if (Array.isArray(fm.tags) && fm.tags.length > 0) {
132
+ const fmTags = fm.tags.filter((t) => typeof t === "string" && t.trim().length > 0);
133
+ if (fmTags.length > 0) {
134
+ out.tags = Array.from(new Set([...(out.tags ?? []), ...fmTags]));
135
+ }
136
+ }
137
+ }
138
+ /** Collect + finalize a searchHints set the way every contributor does (`Array.from(hints).filter(Boolean)`, assigned only when non-empty). */
139
+ function finalizeHints(out, hints) {
140
+ if (hints.size > 0)
141
+ out.searchHints = Array.from(hints).filter(Boolean);
142
+ }
143
+ /**
144
+ * The metadata fold, keyed on the winning renderer NAME. Returns the fields the
145
+ * 11 contributors would add to a MINIMAL (name+type) `IndexDocument`. `recognize`
146
+ * maps the result onto the `IndexDocument`. Reads the live file (index-time, so
147
+ * disk reads are legitimate — unlike `validate`).
148
+ */
149
+ export function foldRecognizedMetadata(rendererName, file) {
150
+ const out = {};
151
+ switch (rendererName) {
152
+ // ── toc-metadata (knowledge-md) ──
153
+ case "knowledge-md": {
154
+ try {
155
+ const toc = parseMarkdownToc(file.content());
156
+ if (toc.headings.length > 0)
157
+ out.toc = toc.headings;
158
+ }
159
+ catch {
160
+ // Non-fatal: skip TOC if file can't be read
161
+ }
162
+ return out;
163
+ }
164
+ // ── lesson-frontmatter-metadata (lesson-md) ──
165
+ case "lesson-md": {
166
+ try {
167
+ const fm = parseFrontmatter(file.content()).data;
168
+ applyFrontmatterDescriptionAndTags(fm, out);
169
+ const whenToUse = nonEmptyString(fm.when_to_use);
170
+ if (whenToUse)
171
+ finalizeHints(out, new Set([`when_to_use:${whenToUse}`]));
172
+ }
173
+ catch {
174
+ // Non-fatal: skip metadata extraction on parse error
175
+ }
176
+ return out;
177
+ }
178
+ // ── memory-frontmatter-metadata (memory-md) ──
179
+ case "memory-md": {
180
+ try {
181
+ const fm = parseFrontmatter(file.content()).data;
182
+ applyFrontmatterDescriptionAndTags(fm, out);
183
+ const hints = new Set();
184
+ const source = nonEmptyString(fm.source);
185
+ if (source)
186
+ hints.add(source);
187
+ const fmObservedAt = nonEmptyString(fm.observed_at);
188
+ if (fmObservedAt) {
189
+ hints.add(`observed_at:${fmObservedAt}`);
190
+ }
191
+ else {
192
+ try {
193
+ const isoDate = file.stat().mtime.toISOString().slice(0, 10);
194
+ hints.add(`observed_at:${isoDate}`);
195
+ }
196
+ catch {
197
+ // Non-fatal: skip mtime fallback on stat error
198
+ }
199
+ }
200
+ const expires = nonEmptyString(fm.expires);
201
+ if (expires)
202
+ hints.add(`expires:${expires}`);
203
+ if (fm.subjective === true)
204
+ hints.add("subjective");
205
+ finalizeHints(out, hints);
206
+ }
207
+ catch {
208
+ // Non-fatal: skip metadata extraction on error
209
+ }
210
+ return out;
211
+ }
212
+ // ── script-comment-metadata (script-source) ──
213
+ case "script-source": {
214
+ if (file.ext === ".md")
215
+ return out;
216
+ const commentDesc = extractDescriptionFromComments(file.absPath);
217
+ if (commentDesc && !out.description) {
218
+ out.description = commentDesc;
219
+ out.source = "comments";
220
+ out.confidence = 0.7;
221
+ }
222
+ return out;
223
+ }
224
+ // ── env-file-metadata (env-file) ──
225
+ case "env-file": {
226
+ const { keys } = listKeys(file.absPath);
227
+ if (keys.length > 0)
228
+ out.searchHints = keys;
229
+ out.tags = Array.from(new Set([...(out.tags ?? []), "env", "secrets"]));
230
+ return out;
231
+ }
232
+ // ── secret-file-metadata (secret-file) — tags only, NEVER reads the body ──
233
+ case "secret-file": {
234
+ out.tags = Array.from(new Set([...(out.tags ?? []), "secret", "sensitive"]));
235
+ return out;
236
+ }
237
+ // ── task-yaml-metadata (task-yaml) ──
238
+ case "task-yaml": {
239
+ out.tags = Array.from(new Set([...(out.tags ?? []), "task", "scheduled"]));
240
+ try {
241
+ const doc = parseYaml(file.content());
242
+ const data = doc && typeof doc === "object" && !Array.isArray(doc) ? doc : {};
243
+ const hints = new Set();
244
+ const schedule = nonEmptyString(data.schedule);
245
+ if (schedule)
246
+ hints.add(`schedule:${schedule}`);
247
+ const workflow = nonEmptyString(data.workflow);
248
+ if (workflow)
249
+ hints.add(`workflow:${workflow}`);
250
+ const prompt = nonEmptyString(data.prompt);
251
+ if (prompt)
252
+ hints.add(`prompt:${prompt}`);
253
+ finalizeHints(out, hints);
254
+ }
255
+ catch {
256
+ // Non-fatal: skip metadata extraction on parse error
257
+ }
258
+ return out;
259
+ }
260
+ // ── session-md-metadata (session-md) ──
261
+ case "session-md": {
262
+ try {
263
+ const fm = parseFrontmatter(file.content()).data;
264
+ applyFrontmatterDescriptionAndTags(fm, out);
265
+ out.tags = Array.from(new Set([...(out.tags ?? []), "session"]));
266
+ const hints = new Set();
267
+ const harness = nonEmptyString(fm.harness);
268
+ if (harness)
269
+ hints.add(`harness:${harness}`);
270
+ const project = nonEmptyString(fm.project);
271
+ if (project)
272
+ hints.add(`project:${project}`);
273
+ const logPath = nonEmptyString(fm.log_path);
274
+ if (logPath)
275
+ hints.add(`log_path:${logPath}`);
276
+ finalizeHints(out, hints);
277
+ }
278
+ catch {
279
+ // Non-fatal: skip metadata extraction on parse error
280
+ }
281
+ return out;
282
+ }
283
+ // ── fact-md-metadata (fact-md) ──
284
+ case "fact-md": {
285
+ try {
286
+ const fm = parseFrontmatter(file.content()).data;
287
+ applyFrontmatterDescriptionAndTags(fm, out);
288
+ const tags = new Set([...(out.tags ?? []), "fact"]);
289
+ const hints = new Set();
290
+ const category = nonEmptyString(fm.category);
291
+ if (category) {
292
+ tags.add(category);
293
+ hints.add(`category:${category}`);
294
+ }
295
+ if (fm.pinned === true) {
296
+ tags.add("pinned");
297
+ hints.add("pinned");
298
+ }
299
+ out.tags = Array.from(tags).filter(Boolean);
300
+ finalizeHints(out, hints);
301
+ }
302
+ catch {
303
+ // Non-fatal: skip metadata extraction on parse error
304
+ }
305
+ return out;
306
+ }
307
+ // ── workflow-document-metadata (workflow-md) ──
308
+ case "workflow-md": {
309
+ try {
310
+ const result = parseWorkflow(file.content(), { path: file.relPath });
311
+ if (!result.ok)
312
+ return out;
313
+ const doc = result.document;
314
+ const hints = new Set();
315
+ hints.add(doc.title);
316
+ for (const step of doc.steps) {
317
+ hints.add(step.title);
318
+ hints.add(step.id);
319
+ hints.add(step.instructions.text);
320
+ for (const criterion of step.completionCriteria ?? [])
321
+ hints.add(criterion.text);
322
+ }
323
+ out.searchHints = Array.from(hints).filter(Boolean);
324
+ if (doc.parameters?.length) {
325
+ out.parameters = doc.parameters.map((p) => ({
326
+ name: p.name,
327
+ ...(p.description ? { description: p.description } : {}),
328
+ }));
329
+ }
330
+ }
331
+ catch {
332
+ // See file header: broken workflows drop at drain time, not here.
333
+ }
334
+ return out;
335
+ }
336
+ // ── workflow-program-metadata (workflow-program-yaml) ──
337
+ case "workflow-program-yaml": {
338
+ try {
339
+ const result = parseWorkflowProgram(file.content(), { path: file.relPath });
340
+ if (!result.ok)
341
+ return out;
342
+ const program = result.program;
343
+ const hints = new Set();
344
+ hints.add(program.name);
345
+ for (const step of program.steps) {
346
+ hints.add(step.id);
347
+ if (step.title)
348
+ hints.add(step.title);
349
+ hints.add(programStepInstructions(step));
350
+ for (const criterion of step.gate?.criteria ?? [])
351
+ hints.add(criterion);
352
+ }
353
+ out.searchHints = Array.from(hints).filter(Boolean);
354
+ if (!out.description && program.description)
355
+ out.description = program.description;
356
+ const parameters = projectProgramParameters(program);
357
+ if (parameters?.length)
358
+ out.parameters = parameters;
359
+ }
360
+ catch {
361
+ // See file header: broken programs drop at drain time, not here.
362
+ }
363
+ return out;
364
+ }
365
+ default:
366
+ // No contributor applies to this renderer (e.g. skill-md/command-md/
367
+ // agent-md — the static-only mappings carry no metadata contributor).
368
+ return out;
369
+ }
370
+ }
371
+ /**
372
+ * Apply {@link foldRecognizedMetadata}'s output onto a `IndexDocument` with the
373
+ * SAME precedence the live in-place renderer contributors use (Chunk 5 M-b), so
374
+ * `entry.applyPreContributorFields → applyFoldedMetadata → applyPostContributorFields`
375
+ * reproduces `buildEntryFromFile`'s `P1/P2 → contributors → P4` byte-for-byte.
376
+ *
377
+ * Precedence, verified against every case in {@link foldRecognizedMetadata}:
378
+ * - description/source/confidence travel together and only when the entry has
379
+ * no description yet (contributors gate on `!entry.description`); a
380
+ * contributor that sets description WITHOUT source/confidence
381
+ * (workflow-program-yaml) leaves those untouched — mirrored by the
382
+ * `folded.source`/`folded.confidence` guards below;
383
+ * - tags UNION into the existing set (order-preserving Set dedup), matching the
384
+ * contributors' `Array.from(new Set([...entry.tags, ...added]))`;
385
+ * - searchHints / toc / parameters are SET (overwrite), matching the
386
+ * contributors' direct assignment.
387
+ *
388
+ * The fold computes each field unconditionally from an empty seed; re-gating on
389
+ * `entry` state here is what recovers the in-place precedence (the fold ≡
390
+ * contributors-on-a-minimal-seed is pinned by the akm-adapter fold-parity test).
391
+ */
392
+ export function applyFoldedMetadata(entry, folded) {
393
+ if (folded.description && !entry.description) {
394
+ entry.description = folded.description;
395
+ if (folded.source)
396
+ entry.source = folded.source;
397
+ if (folded.confidence !== undefined)
398
+ entry.confidence = folded.confidence;
399
+ }
400
+ if (folded.tags && folded.tags.length > 0) {
401
+ entry.tags = Array.from(new Set([...(entry.tags ?? []), ...folded.tags]));
402
+ }
403
+ // searchHints MERGE (not overwrite): every live contributor seeds its hints
404
+ // from `new Set(entry.searchHints ?? [])` before adding, so a frontmatter
405
+ // `searchHints:` set by P2 (applyCuratedFrontmatter) survives and the
406
+ // contributor's hints append to it. The fold computes only the contributor's
407
+ // additions (from an empty seed), so unioning them onto the existing set —
408
+ // existing first, deduped, truthy-filtered — reproduces the live merge exactly.
409
+ if (folded.searchHints) {
410
+ entry.searchHints = Array.from(new Set([...(entry.searchHints ?? []), ...folded.searchHints])).filter(Boolean);
411
+ }
412
+ if (folded.toc)
413
+ entry.toc = folded.toc;
414
+ if (folded.parameters)
415
+ entry.parameters = folded.parameters;
416
+ }
@@ -0,0 +1,150 @@
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-task` adapter — akm 0.9.0 format-family work item (#46).
6
+ *
7
+ * A native akm task-YAML bundle (spec §6/§7). A `.yml` file derives
8
+ * `type: task`; conceptId strips the `.yml` extension. Tasks are AKM-native
9
+ * YAML, NOT OKF markdown concepts. Recognition does NOT gate on validity — an
10
+ * invalid task (e.g. two targets) is still RECOGNIZED; the `invalid-task-yaml`
11
+ * violation surfaces only in `validate`.
12
+ *
13
+ * ── validate (spec §6 task validation column) ──
14
+ *
15
+ * A task must declare a `schedule`, an `enabled` boolean, and EXACTLY ONE
16
+ * target (`prompt` XOR `workflow` XOR `command`). The akm adapter's
17
+ * `TaskLinter` port checks "at least one" target; the native task family here is
18
+ * STRICTER — declaring two targets is `invalid-task-yaml`. So this adapter owns
19
+ * a purpose-built one-target check rather than reusing that port.
20
+ *
21
+ * Conformance oracle (authored, DO NOT modify): fixture
22
+ * `tests/fixtures/bundles/akm-task/` + goldens
23
+ * `tests/fixtures/format-family-goldens/akm-task/{recognition,placement,lint,renderer}.json`.
24
+ */
25
+ import fs from "node:fs";
26
+ import path from "node:path";
27
+ import { parse as parseYaml } from "yaml";
28
+ import { hashContent } from "./shared.js";
29
+ /** A native task bundle is single-component; its one component is `main`. */
30
+ const COMPONENT_ID = "main";
31
+ /** The task YAML extension (spec §6 task row). */
32
+ const TASK_EXT = ".yml";
33
+ /** The mutually-exclusive task target keys (exactly one required). */
34
+ const TARGET_KEYS = ["prompt", "workflow", "command"];
35
+ /** Upper bound on the bounded `content` FTS field (mirrors okf-adapter). */
36
+ const MAX_CONTENT_CHARS = 100_000;
37
+ function toPosix(p) {
38
+ return p.replace(/\\/g, "/");
39
+ }
40
+ function recognize(c, file) {
41
+ if (file.ext !== TASK_EXT)
42
+ return null;
43
+ const conceptId = toPosix(file.relPath).replace(/\.yml$/i, "");
44
+ const name = conceptId.split("/").pop() ?? conceptId;
45
+ const raw = file.content();
46
+ return {
47
+ ref: `${c.id}//${conceptId}`,
48
+ bundle: c.id,
49
+ component: COMPONENT_ID,
50
+ conceptId,
51
+ path: file.absPath,
52
+ hash: hashContent(raw),
53
+ adapterId: "akm-task",
54
+ type: "task",
55
+ name,
56
+ content: raw.length > MAX_CONTENT_CHARS ? raw.slice(0, MAX_CONTENT_CHARS) : raw,
57
+ };
58
+ }
59
+ /** Parse a task YAML into a plain record (tolerant: malformed / non-mapping → {}). */
60
+ function parseTaskYaml(raw) {
61
+ try {
62
+ const doc = parseYaml(raw);
63
+ if (doc && typeof doc === "object" && !Array.isArray(doc))
64
+ return doc;
65
+ }
66
+ catch {
67
+ // malformed YAML
68
+ }
69
+ return {};
70
+ }
71
+ /** The native `invalid-task-yaml` check: schedule + enabled(boolean) + EXACTLY ONE target. */
72
+ function taskDiagnostics(relPath, data) {
73
+ if (Object.keys(data).length === 0)
74
+ return [];
75
+ const problems = [];
76
+ if (typeof data.schedule !== "string" || data.schedule.trim() === "")
77
+ problems.push("schedule");
78
+ if (typeof data.enabled !== "boolean")
79
+ problems.push("enabled (must be a boolean)");
80
+ const targets = TARGET_KEYS.filter((k) => k in data && data[k] !== undefined && data[k] !== null);
81
+ if (targets.length === 0)
82
+ problems.push("exactly one target (prompt, workflow, or command)");
83
+ else if (targets.length > 1)
84
+ problems.push(`exactly one target — declares ${targets.length} (${targets.join(", ")})`);
85
+ if (problems.length === 0)
86
+ return [];
87
+ return [
88
+ { file: relPath, issue: "invalid-task-yaml", detail: `task field errors: ${problems.join("; ")}`, fixed: false },
89
+ ];
90
+ }
91
+ async function validate(_c, changes, ctx) {
92
+ const diagnostics = [];
93
+ for (const change of changes) {
94
+ if (change.op === "delete")
95
+ continue;
96
+ const raw = change.after ?? (await ctx.readFile(change.path));
97
+ if (typeof raw !== "string")
98
+ continue;
99
+ if (path.extname(change.path).toLowerCase() !== TASK_EXT)
100
+ continue;
101
+ diagnostics.push(...taskDiagnostics(toPosix(change.path), parseTaskYaml(raw)));
102
+ }
103
+ return diagnostics;
104
+ }
105
+ export const akmTaskAdapter = {
106
+ id: "akm-task",
107
+ version: "0.9.0",
108
+ extensions: [TASK_EXT],
109
+ recognize,
110
+ validate,
111
+ /** A task places to `<conceptId>.yml`; an already-suffixed conceptId is idempotent. */
112
+ placeNew(c, conceptId) {
113
+ const posix = toPosix(conceptId);
114
+ return path.join(c.root, /\.yml$/i.test(posix) ? posix : `${posix}.yml`);
115
+ },
116
+ /** Tasks live anywhere under the component root. */
117
+ directoryList() {
118
+ return ["."];
119
+ },
120
+ /**
121
+ * Install-time probe (§1.2): a root holding a top-level `.yml` file that
122
+ * parses as a task (a `schedule` key). The task-shape probe keeps it disjoint
123
+ * from the `akm-workflow` YAML program (`version` + `steps`, no `schedule`)
124
+ * and from any non-task YAML.
125
+ */
126
+ looksLikeRoot(root) {
127
+ let entries;
128
+ try {
129
+ entries = fs.readdirSync(root, { withFileTypes: true });
130
+ }
131
+ catch {
132
+ return false;
133
+ }
134
+ for (const entry of entries) {
135
+ if (!entry.isFile() || path.extname(entry.name).toLowerCase() !== TASK_EXT)
136
+ continue;
137
+ let raw;
138
+ try {
139
+ raw = fs.readFileSync(path.join(root, entry.name), "utf8");
140
+ }
141
+ catch {
142
+ continue;
143
+ }
144
+ const data = parseTaskYaml(raw);
145
+ if (typeof data.schedule === "string" && data.schedule.trim() !== "")
146
+ return true;
147
+ }
148
+ return false;
149
+ },
150
+ };