@askdkc/kiokuko 0.1.16 → 0.1.19

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 (549) hide show
  1. package/README.ja.md +91 -112
  2. package/README.ko.md +90 -102
  3. package/README.md +103 -260
  4. package/README.zh-CN.md +88 -102
  5. package/dist/agent-file/atomic-write.d.ts +90 -3
  6. package/dist/agent-file/atomic-write.d.ts.map +1 -1
  7. package/dist/agent-file/atomic-write.js +990 -14
  8. package/dist/agent-file/atomic-write.js.map +1 -1
  9. package/dist/agent-file/managed-block.d.ts +12 -1
  10. package/dist/agent-file/managed-block.d.ts.map +1 -1
  11. package/dist/agent-file/managed-block.js +49 -4
  12. package/dist/agent-file/managed-block.js.map +1 -1
  13. package/dist/agent-file/render.d.ts +1 -1
  14. package/dist/agent-file/render.d.ts.map +1 -1
  15. package/dist/agent-file/render.js +10 -7
  16. package/dist/agent-file/render.js.map +1 -1
  17. package/dist/akinator/agent-task.d.ts +14 -24
  18. package/dist/akinator/agent-task.d.ts.map +1 -1
  19. package/dist/akinator/agent-task.js +460 -103
  20. package/dist/akinator/agent-task.js.map +1 -1
  21. package/dist/akinator/capabilities.d.ts +52 -7
  22. package/dist/akinator/capabilities.d.ts.map +1 -1
  23. package/dist/akinator/capabilities.js +226 -28
  24. package/dist/akinator/capabilities.js.map +1 -1
  25. package/dist/akinator/capability-binding.d.ts +11 -0
  26. package/dist/akinator/capability-binding.d.ts.map +1 -0
  27. package/dist/akinator/capability-binding.js +56 -0
  28. package/dist/akinator/capability-binding.js.map +1 -0
  29. package/dist/akinator/domain.js +2 -2
  30. package/dist/akinator/domain.js.map +1 -1
  31. package/dist/akinator/knowledge-path.d.ts.map +1 -1
  32. package/dist/akinator/knowledge-path.js +409 -39
  33. package/dist/akinator/knowledge-path.js.map +1 -1
  34. package/dist/akinator/orchestrator.d.ts +3 -4
  35. package/dist/akinator/orchestrator.d.ts.map +1 -1
  36. package/dist/akinator/orchestrator.js +1 -4
  37. package/dist/akinator/orchestrator.js.map +1 -1
  38. package/dist/akinator/service.d.ts +0 -4
  39. package/dist/akinator/service.d.ts.map +1 -1
  40. package/dist/akinator/service.js +19 -35
  41. package/dist/akinator/service.js.map +1 -1
  42. package/dist/akinator/skill-discovery-attempt.d.ts +20 -0
  43. package/dist/akinator/skill-discovery-attempt.d.ts.map +1 -0
  44. package/dist/akinator/skill-discovery-attempt.js +390 -0
  45. package/dist/akinator/skill-discovery-attempt.js.map +1 -0
  46. package/dist/akinator/store.d.ts.map +1 -1
  47. package/dist/akinator/store.js +107 -52
  48. package/dist/akinator/store.js.map +1 -1
  49. package/dist/akinator/types.d.ts +0 -12
  50. package/dist/akinator/types.d.ts.map +1 -1
  51. package/dist/bin/kiokuko.js +0 -0
  52. package/dist/cli.d.ts +2 -0
  53. package/dist/cli.d.ts.map +1 -1
  54. package/dist/cli.js +561 -144
  55. package/dist/cli.js.map +1 -1
  56. package/dist/client/server-client.d.ts +5 -3
  57. package/dist/client/server-client.d.ts.map +1 -1
  58. package/dist/client/server-client.js +486 -181
  59. package/dist/client/server-client.js.map +1 -1
  60. package/dist/commands/agent.d.ts +2 -0
  61. package/dist/commands/agent.d.ts.map +1 -1
  62. package/dist/commands/agent.js +861 -86
  63. package/dist/commands/agent.js.map +1 -1
  64. package/dist/commands/backup.d.ts +2 -1
  65. package/dist/commands/backup.d.ts.map +1 -1
  66. package/dist/commands/backup.js +64 -8
  67. package/dist/commands/backup.js.map +1 -1
  68. package/dist/commands/doctor.d.ts +5 -1
  69. package/dist/commands/doctor.d.ts.map +1 -1
  70. package/dist/commands/doctor.js +70 -26
  71. package/dist/commands/doctor.js.map +1 -1
  72. package/dist/commands/export.d.ts +0 -4
  73. package/dist/commands/export.d.ts.map +1 -1
  74. package/dist/commands/export.js +191 -32
  75. package/dist/commands/export.js.map +1 -1
  76. package/dist/commands/import.d.ts +10 -1
  77. package/dist/commands/import.d.ts.map +1 -1
  78. package/dist/commands/import.js +592 -113
  79. package/dist/commands/import.js.map +1 -1
  80. package/dist/commands/init.d.ts +19 -1
  81. package/dist/commands/init.d.ts.map +1 -1
  82. package/dist/commands/init.js +569 -22
  83. package/dist/commands/init.js.map +1 -1
  84. package/dist/commands/purge.d.ts.map +1 -1
  85. package/dist/commands/purge.js +3 -0
  86. package/dist/commands/purge.js.map +1 -1
  87. package/dist/commands/setup.d.ts +34 -8
  88. package/dist/commands/setup.d.ts.map +1 -1
  89. package/dist/commands/setup.js +418 -86
  90. package/dist/commands/setup.js.map +1 -1
  91. package/dist/commands/skills.d.ts +9 -0
  92. package/dist/commands/skills.d.ts.map +1 -0
  93. package/dist/commands/skills.js +317 -0
  94. package/dist/commands/skills.js.map +1 -0
  95. package/dist/commands/use.d.ts +10 -2
  96. package/dist/commands/use.d.ts.map +1 -1
  97. package/dist/commands/use.js +851 -73
  98. package/dist/commands/use.js.map +1 -1
  99. package/dist/config/paths.d.ts +11 -1
  100. package/dist/config/paths.d.ts.map +1 -1
  101. package/dist/config/paths.js +64 -29
  102. package/dist/config/paths.js.map +1 -1
  103. package/dist/config/project-config.d.ts +1 -0
  104. package/dist/config/project-config.d.ts.map +1 -1
  105. package/dist/config/project-config.js +70 -32
  106. package/dist/config/project-config.js.map +1 -1
  107. package/dist/context/broker.d.ts +30 -14
  108. package/dist/context/broker.d.ts.map +1 -1
  109. package/dist/context/broker.js +628 -150
  110. package/dist/context/broker.js.map +1 -1
  111. package/dist/context/delivery.d.ts +8 -22
  112. package/dist/context/delivery.d.ts.map +1 -1
  113. package/dist/context/delivery.js +204 -152
  114. package/dist/context/delivery.js.map +1 -1
  115. package/dist/context/feedback.d.ts +11 -12
  116. package/dist/context/feedback.d.ts.map +1 -1
  117. package/dist/context/feedback.js +250 -268
  118. package/dist/context/feedback.js.map +1 -1
  119. package/dist/context/origin.d.ts +9 -0
  120. package/dist/context/origin.d.ts.map +1 -0
  121. package/dist/context/origin.js +15 -0
  122. package/dist/context/origin.js.map +1 -0
  123. package/dist/context/ranking.d.ts +4 -13
  124. package/dist/context/ranking.d.ts.map +1 -1
  125. package/dist/context/ranking.js +21 -5
  126. package/dist/context/ranking.js.map +1 -1
  127. package/dist/context/recommendations.d.ts +0 -5
  128. package/dist/context/recommendations.d.ts.map +1 -1
  129. package/dist/context/recommendations.js +0 -1
  130. package/dist/context/recommendations.js.map +1 -1
  131. package/dist/context/run-state.d.ts +26 -0
  132. package/dist/context/run-state.d.ts.map +1 -0
  133. package/dist/context/run-state.js +399 -0
  134. package/dist/context/run-state.js.map +1 -0
  135. package/dist/context/scoped-broker.d.ts +19 -6
  136. package/dist/context/scoped-broker.d.ts.map +1 -1
  137. package/dist/context/scoped-broker.js +530 -131
  138. package/dist/context/scoped-broker.js.map +1 -1
  139. package/dist/context/selection-state.d.ts +19 -0
  140. package/dist/context/selection-state.d.ts.map +1 -0
  141. package/dist/context/selection-state.js +250 -0
  142. package/dist/context/selection-state.js.map +1 -0
  143. package/dist/db/adapter.d.ts +5 -3
  144. package/dist/db/adapter.d.ts.map +1 -1
  145. package/dist/db/adapter.js +6 -3
  146. package/dist/db/adapter.js.map +1 -1
  147. package/dist/db/capabilities.d.ts.map +1 -1
  148. package/dist/db/capabilities.js +34 -16
  149. package/dist/db/capabilities.js.map +1 -1
  150. package/dist/db/connection.d.ts +8 -0
  151. package/dist/db/connection.d.ts.map +1 -1
  152. package/dist/db/connection.js +55 -26
  153. package/dist/db/connection.js.map +1 -1
  154. package/dist/db/migrate.d.ts +28 -7
  155. package/dist/db/migrate.d.ts.map +1 -1
  156. package/dist/db/migrate.js +106 -78
  157. package/dist/db/migrate.js.map +1 -1
  158. package/dist/db/sqlite-retry.d.ts +11 -0
  159. package/dist/db/sqlite-retry.d.ts.map +1 -0
  160. package/dist/db/sqlite-retry.js +66 -0
  161. package/dist/db/sqlite-retry.js.map +1 -0
  162. package/dist/db/transaction.d.ts +13 -0
  163. package/dist/db/transaction.d.ts.map +1 -1
  164. package/dist/db/transaction.js +53 -24
  165. package/dist/db/transaction.js.map +1 -1
  166. package/dist/db/upgrade-backup.d.ts +58 -2
  167. package/dist/db/upgrade-backup.d.ts.map +1 -1
  168. package/dist/db/upgrade-backup.js +757 -28
  169. package/dist/db/upgrade-backup.js.map +1 -1
  170. package/dist/errors.js +1 -1
  171. package/dist/errors.js.map +1 -1
  172. package/dist/gateway/agent-service.d.ts +4 -1
  173. package/dist/gateway/agent-service.d.ts.map +1 -1
  174. package/dist/gateway/agent-service.js +71 -58
  175. package/dist/gateway/agent-service.js.map +1 -1
  176. package/dist/gateway/checkpoint-service.d.ts +1 -0
  177. package/dist/gateway/checkpoint-service.d.ts.map +1 -1
  178. package/dist/gateway/checkpoint-service.js +47 -24
  179. package/dist/gateway/checkpoint-service.js.map +1 -1
  180. package/dist/ledger/archive.d.ts +1 -4
  181. package/dist/ledger/archive.d.ts.map +1 -1
  182. package/dist/ledger/archive.js +134 -54
  183. package/dist/ledger/archive.js.map +1 -1
  184. package/dist/ledger/maintenance.d.ts +0 -11
  185. package/dist/ledger/maintenance.d.ts.map +1 -1
  186. package/dist/ledger/maintenance.js +41 -44
  187. package/dist/ledger/maintenance.js.map +1 -1
  188. package/dist/ledger/projection.d.ts +0 -1
  189. package/dist/ledger/projection.d.ts.map +1 -1
  190. package/dist/ledger/projection.js.map +1 -1
  191. package/dist/ledger/promotion.d.ts +0 -9
  192. package/dist/ledger/promotion.d.ts.map +1 -1
  193. package/dist/ledger/promotion.js.map +1 -1
  194. package/dist/ledger/query.d.ts +1 -15
  195. package/dist/ledger/query.d.ts.map +1 -1
  196. package/dist/ledger/query.js.map +1 -1
  197. package/dist/ledger/store.d.ts +0 -1
  198. package/dist/ledger/store.d.ts.map +1 -1
  199. package/dist/ledger/store.js +11 -8
  200. package/dist/ledger/store.js.map +1 -1
  201. package/dist/ledger/types.d.ts +0 -4
  202. package/dist/ledger/types.d.ts.map +1 -1
  203. package/dist/ledger/types.js.map +1 -1
  204. package/dist/ledger/validate.d.ts.map +1 -1
  205. package/dist/ledger/validate.js +0 -5
  206. package/dist/ledger/validate.js.map +1 -1
  207. package/dist/mcp/bounded-stdio-transport.d.ts +23 -0
  208. package/dist/mcp/bounded-stdio-transport.d.ts.map +1 -0
  209. package/dist/mcp/bounded-stdio-transport.js +109 -0
  210. package/dist/mcp/bounded-stdio-transport.js.map +1 -0
  211. package/dist/mcp/server.d.ts +4 -0
  212. package/dist/mcp/server.d.ts.map +1 -1
  213. package/dist/mcp/server.js +111 -75
  214. package/dist/mcp/server.js.map +1 -1
  215. package/dist/memory/audit.d.ts +0 -1
  216. package/dist/memory/audit.d.ts.map +1 -1
  217. package/dist/memory/audit.js +0 -1
  218. package/dist/memory/audit.js.map +1 -1
  219. package/dist/memory/curator.d.ts +45 -1
  220. package/dist/memory/curator.d.ts.map +1 -1
  221. package/dist/memory/curator.js +290 -68
  222. package/dist/memory/curator.js.map +1 -1
  223. package/dist/memory/entries.d.ts +12 -2
  224. package/dist/memory/entries.d.ts.map +1 -1
  225. package/dist/memory/entries.js +198 -114
  226. package/dist/memory/entries.js.map +1 -1
  227. package/dist/memory/federated-retrieval.d.ts +78 -0
  228. package/dist/memory/federated-retrieval.d.ts.map +1 -0
  229. package/dist/memory/federated-retrieval.js +441 -0
  230. package/dist/memory/federated-retrieval.js.map +1 -0
  231. package/dist/memory/hybrid-retrieval.d.ts +5 -11
  232. package/dist/memory/hybrid-retrieval.d.ts.map +1 -1
  233. package/dist/memory/hybrid-retrieval.js +78 -58
  234. package/dist/memory/hybrid-retrieval.js.map +1 -1
  235. package/dist/memory/lifecycle.d.ts.map +1 -1
  236. package/dist/memory/lifecycle.js +17 -13
  237. package/dist/memory/lifecycle.js.map +1 -1
  238. package/dist/memory/portability.d.ts +10 -0
  239. package/dist/memory/portability.d.ts.map +1 -0
  240. package/dist/memory/portability.js +44 -0
  241. package/dist/memory/portability.js.map +1 -0
  242. package/dist/memory/rebuild-search.d.ts +5 -0
  243. package/dist/memory/rebuild-search.d.ts.map +1 -1
  244. package/dist/memory/rebuild-search.js +101 -76
  245. package/dist/memory/rebuild-search.js.map +1 -1
  246. package/dist/memory/retrieval-query.d.ts +0 -5
  247. package/dist/memory/retrieval-query.d.ts.map +1 -1
  248. package/dist/memory/retrieval-query.js +0 -5
  249. package/dist/memory/retrieval-query.js.map +1 -1
  250. package/dist/memory/retrieval.d.ts +11 -0
  251. package/dist/memory/retrieval.d.ts.map +1 -1
  252. package/dist/memory/retrieval.js +34 -120
  253. package/dist/memory/retrieval.js.map +1 -1
  254. package/dist/memory/revisions.d.ts +76 -1
  255. package/dist/memory/revisions.d.ts.map +1 -1
  256. package/dist/memory/revisions.js +539 -35
  257. package/dist/memory/revisions.js.map +1 -1
  258. package/dist/memory/scoped-memory.d.ts +22 -13
  259. package/dist/memory/scoped-memory.d.ts.map +1 -1
  260. package/dist/memory/scoped-memory.js +248 -139
  261. package/dist/memory/scoped-memory.js.map +1 -1
  262. package/dist/memory/secrets.d.ts +2 -0
  263. package/dist/memory/secrets.d.ts.map +1 -1
  264. package/dist/memory/secrets.js +36 -0
  265. package/dist/memory/secrets.js.map +1 -1
  266. package/dist/memory/structured-memory.d.ts +8 -1
  267. package/dist/memory/structured-memory.d.ts.map +1 -1
  268. package/dist/memory/structured-memory.js +74 -20
  269. package/dist/memory/structured-memory.js.map +1 -1
  270. package/dist/memory/workspaces.d.ts +9 -0
  271. package/dist/memory/workspaces.d.ts.map +1 -1
  272. package/dist/memory/workspaces.js +67 -0
  273. package/dist/memory/workspaces.js.map +1 -1
  274. package/dist/package-version.d.ts +2 -0
  275. package/dist/package-version.d.ts.map +1 -0
  276. package/dist/package-version.js +7 -0
  277. package/dist/package-version.js.map +1 -0
  278. package/dist/repository/binding.d.ts +5 -0
  279. package/dist/repository/binding.d.ts.map +1 -1
  280. package/dist/repository/binding.js +117 -17
  281. package/dist/repository/binding.js.map +1 -1
  282. package/dist/repository/framework-version.d.ts +8 -0
  283. package/dist/repository/framework-version.d.ts.map +1 -0
  284. package/dist/repository/framework-version.js +29 -0
  285. package/dist/repository/framework-version.js.map +1 -0
  286. package/dist/repository/identity-value.d.ts +4 -0
  287. package/dist/repository/identity-value.d.ts.map +1 -0
  288. package/dist/repository/identity-value.js +24 -0
  289. package/dist/repository/identity-value.js.map +1 -0
  290. package/dist/repository/identity.d.ts.map +1 -1
  291. package/dist/repository/identity.js +2 -0
  292. package/dist/repository/identity.js.map +1 -1
  293. package/dist/repository/project-fingerprint.d.ts +33 -0
  294. package/dist/repository/project-fingerprint.d.ts.map +1 -0
  295. package/dist/repository/project-fingerprint.js +429 -0
  296. package/dist/repository/project-fingerprint.js.map +1 -0
  297. package/dist/repository/remote-url.d.ts +0 -1
  298. package/dist/repository/remote-url.d.ts.map +1 -1
  299. package/dist/repository/remote-url.js +0 -1
  300. package/dist/repository/remote-url.js.map +1 -1
  301. package/dist/runtime-version.d.ts +2 -1
  302. package/dist/runtime-version.d.ts.map +1 -1
  303. package/dist/runtime-version.js +21 -4
  304. package/dist/runtime-version.js.map +1 -1
  305. package/dist/serialization/boundary-json.d.ts +20 -0
  306. package/dist/serialization/boundary-json.d.ts.map +1 -0
  307. package/dist/serialization/boundary-json.js +129 -0
  308. package/dist/serialization/boundary-json.js.map +1 -0
  309. package/dist/serialization/envelope.js +1 -1
  310. package/dist/serialization/envelope.js.map +1 -1
  311. package/dist/serialization/validate.d.ts +7 -0
  312. package/dist/serialization/validate.d.ts.map +1 -1
  313. package/dist/serialization/validate.js +53 -13
  314. package/dist/serialization/validate.js.map +1 -1
  315. package/dist/server/app.js +1 -1
  316. package/dist/server/app.js.map +1 -1
  317. package/dist/server/http.d.ts +4 -3
  318. package/dist/server/http.d.ts.map +1 -1
  319. package/dist/server/http.js +90 -50
  320. package/dist/server/http.js.map +1 -1
  321. package/dist/server/idempotency.d.ts +0 -6
  322. package/dist/server/idempotency.d.ts.map +1 -1
  323. package/dist/server/idempotency.js.map +1 -1
  324. package/dist/server/router.d.ts.map +1 -1
  325. package/dist/server/router.js +21 -4
  326. package/dist/server/router.js.map +1 -1
  327. package/dist/server/routes/agent-capability-gate.d.ts +40 -0
  328. package/dist/server/routes/agent-capability-gate.d.ts.map +1 -0
  329. package/dist/server/routes/agent-capability-gate.js +182 -0
  330. package/dist/server/routes/agent-capability-gate.js.map +1 -0
  331. package/dist/server/routes/agent-events.d.ts.map +1 -1
  332. package/dist/server/routes/agent-events.js +8 -1
  333. package/dist/server/routes/agent-events.js.map +1 -1
  334. package/dist/server/routes/agent-intake.d.ts.map +1 -1
  335. package/dist/server/routes/agent-intake.js +10 -2
  336. package/dist/server/routes/agent-intake.js.map +1 -1
  337. package/dist/server/routes/agent-promotions.d.ts.map +1 -1
  338. package/dist/server/routes/agent-promotions.js +5 -2
  339. package/dist/server/routes/agent-promotions.js.map +1 -1
  340. package/dist/server/routes/agent-runs.d.ts.map +1 -1
  341. package/dist/server/routes/agent-runs.js +18 -4
  342. package/dist/server/routes/agent-runs.js.map +1 -1
  343. package/dist/server/routes/request-binding.d.ts +5 -0
  344. package/dist/server/routes/request-binding.d.ts.map +1 -0
  345. package/dist/server/routes/request-binding.js +49 -0
  346. package/dist/server/routes/request-binding.js.map +1 -0
  347. package/dist/server/routes/task5-support.d.ts +1 -8
  348. package/dist/server/routes/task5-support.d.ts.map +1 -1
  349. package/dist/server/routes/task5-support.js +1 -17
  350. package/dist/server/routes/task5-support.js.map +1 -1
  351. package/dist/server/routes/task5.d.ts.map +1 -1
  352. package/dist/server/routes/task5.js +106 -36
  353. package/dist/server/routes/task5.js.map +1 -1
  354. package/dist/server/write-queue.js +2 -2
  355. package/dist/server/write-queue.js.map +1 -1
  356. package/dist/setup/claude-config.d.ts +2 -1
  357. package/dist/setup/claude-config.d.ts.map +1 -1
  358. package/dist/setup/claude-config.js +54 -4
  359. package/dist/setup/claude-config.js.map +1 -1
  360. package/dist/setup/client-detection.d.ts +7 -2
  361. package/dist/setup/client-detection.d.ts.map +1 -1
  362. package/dist/setup/client-detection.js +27 -9
  363. package/dist/setup/client-detection.js.map +1 -1
  364. package/dist/setup/hermes-config.d.ts +2 -1
  365. package/dist/setup/hermes-config.d.ts.map +1 -1
  366. package/dist/setup/hermes-config.js +53 -12
  367. package/dist/setup/hermes-config.js.map +1 -1
  368. package/dist/setup/legacy-client-cleanup.d.ts +6 -0
  369. package/dist/setup/legacy-client-cleanup.d.ts.map +1 -0
  370. package/dist/setup/legacy-client-cleanup.js +152 -0
  371. package/dist/setup/legacy-client-cleanup.js.map +1 -0
  372. package/dist/setup/managed-text.d.ts.map +1 -1
  373. package/dist/setup/managed-text.js +11 -1
  374. package/dist/setup/managed-text.js.map +1 -1
  375. package/dist/setup/opencode-config.d.ts +2 -1
  376. package/dist/setup/opencode-config.d.ts.map +1 -1
  377. package/dist/setup/opencode-config.js +57 -5
  378. package/dist/setup/opencode-config.js.map +1 -1
  379. package/dist/setup/render.d.ts +2 -1
  380. package/dist/setup/render.d.ts.map +1 -1
  381. package/dist/setup/render.js +91 -17
  382. package/dist/setup/render.js.map +1 -1
  383. package/dist/setup/standard-skills.d.ts +16 -2
  384. package/dist/setup/standard-skills.d.ts.map +1 -1
  385. package/dist/setup/standard-skills.js +37 -13
  386. package/dist/setup/standard-skills.js.map +1 -1
  387. package/dist/setup/strict-json.d.ts +7 -0
  388. package/dist/setup/strict-json.d.ts.map +1 -0
  389. package/dist/setup/strict-json.js +98 -0
  390. package/dist/setup/strict-json.js.map +1 -0
  391. package/dist/setup/strict-toml.d.ts +7 -0
  392. package/dist/setup/strict-toml.d.ts.map +1 -0
  393. package/dist/setup/strict-toml.js +470 -0
  394. package/dist/setup/strict-toml.js.map +1 -0
  395. package/dist/skills/cache.d.ts +15 -0
  396. package/dist/skills/cache.d.ts.map +1 -0
  397. package/dist/skills/cache.js +19 -0
  398. package/dist/skills/cache.js.map +1 -0
  399. package/dist/skills/candidate-ranking.d.ts +15 -0
  400. package/dist/skills/candidate-ranking.d.ts.map +1 -0
  401. package/dist/skills/candidate-ranking.js +52 -0
  402. package/dist/skills/candidate-ranking.js.map +1 -0
  403. package/dist/skills/chunking.d.ts +11 -0
  404. package/dist/skills/chunking.d.ts.map +1 -0
  405. package/dist/skills/chunking.js +291 -0
  406. package/dist/skills/chunking.js.map +1 -0
  407. package/dist/skills/config.d.ts +19 -0
  408. package/dist/skills/config.d.ts.map +1 -0
  409. package/dist/skills/config.js +103 -0
  410. package/dist/skills/config.js.map +1 -0
  411. package/dist/skills/discovery-service.d.ts +26 -0
  412. package/dist/skills/discovery-service.d.ts.map +1 -0
  413. package/dist/skills/discovery-service.js +921 -0
  414. package/dist/skills/discovery-service.js.map +1 -0
  415. package/dist/skills/external-transport.d.ts +2 -0
  416. package/dist/skills/external-transport.d.ts.map +1 -0
  417. package/dist/skills/external-transport.js +30 -0
  418. package/dist/skills/external-transport.js.map +1 -0
  419. package/dist/skills/find.d.ts +16 -0
  420. package/dist/skills/find.d.ts.map +1 -0
  421. package/dist/skills/find.js +58 -0
  422. package/dist/skills/find.js.map +1 -0
  423. package/dist/skills/gap-detection.d.ts +23 -0
  424. package/dist/skills/gap-detection.d.ts.map +1 -0
  425. package/dist/skills/gap-detection.js +62 -0
  426. package/dist/skills/gap-detection.js.map +1 -0
  427. package/dist/skills/import-preparation.d.ts +4 -0
  428. package/dist/skills/import-preparation.d.ts.map +1 -0
  429. package/dist/skills/import-preparation.js +20 -0
  430. package/dist/skills/import-preparation.js.map +1 -0
  431. package/dist/skills/materialization-authority.d.ts +11 -0
  432. package/dist/skills/materialization-authority.d.ts.map +1 -0
  433. package/dist/skills/materialization-authority.js +92 -0
  434. package/dist/skills/materialization-authority.js.map +1 -0
  435. package/dist/skills/materialization-service.d.ts +22 -0
  436. package/dist/skills/materialization-service.d.ts.map +1 -0
  437. package/dist/skills/materialization-service.js +101 -0
  438. package/dist/skills/materialization-service.js.map +1 -0
  439. package/dist/skills/official-catalog.d.ts +31 -0
  440. package/dist/skills/official-catalog.d.ts.map +1 -0
  441. package/dist/skills/official-catalog.js +110 -0
  442. package/dist/skills/official-catalog.js.map +1 -0
  443. package/dist/skills/providers/schema.d.ts +30 -0
  444. package/dist/skills/providers/schema.d.ts.map +1 -0
  445. package/dist/skills/providers/schema.js +354 -0
  446. package/dist/skills/providers/schema.js.map +1 -0
  447. package/dist/skills/providers/skills-sh-compat.d.ts +17 -0
  448. package/dist/skills/providers/skills-sh-compat.d.ts.map +1 -0
  449. package/dist/skills/providers/skills-sh-compat.js +71 -0
  450. package/dist/skills/providers/skills-sh-compat.js.map +1 -0
  451. package/dist/skills/providers/skills-sh-v1.d.ts +23 -0
  452. package/dist/skills/providers/skills-sh-v1.d.ts.map +1 -0
  453. package/dist/skills/providers/skills-sh-v1.js +134 -0
  454. package/dist/skills/providers/skills-sh-v1.js.map +1 -0
  455. package/dist/skills/query-builder.d.ts +18 -0
  456. package/dist/skills/query-builder.d.ts.map +1 -0
  457. package/dist/skills/query-builder.js +93 -0
  458. package/dist/skills/query-builder.js.map +1 -0
  459. package/dist/skills/source/errors.d.ts +9 -0
  460. package/dist/skills/source/errors.d.ts.map +1 -0
  461. package/dist/skills/source/errors.js +15 -0
  462. package/dist/skills/source/errors.js.map +1 -0
  463. package/dist/skills/source/frontmatter.d.ts +9 -0
  464. package/dist/skills/source/frontmatter.d.ts.map +1 -0
  465. package/dist/skills/source/frontmatter.js +77 -0
  466. package/dist/skills/source/frontmatter.js.map +1 -0
  467. package/dist/skills/source/github-fetcher.d.ts +20 -0
  468. package/dist/skills/source/github-fetcher.d.ts.map +1 -0
  469. package/dist/skills/source/github-fetcher.js +292 -0
  470. package/dist/skills/source/github-fetcher.js.map +1 -0
  471. package/dist/skills/source/snapshot-validator.d.ts +28 -0
  472. package/dist/skills/source/snapshot-validator.d.ts.map +1 -0
  473. package/dist/skills/source/snapshot-validator.js +186 -0
  474. package/dist/skills/source/snapshot-validator.js.map +1 -0
  475. package/dist/skills/store.d.ts +181 -0
  476. package/dist/skills/store.d.ts.map +1 -0
  477. package/dist/skills/store.js +1710 -0
  478. package/dist/skills/store.js.map +1 -0
  479. package/dist/skills/types.d.ts +169 -0
  480. package/dist/skills/types.d.ts.map +1 -0
  481. package/dist/skills/types.js +2 -0
  482. package/dist/skills/types.js.map +1 -0
  483. package/dist/web/i18n.d.ts +56 -8
  484. package/dist/web/i18n.d.ts.map +1 -1
  485. package/dist/web/i18n.js +224 -32
  486. package/dist/web/i18n.js.map +1 -1
  487. package/dist/web/server.d.ts.map +1 -1
  488. package/dist/web/server.js +458 -42
  489. package/dist/web/server.js.map +1 -1
  490. package/dist/web/ui.d.ts +4 -0
  491. package/dist/web/ui.d.ts.map +1 -1
  492. package/dist/web/ui.js +697 -61
  493. package/dist/web/ui.js.map +1 -1
  494. package/migrations/008_federated_memory.sql +46 -0
  495. package/migrations/009_external_skill_discovery.sql +126 -0
  496. package/package.json +6 -3
  497. package/skills/kiokuko-single-purpose-functions/SKILL.md +288 -0
  498. package/skills/kiokuko-single-purpose-functions/references/kiokuko-patterns.md +344 -0
  499. package/skills/kiokuko-single-purpose-functions/references/review-checklist.md +97 -0
  500. package/skills/kiokuko-ui-design-soul/SKILL.md +1186 -28
  501. package/templates/AGENTS.md +8 -7
  502. package/dist/client/runtime-discovery.d.ts +0 -15
  503. package/dist/client/runtime-discovery.d.ts.map +0 -1
  504. package/dist/client/runtime-discovery.js +0 -45
  505. package/dist/client/runtime-discovery.js.map +0 -1
  506. package/dist/commands/call.d.ts +0 -7
  507. package/dist/commands/call.d.ts.map +0 -1
  508. package/dist/commands/call.js +0 -10
  509. package/dist/commands/call.js.map +0 -1
  510. package/dist/commands/link.d.ts +0 -6
  511. package/dist/commands/link.d.ts.map +0 -1
  512. package/dist/commands/link.js +0 -6
  513. package/dist/commands/link.js.map +0 -1
  514. package/dist/commands/promote.d.ts +0 -6
  515. package/dist/commands/promote.d.ts.map +0 -1
  516. package/dist/commands/promote.js +0 -6
  517. package/dist/commands/promote.js.map +0 -1
  518. package/dist/commands/read.d.ts +0 -6
  519. package/dist/commands/read.d.ts.map +0 -1
  520. package/dist/commands/read.js +0 -4
  521. package/dist/commands/read.js.map +0 -1
  522. package/dist/commands/recall.d.ts +0 -6
  523. package/dist/commands/recall.d.ts.map +0 -1
  524. package/dist/commands/recall.js +0 -4
  525. package/dist/commands/recall.js.map +0 -1
  526. package/dist/commands/record.d.ts +0 -6
  527. package/dist/commands/record.d.ts.map +0 -1
  528. package/dist/commands/record.js +0 -4
  529. package/dist/commands/record.js.map +0 -1
  530. package/dist/commands/search.d.ts +0 -6
  531. package/dist/commands/search.d.ts.map +0 -1
  532. package/dist/commands/search.js +0 -4
  533. package/dist/commands/search.js.map +0 -1
  534. package/dist/commands/supersede.d.ts +0 -6
  535. package/dist/commands/supersede.d.ts.map +0 -1
  536. package/dist/commands/supersede.js +0 -6
  537. package/dist/commands/supersede.js.map +0 -1
  538. package/dist/knowledge/sources.d.ts +0 -72
  539. package/dist/knowledge/sources.d.ts.map +0 -1
  540. package/dist/knowledge/sources.js +0 -388
  541. package/dist/knowledge/sources.js.map +0 -1
  542. package/dist/setup/opencode-evidence.d.ts +0 -37
  543. package/dist/setup/opencode-evidence.d.ts.map +0 -1
  544. package/dist/setup/opencode-evidence.js +0 -58
  545. package/dist/setup/opencode-evidence.js.map +0 -1
  546. package/dist/setup/opencode-loop-guard.d.ts +0 -9
  547. package/dist/setup/opencode-loop-guard.d.ts.map +0 -1
  548. package/dist/setup/opencode-loop-guard.js +0 -248
  549. package/dist/setup/opencode-loop-guard.js.map +0 -1
