@askdkc/kiokuko 0.1.17 → 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 (534) hide show
  1. package/README.ja.md +91 -112
  2. package/README.ko.md +90 -102
  3. package/README.md +103 -262
  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 +11 -22
  18. package/dist/akinator/agent-task.d.ts.map +1 -1
  19. package/dist/akinator/agent-task.js +454 -99
  20. package/dist/akinator/agent-task.js.map +1 -1
  21. package/dist/akinator/capabilities.d.ts +18 -6
  22. package/dist/akinator/capabilities.d.ts.map +1 -1
  23. package/dist/akinator/capabilities.js +72 -35
  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 +534 -148
  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 +28 -14
  108. package/dist/context/broker.d.ts.map +1 -1
  109. package/dist/context/broker.js +604 -145
  110. package/dist/context/broker.js.map +1 -1
  111. package/dist/context/delivery.d.ts +6 -21
  112. package/dist/context/delivery.d.ts.map +1 -1
  113. package/dist/context/delivery.js +196 -147
  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 +229 -261
  118. package/dist/context/feedback.js.map +1 -1
  119. package/dist/context/ranking.d.ts +1 -12
  120. package/dist/context/ranking.d.ts.map +1 -1
  121. package/dist/context/ranking.js +13 -4
  122. package/dist/context/ranking.js.map +1 -1
  123. package/dist/context/recommendations.d.ts +0 -5
  124. package/dist/context/recommendations.d.ts.map +1 -1
  125. package/dist/context/recommendations.js +0 -1
  126. package/dist/context/recommendations.js.map +1 -1
  127. package/dist/context/run-state.d.ts +26 -0
  128. package/dist/context/run-state.d.ts.map +1 -0
  129. package/dist/context/run-state.js +399 -0
  130. package/dist/context/run-state.js.map +1 -0
  131. package/dist/context/scoped-broker.d.ts +17 -5
  132. package/dist/context/scoped-broker.d.ts.map +1 -1
  133. package/dist/context/scoped-broker.js +512 -106
  134. package/dist/context/scoped-broker.js.map +1 -1
  135. package/dist/context/selection-state.d.ts +19 -0
  136. package/dist/context/selection-state.d.ts.map +1 -0
  137. package/dist/context/selection-state.js +250 -0
  138. package/dist/context/selection-state.js.map +1 -0
  139. package/dist/db/adapter.d.ts +5 -3
  140. package/dist/db/adapter.d.ts.map +1 -1
  141. package/dist/db/adapter.js +6 -3
  142. package/dist/db/adapter.js.map +1 -1
  143. package/dist/db/capabilities.d.ts.map +1 -1
  144. package/dist/db/capabilities.js +34 -16
  145. package/dist/db/capabilities.js.map +1 -1
  146. package/dist/db/connection.d.ts +8 -0
  147. package/dist/db/connection.d.ts.map +1 -1
  148. package/dist/db/connection.js +55 -26
  149. package/dist/db/connection.js.map +1 -1
  150. package/dist/db/migrate.d.ts +28 -7
  151. package/dist/db/migrate.d.ts.map +1 -1
  152. package/dist/db/migrate.js +106 -78
  153. package/dist/db/migrate.js.map +1 -1
  154. package/dist/db/sqlite-retry.d.ts +11 -0
  155. package/dist/db/sqlite-retry.d.ts.map +1 -0
  156. package/dist/db/sqlite-retry.js +66 -0
  157. package/dist/db/sqlite-retry.js.map +1 -0
  158. package/dist/db/transaction.d.ts +13 -0
  159. package/dist/db/transaction.d.ts.map +1 -1
  160. package/dist/db/transaction.js +53 -24
  161. package/dist/db/transaction.js.map +1 -1
  162. package/dist/db/upgrade-backup.d.ts +58 -2
  163. package/dist/db/upgrade-backup.d.ts.map +1 -1
  164. package/dist/db/upgrade-backup.js +757 -28
  165. package/dist/db/upgrade-backup.js.map +1 -1
  166. package/dist/errors.js +1 -1
  167. package/dist/errors.js.map +1 -1
  168. package/dist/gateway/agent-service.d.ts +4 -1
  169. package/dist/gateway/agent-service.d.ts.map +1 -1
  170. package/dist/gateway/agent-service.js +71 -58
  171. package/dist/gateway/agent-service.js.map +1 -1
  172. package/dist/gateway/checkpoint-service.d.ts +1 -0
  173. package/dist/gateway/checkpoint-service.d.ts.map +1 -1
  174. package/dist/gateway/checkpoint-service.js +47 -24
  175. package/dist/gateway/checkpoint-service.js.map +1 -1
  176. package/dist/ledger/archive.d.ts +1 -4
  177. package/dist/ledger/archive.d.ts.map +1 -1
  178. package/dist/ledger/archive.js +77 -39
  179. package/dist/ledger/archive.js.map +1 -1
  180. package/dist/ledger/maintenance.d.ts +0 -11
  181. package/dist/ledger/maintenance.d.ts.map +1 -1
  182. package/dist/ledger/maintenance.js +24 -40
  183. package/dist/ledger/maintenance.js.map +1 -1
  184. package/dist/ledger/projection.d.ts +0 -1
  185. package/dist/ledger/projection.d.ts.map +1 -1
  186. package/dist/ledger/projection.js.map +1 -1
  187. package/dist/ledger/promotion.d.ts +0 -9
  188. package/dist/ledger/promotion.d.ts.map +1 -1
  189. package/dist/ledger/promotion.js.map +1 -1
  190. package/dist/ledger/query.d.ts +1 -15
  191. package/dist/ledger/query.d.ts.map +1 -1
  192. package/dist/ledger/query.js.map +1 -1
  193. package/dist/ledger/store.d.ts +0 -1
  194. package/dist/ledger/store.d.ts.map +1 -1
  195. package/dist/ledger/store.js +11 -8
  196. package/dist/ledger/store.js.map +1 -1
  197. package/dist/ledger/types.d.ts +0 -4
  198. package/dist/ledger/types.d.ts.map +1 -1
  199. package/dist/ledger/types.js.map +1 -1
  200. package/dist/ledger/validate.d.ts.map +1 -1
  201. package/dist/ledger/validate.js +0 -5
  202. package/dist/ledger/validate.js.map +1 -1
  203. package/dist/mcp/server.d.ts +4 -0
  204. package/dist/mcp/server.d.ts.map +1 -1
  205. package/dist/mcp/server.js +105 -54
  206. package/dist/mcp/server.js.map +1 -1
  207. package/dist/memory/audit.d.ts +0 -1
  208. package/dist/memory/audit.d.ts.map +1 -1
  209. package/dist/memory/audit.js +0 -1
  210. package/dist/memory/audit.js.map +1 -1
  211. package/dist/memory/curator.d.ts.map +1 -1
  212. package/dist/memory/curator.js +172 -96
  213. package/dist/memory/curator.js.map +1 -1
  214. package/dist/memory/entries.d.ts +12 -2
  215. package/dist/memory/entries.d.ts.map +1 -1
  216. package/dist/memory/entries.js +198 -114
  217. package/dist/memory/entries.js.map +1 -1
  218. package/dist/memory/federated-retrieval.d.ts +12 -1
  219. package/dist/memory/federated-retrieval.d.ts.map +1 -1
  220. package/dist/memory/federated-retrieval.js +183 -70
  221. package/dist/memory/federated-retrieval.js.map +1 -1
  222. package/dist/memory/hybrid-retrieval.d.ts +5 -11
  223. package/dist/memory/hybrid-retrieval.d.ts.map +1 -1
  224. package/dist/memory/hybrid-retrieval.js +78 -58
  225. package/dist/memory/hybrid-retrieval.js.map +1 -1
  226. package/dist/memory/lifecycle.d.ts.map +1 -1
  227. package/dist/memory/lifecycle.js +17 -13
  228. package/dist/memory/lifecycle.js.map +1 -1
  229. package/dist/memory/rebuild-search.d.ts +5 -0
  230. package/dist/memory/rebuild-search.d.ts.map +1 -1
  231. package/dist/memory/rebuild-search.js +101 -76
  232. package/dist/memory/rebuild-search.js.map +1 -1
  233. package/dist/memory/retrieval-query.d.ts +0 -5
  234. package/dist/memory/retrieval-query.d.ts.map +1 -1
  235. package/dist/memory/retrieval-query.js +0 -5
  236. package/dist/memory/retrieval-query.js.map +1 -1
  237. package/dist/memory/retrieval.d.ts.map +1 -1
  238. package/dist/memory/retrieval.js +25 -131
  239. package/dist/memory/retrieval.js.map +1 -1
  240. package/dist/memory/revisions.d.ts +76 -1
  241. package/dist/memory/revisions.d.ts.map +1 -1
  242. package/dist/memory/revisions.js +539 -35
  243. package/dist/memory/revisions.js.map +1 -1
  244. package/dist/memory/scoped-memory.d.ts +16 -1
  245. package/dist/memory/scoped-memory.d.ts.map +1 -1
  246. package/dist/memory/scoped-memory.js +240 -107
  247. package/dist/memory/scoped-memory.js.map +1 -1
  248. package/dist/memory/secrets.d.ts +2 -0
  249. package/dist/memory/secrets.d.ts.map +1 -1
  250. package/dist/memory/secrets.js +36 -0
  251. package/dist/memory/secrets.js.map +1 -1
  252. package/dist/memory/structured-memory.d.ts +3 -2
  253. package/dist/memory/structured-memory.d.ts.map +1 -1
  254. package/dist/memory/structured-memory.js +54 -22
  255. package/dist/memory/structured-memory.js.map +1 -1
  256. package/dist/memory/workspaces.d.ts +9 -0
  257. package/dist/memory/workspaces.d.ts.map +1 -1
  258. package/dist/memory/workspaces.js +67 -0
  259. package/dist/memory/workspaces.js.map +1 -1
  260. package/dist/package-version.d.ts +2 -0
  261. package/dist/package-version.d.ts.map +1 -0
  262. package/dist/package-version.js +7 -0
  263. package/dist/package-version.js.map +1 -0
  264. package/dist/repository/binding.d.ts +5 -0
  265. package/dist/repository/binding.d.ts.map +1 -1
  266. package/dist/repository/binding.js +117 -17
  267. package/dist/repository/binding.js.map +1 -1
  268. package/dist/repository/framework-version.d.ts +8 -0
  269. package/dist/repository/framework-version.d.ts.map +1 -0
  270. package/dist/repository/framework-version.js +29 -0
  271. package/dist/repository/framework-version.js.map +1 -0
  272. package/dist/repository/identity-value.d.ts +4 -0
  273. package/dist/repository/identity-value.d.ts.map +1 -0
  274. package/dist/repository/identity-value.js +24 -0
  275. package/dist/repository/identity-value.js.map +1 -0
  276. package/dist/repository/identity.d.ts.map +1 -1
  277. package/dist/repository/identity.js +2 -0
  278. package/dist/repository/identity.js.map +1 -1
  279. package/dist/repository/project-fingerprint.d.ts +14 -2
  280. package/dist/repository/project-fingerprint.d.ts.map +1 -1
  281. package/dist/repository/project-fingerprint.js +312 -33
  282. package/dist/repository/project-fingerprint.js.map +1 -1
  283. package/dist/repository/remote-url.d.ts +0 -1
  284. package/dist/repository/remote-url.d.ts.map +1 -1
  285. package/dist/repository/remote-url.js +0 -1
  286. package/dist/repository/remote-url.js.map +1 -1
  287. package/dist/runtime-version.d.ts +2 -1
  288. package/dist/runtime-version.d.ts.map +1 -1
  289. package/dist/runtime-version.js +21 -4
  290. package/dist/runtime-version.js.map +1 -1
  291. package/dist/serialization/boundary-json.d.ts +20 -0
  292. package/dist/serialization/boundary-json.d.ts.map +1 -0
  293. package/dist/serialization/boundary-json.js +129 -0
  294. package/dist/serialization/boundary-json.js.map +1 -0
  295. package/dist/serialization/envelope.js +1 -1
  296. package/dist/serialization/envelope.js.map +1 -1
  297. package/dist/serialization/validate.d.ts +7 -0
  298. package/dist/serialization/validate.d.ts.map +1 -1
  299. package/dist/serialization/validate.js +53 -13
  300. package/dist/serialization/validate.js.map +1 -1
  301. package/dist/server/app.js +1 -1
  302. package/dist/server/app.js.map +1 -1
  303. package/dist/server/http.d.ts +4 -3
  304. package/dist/server/http.d.ts.map +1 -1
  305. package/dist/server/http.js +90 -50
  306. package/dist/server/http.js.map +1 -1
  307. package/dist/server/idempotency.d.ts +0 -6
  308. package/dist/server/idempotency.d.ts.map +1 -1
  309. package/dist/server/idempotency.js.map +1 -1
  310. package/dist/server/router.d.ts.map +1 -1
  311. package/dist/server/router.js +21 -4
  312. package/dist/server/router.js.map +1 -1
  313. package/dist/server/routes/agent-capability-gate.d.ts +40 -0
  314. package/dist/server/routes/agent-capability-gate.d.ts.map +1 -0
  315. package/dist/server/routes/agent-capability-gate.js +182 -0
  316. package/dist/server/routes/agent-capability-gate.js.map +1 -0
  317. package/dist/server/routes/agent-events.d.ts.map +1 -1
  318. package/dist/server/routes/agent-events.js +8 -1
  319. package/dist/server/routes/agent-events.js.map +1 -1
  320. package/dist/server/routes/agent-intake.d.ts.map +1 -1
  321. package/dist/server/routes/agent-intake.js +10 -2
  322. package/dist/server/routes/agent-intake.js.map +1 -1
  323. package/dist/server/routes/agent-promotions.d.ts.map +1 -1
  324. package/dist/server/routes/agent-promotions.js +5 -2
  325. package/dist/server/routes/agent-promotions.js.map +1 -1
  326. package/dist/server/routes/agent-runs.d.ts.map +1 -1
  327. package/dist/server/routes/agent-runs.js +18 -4
  328. package/dist/server/routes/agent-runs.js.map +1 -1
  329. package/dist/server/routes/request-binding.d.ts +5 -0
  330. package/dist/server/routes/request-binding.d.ts.map +1 -0
  331. package/dist/server/routes/request-binding.js +49 -0
  332. package/dist/server/routes/request-binding.js.map +1 -0
  333. package/dist/server/routes/task5-support.d.ts +1 -8
  334. package/dist/server/routes/task5-support.d.ts.map +1 -1
  335. package/dist/server/routes/task5-support.js +1 -17
  336. package/dist/server/routes/task5-support.js.map +1 -1
  337. package/dist/server/routes/task5.d.ts.map +1 -1
  338. package/dist/server/routes/task5.js +106 -36
  339. package/dist/server/routes/task5.js.map +1 -1
  340. package/dist/server/write-queue.js +2 -2
  341. package/dist/server/write-queue.js.map +1 -1
  342. package/dist/setup/claude-config.d.ts +2 -1
  343. package/dist/setup/claude-config.d.ts.map +1 -1
  344. package/dist/setup/claude-config.js +54 -4
  345. package/dist/setup/claude-config.js.map +1 -1
  346. package/dist/setup/client-detection.d.ts +7 -2
  347. package/dist/setup/client-detection.d.ts.map +1 -1
  348. package/dist/setup/client-detection.js +27 -9
  349. package/dist/setup/client-detection.js.map +1 -1
  350. package/dist/setup/hermes-config.d.ts +2 -1
  351. package/dist/setup/hermes-config.d.ts.map +1 -1
  352. package/dist/setup/hermes-config.js +53 -12
  353. package/dist/setup/hermes-config.js.map +1 -1
  354. package/dist/setup/legacy-client-cleanup.d.ts +6 -0
  355. package/dist/setup/legacy-client-cleanup.d.ts.map +1 -0
  356. package/dist/setup/legacy-client-cleanup.js +152 -0
  357. package/dist/setup/legacy-client-cleanup.js.map +1 -0
  358. package/dist/setup/managed-text.d.ts.map +1 -1
  359. package/dist/setup/managed-text.js +11 -1
  360. package/dist/setup/managed-text.js.map +1 -1
  361. package/dist/setup/opencode-config.d.ts +2 -1
  362. package/dist/setup/opencode-config.d.ts.map +1 -1
  363. package/dist/setup/opencode-config.js +57 -5
  364. package/dist/setup/opencode-config.js.map +1 -1
  365. package/dist/setup/render.d.ts +2 -1
  366. package/dist/setup/render.d.ts.map +1 -1
  367. package/dist/setup/render.js +91 -17
  368. package/dist/setup/render.js.map +1 -1
  369. package/dist/setup/standard-skills.d.ts +16 -2
  370. package/dist/setup/standard-skills.d.ts.map +1 -1
  371. package/dist/setup/standard-skills.js +37 -13
  372. package/dist/setup/standard-skills.js.map +1 -1
  373. package/dist/setup/strict-json.d.ts +7 -0
  374. package/dist/setup/strict-json.d.ts.map +1 -0
  375. package/dist/setup/strict-json.js +98 -0
  376. package/dist/setup/strict-json.js.map +1 -0
  377. package/dist/setup/strict-toml.d.ts +7 -0
  378. package/dist/setup/strict-toml.d.ts.map +1 -0
  379. package/dist/setup/strict-toml.js +470 -0
  380. package/dist/setup/strict-toml.js.map +1 -0
  381. package/dist/skills/cache.d.ts +15 -0
  382. package/dist/skills/cache.d.ts.map +1 -0
  383. package/dist/skills/cache.js +19 -0
  384. package/dist/skills/cache.js.map +1 -0
  385. package/dist/skills/candidate-ranking.d.ts +15 -0
  386. package/dist/skills/candidate-ranking.d.ts.map +1 -0
  387. package/dist/skills/candidate-ranking.js +52 -0
  388. package/dist/skills/candidate-ranking.js.map +1 -0
  389. package/dist/skills/chunking.d.ts +11 -0
  390. package/dist/skills/chunking.d.ts.map +1 -0
  391. package/dist/skills/chunking.js +291 -0
  392. package/dist/skills/chunking.js.map +1 -0
  393. package/dist/skills/config.d.ts +19 -0
  394. package/dist/skills/config.d.ts.map +1 -0
  395. package/dist/skills/config.js +103 -0
  396. package/dist/skills/config.js.map +1 -0
  397. package/dist/skills/discovery-service.d.ts +26 -0
  398. package/dist/skills/discovery-service.d.ts.map +1 -0
  399. package/dist/skills/discovery-service.js +921 -0
  400. package/dist/skills/discovery-service.js.map +1 -0
  401. package/dist/skills/external-transport.d.ts +2 -0
  402. package/dist/skills/external-transport.d.ts.map +1 -0
  403. package/dist/skills/external-transport.js +30 -0
  404. package/dist/skills/external-transport.js.map +1 -0
  405. package/dist/skills/find.d.ts +16 -0
  406. package/dist/skills/find.d.ts.map +1 -0
  407. package/dist/skills/find.js +58 -0
  408. package/dist/skills/find.js.map +1 -0
  409. package/dist/skills/gap-detection.d.ts +23 -0
  410. package/dist/skills/gap-detection.d.ts.map +1 -0
  411. package/dist/skills/gap-detection.js +62 -0
  412. package/dist/skills/gap-detection.js.map +1 -0
  413. package/dist/skills/import-preparation.d.ts +4 -0
  414. package/dist/skills/import-preparation.d.ts.map +1 -0
  415. package/dist/skills/import-preparation.js +20 -0
  416. package/dist/skills/import-preparation.js.map +1 -0
  417. package/dist/skills/materialization-authority.d.ts +11 -0
  418. package/dist/skills/materialization-authority.d.ts.map +1 -0
  419. package/dist/skills/materialization-authority.js +92 -0
  420. package/dist/skills/materialization-authority.js.map +1 -0
  421. package/dist/skills/materialization-service.d.ts +22 -0
  422. package/dist/skills/materialization-service.d.ts.map +1 -0
  423. package/dist/skills/materialization-service.js +101 -0
  424. package/dist/skills/materialization-service.js.map +1 -0
  425. package/dist/skills/official-catalog.d.ts +31 -0
  426. package/dist/skills/official-catalog.d.ts.map +1 -0
  427. package/dist/skills/official-catalog.js +110 -0
  428. package/dist/skills/official-catalog.js.map +1 -0
  429. package/dist/skills/providers/schema.d.ts +30 -0
  430. package/dist/skills/providers/schema.d.ts.map +1 -0
  431. package/dist/skills/providers/schema.js +354 -0
  432. package/dist/skills/providers/schema.js.map +1 -0
  433. package/dist/skills/providers/skills-sh-compat.d.ts +17 -0
  434. package/dist/skills/providers/skills-sh-compat.d.ts.map +1 -0
  435. package/dist/skills/providers/skills-sh-compat.js +71 -0
  436. package/dist/skills/providers/skills-sh-compat.js.map +1 -0
  437. package/dist/skills/providers/skills-sh-v1.d.ts +23 -0
  438. package/dist/skills/providers/skills-sh-v1.d.ts.map +1 -0
  439. package/dist/skills/providers/skills-sh-v1.js +134 -0
  440. package/dist/skills/providers/skills-sh-v1.js.map +1 -0
  441. package/dist/skills/query-builder.d.ts +18 -0
  442. package/dist/skills/query-builder.d.ts.map +1 -0
  443. package/dist/skills/query-builder.js +93 -0
  444. package/dist/skills/query-builder.js.map +1 -0
  445. package/dist/skills/source/errors.d.ts +9 -0
  446. package/dist/skills/source/errors.d.ts.map +1 -0
  447. package/dist/skills/source/errors.js +15 -0
  448. package/dist/skills/source/errors.js.map +1 -0
  449. package/dist/skills/source/frontmatter.d.ts +9 -0
  450. package/dist/skills/source/frontmatter.d.ts.map +1 -0
  451. package/dist/skills/source/frontmatter.js +77 -0
  452. package/dist/skills/source/frontmatter.js.map +1 -0
  453. package/dist/skills/source/github-fetcher.d.ts +20 -0
  454. package/dist/skills/source/github-fetcher.d.ts.map +1 -0
  455. package/dist/skills/source/github-fetcher.js +292 -0
  456. package/dist/skills/source/github-fetcher.js.map +1 -0
  457. package/dist/skills/source/snapshot-validator.d.ts +28 -0
  458. package/dist/skills/source/snapshot-validator.d.ts.map +1 -0
  459. package/dist/skills/source/snapshot-validator.js +186 -0
  460. package/dist/skills/source/snapshot-validator.js.map +1 -0
  461. package/dist/skills/store.d.ts +181 -0
  462. package/dist/skills/store.d.ts.map +1 -0
  463. package/dist/skills/store.js +1710 -0
  464. package/dist/skills/store.js.map +1 -0
  465. package/dist/skills/types.d.ts +169 -0
  466. package/dist/skills/types.d.ts.map +1 -0
  467. package/dist/skills/types.js +2 -0
  468. package/dist/skills/types.js.map +1 -0
  469. package/dist/web/i18n.d.ts +32 -0
  470. package/dist/web/i18n.d.ts.map +1 -1
  471. package/dist/web/i18n.js +128 -0
  472. package/dist/web/i18n.js.map +1 -1
  473. package/dist/web/server.d.ts.map +1 -1
  474. package/dist/web/server.js +386 -38
  475. package/dist/web/server.js.map +1 -1
  476. package/dist/web/ui.d.ts +4 -0
  477. package/dist/web/ui.d.ts.map +1 -1
  478. package/dist/web/ui.js +382 -6
  479. package/dist/web/ui.js.map +1 -1
  480. package/migrations/009_external_skill_discovery.sql +126 -0
  481. package/package.json +4 -3
  482. package/skills/kiokuko-single-purpose-functions/SKILL.md +288 -0
  483. package/skills/kiokuko-single-purpose-functions/references/kiokuko-patterns.md +344 -0
  484. package/skills/kiokuko-single-purpose-functions/references/review-checklist.md +97 -0
  485. package/skills/kiokuko-ui-design-soul/SKILL.md +1186 -28
  486. package/templates/AGENTS.md +8 -7
  487. package/dist/client/runtime-discovery.d.ts +0 -15
  488. package/dist/client/runtime-discovery.d.ts.map +0 -1
  489. package/dist/client/runtime-discovery.js +0 -45
  490. package/dist/client/runtime-discovery.js.map +0 -1
  491. package/dist/commands/call.d.ts +0 -7
  492. package/dist/commands/call.d.ts.map +0 -1
  493. package/dist/commands/call.js +0 -10
  494. package/dist/commands/call.js.map +0 -1
  495. package/dist/commands/link.d.ts +0 -6
  496. package/dist/commands/link.d.ts.map +0 -1
  497. package/dist/commands/link.js +0 -6
  498. package/dist/commands/link.js.map +0 -1
  499. package/dist/commands/promote.d.ts +0 -6
  500. package/dist/commands/promote.d.ts.map +0 -1
  501. package/dist/commands/promote.js +0 -6
  502. package/dist/commands/promote.js.map +0 -1
  503. package/dist/commands/read.d.ts +0 -6
  504. package/dist/commands/read.d.ts.map +0 -1
  505. package/dist/commands/read.js +0 -4
  506. package/dist/commands/read.js.map +0 -1
  507. package/dist/commands/recall.d.ts +0 -6
  508. package/dist/commands/recall.d.ts.map +0 -1
  509. package/dist/commands/recall.js +0 -4
  510. package/dist/commands/recall.js.map +0 -1
  511. package/dist/commands/record.d.ts +0 -6
  512. package/dist/commands/record.d.ts.map +0 -1
  513. package/dist/commands/record.js +0 -4
  514. package/dist/commands/record.js.map +0 -1
  515. package/dist/commands/search.d.ts +0 -6
  516. package/dist/commands/search.d.ts.map +0 -1
  517. package/dist/commands/search.js +0 -4
  518. package/dist/commands/search.js.map +0 -1
  519. package/dist/commands/supersede.d.ts +0 -6
  520. package/dist/commands/supersede.d.ts.map +0 -1
  521. package/dist/commands/supersede.js +0 -6
  522. package/dist/commands/supersede.js.map +0 -1
  523. package/dist/knowledge/sources.d.ts +0 -72
  524. package/dist/knowledge/sources.d.ts.map +0 -1
  525. package/dist/knowledge/sources.js +0 -388
  526. package/dist/knowledge/sources.js.map +0 -1
  527. package/dist/setup/opencode-evidence.d.ts +0 -37
  528. package/dist/setup/opencode-evidence.d.ts.map +0 -1
  529. package/dist/setup/opencode-evidence.js +0 -58
  530. package/dist/setup/opencode-evidence.js.map +0 -1
  531. package/dist/setup/opencode-loop-guard.d.ts +0 -9
  532. package/dist/setup/opencode-loop-guard.d.ts.map +0 -1
  533. package/dist/setup/opencode-loop-guard.js +0 -248
  534. package/dist/setup/opencode-loop-guard.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,5 +1,7 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { createRequire } from 'node:module';
