@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
@@ -1,16 +1,272 @@
1
1
  import { KiokukoError } from '../errors.js';
2
- import { canonicalContentHash, canonicalJson, requireWorkspace, validateRecordInput, } from '../serialization/validate.js';
3
- function parseObject(value, field) {
2
+ import { canonicalContentHash, canonicalEntryRevisionContentHash, canonicalJson, ENTRY_STATUSES, requireWorkspace, TRUST_LEVELS, validateRecordInput, } from '../serialization/validate.js';
3
+ import { buildStructuredScope, } from './structured-memory.js';
4
+ const SQLITE_CONSTRAINT_PRIMARY_KEY = 1_555;
5
+ const SQLITE_CONSTRAINT_UNIQUE = 2_067;
6
+ const REVISION_UNIQUENESS_FAILURES = new Set([
7
+ 'UNIQUE constraint failed: entry_revisions.entry_id, entry_revisions.revision',
8
+ 'UNIQUE constraint failed: entry_revisions.workspace, entry_revisions.content_hash',
9
+ ]);
10
+ function isExpectedRevisionConflict(error) {
11
+ if (!(error instanceof Error))
12
+ return false;
13
+ const failure = error;
14
+ return failure.code === 'ERR_SQLITE_ERROR'
15
+ && (failure.errcode === SQLITE_CONSTRAINT_PRIMARY_KEY || failure.errcode === SQLITE_CONSTRAINT_UNIQUE)
16
+ && REVISION_UNIQUENESS_FAILURES.has(failure.message);
17
+ }
18
+ function storedIntegrity() {
19
+ throw new KiokukoError('INTEGRITY_ERROR', 'Stored entry or revision is invalid');
20
+ }
21
+ function isPlainObject(value) {
22
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
23
+ return false;
24
+ const prototype = Object.getPrototypeOf(value);
25
+ return prototype === Object.prototype || prototype === null;
26
+ }
27
+ function hasOwn(value, field) {
28
+ return Object.prototype.hasOwnProperty.call(value, field);
29
+ }
30
+ function storedNonEmptyString(value) {
31
+ if (typeof value !== 'string' || value.trim().length === 0)
32
+ storedIntegrity();
33
+ return value;
34
+ }
35
+ function canonicalTimestamp(value) {
36
+ if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u.test(value))
37
+ return false;
38
+ const milliseconds = Date.parse(value);
39
+ return Number.isFinite(milliseconds) && new Date(milliseconds).toISOString() === value;
40
+ }
41
+ function parseStoredObject(value) {
42
+ if (typeof value !== 'string')
43
+ storedIntegrity();
44
+ let parsed;
45
+ try {
46
+ parsed = JSON.parse(value);
47
+ }
48
+ catch (error) {
49
+ if (error instanceof SyntaxError)
50
+ storedIntegrity();
51
+ throw error;
52
+ }
53
+ if (!isPlainObject(parsed))
54
+ storedIntegrity();
55
+ try {
56
+ if (canonicalJson(parsed) !== value)
57
+ storedIntegrity();
58
+ }
59
+ catch (error) {
60
+ if (error instanceof KiokukoError && error.code === 'VALIDATION_ERROR')
61
+ storedIntegrity();
62
+ throw error;
63
+ }
64
+ return parsed;
65
+ }
66
+ function exactLegacyFrameworkOrder(scope, normalized) {
67
+ if (!isPlainObject(scope.applicability) || !isPlainObject(normalized.applicability))
68
+ return false;
69
+ const storedFrameworks = scope.applicability.frameworks;
70
+ const normalizedFrameworks = normalized.applicability.frameworks;
71
+ if (!Array.isArray(storedFrameworks) || !Array.isArray(normalizedFrameworks)
72
+ || storedFrameworks.length !== normalizedFrameworks.length)
73
+ return false;
74
+ let storedMembers;
75
+ let normalizedMembers;
76
+ try {
77
+ storedMembers = storedFrameworks.map((framework) => canonicalJson(framework));
78
+ normalizedMembers = normalizedFrameworks.map((framework) => canonicalJson(framework));
79
+ }
80
+ catch (error) {
81
+ if (error instanceof KiokukoError && error.code === 'VALIDATION_ERROR')
82
+ return false;
83
+ throw error;
84
+ }
85
+ const sortedStoredMembers = [...storedMembers].sort();
86
+ const sortedNormalizedMembers = [...normalizedMembers].sort();
87
+ if (new Set(storedMembers).size !== storedMembers.length
88
+ || new Set(normalizedMembers).size !== normalizedMembers.length
89
+ || sortedStoredMembers.some((member, index) => member !== sortedNormalizedMembers[index]))
90
+ return false;
91
+ const reconstructed = {
92
+ ...normalized,
93
+ applicability: { ...normalized.applicability, frameworks: storedFrameworks },
94
+ };
95
+ return canonicalJson(reconstructed) === canonicalJson(scope);
96
+ }
97
+ /** Normalize caller-supplied structured scope before it is persisted. */
98
+ export function normalizeStructuredScopeInput(scope) {
99
+ if (!hasOwn(scope, 'schemaVersion')) {
100
+ return scope;
101
+ }
102
+ const allowed = new Set([
103
+ 'schemaVersion', 'visibility', 'retrievalScope', 'repositoryId', 'memoryClass',
104
+ 'applicability', 'signals', 'portableReason',
105
+ ]);
106
+ if (Object.keys(scope).some((field) => !allowed.has(field))) {
107
+ throw new KiokukoError('VALIDATION_ERROR', 'Structured memory scope contains an unknown field');
108
+ }
109
+ if (scope.schemaVersion !== 2 && scope.schemaVersion !== 3) {
110
+ throw new KiokukoError('VALIDATION_ERROR', 'Structured memory scope schemaVersion is unsupported');
111
+ }
112
+ const schemaVersion = scope.schemaVersion;
113
+ if (schemaVersion === 2 && hasOwn(scope, 'retrievalScope')) {
114
+ throw new KiokukoError('VALIDATION_ERROR', 'Structured memory scope schemaVersion 2 cannot contain retrievalScope');
115
+ }
116
+ let normalized = buildStructuredScope({
117
+ visibility: scope.visibility,
118
+ ...(schemaVersion === 3 && hasOwn(scope, 'retrievalScope') ? { retrievalScope: scope.retrievalScope } : {}),
119
+ ...(hasOwn(scope, 'repositoryId') ? { repositoryId: scope.repositoryId } : {}),
120
+ ...(hasOwn(scope, 'memoryClass') ? { memoryClass: scope.memoryClass } : {}),
121
+ ...(hasOwn(scope, 'applicability') ? { applicability: scope.applicability } : {}),
122
+ ...(hasOwn(scope, 'signals') ? { signals: scope.signals } : {}),
123
+ ...(hasOwn(scope, 'portableReason') ? { portableReason: scope.portableReason } : {}),
124
+ });
125
+ if (schemaVersion === 2)
126
+ normalized = { ...normalized, schemaVersion: 2 };
127
+ return normalized;
128
+ }
129
+ function normalizeStoredStructuredScope(scope, required) {
130
+ if (required && scope.schemaVersion !== 3)
131
+ storedIntegrity();
4
132
  try {
5
- const parsed = JSON.parse(value);
6
- if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
7
- throw new Error('not object');
8
- return parsed;
133
+ return normalizeStructuredScopeInput(scope);
9
134
  }
10
- catch {
11
- throw new KiokukoError('INTEGRITY_ERROR', `Stored ${field} is not valid JSON`);
135
+ catch (error) {
136
+ if (error instanceof KiokukoError && (error.code === 'VALIDATION_ERROR' || error.code === 'SECURITY_REJECTION'))
137
+ storedIntegrity();
138
+ throw error;
12
139
  }
13
140
  }
141
+ /** Decode only the canonical persisted structured-scope representation. */
142
+ export function decodeStoredStructuredScope(scope, required = false) {
143
+ const normalized = normalizeStoredStructuredScope(scope, required);
144
+ if (canonicalJson(normalized) !== canonicalJson(scope))
145
+ storedIntegrity();
146
+ return { scope: normalized, canonicalScope: normalized };
147
+ }
148
+ function decodeMigratableStoredStructuredScope(scope) {
149
+ const normalized = normalizeStoredStructuredScope(scope, false);
150
+ if (canonicalJson(normalized) !== canonicalJson(scope) && !exactLegacyFrameworkOrder(scope, normalized))
151
+ storedIntegrity();
152
+ return { scope: normalized, canonicalScope: normalized, persistedScope: scope };
153
+ }
154
+ function normalizedStoredRecord(input, tags, options) {
155
+ const entryId = storedNonEmptyString(input.entryId);
156
+ const createdBy = storedNonEmptyString(input.createdBy);
157
+ const createdAt = storedNonEmptyString(input.createdAt);
158
+ if (!canonicalTimestamp(createdAt)
159
+ || !Number.isSafeInteger(input.revision) || Number(input.revision) < 1
160
+ || input.summary !== null && typeof input.summary !== 'string'
161
+ || !Array.isArray(tags))
162
+ storedIntegrity();
163
+ const decodedScope = decodeStoredStructuredScope(parseStoredObject(input.scopeJson), options.requireStructuredScope === true);
164
+ const scope = decodedScope.canonicalScope;
165
+ const provenance = parseStoredObject(input.provenanceJson);
166
+ let validated;
167
+ try {
168
+ validated = validateRecordInput({
169
+ workspace: input.workspace,
170
+ kind: input.kind,
171
+ status: 'candidate',
172
+ title: input.title,
173
+ body: input.body,
174
+ summary: input.summary,
175
+ scope,
176
+ provenance,
177
+ trustLevel: 'user_asserted',
178
+ confidence: 1,
179
+ tags,
180
+ createdBy,
181
+ actor: createdBy,
182
+ });
183
+ }
184
+ catch (error) {
185
+ if (error instanceof KiokukoError && (error.code === 'VALIDATION_ERROR' || error.code === 'SECURITY_REJECTION'))
186
+ storedIntegrity();
187
+ throw error;
188
+ }
189
+ if (validated.tags.length !== tags.length)
190
+ storedIntegrity();
191
+ const hashInput = {
192
+ kind: validated.kind,
193
+ title: validated.title,
194
+ body: validated.body,
195
+ summary: validated.summary,
196
+ scope: validated.scope,
197
+ provenance: validated.provenance,
198
+ tags: validated.tags,
199
+ };
200
+ const contentHash = canonicalEntryRevisionContentHash(hashInput);
201
+ if (input.contentHash !== contentHash)
202
+ storedIntegrity();
203
+ return {
204
+ entryId,
205
+ workspace: validated.workspace,
206
+ revision: Number(input.revision),
207
+ kind: validated.kind,
208
+ title: validated.title,
209
+ body: validated.body,
210
+ summary: validated.summary,
211
+ scope: decodedScope.canonicalScope,
212
+ provenance: validated.provenance,
213
+ tags: validated.tags,
214
+ contentHash,
215
+ createdBy,
216
+ createdAt,
217
+ };
218
+ }
219
+ function decodedStoredEntry(input, revision) {
220
+ const id = storedNonEmptyString(input.id);
221
+ const workspace = storedNonEmptyString(input.workspace);
222
+ const createdBy = storedNonEmptyString(input.createdBy);
223
+ const createdAt = storedNonEmptyString(input.createdAt);
224
+ const updatedAt = storedNonEmptyString(input.updatedAt);
225
+ if (id !== revision.entryId || workspace !== revision.workspace
226
+ || !Number.isSafeInteger(input.currentRevision) || input.currentRevision !== revision.revision
227
+ || input.minRevision !== 1
228
+ || !Number.isSafeInteger(input.maxRevision) || input.currentRevision !== input.maxRevision
229
+ || !Number.isSafeInteger(input.revisionCount) || input.revisionCount !== input.maxRevision
230
+ || input.invalidRevisionCount !== 0
231
+ || typeof input.status !== 'string' || !ENTRY_STATUSES.includes(input.status)
232
+ || typeof input.trustLevel !== 'string' || !TRUST_LEVELS.includes(input.trustLevel)
233
+ || typeof input.confidence !== 'number' || !Number.isFinite(input.confidence) || input.confidence < 0 || input.confidence > 1
234
+ || input.supersededBy !== null && (typeof input.supersededBy !== 'string' || input.supersededBy.trim().length === 0)
235
+ || input.verifiedAt !== null && (typeof input.verifiedAt !== 'string' || input.verifiedAt.trim().length === 0))
236
+ storedIntegrity();
237
+ const status = input.status;
238
+ const supersededBy = input.supersededBy;
239
+ const verifiedAt = input.verifiedAt;
240
+ if ((status === 'superseded') !== (supersededBy !== null)
241
+ || status === 'candidate' && verifiedAt !== null
242
+ || status === 'verified' && verifiedAt === null
243
+ || !canonicalTimestamp(createdAt) || !canonicalTimestamp(updatedAt)
244
+ || verifiedAt !== null && !canonicalTimestamp(verifiedAt)
245
+ || createdAt > revision.createdAt || revision.createdAt > updatedAt
246
+ || createdAt > updatedAt
247
+ || verifiedAt !== null && (verifiedAt < createdAt || verifiedAt > updatedAt))
248
+ storedIntegrity();
249
+ return {
250
+ id,
251
+ workspace,
252
+ status,
253
+ trustLevel: input.trustLevel,
254
+ confidence: input.confidence,
255
+ currentRevision: input.currentRevision,
256
+ supersededBy,
257
+ createdBy,
258
+ createdAt,
259
+ updatedAt,
260
+ verifiedAt,
261
+ };
262
+ }
263
+ /** Decode persisted entry/revision data without trusting TypeScript row casts. */
264
+ export function decodeStoredMemoryRow(input) {
265
+ const revision = normalizedStoredRecord(input.revision, input.tags, input.options ?? {});
266
+ if (input.entry === undefined)
267
+ return { revision };
268
+ return { revision, entry: decodedStoredEntry(input.entry, revision) };
269
+ }
14
270
  function revisionKey(input) {
15
271
  if (typeof input.entryId !== 'string' || input.entryId.length === 0) {
16
272
  throw new KiokukoError('VALIDATION_ERROR', 'entryId must be a non-empty string');
@@ -20,37 +276,267 @@ function revisionKey(input) {
20
276
  throw new KiokukoError('VALIDATION_ERROR', 'revision must be a positive integer');
21
277
  }
22
278
  }
279
+ function completeRevisionChain(row) {
280
+ return Number.isSafeInteger(row.current_revision)
281
+ && row.min_revision === 1
282
+ && Number.isSafeInteger(row.max_revision)
283
+ && row.current_revision === row.max_revision
284
+ && Number.isSafeInteger(row.revision_count)
285
+ && row.revision_count === row.max_revision
286
+ && row.invalid_revision_count === 0;
287
+ }
288
+ function ownerRevisionChain(database, entryId) {
289
+ return database.prepare(`
290
+ SELECT e.workspace, e.current_revision,
291
+ MIN(r.revision) AS min_revision,
292
+ MAX(r.revision) AS max_revision,
293
+ COUNT(r.revision) AS revision_count,
294
+ COUNT(CASE
295
+ WHEN r.revision IS NOT NULL
296
+ AND (typeof(r.revision) <> 'integer' OR r.revision < 1)
297
+ THEN 1
298
+ END) AS invalid_revision_count
299
+ FROM entries AS e
300
+ LEFT JOIN entry_revisions AS r ON r.entry_id = e.id
301
+ WHERE e.id = ?
302
+ GROUP BY e.id
303
+ `).get(entryId);
304
+ }
305
+ const REVISION_HASH_ALGORITHM = 'canonical-json-utf16-tags-v1';
306
+ const REVISION_IMMUTABILITY_TRIGGER_SQL = `CREATE TRIGGER entry_revisions_immutable_update
307
+ BEFORE UPDATE ON entry_revisions
308
+ BEGIN
309
+ SELECT RAISE(ABORT, 'entry_revisions are immutable');
310
+ END`;
311
+ function migratableRevision(database, row) {
312
+ const entryId = storedNonEmptyString(row.entry_id);
313
+ const createdBy = storedNonEmptyString(row.created_by);
314
+ const createdAt = storedNonEmptyString(row.created_at);
315
+ if (!canonicalTimestamp(createdAt)
316
+ || !Number.isSafeInteger(row.revision) || Number(row.revision) < 1
317
+ || row.summary !== null && typeof row.summary !== 'string')
318
+ storedIntegrity();
319
+ const revision = Number(row.revision);
320
+ const owner = ownerRevisionChain(database, entryId);
321
+ if (owner === undefined || owner.workspace !== row.workspace || !completeRevisionChain(owner))
322
+ storedIntegrity();
323
+ const persistedScope = parseStoredObject(row.scope_json);
324
+ const decodedScope = decodeMigratableStoredStructuredScope(persistedScope);
325
+ const provenance = parseStoredObject(row.provenance_json);
326
+ const persistedTags = database
327
+ .prepare('SELECT tag FROM entry_revision_tags WHERE entry_id = ? AND revision = ? ORDER BY rowid ASC')
328
+ .all(entryId, revision)
329
+ .map((tag) => tag.tag);
330
+ let validated;
331
+ try {
332
+ validated = validateRecordInput({
333
+ workspace: row.workspace,
334
+ kind: row.kind,
335
+ status: 'candidate',
336
+ title: row.title,
337
+ body: row.body,
338
+ summary: row.summary,
339
+ scope: decodedScope.canonicalScope,
340
+ provenance,
341
+ trustLevel: 'user_asserted',
342
+ confidence: 1,
343
+ tags: persistedTags,
344
+ createdBy,
345
+ actor: createdBy,
346
+ });
347
+ }
348
+ catch (error) {
349
+ if (error instanceof KiokukoError && (error.code === 'VALIDATION_ERROR' || error.code === 'SECURITY_REJECTION'))
350
+ storedIntegrity();
351
+ throw error;
352
+ }
353
+ if (validated.tags.length !== persistedTags.length
354
+ || persistedTags.some((tag) => typeof tag !== 'string'))
355
+ storedIntegrity();
356
+ const hashInput = {
357
+ kind: validated.kind,
358
+ title: validated.title,
359
+ body: validated.body,
360
+ summary: validated.summary,
361
+ scope: validated.scope,
362
+ provenance: validated.provenance,
363
+ tags: validated.tags,
364
+ };
365
+ const canonicalHash = canonicalEntryRevisionContentHash(hashInput);
366
+ const previousHash = row.content_hash;
367
+ if (typeof previousHash !== 'string' || !/^[0-9a-f]{64}$/u.test(previousHash))
368
+ storedIntegrity();
369
+ if (previousHash !== canonicalHash) {
370
+ const legacyPayload = {
371
+ kind: hashInput.kind,
372
+ title: hashInput.title,
373
+ body: hashInput.body,
374
+ summary: hashInput.summary,
375
+ provenance: hashInput.provenance,
376
+ tags: persistedTags,
377
+ };
378
+ const canonicalScopeLegacyHash = canonicalContentHash({
379
+ ...legacyPayload,
380
+ scope: hashInput.scope,
381
+ });
382
+ const persistedScopeLegacyHash = canonicalContentHash({
383
+ ...legacyPayload,
384
+ scope: decodedScope.persistedScope,
385
+ });
386
+ if (previousHash !== canonicalScopeLegacyHash && previousHash !== persistedScopeLegacyHash)
387
+ storedIntegrity();
388
+ }
389
+ return {
390
+ entryId,
391
+ workspace: validated.workspace,
392
+ revision,
393
+ previousScopeJson: row.scope_json,
394
+ previousHash,
395
+ canonicalScopeJson: canonicalJson(validated.scope),
396
+ canonicalHash,
397
+ };
398
+ }
399
+ /**
400
+ * One-time migration operation for migration 009. This is the only place that
401
+ * recognizes the released locale-dependent hash preimage. The caller must own
402
+ * the migration transaction; any invalid preimage or canonical collision
403
+ * aborts the whole schema upgrade.
404
+ */
405
+ export function canonicalizeEntryRevisionHashesInMigration(database) {
406
+ const formatTable = database.prepare(`
407
+ SELECT type
408
+ FROM sqlite_schema
409
+ WHERE name = 'entry_revision_hash_format'
410
+ `).get();
411
+ const existingFormat = formatTable?.type === 'table'
412
+ ? database.prepare('SELECT singleton, algorithm FROM entry_revision_hash_format').all()
413
+ : [];
414
+ if (formatTable?.type !== 'table' || existingFormat.length !== 0)
415
+ storedIntegrity();
416
+ const trigger = database.prepare(`
417
+ SELECT sql
418
+ FROM sqlite_schema
419
+ WHERE type = 'trigger' AND name = 'entry_revisions_immutable_update'
420
+ `).get();
421
+ if (trigger?.sql !== REVISION_IMMUTABILITY_TRIGGER_SQL)
422
+ storedIntegrity();
423
+ const rows = database.prepare(`
424
+ SELECT entry_id, workspace, revision, kind, title, body, summary,
425
+ scope_json, provenance_json, content_hash, created_by, created_at
426
+ FROM entry_revisions
427
+ ORDER BY entry_id, revision
428
+ `).all();
429
+ const entries = database.prepare('SELECT id, workspace FROM entries ORDER BY id')
430
+ .all();
431
+ for (const entry of entries) {
432
+ const entryId = storedNonEmptyString(entry.id);
433
+ const workspace = storedNonEmptyString(entry.workspace);
434
+ const owner = ownerRevisionChain(database, entryId);
435
+ if (owner === undefined || owner.workspace !== workspace || !completeRevisionChain(owner))
436
+ storedIntegrity();
437
+ }
438
+ const updates = rows.map((row) => migratableRevision(database, row));
439
+ const canonicalIdentities = new Set();
440
+ for (const update of updates) {
441
+ const identity = `${update.workspace}\u0000${update.canonicalHash}`;
442
+ if (canonicalIdentities.has(identity)) {
443
+ throw new KiokukoError('INTEGRITY_ERROR', 'Stored revisions collide under the canonical revision hash');
444
+ }
445
+ canonicalIdentities.add(identity);
446
+ }
447
+ const changed = updates.filter((update) => update.previousHash !== update.canonicalHash
448
+ || update.previousScopeJson !== update.canonicalScopeJson);
449
+ if (changed.length > 0) {
450
+ database.exec('DROP TRIGGER entry_revisions_immutable_update');
451
+ const park = database.prepare(`
452
+ UPDATE entry_revisions
453
+ SET content_hash = ?
454
+ WHERE entry_id = ? AND revision = ? AND scope_json = ? AND content_hash = ?
455
+ `);
456
+ const install = database.prepare(`
457
+ UPDATE entry_revisions
458
+ SET scope_json = ?, content_hash = ?
459
+ WHERE entry_id = ? AND revision = ? AND content_hash = ?
460
+ `);
461
+ for (const [index, update] of changed.entries()) {
462
+ const temporaryHash = `migration-009:${index}`;
463
+ park.run(temporaryHash, update.entryId, update.revision, update.previousScopeJson, update.previousHash);
464
+ if (database.prepare('SELECT changes() AS changes').get()?.changes !== 1)
465
+ storedIntegrity();
466
+ }
467
+ for (const [index, update] of changed.entries()) {
468
+ install.run(update.canonicalScopeJson, update.canonicalHash, update.entryId, update.revision, `migration-009:${index}`);
469
+ if (database.prepare('SELECT changes() AS changes').get()?.changes !== 1)
470
+ storedIntegrity();
471
+ }
472
+ database.exec(REVISION_IMMUTABILITY_TRIGGER_SQL);
473
+ }
474
+ database.prepare('INSERT INTO entry_revision_hash_format (singleton, algorithm) VALUES (1, ?)')
475
+ .run(REVISION_HASH_ALGORITHM);
476
+ return { inspected: updates.length, rewritten: changed.length };
477
+ }
23
478
  function tagsFor(database, entryId, revision) {
24
479
  return database
25
480
  .prepare('SELECT tag FROM entry_revision_tags WHERE entry_id = ? AND revision = ? ORDER BY tag ASC')
26
481
  .all(entryId, revision)
27
482
  .map((row) => row.tag);
28
483
  }
29
- function rowToRevision(database, row) {
30
- return {
31
- entryId: row.entry_id,
32
- workspace: row.workspace,
33
- revision: Number(row.revision),
34
- kind: row.kind,
35
- title: row.title,
36
- body: row.body,
37
- summary: row.summary,
38
- scope: parseObject(row.scope_json, 'scope'),
39
- provenance: parseObject(row.provenance_json, 'provenance'),
40
- tags: tagsFor(database, row.entry_id, Number(row.revision)),
41
- contentHash: row.content_hash,
42
- createdBy: row.created_by,
43
- createdAt: row.created_at,
44
- };
484
+ function rowToRevision(database, row, checkOwnerChronology = true) {
485
+ const entryId = storedNonEmptyString(row.entry_id);
486
+ if (!Number.isSafeInteger(row.revision))
487
+ storedIntegrity();
488
+ const tags = tagsFor(database, entryId, Number(row.revision));
489
+ const decoded = decodeStoredMemoryRow({
490
+ revision: {
491
+ entryId,
492
+ workspace: row.workspace,
493
+ revision: row.revision,
494
+ kind: row.kind,
495
+ title: row.title,
496
+ body: row.body,
497
+ summary: row.summary,
498
+ scopeJson: row.scope_json,
499
+ provenanceJson: row.provenance_json,
500
+ contentHash: row.content_hash,
501
+ createdBy: row.created_by,
502
+ createdAt: row.created_at,
503
+ },
504
+ tags,
505
+ }).revision;
506
+ if (checkOwnerChronology) {
507
+ const owner = database.prepare(`
508
+ SELECT e.created_at, e.updated_at, e.current_revision,
509
+ (SELECT MIN(all_revisions.revision)
510
+ FROM entry_revisions AS all_revisions
511
+ WHERE all_revisions.entry_id = e.id) AS min_revision,
512
+ (SELECT MAX(all_revisions.revision)
513
+ FROM entry_revisions AS all_revisions
514
+ WHERE all_revisions.entry_id = e.id) AS max_revision,
515
+ (SELECT COUNT(all_revisions.revision)
516
+ FROM entry_revisions AS all_revisions
517
+ WHERE all_revisions.entry_id = e.id) AS revision_count,
518
+ (SELECT COUNT(*)
519
+ FROM entry_revisions AS all_revisions
520
+ WHERE all_revisions.entry_id = e.id
521
+ AND (typeof(all_revisions.revision) <> 'integer' OR all_revisions.revision < 1)) AS invalid_revision_count
522
+ FROM entries AS e
523
+ WHERE e.id = ? AND e.workspace = ?
524
+ `).get(decoded.entryId, decoded.workspace);
525
+ if (owner === undefined || !canonicalTimestamp(owner.created_at) || !canonicalTimestamp(owner.updated_at)
526
+ || !completeRevisionChain({ workspace: decoded.workspace, ...owner })
527
+ || owner.created_at > decoded.createdAt || decoded.createdAt > owner.updated_at)
528
+ storedIntegrity();
529
+ }
530
+ return decoded;
45
531
  }
46
- function selectRevision(database, input) {
532
+ function selectRevision(database, input, checkOwnerChronology = true) {
47
533
  const row = database.prepare(`
48
534
  SELECT entry_id, workspace, revision, kind, title, body, summary,
49
535
  scope_json, provenance_json, content_hash, created_by, created_at
50
536
  FROM entry_revisions
51
537
  WHERE entry_id = ? AND workspace = ? AND revision = ?
52
538
  `).get(input.entryId, input.workspace, input.revision);
53
- return row === undefined ? undefined : rowToRevision(database, row);
539
+ return row === undefined ? undefined : rowToRevision(database, row, checkOwnerChronology);
54
540
  }
55
541
  export function readEntryRevision(database, input) {
56
542
  revisionKey(input);
@@ -68,11 +554,28 @@ export function insertEntryRevisionInTransaction(database, input) {
68
554
  if (typeof input.createdBy !== 'string' || input.createdBy.length === 0 || typeof input.createdAt !== 'string' || input.createdAt.length === 0) {
69
555
  throw new KiokukoError('VALIDATION_ERROR', 'Revision creator and timestamp are required');
70
556
  }
71
- const owner = database.prepare('SELECT workspace FROM entries WHERE id = ?').get(input.entryId);
557
+ const owner = ownerRevisionChain(database, input.entryId);
72
558
  if (owner === undefined)
73
559
  throw new KiokukoError('NOT_FOUND', 'Entry not found');
74
560
  if (owner.workspace !== input.workspace)
75
561
  throw new KiokukoError('NOT_FOUND', 'Entry does not belong to workspace');
562
+ let nextRevision;
563
+ if (owner.revision_count === 0) {
564
+ if (owner.min_revision !== null || owner.max_revision !== null || owner.current_revision !== 1)
565
+ storedIntegrity();
566
+ nextRevision = 1;
567
+ }
568
+ else {
569
+ if (!completeRevisionChain(owner))
570
+ storedIntegrity();
571
+ nextRevision = Number(owner.max_revision) + 1;
572
+ }
573
+ if (input.revision !== nextRevision) {
574
+ throw new KiokukoError('CONFLICT', 'Entry revision must be the exact next revision', {
575
+ expectedRevision: nextRevision,
576
+ actualRevision: input.revision,
577
+ });
578
+ }
76
579
  const validated = validateRecordInput({
77
580
  workspace: input.workspace,
78
581
  kind: input.kind,
@@ -85,12 +588,13 @@ export function insertEntryRevisionInTransaction(database, input) {
85
588
  createdBy: input.createdBy,
86
589
  actor: input.createdBy,
87
590
  });
88
- const contentHash = canonicalContentHash({
591
+ const canonicalScope = normalizeStructuredScopeInput(validated.scope);
592
+ const contentHash = canonicalEntryRevisionContentHash({
89
593
  kind: validated.kind,
90
594
  title: validated.title,
91
595
  body: validated.body,
92
596
  summary: validated.summary,
93
- scope: validated.scope,
597
+ scope: canonicalScope,
94
598
  provenance: validated.provenance,
95
599
  tags: validated.tags,
96
600
  });
@@ -103,18 +607,18 @@ export function insertEntryRevisionInTransaction(database, input) {
103
607
  entry_id, workspace, revision, kind, title, body, summary, scope_json,
104
608
  provenance_json, content_hash, created_by, created_at
105
609
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
106
- `).run(input.entryId, input.workspace, input.revision, validated.kind, validated.title, validated.body, validated.summary, canonicalJson(validated.scope), canonicalJson(validated.provenance), contentHash, input.createdBy, input.createdAt);
107
- for (const tag of validated.tags) {
108
- database.prepare('INSERT INTO entry_revision_tags (entry_id, revision, tag) VALUES (?, ?, ?)').run(input.entryId, input.revision, tag);
109
- }
610
+ `).run(input.entryId, input.workspace, input.revision, validated.kind, validated.title, validated.body, validated.summary, canonicalJson(canonicalScope), canonicalJson(validated.provenance), contentHash, input.createdBy, input.createdAt);
110
611
  }
111
612
  catch (error) {
112
- if (error instanceof Error && /UNIQUE|constraint/i.test(error.message)) {
613
+ if (isExpectedRevisionConflict(error)) {
113
614
  throw new KiokukoError('CONFLICT', 'Entry revision or content already exists');
114
615
  }
115
616
  throw error;
116
617
  }
117
- const result = selectRevision(database, input);
618
+ for (const tag of validated.tags) {
619
+ database.prepare('INSERT INTO entry_revision_tags (entry_id, revision, tag) VALUES (?, ?, ?)').run(input.entryId, input.revision, tag);
620
+ }
621
+ const result = selectRevision(database, input, false);
118
622
  if (result === undefined)
119
623
  throw new KiokukoError('INTEGRITY_ERROR', 'Inserted entry revision could not be read back');
120
624
  return result;