@@ -1,21 +1,26 @@
1
- import { access, unlink } from 'node:fs/promises';
2
1
  import path from 'node:path';
2
+ import { mkdir, rmdir } from 'node:fs/promises';
3
3
  import { createInterface } from 'node:readline/promises';
4
4
  import { stdin, stdout } from 'node:process';
5
- import { atomicWriteText, readRegularFile } from '../agent-file/atomic-write.js';
6
- import { getClaudeInstructionsPath, getClaudeMcpConfigPath, getClaudeSkillsDirectory, getCodexConfigPath, getCodexInstructionsPath, getCodexSkillsDirectory, getGlobalDatabasePath, getHermesConfigPath, getHermesSkillsDirectory, getOpenCodeConfigDirectory, getOpenCodeInstructionsPath, getOpenCodeLoopGuardPath, getOpenCodeSkillsDirectory, } from '../config/paths.js';
5
+ import { atomicWriteTextIfUnchanged, assertAtomicCleanupComplete, AtomicCommittedMutationError, AtomicCommittedUnlinkError, assertFileExpectation, readDirectoryIdentity, readRegularFile, unlinkRegularFileIfUnchanged, } from '../agent-file/atomic-write.js';
6
+ import { getClaudeInstructionsPath, getClaudeMcpConfigPath, getClaudeSkillsDirectory, getCodexConfigPath, getCodexInstructionsPath, getCodexSkillsDirectory, getGlobalDatabasePath, getLegacyClaudePromptHookSettingsPath, getLegacyOpenCodeLoopGuardPath, getOpenCodeConfigDirectory, getOpenCodeInstructionsPath, getOpenCodeSkillsDirectory, resolveHermesProfilePaths, } from '../config/paths.js';
7
7
  import { initializeDatabase } from './init.js';