1
+ import { constants as fsConstants } from 'node:fs';
2
+ import { open } from 'node:fs/promises';
3
+ import { TextDecoder } from 'node:util';
4
+ import { isProxy } from 'node:util/types';
3
5
  import { Command, CommanderError } from 'commander';
4
6
  import { initializeDatabase } from './commands/init.js';
5
7
  import { useRepository } from './commands/use.js';
@@ -19,41 +21,153 @@ import { startWebServer } from './web/server.js';
19
21
  import { registerServerCommands } from './commands/server.js';
20
22
  import { registerAgentCommand } from './commands/agent.js';
21
23
  import { registerLedgerCommands } from './commands/ledger.js';
22
- import { answerAkinator, getAkinatorContext, startAkinator } from './akinator/orchestrator.js';
23
- import { parseSetupClients, promptSetupClients, setupGlobalClients } from './commands/setup.js';
24
+ import { answerAkinator, startAkinator } from './akinator/orchestrator.js';
25
+ import { parseSetupClients, parseSetupSkillDiscoveryMode, promptCommunitySkillDiscovery, promptSetupClients, promptSetupConfiguration, setupGlobalClients, } from './commands/setup.js';
24
26
  import { runMcpServer } from './mcp/server.js';
25
27
  import { runCuratorCommand } from './commands/curator.js';