8
8
  import { openConnection } from '../db/connection.js';
9
9
  import { ensureGlobalWorkspace } from '../memory/workspaces.js';
10
10
  import { KiokukoError } from '../errors.js';
11
+ import { isSkillDiscoveryMode, normalizeSkillDiscoveryMode, SKILL_DISCOVERY_ENV } from '../skills/config.js';
11
12
  import { renderOpenCodeConfig } from '../setup/opencode-config.js';
12
- import { renderOpenCodeLoopGuard } from '../setup/opencode-loop-guard.js';
13
13
  import { renderCodexMcpConfig, renderGlobalInstructions } from '../setup/render.js';
14
14
  import { renderClaudeConfig } from '../setup/claude-config.js';
15
15
  import { renderHermesConfig } from '../setup/hermes-config.js';
16
16
  import { detectInstalledClients } from '../setup/client-detection.js';
17
- import { loadBundledStandardSkillFiles, renderStandardSkillFile, STANDARD_UI_SKILL_NAME, } from '../setup/standard-skills.js';
17
+ import { assertExactLegacyOpenCodeLoopGuard, cleanupLegacyClaudePromptHook, } from '../setup/legacy-client-cleanup.js';
18
+ import { loadBundledStandardSkillFiles, renderStandardSkillFile, } from '../setup/standard-skills.js';
18
19
  export const SETUP_CLIENTS = ['codex', 'opencode', 'claude', 'hermes'];
20
+ function setupPathJoin(options, ...segments) {
21
+ const platform = options.platform ?? process.platform;
22
+ return platform === 'win32' ? path.win32.join(...segments) : path.posix.join(...segments);
23
+ }
19
24
  export function parseSetupClients(value) {
20
25
  const clients = [...new Set(value.split(',').map((client) => client.trim()).filter(Boolean))];
21
26
  if (clients.length === 0 || clients.some((client) => !SETUP_CLIENTS.includes(client))) {
@@ -23,6 +28,12 @@ export function parseSetupClients(value) {
23
28
  }
24
29
  return clients;
25
30
  }
31
+ export function parseSetupSkillDiscoveryMode(value) {
32
+ if (!isSkillDiscoveryMode(value)) {
33
+ throw new KiokukoError('VALIDATION_ERROR', 'skill discovery must be off, official, or community');
34
+ }
35
+ return value;
36
+ }
26
37
  function setupClientLabel(client) {
27
38
  if (client === 'codex')
28
39
  return 'Codex';
@@ -32,92 +43,287 @@ function setupClientLabel(client) {
32
43
  return 'Claude Code';
33
44
  return 'Hermes Agent';
34
45
  }
46
+ async function askSetupClients(prompt, output, detected) {
47
+ const defaultSelection = detected.length === 0 ? 'none' : detected.join(',');
48
+ output.write('Select clients to configure (detected clients are preselected):\n');
49
+ for (const [index, client] of SETUP_CLIENTS.entries()) {
50
+ const checked = detected.includes(client) ? 'x' : ' ';
51
+ const status = detected.includes(client) ? 'detected' : 'not detected';
52
+ output.write(` ${index + 1}. [${checked}] ${setupClientLabel(client)} (${status})\n`);
53
+ }
54
+ output.write('Enter client names or numbers separated by commas. Press Enter to accept the checked clients; type none to skip all.\n');
55
+ while (true) {
56
+ const answer = (await prompt.question(`Clients [${defaultSelection}]: `)).trim();
57
+ if (answer.length === 0)
58
+ return detected;
59
+ if (/^(?:none|なし)$/iu.test(answer))
60
+ return [];
61
+ const selected = [];
62
+ let invalid = false;
63
+ for (const token of answer.split(',').map((value) => value.trim()).filter(Boolean)) {
64
+ const index = Number(token);
65
+ const indexedClient = Number.isInteger(index) && index >= 1 && index <= SETUP_CLIENTS.length
66
+ ? SETUP_CLIENTS[index - 1]
67
+ : undefined;
68
+ const client = indexedClient ?? token.toLowerCase();
69
+ if (!SETUP_CLIENTS.includes(client)) {
70
+ invalid = true;
71
+ break;
72
+ }
73
+ selected.push(client);
74
+ }
75
+ if (!invalid)
76
+ return [...new Set(selected)];
77
+ output.write(`Invalid selection. Choose names or numbers for: ${SETUP_CLIENTS.join(', ')}.\n`);
78
+ }
79
+ }
80
+ async function askCommunitySkillDiscovery(prompt, output) {
81
+ output.write('Official external Skill discovery is enabled by default and uses validated content only as untrusted references. It never installs or executes Skills.\n');
82
+ output.write('Community discovery can also use audited community Skills as untrusted references when relevant.\n');
83
+ const answer = (await prompt.question('Enable community Skill discovery? [y/N] ')).trim();
84
+ return /^(?:y|yes|はい)$/iu.test(answer) ? 'community' : 'official';
85
+ }
35
86
  /** Ask which supported clients should receive configuration in an interactive terminal. */
36
87
  export async function promptSetupClients(detected, options = {}) {
37
88
  const input = options.input ?? stdin;
38
89
  const output = options.output ?? stdout;
39
90
  const prompt = createInterface({ input, output });
40
- const defaultSelection = detected.length === 0 ? 'none' : detected.join(',');
41
91
  try {
42
- output.write('Select clients to configure (detected clients are preselected):\n');
43
- for (const [index, client] of SETUP_CLIENTS.entries()) {
44
- const checked = detected.includes(client) ? 'x' : ' ';
45
- const status = detected.includes(client) ? 'detected' : 'not detected';
46
- output.write(` ${index + 1}. [${checked}] ${setupClientLabel(client)} (${status})\n`);
47
- }
48
- output.write('Enter client names or numbers separated by commas. Press Enter to accept the checked clients; type none to skip all.\n');
49
- while (true) {
50
- const answer = (await prompt.question(`Clients [${defaultSelection}]: `)).trim();
51
- if (answer.length === 0)
52
- return detected;
53
- if (/^(?:none|なし)$/iu.test(answer))
54
- return [];
55
- const selected = [];
56
- let invalid = false;
57
- for (const token of answer.split(',').map((value) => value.trim()).filter(Boolean)) {
58
- const index = Number(token);
59
- const indexedClient = Number.isInteger(index) && index >= 1 && index <= SETUP_CLIENTS.length
60
- ? SETUP_CLIENTS[index - 1]
61
- : undefined;
62
- const client = indexedClient ?? token.toLowerCase();
63
- if (!SETUP_CLIENTS.includes(client)) {
64
- invalid = true;
65
- break;
66
- }
67
- selected.push(client);
68
- }
69
- if (!invalid)
70
- return [...new Set(selected)];
71
- output.write(`Invalid selection. Choose names or numbers for: ${SETUP_CLIENTS.join(', ')}.\n`);
72
- }
92
+ return await askSetupClients(prompt, output, detected);
73
93
  }
74
94
  finally {
75
95
  prompt.close();
76
96
  }
77
97
  }
78
- async function exists(filePath) {
98
+ /** Ask whether audited community Skill discovery should be enabled. */
99
+ export async function promptCommunitySkillDiscovery(options = {}) {
100
+ const input = options.input ?? stdin;
101
+ const output = options.output ?? stdout;
102
+ const prompt = createInterface({ input, output });
79
103
  try {
80
- await access(filePath);
81
- return true;
104
+ return await askCommunitySkillDiscovery(prompt, output);
82
105
  }
83
- catch (error) {
84
- if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
85
- return false;
86
- throw error;
106
+ finally {
107
+ prompt.close();
108
+ }
109
+ }
110
+ /** Ask both setup questions through one readline session so buffered input remains intact. */
111
+ export async function promptSetupConfiguration(detected, options = {}) {
112
+ const input = options.input ?? stdin;
113
+ const output = options.output ?? stdout;
114
+ const prompt = createInterface({ input, output });
115
+ try {
116
+ const clients = await askSetupClients(prompt, output, detected);
117
+ const skillDiscoveryMode = clients.length === 0
118
+ ? 'official'
119
+ : await askCommunitySkillDiscovery(prompt, output);
120
+ return { clients, skillDiscoveryMode };
121
+ }
122
+ finally {
123
+ prompt.close();
124
+ }
125
+ }
126
+ function sameFileIdentity(left, right) {
127
+ return left.device === right.device && left.inode === right.inode;
128
+ }
129
+ function setupDirectoryChanged(directoryPath) {
130
+ return new KiokukoError('CONFLICT', 'Setup directory changed after planning', { target: directoryPath });
131
+ }
132
+ function plannedDirectoryIdentity(directory) {
133
+ return directory.original ?? directory.created;
134
+ }
135
+ function directoryLineage(directory) {
136
+ const lineage = [];
137
+ let current = directory;
138
+ while (current !== undefined) {
139
+ lineage.push(current);
140
+ current = current.parent;
141
+ }
142
+ return lineage.reverse();
143
+ }
144
+ async function assertPlannedDirectory(directory) {
145
+ for (const planned of directoryLineage(directory)) {
146
+ const current = await readDirectoryIdentity(planned.path);
147
+ const expected = plannedDirectoryIdentity(planned);
148
+ if ((current === undefined) !== (expected === undefined)
149
+ || (current !== undefined && expected !== undefined && !sameFileIdentity(current, expected))) {
150
+ throw setupDirectoryChanged(planned.path);
151
+ }
152
+ }
153
+ }
154
+ async function planDirectory(planning, directoryPath) {
155
+ const resolved = path.resolve(directoryPath);
156
+ const existing = planning.directories.get(resolved);
157
+ if (existing !== undefined)
158
+ return existing;
159
+ const original = await readDirectoryIdentity(resolved);
160
+ const parentPath = path.dirname(resolved);
161
+ const parent = original !== undefined || parentPath === resolved
162
+ ? undefined
163
+ : await planDirectory(planning, parentPath);
164
+ const planned = {
165
+ path: resolved,
166
+ parent,
167
+ original,
168
+ created: undefined,
169
+ };
170
+ planning.directories.set(resolved, planned);
171
+ return planned;
172
+ }
173
+ async function readPlannedRegularFile(planning, filePath) {
174
+ const parentDirectory = await planDirectory(planning, path.dirname(filePath));
175
+ await assertPlannedDirectory(parentDirectory);
176
+ const snapshot = await readRegularFile(filePath);
177
+ await assertPlannedDirectory(parentDirectory);
178
+ return { parentDirectory, snapshot };
179
+ }
180
+ function errno(error) {
181
+ return error instanceof Error && 'code' in error
182
+ ? String(error.code)
183
+ : undefined;
184
+ }
185
+ async function preparePlannedDirectories(files, createdDirectories) {
186
+ const required = new Set();
187
+ for (const file of files) {
188
+ if (file.action === 'unchanged')
189
+ continue;
190
+ for (const directory of directoryLineage(file.parentDirectory))
191
+ required.add(directory);
192
+ }
193
+ const ordered = [...required].sort((left, right) => directoryLineage(left).length - directoryLineage(right).length);
194
+ for (const directory of ordered) {
195
+ const expected = plannedDirectoryIdentity(directory);
196
+ if (expected !== undefined) {
197
+ await assertPlannedDirectory(directory);
198
+ continue;
199
+ }
200
+ if (directory.parent === undefined) {
201
+ throw new KiokukoError('INTEGRITY_ERROR', 'Setup cannot create a missing filesystem root');
202
+ }
203
+ await assertPlannedDirectory(directory.parent);
204
+ if (await readDirectoryIdentity(directory.path) !== undefined) {
205
+ throw setupDirectoryChanged(directory.path);
206
+ }
207
+ try {
208
+ await mkdir(directory.path, { mode: 0o700 });
209
+ }
210
+ catch (error) {
211
+ if (errno(error) === 'EEXIST')
212
+ throw setupDirectoryChanged(directory.path);
213
+ throw error;
214
+ }
215
+ const created = await readDirectoryIdentity(directory.path);
216
+ if (created === undefined) {
217
+ throw new KiokukoError('INTEGRITY_ERROR', 'Setup directory disappeared immediately after creation', {
218
+ target: directory.path,
219
+ });
220
+ }
221
+ directory.created = created;
222
+ createdDirectories.push(directory);
223
+ await assertPlannedDirectory(directory);
224
+ }
225
+ }
226
+ async function removeCreatedDirectories(createdDirectories) {
227
+ const failures = [];
228
+ for (const directory of [...createdDirectories].reverse()) {
229
+ try {
230
+ await assertPlannedDirectory(directory);
231
+ await rmdir(directory.path);
232
+ if (await readDirectoryIdentity(directory.path) !== undefined) {
233
+ throw setupDirectoryChanged(directory.path);
234
+ }
235
+ directory.created = undefined;
236
+ if (directory.parent !== undefined)
237
+ await assertPlannedDirectory(directory.parent);
238
+ }
239
+ catch (error) {
240
+ failures.push(error);
241
+ }
87
242
  }
243
+ return failures;
88
244
  }
89
- async function planFile(filePath, client, purpose, render) {
90
- const original = await readRegularFile(filePath);
245
+ async function planFile(planning, filePath, client, purpose, render, mustRemainAbsent = []) {
246
+ const { parentDirectory, snapshot: original } = await readPlannedRegularFile(planning, filePath);
91
247
  const rendered = render(original?.content);
92
248
  const action = original === undefined
93
249
  ? 'created'
94
250
  : rendered.content === original.content ? 'unchanged' : 'updated';
95
251
  return {
96
252
  path: filePath,
253
+ parentDirectory,
97
254
  content: rendered.content,
98
255
  mode: original?.mode ?? 0o600,
99
- original: original?.content,
256
+ original,
257
+ ...(mustRemainAbsent.length === 0 ? {} : { mustRemainAbsent }),
100
258
  action,
101
259
  purpose,
102
260
  client,
261
+ report: true,
262
+ };
263
+ }
264
+ async function planLegacyClaudeHookCleanup(planning, options) {
265
+ const filePath = getLegacyClaudePromptHookSettingsPath(options);
266
+ const { parentDirectory, snapshot: original } = await readPlannedRegularFile(planning, filePath);
267
+ const content = original === undefined ? undefined : cleanupLegacyClaudePromptHook(original.content);
268
+ const changed = original !== undefined && content !== original.content;
269
+ return {
270
+ path: filePath,
271
+ parentDirectory,
272
+ content,
273
+ mode: original?.mode ?? 0o600,
274
+ original,
275
+ action: changed ? 'updated' : 'unchanged',
276
+ purpose: 'legacy-cleanup',
277
+ client: 'claude',
278
+ report: changed,
279
+ };
280
+ }
281
+ async function planLegacyOpenCodeGuardCleanup(planning, options) {
282
+ const filePath = getLegacyOpenCodeLoopGuardPath(options);
283
+ const { parentDirectory, snapshot: original } = await readPlannedRegularFile(planning, filePath);
284
+ if (original !== undefined)
285
+ assertExactLegacyOpenCodeLoopGuard(original.content);
286
+ return {
287
+ path: filePath,
288
+ parentDirectory,
289
+ content: undefined,
290
+ mode: original?.mode ?? 0o600,
291
+ original,
292
+ action: original === undefined ? 'unchanged' : 'deleted',
293
+ purpose: 'legacy-cleanup',
294
+ client: 'opencode',
295
+ report: original !== undefined,
103
296
  };
104
297
  }
105
- async function openCodeConfigPath(options) {
298
+ async function openCodeConfigPath(planning, options) {
106
299
  const directory = getOpenCodeConfigDirectory(options);
107
- const jsonc = path.join(directory, 'opencode.jsonc');
108
- if (await exists(jsonc))
109
- return jsonc;
110
- return path.join(directory, 'opencode.json');
300
+ const jsonc = setupPathJoin(options, directory, 'opencode.jsonc');
301
+ if ((await readPlannedRegularFile(planning, jsonc)).snapshot !== undefined) {
302
+ return { path: jsonc, mustRemainAbsent: [] };
303
+ }
304
+ return { path: setupPathJoin(options, directory, 'opencode.json'), mustRemainAbsent: [jsonc] };
111
305
  }
112
- async function restoreFiles(files) {
113
- for (const file of [...files].reverse()) {
114
- if (file.action === 'unchanged')
115
- continue;
116
- if (file.original === undefined)
117
- await unlink(file.path).catch(() => undefined);
118
- else
119
- await atomicWriteText(file.path, file.original, file.mode).catch(() => undefined);
306
+ async function restoreFiles(mutations, dependencies) {
307
+ const failures = [];
308
+ for (const mutation of [...mutations].reverse()) {
309
+ const { file, installed } = mutation;
310
+ try {
311
+ if (file.original === undefined) {
312
+ if (installed === undefined)
313
+ throw new KiokukoError('INTEGRITY_ERROR', 'Setup rollback record is invalid');
314
+ const outcome = await dependencies.unlinkRegularFileIfUnchanged(file.path, fileExpectation(file, installed, false));
315
+ assertAtomicCleanupComplete(outcome);
316
+ }
317
+ else {
318
+ const outcome = await dependencies.atomicWriteTextIfUnchanged(file.path, file.original.content, fileExpectation(file, installed, false), file.original.mode);
319
+ assertAtomicCleanupComplete(outcome);
320
+ }
321
+ }
322
+ catch (error) {
323
+ failures.push(error);
324
+ }
120
325
  }
326
+ return failures;
121
327
  }
122
328
  function setupNextStep(clients, standardSkills) {
123
329
  return clients.map((client) => {
@@ -130,55 +336,118 @@ function setupNextStep(clients, standardSkills) {
130
336
  return `Restart ${label} so it reloads global MCP and instruction configuration${standardSkills ? ' and standard skills' : ''}.`;
131
337
  }).join(' ');
132
338
  }
133
- async function standardSkillDirectory(client, options) {
339
+ async function standardSkillDirectory(client, options, hermesProfile) {
134
340
  if (client === 'codex')
135
341
  return getCodexSkillsDirectory(options);
136
342
  if (client === 'opencode')
137
343
  return getOpenCodeSkillsDirectory(options);
138
344
  if (client === 'claude')
139
345
  return getClaudeSkillsDirectory(options);
140
- return getHermesSkillsDirectory(options);
346
+ if (hermesProfile === undefined)
347
+ throw new KiokukoError('INTEGRITY_ERROR', 'Hermes profile was not bound during setup planning');
348
+ return hermesProfile.skillsDirectory;
349
+ }
350
+ function fileExpectation(file, expected, includeAlternatePaths = true) {
351
+ const expectedParentDirectory = plannedDirectoryIdentity(file.parentDirectory);
352
+ if (expectedParentDirectory === undefined) {
353
+ throw new KiokukoError('INTEGRITY_ERROR', 'Setup file parent was not created or bound before mutation', {
354
+ target: file.parentDirectory.path,
355
+ });
356
+ }
357
+ return {
358
+ expected,
359
+ expectedParentDirectory,
360
+ ...(includeAlternatePaths && file.mustRemainAbsent !== undefined
361
+ ? { mustRemainAbsent: file.mustRemainAbsent }
362
+ : {}),
363
+ };
141
364
  }
142
- export async function setupGlobalClients(options = {}) {
365
+ async function assertPlannedFile(file, expected) {
366
+ await assertPlannedDirectory(file.parentDirectory);
367
+ if (plannedDirectoryIdentity(file.parentDirectory) === undefined) {
368
+ if (expected !== undefined || await readRegularFile(file.path) !== undefined) {
369
+ throw setupDirectoryChanged(file.parentDirectory.path);
370
+ }
371
+ for (const absentPath of file.mustRemainAbsent ?? []) {
372
+ if (await readRegularFile(absentPath) !== undefined) {
373
+ throw new KiokukoError('CONFLICT', 'Setup target changed after planning', { target: absentPath });
374
+ }
375
+ }
376
+ }
377
+ else {
378
+ await assertFileExpectation(file.path, fileExpectation(file, expected));
379
+ }
380
+ await assertPlannedDirectory(file.parentDirectory);
381
+ }
382
+ async function assertPlannedFiles(files, applied = []) {
383
+ const installedByPath = new Map(applied.map((mutation) => [mutation.file.path, mutation.installed]));
384
+ for (const file of files) {
385
+ const expected = installedByPath.has(file.path) ? installedByPath.get(file.path) : file.original;
386
+ await assertPlannedFile(file, expected);
387
+ }
388
+ }
389
+ export async function setupGlobalClients(options = {}, dependencyOverrides = {}) {
390
+ const dependencies = {
391
+ atomicWriteTextIfUnchanged: dependencyOverrides.atomicWriteTextIfUnchanged ?? atomicWriteTextIfUnchanged,
392
+ unlinkRegularFileIfUnchanged: dependencyOverrides.unlinkRegularFileIfUnchanged ?? unlinkRegularFileIfUnchanged,
393
+ beforeCommit: dependencyOverrides.beforeCommit ?? (() => undefined),
394
+ openConnection: dependencyOverrides.openConnection ?? openConnection,
395
+ ensureGlobalWorkspace: dependencyOverrides.ensureGlobalWorkspace ?? ensureGlobalWorkspace,
396
+ };
143
397
  const pathEnvironment = {
144
398
  ...(options.platform === undefined ? {} : { platform: options.platform }),
145
399
  ...(options.env === undefined ? {} : { env: options.env }),
146
400
  };
401
+ if (options.skillDiscoveryMode !== undefined && !isSkillDiscoveryMode(options.skillDiscoveryMode)) {
402
+ throw new KiokukoError('VALIDATION_ERROR', 'skill discovery must be off, official, or community');
403
+ }
147
404
  const clients = options.clients ?? await detectInstalledClients(pathEnvironment);
148
- if (clients.some((client) => !SETUP_CLIENTS.includes(client))) {
405
+ if (!Array.isArray(clients) || clients.some((client) => !SETUP_CLIENTS.includes(client))) {
149
406
  throw new KiokukoError('VALIDATION_ERROR', `clients must be a subset of: ${SETUP_CLIENTS.join(', ')}`);
150
407
  }
151
408
  const command = options.command ?? 'kiokuko';
152
- if (command.trim().length === 0 || command.includes('\0'))
409
+ if (typeof command !== 'string' || command.trim().length === 0 || command.includes('\0')) {
153
410
  throw new KiokukoError('VALIDATION_ERROR', 'command must be a non-empty executable path or name');
411
+ }
154
412
  const databasePath = options.databasePath ?? getGlobalDatabasePath(pathEnvironment);
155
413
  const standardSkills = options.standardSkills ?? true;
414
+ const environment = options.env ?? process.env;
415
+ const environmentSkillDiscoveryMode = options.skillDiscoveryMode === undefined
416
+ && Object.prototype.hasOwnProperty.call(environment, SKILL_DISCOVERY_ENV)
417
+ ? normalizeSkillDiscoveryMode(environment[SKILL_DISCOVERY_ENV])
418
+ : undefined;
419
+ const skillDiscoveryMode = options.skillDiscoveryMode ?? environmentSkillDiscoveryMode;
156
420
  const files = [];
421
+ const planning = { directories: new Map() };
422
+ const hermesProfile = clients.includes('hermes')
423
+ ? await resolveHermesProfilePaths(pathEnvironment)
424
+ : undefined;
157
425
  if (clients.includes('codex')) {
158
- files.push(await planFile(getCodexConfigPath(pathEnvironment), 'codex', 'mcp-config', (existing) => renderCodexMcpConfig(existing ?? '', command)));
159
- files.push(await planFile(getCodexInstructionsPath(pathEnvironment), 'codex', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
426
+ files.push(await planFile(planning, getCodexConfigPath(pathEnvironment), 'codex', 'mcp-config', (existing) => renderCodexMcpConfig(existing ?? '', command, skillDiscoveryMode)));
427
+ files.push(await planFile(planning, getCodexInstructionsPath(pathEnvironment), 'codex', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
160
428
  }
161
429
  if (clients.includes('opencode')) {
162
- files.push(await planFile(await openCodeConfigPath(pathEnvironment), 'opencode', 'mcp-config', (existing) => renderOpenCodeConfig(existing, command)));
163
- files.push(await planFile(getOpenCodeInstructionsPath(pathEnvironment), 'opencode', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
164
- files.push(await planFile(getOpenCodeLoopGuardPath(pathEnvironment), 'opencode', 'runtime-guard', (existing) => renderOpenCodeLoopGuard(existing, {
165
- ...(options.opencodeCapture === undefined ? {} : { captureProfile: options.opencodeCapture }),
166
- ...(options.opencodeMode === undefined ? {} : { mode: options.opencodeMode }),
167
- })));
430
+ const selectedConfig = await openCodeConfigPath(planning, pathEnvironment);
431
+ files.push(await planFile(planning, selectedConfig.path, 'opencode', 'mcp-config', (existing) => renderOpenCodeConfig(existing, command, skillDiscoveryMode), selectedConfig.mustRemainAbsent));
432
+ files.push(await planFile(planning, getOpenCodeInstructionsPath(pathEnvironment), 'opencode', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
433
+ files.push(await planLegacyOpenCodeGuardCleanup(planning, pathEnvironment));
168
434
  }
169
435
  if (clients.includes('claude')) {
170
- files.push(await planFile(getClaudeMcpConfigPath(pathEnvironment), 'claude', 'mcp-config', (existing) => renderClaudeConfig(existing, command)));
171
- files.push(await planFile(getClaudeInstructionsPath(pathEnvironment), 'claude', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
436
+ files.push(await planFile(planning, getClaudeMcpConfigPath(pathEnvironment), 'claude', 'mcp-config', (existing) => renderClaudeConfig(existing, command, skillDiscoveryMode)));
437
+ files.push(await planFile(planning, getClaudeInstructionsPath(pathEnvironment), 'claude', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
438
+ files.push(await planLegacyClaudeHookCleanup(planning, pathEnvironment));
172
439
  }
173
440
  if (clients.includes('hermes')) {
174
- files.push(await planFile(await getHermesConfigPath(pathEnvironment), 'hermes', 'mcp-config', (existing) => renderHermesConfig(existing, command)));
441
+ if (hermesProfile === undefined)
442
+ throw new KiokukoError('INTEGRITY_ERROR', 'Hermes profile was not bound during setup planning');
443
+ files.push(await planFile(planning, hermesProfile.configPath, 'hermes', 'mcp-config', (existing) => renderHermesConfig(existing, command, skillDiscoveryMode)));
175
444
  }
176
445
  if (standardSkills) {
177
446
  const bundledFiles = await loadBundledStandardSkillFiles();
178
447
  for (const client of clients) {
179
- const destination = path.join(await standardSkillDirectory(client, pathEnvironment), STANDARD_UI_SKILL_NAME);
448
+ const skillsDirectory = await standardSkillDirectory(client, pathEnvironment, hermesProfile);
180
449
  for (const bundled of bundledFiles) {
181
- files.push(await planFile(path.join(destination, bundled.relativePath), client, 'standard-skill', (existing) => renderStandardSkillFile(existing, bundled)));
450
+ files.push(await planFile(planning, setupPathJoin(pathEnvironment, skillsDirectory, bundled.skillName, bundled.relativePath), client, 'standard-skill', (existing) => renderStandardSkillFile(existing, bundled)));
182
451
  }
183
452
  }
184
453
  }
@@ -188,7 +457,9 @@ export async function setupGlobalClients(options = {}) {
188
457
  databaseAction: options.dryRun ? 'planned' : 'initialized',
189
458
  databaseBackupPath: null,
190
459
  appliedMigrations: [],
191
- files: files.map(({ path: filePath, action, purpose, client }) => ({ path: filePath, action, purpose, client })),
460
+ files: files
461
+ .filter((file) => file.report)
462
+ .map(({ path: filePath, action, purpose, client }) => ({ path: filePath, action, purpose, client })),
192
463
  standardSkills,
193
464
  dryRun: options.dryRun ?? false,
194
465
  nextStep: setupNextStep(clients, standardSkills),
@@ -201,24 +472,85 @@ export async function setupGlobalClients(options = {}) {
201
472
  });
202
473
  result.databaseBackupPath = initialized.backupPath;
203
474
  result.appliedMigrations = initialized.applied;
204
- const database = openConnection(databasePath);
475
+ const database = dependencies.openConnection(databasePath);
476
+ let workspaceInitializationFailed = false;
477
+ let workspaceInitializationError;
205
478
  try {
206
- ensureGlobalWorkspace(database);
479
+ dependencies.ensureGlobalWorkspace(database);
207
480
  }
208
- finally {
481
+ catch (error) {
482
+ workspaceInitializationFailed = true;
483
+ workspaceInitializationError = error;
484
+ }
485
+ try {
209
486
  database.close();
210
487
  }
211
- const written = [];
488
+ catch (closeError) {
489
+ if (workspaceInitializationFailed) {
490
+ throw new AggregateError([workspaceInitializationError, closeError], 'Global workspace initialization failed and closing the database connection also failed');
491
+ }
492
+ throw closeError;
493
+ }
494
+ if (workspaceInitializationFailed)
495
+ throw workspaceInitializationError;
496
+ const applied = [];
497
+ const createdDirectories = [];
212
498
  try {
499
+ await dependencies.beforeCommit();
500
+ await preparePlannedDirectories(files, createdDirectories);
501
+ await assertPlannedFiles(files);
213
502
  for (const file of files) {
214
503
  if (file.action === 'unchanged')
215
504
  continue;
216
- await atomicWriteText(file.path, file.content, file.mode);
217
- written.push(file);
505
+ // Record a committed mutation before inspecting its cleanup outcome so
506
+ // rollback never loses ownership of a target that already changed.
507
+ let installed;
508
+ if (file.action === 'deleted') {
509
+ if (file.original === undefined)
510
+ throw new KiokukoError('INTEGRITY_ERROR', 'Setup deletion plan is missing original content');
511
+ let outcome;
512
+ try {
513
+ outcome = await dependencies.unlinkRegularFileIfUnchanged(file.path, fileExpectation(file, file.original));
514
+ }
515
+ catch (error) {
516
+ if (error instanceof AtomicCommittedUnlinkError) {
517
+ applied.push({ file, installed: undefined });
518
+ }
519
+ throw error;
520
+ }
521
+ applied.push({ file, installed: undefined });
522
+ assertAtomicCleanupComplete(outcome);
523
+ }
524
+ else {
525
+ if (file.content === undefined)
526
+ throw new KiokukoError('INTEGRITY_ERROR', 'Setup file plan is missing rendered content');
527
+ let outcome;
528
+ try {
529
+ outcome = await dependencies.atomicWriteTextIfUnchanged(file.path, file.content, fileExpectation(file, file.original), file.mode);
530
+ }
531
+ catch (error) {
532
+ if (error instanceof AtomicCommittedMutationError) {
533
+ applied.push({ file, installed: error.outcome.installed });
534
+ }
535
+ else if (error instanceof AtomicCommittedUnlinkError) {
536
+ applied.push({ file, installed: undefined });
537
+ }
538
+ throw error;
539
+ }
540
+ installed = outcome.installed;
541
+ applied.push({ file, installed });
542
+ assertAtomicCleanupComplete(outcome);
543
+ }
218
544
  }
545
+ await assertPlannedFiles(files, applied);
219
546
  }
220
547
  catch (error) {
221
- await restoreFiles(written);
548
+ const restorationFailures = await restoreFiles(applied, dependencies);
549
+ const directoryRestorationFailures = await removeCreatedDirectories(createdDirectories);
550
+ const failures = [...restorationFailures, ...directoryRestorationFailures];
551
+ if (failures.length > 0) {
552
+ throw new AggregateError([error, ...failures], 'Setup failed and filesystem restoration also failed');
553
+ }
222
554
  throw error;
223
555
  }
224
556
  return result;