26
28
  import { globalizeCuratorCandidate } from './memory/curator.js';
27
29
  import { detectInstalledClients } from './setup/client-detection.js';
28
- const packageMetadata = createRequire(import.meta.url)('../package.json');
29
- if (typeof packageMetadata.version !== 'string' || packageMetadata.version.length === 0) {
30
- throw new Error('Kiokuko package version is unavailable');
30
+ import { registerSkillsCommands } from './commands/skills.js';
31
+ import { normalizeSkillDiscoveryMode, SKILL_DISCOVERY_ENV } from './skills/config.js';
32
+ import { PACKAGE_VERSION } from './package-version.js';
33
+ import { parseStrictJson } from './setup/strict-json.js';
34
+ import { validateRecordInput } from './serialization/validate.js';
35
+ const MAX_CLI_JSON_INPUT_BYTES = 2 * 1024 * 1024;
36
+ const MAX_CALL_PATH_BYTES = 4 * 1024;
37
+ const CONTROL_CHARACTERS = /\p{Cc}/u;
38
+ function invalidJsonInput() {
39
+ return new KiokukoError('VALIDATION_ERROR', 'Input is not valid JSON with unique keys');
40
+ }
41
+ async function readBoundedStdin() {
42
+ if (process.stdin.readableEncoding !== null || process.stdin.readableDidRead) {
43
+ throw invalidJsonInput();
44
+ }
45
+ const chunks = [];
46
+ let size = 0;
47
+ for await (const chunk of process.stdin) {
48
+ if (!Buffer.isBuffer(chunk))
49
+ throw invalidJsonInput();
50
+ const bytes = chunk;
51
+ size += bytes.byteLength;
52
+ if (size > MAX_CLI_JSON_INPUT_BYTES)
53
+ throw invalidJsonInput();
54
+ chunks.push(bytes);
55
+ }
56
+ return Buffer.concat(chunks);
57
+ }
58
+ function filesystemErrorCode(error) {
59
+ if ((typeof error !== 'object' && typeof error !== 'function') || error === null || isProxy(error)) {
60
+ return undefined;
61
+ }
62
+ const descriptor = Object.getOwnPropertyDescriptor(error, 'code');
63
+ return descriptor !== undefined && 'value' in descriptor && typeof descriptor.value === 'string'
64
+ ? descriptor.value
65
+ : undefined;
66
+ }
67
+ async function readBoundedJsonFile(filePath) {
68
+ let handle;
69
+ try {
70
+ handle = await open(filePath, fsConstants.O_RDONLY | fsConstants.O_NONBLOCK);
71
+ }
72
+ catch (error) {
73
+ if (filesystemErrorCode(error) === 'ENOENT' || filesystemErrorCode(error) === 'ENOTDIR') {
74
+ throw new KiokukoError('NOT_FOUND', 'JSON input file does not exist');
75
+ }
76
+ throw error;
77
+ }
78
+ let result;
79
+ let operationFailed = false;
80
+ let operationError;
81
+ try {
82
+ const initial = await handle.stat({ bigint: true });
83
+ if (!initial.isFile()) {
84
+ throw invalidJsonInput();
85
+ }
86
+ if (initial.size < 0n || initial.size > BigInt(MAX_CLI_JSON_INPUT_BYTES)) {
87
+ throw invalidJsonInput();
88
+ }
89
+ const expectedSize = Number(initial.size);
90
+ const bytes = Buffer.allocUnsafe(expectedSize + 1);
91
+ let offset = 0;
92
+ while (offset < bytes.byteLength) {
93
+ const read = await handle.read(bytes, offset, bytes.byteLength - offset, offset);
94
+ if (read.bytesRead === 0)
95
+ break;
96
+ offset += read.bytesRead;
97
+ }
98
+ const final = await handle.stat({ bigint: true });
99
+ if (offset !== expectedSize
100
+ || final.size !== initial.size
101
+ || final.dev !== initial.dev
102
+ || final.ino !== initial.ino
103
+ || final.mtimeNs !== initial.mtimeNs
104
+ || final.ctimeNs !== initial.ctimeNs) {
105
+ throw new KiokukoError('CONFLICT', 'JSON input file changed while it was being read');
106
+ }
107
+ result = bytes.subarray(0, offset);
108
+ }
109
+ catch (error) {
110
+ operationFailed = true;
111
+ operationError = error;
112
+ }
113
+ try {
114
+ await handle.close();
115
+ }
116
+ catch (closeError) {
117
+ if (operationFailed) {
118
+ throw new AggregateError([operationError, closeError], 'JSON input read failed and its file descriptor could not be closed');
119
+ }
120
+ throw new AggregateError([closeError], 'JSON input was read, but its file descriptor could not be closed');
121
+ }
122
+ if (operationFailed) {
123
+ if (operationError instanceof KiokukoError && operationError.code === 'VALIDATION_ERROR') {
124
+ throw operationError;
125
+ }
126
+ throw operationError;
127
+ }
128
+ if (result === undefined)
129
+ throw invalidJsonInput();
130
+ return result;
31
131
  }
32
- const packageVersion = packageMetadata.version;
33
132
  async function readJsonInput(filePath) {
34
- const text = filePath === '-' ? await new Promise((resolve, reject) => {
35
- let value = '';
36
- process.stdin.setEncoding('utf8');
37
- process.stdin.on('data', (chunk) => { value += chunk; });
38
- process.stdin.on('end', () => resolve(value));
39
- process.stdin.on('error', reject);
40
- }) : await readFile(filePath, 'utf8');
133
+ const bytes = filePath === '-' ? await readBoundedStdin() : await readBoundedJsonFile(filePath);
134
+ let text;
41
135
  try {
42
- return JSON.parse(text);
136
+ text = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes);
43
137
  }
44
138
  catch {
45
- throw new KiokukoError('VALIDATION_ERROR', 'Input is not valid JSON');
139
+ throw invalidJsonInput();
46
140
  }
141
+ return parseStrictJson(text, { allowTrailingComma: false, disallowComments: true, allowEmptyContent: false }, 'Input is not valid JSON with unique keys');
47
142
  }
48
143
  async function withDatabase(operation) {
49
144
  const result = await initializeDatabase();
50
145
  const database = openConnection(result.databasePath);
146
+ let operationResult;
147
+ let operationFailed = false;
148
+ let operationError;
51
149
  try {
52
- return await operation(database);
150
+ operationResult = { value: await operation(database) };
53
151
  }
54
- finally {
152
+ catch (error) {
153
+ operationFailed = true;
154
+ operationError = error;
155
+ }
156
+ try {
55
157
  database.close();
56
158
  }
159
+ catch (closeError) {
160
+ if (operationFailed) {
161
+ throw new AggregateError([operationError, closeError], 'Database operation failed and closing its connection also failed');
162
+ }
163
+ throw new AggregateError([closeError], 'Database operation completed, but closing its connection failed');
164
+ }
165
+ if (operationFailed)
166
+ throw operationError;
167
+ if (operationResult === undefined) {
168
+ throw new KiokukoError('INTEGRITY_ERROR', 'Database operation produced no result');
169
+ }
170
+ return operationResult.value;
57
171
  }
58
172
  function emit(value) {
59
173
  process.stdout.write(`${JSON.stringify(value)}\n`);
@@ -76,7 +190,7 @@ function addWorkspaceOptions(command) {
76
190
  return command.option('--workspace <name>', 'Workspace name').option('--json', 'Emit a JSON response');
77
191
  }
78
192
  function configureRecallCommand(command) {
79
- const recall = addWorkspaceOptions(command.description('Recall relevant memory entries').argument('<query>'))
193
+ const recall = addWorkspaceOptions(command.description('Human/operator management: recall relevant memory entries').argument('<query>'))
80
194
  .option('--limit <number>', 'Maximum entries', '5').option('--max-chars <number>', 'Context character budget', '8000')
81
195
  .option('--scope <scope>', 'auto, project, ecosystem, or global', 'auto').option('--cwd <path>', 'Repository path used for scoped recall');
82
196
  recall.action(async (query, options) => {
@@ -100,112 +214,376 @@ function configureRecallCommand(command) {
100
214
  });
101
215
  return recall;
102
216
  }
103
- async function dispatchRequest(request) {
104
- if (typeof request !== 'object' || request === null || Array.isArray(request))
105
- throw new KiokukoError('VALIDATION_ERROR', 'Request must be a JSON object');
106
- const value = request;
107
- if (value.apiVersion !== '1')
217
+ const CALL_OPERATIONS = [
218
+ 'init',
219
+ 'use',
220
+ 'record',
221
+ 'curator',
222
+ 'curator_globalize',
223
+ 'guide_start',
224
+ 'guide_answer',
225
+ 'promote',
226
+ 'supersede',
227
+ 'link',
228
+ 'purge',
229
+ 'export',
230
+ 'import',
231
+ 'backup',
232
+ 'doctor',
233
+ ];
234
+ const SUPPORTED_CALL_OPERATIONS = new Set(CALL_OPERATIONS);
235
+ function snapshotPlainJsonObject(value, message) {
236
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
237
+ throw new KiokukoError('VALIDATION_ERROR', message);
238
+ }
239
+ const prototype = Object.getPrototypeOf(value);
240
+ if (prototype !== Object.prototype && prototype !== null) {
241
+ throw new KiokukoError('VALIDATION_ERROR', message);
242
+ }
243
+ const result = Object.create(null);
244
+ for (const key of Reflect.ownKeys(value)) {
245
+ if (typeof key !== 'string')
246
+ throw new KiokukoError('VALIDATION_ERROR', message);
247
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
248
+ if (descriptor === undefined || !('value' in descriptor) || descriptor.enumerable !== true) {
249
+ throw new KiokukoError('VALIDATION_ERROR', message);
250
+ }
251
+ Object.defineProperty(result, key, {
252
+ value: descriptor.value,
253
+ enumerable: true,
254
+ writable: true,
255
+ configurable: true,
256
+ });
257
+ }
258
+ return result;
259
+ }
260
+ function assertExactCallArguments(args, operation, allowed, required = []) {
261
+ const allowedFields = new Set(allowed);
262
+ for (const field of Object.keys(args)) {
263
+ if (!allowedFields.has(field)) {
264
+ throw new KiokukoError('VALIDATION_ERROR', `Unknown ${operation} argument: ${field}`);
265
+ }
266
+ }
267
+ for (const field of required) {
268
+ if (!Object.hasOwn(args, field)) {
269
+ throw new KiokukoError('VALIDATION_ERROR', `${operation}.${field} is required`);
270
+ }
271
+ }
272
+ }
273
+ function requiredStringArgument(args, operation, field) {
274
+ const value = args[field];
275
+ if (typeof value !== 'string' || value.trim().length === 0) {
276
+ throw new KiokukoError('VALIDATION_ERROR', `${operation}.${field} must be a non-empty string`);
277
+ }
278
+ return value;
279
+ }
280
+ function optionalStringArgument(args, operation, field) {
281
+ return Object.hasOwn(args, field) ? requiredStringArgument(args, operation, field) : undefined;
282
+ }
283
+ function requiredPathArgument(args, operation, field) {
284
+ const value = requiredStringArgument(args, operation, field);
285
+ if (CONTROL_CHARACTERS.test(value) || Buffer.byteLength(value, 'utf8') > MAX_CALL_PATH_BYTES) {
286
+ throw new KiokukoError('VALIDATION_ERROR', `${operation}.${field} must be a bounded path without control characters`);
287
+ }
288
+ return value;
289
+ }
290
+ function optionalPathArgument(args, operation, field) {
291
+ return Object.hasOwn(args, field) ? requiredPathArgument(args, operation, field) : undefined;
292
+ }
293
+ function requiredBooleanArgument(args, operation, field) {
294
+ const value = args[field];
295
+ if (typeof value !== 'boolean') {
296
+ throw new KiokukoError('VALIDATION_ERROR', `${operation}.${field} must be a boolean`);
297
+ }
298
+ return value;
299
+ }
300
+ function optionalBooleanArgument(args, operation, field) {
301
+ return Object.hasOwn(args, field) ? requiredBooleanArgument(args, operation, field) : undefined;
302
+ }
303
+ function requiredPositiveIntegerArgument(args, operation, field) {
304
+ const value = args[field];
305
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 1) {
306
+ throw new KiokukoError('VALIDATION_ERROR', `${operation}.${field} must be a positive integer`);
307
+ }
308
+ return value;
309
+ }
310
+ function validateUseCallArguments(args) {
311
+ const operation = 'use';
312
+ assertExactCallArguments(args, operation, [
313
+ 'cwd',
314
+ 'root',
315
+ 'workspace',
316
+ 'agentFile',
317
+ 'dryRun',
318
+ 'noAgentFile',
319
+ 'forceRebind',
320
+ 'allowDirectory',
321
+ 'databasePath',
322
+ 'migrationsDirectory',
323
+ 'repositoryId',
324
+ ]);
325
+ const result = {};
326
+ const cwd = optionalPathArgument(args, operation, 'cwd');
327
+ const root = optionalPathArgument(args, operation, 'root');
328
+ const workspace = optionalStringArgument(args, operation, 'workspace');
329
+ const agentFile = optionalPathArgument(args, operation, 'agentFile');
330
+ const databasePath = optionalPathArgument(args, operation, 'databasePath');
331
+ const migrationsDirectory = optionalPathArgument(args, operation, 'migrationsDirectory');
332
+ const repositoryId = optionalStringArgument(args, operation, 'repositoryId');
333
+ const dryRun = optionalBooleanArgument(args, operation, 'dryRun');
334
+ const noAgentFile = optionalBooleanArgument(args, operation, 'noAgentFile');
335
+ const forceRebind = optionalBooleanArgument(args, operation, 'forceRebind');
336
+ const allowDirectory = optionalBooleanArgument(args, operation, 'allowDirectory');
337
+ if (cwd !== undefined)
338
+ result.cwd = cwd;
339
+ if (root !== undefined)
340
+ result.root = root;
341
+ if (workspace !== undefined)
342
+ result.workspace = workspace;
343
+ if (agentFile !== undefined)
344
+ result.agentFile = agentFile;
345
+ if (databasePath !== undefined)
346
+ result.databasePath = databasePath;
347
+ if (migrationsDirectory !== undefined)
348
+ result.migrationsDirectory = migrationsDirectory;
349
+ if (repositoryId !== undefined)
350
+ result.repositoryId = repositoryId;
351
+ if (dryRun !== undefined)
352
+ result.dryRun = dryRun;
353
+ if (noAgentFile !== undefined)
354
+ result.noAgentFile = noAgentFile;
355
+ if (forceRebind !== undefined)
356
+ result.forceRebind = forceRebind;
357
+ if (allowDirectory !== undefined)
358
+ result.allowDirectory = allowDirectory;
359
+ return result;
360
+ }
361
+ function validateRecordCallArguments(args) {
362
+ return validateRecordInput(args);
363
+ }
364
+ function validateCuratorCallArguments(args) {
365
+ const operation = 'curator';
366
+ assertExactCallArguments(args, operation, ['workspace', 'cwd', 'limit', 'entryId', 'yes']);
367
+ const workspace = optionalStringArgument(args, operation, 'workspace');
368
+ const cwd = optionalPathArgument(args, operation, 'cwd');
369
+ const entryId = optionalStringArgument(args, operation, 'entryId');
370
+ const yes = optionalBooleanArgument(args, operation, 'yes');
371
+ const limit = Object.hasOwn(args, 'limit')
372
+ ? requiredPositiveIntegerArgument(args, operation, 'limit')
373
+ : undefined;
374
+ if (limit !== undefined && limit > 50) {
375
+ throw new KiokukoError('VALIDATION_ERROR', 'curator.limit must be an integer between 1 and 50');
376
+ }
377
+ return {
378
+ ...(workspace === undefined ? {} : { workspace }),
379
+ ...(cwd === undefined ? {} : { cwd }),
380
+ ...(limit === undefined ? {} : { limit }),
381
+ ...(entryId === undefined ? {} : { entryId }),
382
+ ...(yes === undefined ? {} : { yes }),
383
+ };
384
+ }
385
+ function validateCuratorGlobalizeCallArguments(args) {
386
+ const operation = 'curator_globalize';
387
+ assertExactCallArguments(args, operation, ['workspace', 'entryId', 'expectedRevision', 'actor'], ['workspace', 'entryId', 'expectedRevision']);
388
+ const actor = optionalStringArgument(args, operation, 'actor');
389
+ return {
390
+ workspace: requiredStringArgument(args, operation, 'workspace'),
391
+ entryId: requiredStringArgument(args, operation, 'entryId'),
392
+ expectedRevision: requiredPositiveIntegerArgument(args, operation, 'expectedRevision'),
393
+ ...(actor === undefined ? {} : { actor }),
394
+ };
395
+ }
396
+ function validateGuideStartCallArguments(args) {
397
+ const operation = 'guide_start';
398
+ assertExactCallArguments(args, operation, ['workspace', 'task'], ['workspace', 'task']);
399
+ return {
400
+ workspace: requiredStringArgument(args, operation, 'workspace'),
401
+ task: requiredStringArgument(args, operation, 'task'),
402
+ };
403
+ }
404
+ function validateGuideAnswerCallArguments(args) {
405
+ const operation = 'guide_answer';
406
+ assertExactCallArguments(args, operation, ['workspace', 'sessionId', 'questionId', 'value'], ['workspace', 'sessionId', 'questionId', 'value']);
407
+ const questionId = requiredStringArgument(args, operation, 'questionId');
408
+ if (!['taskType', 'target', 'expected', 'constraints'].includes(questionId)) {
409
+ throw new KiokukoError('VALIDATION_ERROR', 'guide_answer.questionId is unsupported');
410
+ }
411
+ return {
412
+ workspace: requiredStringArgument(args, operation, 'workspace'),
413
+ sessionId: requiredStringArgument(args, operation, 'sessionId'),
414
+ questionId: questionId,
415
+ value: requiredStringArgument(args, operation, 'value'),
416
+ };
417
+ }
418
+ function validatePromoteCallArguments(args) {
419
+ const operation = 'promote';
420
+ assertExactCallArguments(args, operation, ['workspace', 'entryId', 'expectedRevision'], ['workspace', 'entryId', 'expectedRevision']);
421
+ return {
422
+ workspace: requiredStringArgument(args, operation, 'workspace'),
423
+ entryId: requiredStringArgument(args, operation, 'entryId'),
424
+ expectedRevision: requiredPositiveIntegerArgument(args, operation, 'expectedRevision'),
425
+ };
426
+ }
427
+ function validateSupersedeCallArguments(args) {
428
+ const operation = 'supersede';
429
+ assertExactCallArguments(args, operation, ['workspace', 'oldEntryId', 'replacementEntryId', 'expectedRevision'], ['workspace', 'oldEntryId', 'replacementEntryId', 'expectedRevision']);
430
+ return {
431
+ workspace: requiredStringArgument(args, operation, 'workspace'),
432
+ oldEntryId: requiredStringArgument(args, operation, 'oldEntryId'),
433
+ replacementEntryId: requiredStringArgument(args, operation, 'replacementEntryId'),
434
+ expectedRevision: requiredPositiveIntegerArgument(args, operation, 'expectedRevision'),
435
+ };
436
+ }
437
+ function validateLinkCallArguments(args) {
438
+ const operation = 'link';
439
+ assertExactCallArguments(args, operation, ['workspace', 'fromEntryId', 'toEntryId', 'relation', 'actor', 'now'], ['workspace', 'fromEntryId', 'toEntryId', 'relation']);
440
+ const relation = requiredStringArgument(args, operation, 'relation');
441
+ if (!['supports', 'contradicts', 'derived_from', 'related_to'].includes(relation)) {
442
+ throw new KiokukoError('VALIDATION_ERROR', 'link.relation is unsupported');
443
+ }
444
+ const actor = optionalStringArgument(args, operation, 'actor');
445
+ const now = optionalStringArgument(args, operation, 'now');
446
+ return {
447
+ workspace: requiredStringArgument(args, operation, 'workspace'),
448
+ fromEntryId: requiredStringArgument(args, operation, 'fromEntryId'),
449
+ toEntryId: requiredStringArgument(args, operation, 'toEntryId'),
450
+ relation: relation,
451
+ ...(actor === undefined ? {} : { actor }),
452
+ ...(now === undefined ? {} : { now }),
453
+ };
454
+ }
455
+ function validatePurgeCallArguments(args) {
456
+ const operation = 'purge';
457
+ assertExactCallArguments(args, operation, ['workspace', 'entryId', 'confirm'], ['workspace', 'entryId', 'confirm']);
458
+ return {
459
+ workspace: requiredStringArgument(args, operation, 'workspace'),
460
+ entryId: requiredStringArgument(args, operation, 'entryId'),
461
+ confirm: requiredBooleanArgument(args, operation, 'confirm'),
462
+ };
463
+ }
464
+ function parseCallRequest(request) {
465
+ const value = snapshotPlainJsonObject(request, 'Request must be a JSON object');
466
+ const fields = Object.keys(value).sort();
467
+ if (fields.length !== 3
468
+ || fields[0] !== 'apiVersion'
469
+ || fields[1] !== 'arguments'
470
+ || fields[2] !== 'operation') {
471
+ throw new KiokukoError('VALIDATION_ERROR', 'Request must contain exactly apiVersion, operation, and arguments');
472
+ }
473
+ if (value.apiVersion !== '1') {
108
474
  throw new KiokukoError('VALIDATION_ERROR', 'apiVersion must be "1"');
109
- if (typeof value.operation !== 'string' || value.operation.length === 0)
475
+ }
476
+ if (typeof value.operation !== 'string' || value.operation.length === 0) {
110
477
  throw new KiokukoError('VALIDATION_ERROR', 'operation must be a non-empty string');
111
- const args = typeof value.arguments === 'object' && value.arguments !== null && !Array.isArray(value.arguments) ? value.arguments : {};
112
- const operation = value.operation;
113
- if (operation === 'init')
478
+ }
479
+ const args = snapshotPlainJsonObject(value.arguments, 'arguments must be a JSON object');
480
+ if (!SUPPORTED_CALL_OPERATIONS.has(value.operation)) {
481
+ throw new KiokukoError('VALIDATION_ERROR', `Unknown operation: ${value.operation}`);
482
+ }
483
+ return {
484
+ apiVersion: '1',
485
+ operation: value.operation,
486
+ arguments: args,
487
+ };
488
+ }
489
+ async function dispatchRequest(request) {
490
+ const args = request.arguments;
491
+ const operation = request.operation;
492
+ if (operation === 'init') {
493
+ assertExactCallArguments(args, operation, []);
114
494
  return initializeDatabase();
495
+ }
115
496
  if (operation === 'use')
116
- return useRepository(args);
117
- if (operation === 'record')
118
- return withDatabase((database) => recordEntry(database, args));
119
- if (operation === 'read')
120
- return withDatabase((database) => readEntry(database, { workspace: String(args.workspace ?? ''), entryId: String(args.entryId ?? '') }));
121
- if (operation === 'search')
122
- return withDatabase((database) => searchEntries(database, args));
123
- if (operation === 'recall') {
124
- if (typeof args.scope === 'string' || typeof args.cwd === 'string' || args.workspace === undefined) {
125
- return withDatabase((database) => recallScopedMemory(database, {
126
- query: String(args.query ?? ''),
127
- scope: String(args.scope ?? 'auto'),
128
- ...(typeof args.limit === 'number' ? { limit: args.limit } : {}),
129
- ...(typeof args.maxChars === 'number' ? { maxChars: args.maxChars } : {}),
130
- ...(typeof args.cwd === 'string' ? { cwd: args.cwd } : {}),
131
- }));
132
- }
133
- return withDatabase((database) => recallEntries(database, args));
134
- }
135
- if (operation === 'curator')
136
- return withDatabase((database) => runCuratorCommand(database, {
137
- ...(typeof args.workspace === 'string' ? { workspace: args.workspace } : {}),
138
- ...(typeof args.cwd === 'string' ? { cwd: args.cwd } : {}),
139
- ...(typeof args.limit === 'number' ? { limit: args.limit } : {}),
140
- ...(typeof args.entryId === 'string' ? { entryId: args.entryId } : {}),
141
- yes: args.yes === true,
142
- json: true,
143
- }));
144
- if (operation === 'curator_globalize')
145
- return withDatabase((database) => globalizeCuratorCandidate(database, {
146
- workspace: String(args.workspace ?? ''),
147
- entryId: String(args.entryId ?? ''),
148
- expectedRevision: Number(args.expectedRevision),
149
- ...(typeof args.actor === 'string' ? { actor: args.actor } : {}),
150
- }));
151
- if (operation === 'guide_start')
152
- return withDatabase((database) => startAkinator(database, {
153
- workspace: String(args.workspace ?? ''),
154
- task: String(args.task ?? ''),
155
- }));
156
- if (operation === 'guide_answer')
157
- return withDatabase((database) => answerAkinator(database, {
158
- workspace: String(args.workspace ?? ''),
159
- sessionId: String(args.sessionId ?? ''),
160
- questionId: String(args.questionId ?? ''),
161
- value: String(args.value ?? ''),
162
- }));
163
- if (operation === 'guide_context')
164
- return withDatabase((database) => getAkinatorContext(database, {
165
- workspace: String(args.workspace ?? ''),
166
- sessionId: String(args.sessionId ?? ''),
167
- }));
168
- if (operation === 'promote')
169
- return withDatabase((database) => promoteEntry(database, { workspace: String(args.workspace ?? ''), entryId: String(args.entryId ?? ''), expectedRevision: Number(args.expectedRevision) }));
170
- if (operation === 'supersede')
171
- return withDatabase((database) => supersedeEntry(database, { workspace: String(args.workspace ?? ''), oldEntryId: String(args.oldEntryId ?? ''), replacementEntryId: String(args.replacementEntryId ?? ''), expectedRevision: Number(args.expectedRevision) }));
172
- if (operation === 'link')
173
- return withDatabase((database) => { linkEntries(database, args); return { linked: true }; });
174
- if (operation === 'purge')
175
- return withDatabase((database) => { purgeEntry(database, { workspace: String(args.workspace ?? ''), entryId: String(args.entryId ?? ''), confirm: args.confirm === true }); return { purged: true }; });
497
+ return useRepository(validateUseCallArguments(args));
498
+ if (operation === 'record') {
499
+ const input = validateRecordCallArguments(args);
500
+ return withDatabase((database) => recordEntry(database, input));
501
+ }
502
+ if (operation === 'curator') {
503
+ const input = validateCuratorCallArguments(args);
504
+ return withDatabase((database) => runCuratorCommand(database, { ...input, json: true }));
505
+ }
506
+ if (operation === 'curator_globalize') {
507
+ const input = validateCuratorGlobalizeCallArguments(args);
508
+ return withDatabase((database) => globalizeCuratorCandidate(database, input));
509
+ }
510
+ if (operation === 'guide_start') {
511
+ const input = validateGuideStartCallArguments(args);
512
+ return withDatabase((database) => startAkinator(database, input));
513
+ }
514
+ if (operation === 'guide_answer') {
515
+ const input = validateGuideAnswerCallArguments(args);
516
+ return withDatabase((database) => answerAkinator(database, input));
517
+ }
518
+ if (operation === 'promote') {
519
+ const input = validatePromoteCallArguments(args);
520
+ return withDatabase((database) => promoteEntry(database, input));
521
+ }
522
+ if (operation === 'supersede') {
523
+ const input = validateSupersedeCallArguments(args);
524
+ return withDatabase((database) => supersedeEntry(database, input));
525
+ }
526
+ if (operation === 'link') {
527
+ const input = validateLinkCallArguments(args);
528
+ return withDatabase((database) => {
529
+ linkEntries(database, input);
530
+ return { linked: true };
531
+ });
532
+ }
533
+ if (operation === 'purge') {
534
+ const input = validatePurgeCallArguments(args);
535
+ return withDatabase((database) => {
536
+ purgeEntry(database, input);
537
+ return { purged: true };
538
+ });
539
+ }
176
540
  if (operation === 'export') {
177
- const workspace = String(args.workspace ?? '');
178
- const output = String(args.output ?? '');
179
- if (output.length === 0)
541
+ assertExactCallArguments(args, operation, ['workspace', 'output']);
542
+ if (!Object.hasOwn(args, 'output')) {
180
543
  throw new KiokukoError('VALIDATION_ERROR', 'export output is required');
544
+ }
545
+ const workspace = requiredStringArgument(args, operation, 'workspace');
546
+ const output = requiredPathArgument(args, operation, 'output');
181
547
  return withDatabase((database) => writeExport(database, { workspace, output }));
182
548
  }
183
549
  if (operation === 'import') {
184
- const input = String(args.input ?? '');
185
- if (input.length === 0)
550
+ assertExactCallArguments(args, operation, ['input', 'workspace', 'dryRun']);
551
+ if (!Object.hasOwn(args, 'input')) {
186
552
  throw new KiokukoError('VALIDATION_ERROR', 'import input is required');
187
- const importOptions = { input, dryRun: args.dryRun === true };
188
- if (typeof args.workspace === 'string')
189
- importOptions.workspace = args.workspace;
190
- return args.dryRun === true ? importWorkspace(undefined, importOptions) : withDatabase((database) => importWorkspace(database, importOptions));
553
+ }
554
+ const input = requiredPathArgument(args, operation, 'input');
555
+ const workspace = optionalStringArgument(args, operation, 'workspace');
556
+ const dryRun = optionalBooleanArgument(args, operation, 'dryRun');
557
+ const importOptions = {
558
+ input,
559
+ ...(workspace === undefined ? {} : { workspace }),
560
+ ...(dryRun === undefined ? {} : { dryRun }),
561
+ };
562
+ return dryRun === true
563
+ ? importWorkspace(undefined, importOptions)
564
+ : withDatabase((database) => importWorkspace(database, importOptions));
191
565
  }
192
566
  if (operation === 'backup') {
193
- const output = String(args.output ?? '');
194
- if (output.length === 0)
567
+ assertExactCallArguments(args, operation, ['output']);
568
+ if (!Object.hasOwn(args, 'output')) {
195
569
  throw new KiokukoError('VALIDATION_ERROR', 'backup output is required');
570
+ }
571
+ const output = requiredPathArgument(args, operation, 'output');
196
572
  return createBackup(output);
197
573
  }
198
- if (operation === 'doctor')
574
+ if (operation === 'doctor') {
575
+ assertExactCallArguments(args, operation, []);
199
576
  return runDoctor();
200
- throw new KiokukoError('VALIDATION_ERROR', `Unknown operation: ${operation}`);
577
+ }
578
+ throw new KiokukoError('INTEGRITY_ERROR', 'Supported call operation has no dispatcher');
201
579
  }
202
580
  export function buildCli(dependencies = {}) {
203
581
  const cli = new Command();
204
- cli.name('kiokuko').description('Model-agnostic external memory for AI coding agents').version(packageVersion);
582
+ cli.name('kiokuko').description('Model-agnostic external memory for AI coding agents').version(PACKAGE_VERSION);
205
583
  cli.exitOverride();
206
584
  cli.configureOutput({ outputError: () => undefined });
207
585
  cli.command('version').description('Show the Kiokuko package version').action(() => {
208
- process.stdout.write(`${packageVersion}\n`);
586
+ process.stdout.write(`${PACKAGE_VERSION}\n`);
209
587
  });
210
588
  cli.command('init').description('Initialize the global Kiokuko database').option('--json').action(async (options) => {
211
589
  const result = await initializeDatabase();
@@ -217,35 +595,49 @@ export function buildCli(dependencies = {}) {
217
595
  .option('--command <path>', 'Kiokuko executable name or absolute path', 'kiokuko')
218
596
  .option('--dry-run', 'Validate and show planned changes without writing')
219
597
  .option('--no-standard-skills', 'Skip installing bundled Kiokuko standard skills')
220
- .option('--opencode-capture <profile>', 'OpenCode evidence capture: off,minimal,standard', 'off')
221
- .option('--opencode-mode <mode>', 'OpenCode prepare enforcement: advisory,strict', 'advisory')
598
+ .option('--skill-discovery <mode>', 'External Skill discovery: off,official,community')
222
599
  .option('--json', 'Emit a JSON response')
223
600
  .action(async (options) => {
224
- if (!['off', 'minimal', 'standard'].includes(options.opencodeCapture))
225
- throw new KiokukoError('VALIDATION_ERROR', 'opencode capture must be off, minimal, or standard');
226
- if (!['advisory', 'strict'].includes(options.opencodeMode))
227
- throw new KiokukoError('VALIDATION_ERROR', 'opencode mode must be advisory or strict');
601
+ const optionSkillDiscoveryMode = options.skillDiscovery === undefined
602
+ ? undefined
603
+ : parseSetupSkillDiscoveryMode(options.skillDiscovery);
228
604
  const setupEnvironment = dependencies.setupEnvironment ?? {};
605
+ const setupProcessEnvironment = setupEnvironment.env ?? process.env;
606
+ const environmentSkillDiscoveryMode = optionSkillDiscoveryMode === undefined
607
+ && Object.prototype.hasOwnProperty.call(setupProcessEnvironment, SKILL_DISCOVERY_ENV)
608
+ ? normalizeSkillDiscoveryMode(setupProcessEnvironment[SKILL_DISCOVERY_ENV])
609
+ : undefined;
610
+ const requestedSkillDiscoveryMode = optionSkillDiscoveryMode ?? environmentSkillDiscoveryMode;
229
611
  const detectedClients = options.clients === undefined ? await detectInstalledClients(setupEnvironment) : [];
230
612
  const setupInput = dependencies.setupInput ?? process.stdin;
231
613
  const setupOutput = dependencies.setupOutput ?? process.stdout;
232
- const interactive = options.clients === undefined
233
- && options.json !== true
614
+ const interactive = options.json !== true
234
615
  && setupInput.isTTY === true
235
616
  && setupOutput.isTTY === true;
236
- const clients = options.clients !== undefined
237
- ? parseSetupClients(options.clients)
238
- : interactive
239
- ? await promptSetupClients(detectedClients, { input: setupInput, output: setupOutput })
240
- : detectedClients;
617
+ let clients;
618
+ let skillDiscoveryMode = requestedSkillDiscoveryMode;
619
+ if (interactive && options.clients === undefined && requestedSkillDiscoveryMode === undefined) {
620
+ const prompted = await promptSetupConfiguration(detectedClients, { input: setupInput, output: setupOutput });
621
+ clients = prompted.clients;
622
+ skillDiscoveryMode = prompted.skillDiscoveryMode;
623
+ }
624
+ else {
625
+ clients = options.clients !== undefined
626
+ ? parseSetupClients(options.clients)
627
+ : interactive
628
+ ? await promptSetupClients(detectedClients, { input: setupInput, output: setupOutput })
629
+ : detectedClients;
630
+ if (interactive && clients.length > 0 && skillDiscoveryMode === undefined) {
631
+ skillDiscoveryMode = await promptCommunitySkillDiscovery({ input: setupInput, output: setupOutput });
632
+ }
633
+ }
241
634
  const data = await setupGlobalClients({
242
635
  ...setupEnvironment,
243
636
  clients,
244
637
  command: options.command,
245
638
  dryRun: options.dryRun === true,
246
639
  standardSkills: options.standardSkills,
247
- opencodeCapture: options.opencodeCapture,
248
- opencodeMode: options.opencodeMode,
640
+ ...(skillDiscoveryMode === undefined ? {} : { skillDiscoveryMode }),
249
641
  });
250
642
  const changed = data.files.filter((file) => file.action !== 'unchanged').length;
251
643
  const clientLabel = data.clients.length === 0 ? 'no detected clients' : data.clients.join(', ');
@@ -260,7 +652,7 @@ export function buildCli(dependencies = {}) {
260
652
  await runMcpServer();
261
653
  });
262
654
  cli.command('use').description('Bind this repository to Kiokuko external memory')
263
- .option('--root <path>').option('--workspace <name>').option('--agent-file <path>', 'Agent instruction file', 'AGENTS.md')
655
+ .option('--root <path>').option('--workspace <name>').option('--agent-file <path>', 'Agent instruction file')
264
656
  .option('--dry-run').option('--no-agent-file').option('--force-rebind').option('--allow-directory').option('--json')
265
657
  .action(async (options) => {
266
658
  const useOptions = {};
@@ -282,7 +674,7 @@ export function buildCli(dependencies = {}) {
282
674
  humanOrJson(options.json === true, 'use', result, `Kiokuko enabled for ${result.repositoryRoot}`);
283
675
  });
284
676
  configureRecallCommand(cli.command('recall'));
285
- const memory = cli.command('memory').description('Memory operations');
677
+ const memory = cli.command('memory').description('Human/operator memory management');
286
678
  configureRecallCommand(memory.command('recall'));
287
679
  const guide = cli.command('guide').description('Run the Akinator-style knowledge and skill intake');
288
680
  guide.command('start').description('Start an intake session').argument('<task>').requiredOption('--workspace <name>').option('--json').action(async (task, options) => {
@@ -298,17 +690,7 @@ export function buildCli(dependencies = {}) {
298
690
  }));
299
691
  humanOrJson(options.json, 'guide.answer', data, data.question?.prompt ?? 'Akinator context is ready');
300
692
  });
301
- guide.command('context').description('Build the knowledge and skill context for an intake session').argument('<session-id>').requiredOption('--workspace <name>')
302
- .option('--no-client-skills', 'Allow the mattpocock/skills fallback because the client has no available skills')
303
- .option('--json').action(async (sessionId, options) => {
304
- const data = await withDatabase((database) => getAkinatorContext(database, {
305
- workspace: options.workspace,
306
- sessionId,
307
- ...(options.clientSkills === false ? { allowExternalSkillFallback: true } : {}),
308
- }));
309
- humanOrJson(options.json, 'guide.context', data, `${data.entries.length} knowledge entries selected`);
310
- });
311
- const search = addWorkspaceOptions(cli.command('search').description('Search memory entries').argument('<query>'))
693
+ const search = addWorkspaceOptions(cli.command('search').description('Human/operator management: search memory entries').argument('<query>'))
312
694
  .option('--limit <number>', 'Maximum entries', '20').option('--kind <kind>').option('--status <status>').option('--tag <tag>');
313
695
  search.action(async (query, options) => {
314
696
  const searchOptions = { workspace: String(options.workspace ?? ''), query, limit: Number(options.limit) };
@@ -321,17 +703,16 @@ export function buildCli(dependencies = {}) {
321
703
  const data = await withDatabase((database) => searchEntries(database, searchOptions));
322
704
  humanOrJson(options.json === true, 'search', data, `${data.items.length} memory entries found`, { count: data.count });
323
705
  });
324
- const read = addWorkspaceOptions(cli.command('read').description('Read one memory entry').argument('<entry-id>'));
706
+ const read = addWorkspaceOptions(cli.command('read').description('Human/operator management: read one memory entry').argument('<entry-id>'));
325
707
  read.action(async (entryId, options) => {
326
708
  const data = await withDatabase((database) => readEntry(database, { workspace: String(options.workspace ?? ''), entryId }));
327
709
  humanOrJson(options.json === true, 'read', data, `${data.title}\n${data.body}`);
328
710
  });
329
711
  const record = cli.command('record').description('Record a memory entry').requiredOption('--workspace <name>').requiredOption('--input-json <file>').option('--json');
330
712
  record.action(async (options) => {
331
- const input = await readJsonInput(options.inputJson);
332
- if (typeof input !== 'object' || input === null || Array.isArray(input))
333
- throw new KiokukoError('VALIDATION_ERROR', 'record input must be a JSON object');
334
- const data = await withDatabase((database) => recordEntry(database, { ...input, workspace: options.workspace }));
713
+ const parsed = snapshotPlainJsonObject(await readJsonInput(options.inputJson), 'record input must be a JSON object');
714
+ const input = validateRecordInput({ ...parsed, workspace: options.workspace });
715
+ const data = await withDatabase((database) => recordEntry(database, input));
335
716
  humanOrJson(options.json, 'record', data, `Recorded ${data.id}`);
336
717
  });
337
718
  const promote = cli.command('promote').description('Promote a candidate entry').argument('<entry-id>').requiredOption('--workspace <name>').requiredOption('--expected-revision <number>').option('--json');
@@ -387,6 +768,7 @@ export function buildCli(dependencies = {}) {
387
768
  registerServerCommands(cli, dependencies.server);
388
769
  registerAgentCommand(cli, dependencies.agent);
389
770
  registerLedgerCommands(cli, { withDatabase });
771
+ registerSkillsCommands(cli, dependencies.skills ?? { withDatabase });
390
772
  cli.command('web').description('Start the local Kiokuko web UI')
391
773
  .option('--host <host>', 'Loopback host', '127.0.0.1')
392
774
  .option('--port <number>', 'HTTP port', '4173')
@@ -421,20 +803,17 @@ export function buildCli(dependencies = {}) {
421
803
  : await withDatabase((database) => importWorkspace(database, importOptions));
422
804
  humanOrJson(options.json, 'import', data, `${data.count} records inspected`);
423
805
  });
424
- cli.command('call').description('Process one JSON request').requiredOption('--input-json <file>').option('--json').action(async (options) => {
425
- const request = await readJsonInput(options.inputJson);
426
- const operation = typeof request === 'object' && request !== null && !Array.isArray(request) && typeof request.operation === 'string' ? request.operation : 'unknown';
806
+ cli.command('call').description('Process one management JSON request; memory reads are not supported').requiredOption('--input-json <file>').option('--json').action(async (options) => {
807
+ const request = parseCallRequest(await readJsonInput(options.inputJson));
427
808
  const data = await dispatchRequest(request);
428
- emit(successEnvelope(operation, data));
809
+ emit(successEnvelope(request.operation, data));
429
810
  });
430
811
  return cli;
431
812
  }
432
813
  function operationFor(argv) {
433
814
  const command = argv[2] ?? 'unknown';
434
- if (command === 'server' && argv[3] !== undefined && !argv[3].startsWith('-'))
435
- return `server.${argv[3]}`;
436
- if (command === 'agent' && argv[3] !== undefined && !argv[3].startsWith('-'))
437
- return `agent.${argv[3]}`;
815
+ if (['server', 'agent', 'skills'].includes(command) && argv[3] !== undefined && !argv[3].startsWith('-'))
816
+ return `${command}.${argv[3]}`;
438
817
  return command;
439
818
  }
440
819
  function commanderDiagnostic(error) {
@@ -460,15 +839,22 @@ export async function runCli(argv = process.argv, dependencies = {}) {
460
839
  }
461
840
  catch (error) {
462
841
  if (error instanceof CommanderError) {
842
+ if (error.exitCode === 0)
843
+ return 0;
844
+ if (jsonRequested) {
845
+ emit(errorEnvelope(operation, new KiokukoError('USAGE_ERROR', 'Invalid command-line usage', { commanderCode: error.code })));
846
+ return 2;
847
+ }
463
848
  const diagnostic = commanderDiagnostic(error);
464
849
  if (diagnostic.length > 0)
465
850
  process.stderr.write(diagnostic);
466
- return error.exitCode === 0 ? 0 : 2;
851
+ return 2;
467
852
  }
853
+ const envelope = errorEnvelope(operation, error);
468
854
  if (jsonRequested && !(serveStarted && operation === 'serve'))
469
- emit(errorEnvelope(operation, error));
855
+ emit(envelope);
470
856
  else
471
- process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
857
+ process.stderr.write(`${envelope.error.message}\n`);
472
858
  return exitCodeFor(error);
473
859
  }
474
860
  }