@kya-os/cli 1.8.1 → 1.8.3

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 (385) hide show
  1. package/dist/commands/agent.d.ts +35 -0
  2. package/dist/commands/agent.d.ts.map +1 -0
  3. package/dist/commands/agent.js +321 -0
  4. package/dist/commands/agent.js.map +1 -0
  5. package/dist/commands/build.js +2 -2
  6. package/dist/commands/build.js.map +1 -1
  7. package/dist/commands/check.js +3 -3
  8. package/dist/commands/check.js.map +1 -1
  9. package/dist/commands/checkpoint-init.d.ts +1 -1
  10. package/dist/commands/checkpoint-init.d.ts.map +1 -1
  11. package/dist/commands/checkpoint-init.js +8 -41
  12. package/dist/commands/checkpoint-init.js.map +1 -1
  13. package/dist/commands/claim.js +2 -2
  14. package/dist/commands/claim.js.map +1 -1
  15. package/dist/commands/dco.d.ts +59 -0
  16. package/dist/commands/dco.d.ts.map +1 -1
  17. package/dist/commands/dco.js +280 -5
  18. package/dist/commands/dco.js.map +1 -1
  19. package/dist/commands/dev.js +1 -1
  20. package/dist/commands/dev.js.map +1 -1
  21. package/dist/commands/doctor.d.ts.map +1 -1
  22. package/dist/commands/doctor.js +18 -24
  23. package/dist/commands/doctor.js.map +1 -1
  24. package/dist/commands/env.js +6 -6
  25. package/dist/commands/env.js.map +1 -1
  26. package/dist/commands/identity.js +3 -3
  27. package/dist/commands/identity.js.map +1 -1
  28. package/dist/commands/init-stages.d.ts +141 -0
  29. package/dist/commands/init-stages.d.ts.map +1 -0
  30. package/dist/commands/init-stages.js +684 -0
  31. package/dist/commands/init-stages.js.map +1 -0
  32. package/dist/commands/init.d.ts +46 -16
  33. package/dist/commands/init.d.ts.map +1 -1
  34. package/dist/commands/init.js +229 -279
  35. package/dist/commands/init.js.map +1 -1
  36. package/dist/commands/orchestrator.d.ts +18 -0
  37. package/dist/commands/orchestrator.d.ts.map +1 -0
  38. package/dist/commands/orchestrator.js +251 -0
  39. package/dist/commands/orchestrator.js.map +1 -0
  40. package/dist/commands/register.d.ts +1 -1
  41. package/dist/commands/register.d.ts.map +1 -1
  42. package/dist/commands/register.js +35 -7
  43. package/dist/commands/register.js.map +1 -1
  44. package/dist/commands/review.d.ts +48 -0
  45. package/dist/commands/review.d.ts.map +1 -0
  46. package/dist/commands/review.js +220 -0
  47. package/dist/commands/review.js.map +1 -0
  48. package/dist/commands/rotate.js +4 -4
  49. package/dist/commands/rotate.js.map +1 -1
  50. package/dist/commands/score.d.ts +15 -0
  51. package/dist/commands/score.d.ts.map +1 -0
  52. package/dist/commands/score.js +471 -0
  53. package/dist/commands/score.js.map +1 -0
  54. package/dist/commands/start.js +3 -3
  55. package/dist/commands/start.js.map +1 -1
  56. package/dist/commands/status.js +1 -1
  57. package/dist/commands/status.js.map +1 -1
  58. package/dist/commands/verify.js +6 -6
  59. package/dist/commands/verify.js.map +1 -1
  60. package/dist/dco.d.ts +4 -0
  61. package/dist/dco.d.ts.map +1 -0
  62. package/dist/dco.js +23 -0
  63. package/dist/dco.js.map +1 -0
  64. package/dist/index.js +52 -9
  65. package/dist/orchestrator/daemon.d.ts +137 -0
  66. package/dist/orchestrator/daemon.d.ts.map +1 -0
  67. package/dist/orchestrator/daemon.js +242 -0
  68. package/dist/orchestrator/daemon.js.map +1 -0
  69. package/dist/orchestrator/db/dispatches.d.ts +108 -0
  70. package/dist/orchestrator/db/dispatches.d.ts.map +1 -0
  71. package/dist/orchestrator/db/dispatches.js +122 -0
  72. package/dist/orchestrator/db/dispatches.js.map +1 -0
  73. package/dist/orchestrator/db/index.d.ts +50 -0
  74. package/dist/orchestrator/db/index.d.ts.map +1 -0
  75. package/dist/orchestrator/db/index.js +116 -0
  76. package/dist/orchestrator/db/index.js.map +1 -0
  77. package/dist/orchestrator/db/journal.d.ts +93 -0
  78. package/dist/orchestrator/db/journal.d.ts.map +1 -0
  79. package/dist/orchestrator/db/journal.js +91 -0
  80. package/dist/orchestrator/db/journal.js.map +1 -0
  81. package/dist/orchestrator/db/liveness.d.ts +97 -0
  82. package/dist/orchestrator/db/liveness.d.ts.map +1 -0
  83. package/dist/orchestrator/db/liveness.js +105 -0
  84. package/dist/orchestrator/db/liveness.js.map +1 -0
  85. package/dist/orchestrator/db/mission.d.ts +78 -0
  86. package/dist/orchestrator/db/mission.d.ts.map +1 -0
  87. package/dist/orchestrator/db/mission.js +99 -0
  88. package/dist/orchestrator/db/mission.js.map +1 -0
  89. package/dist/orchestrator/db/schema.d.ts +14 -0
  90. package/dist/orchestrator/db/schema.d.ts.map +1 -0
  91. package/dist/orchestrator/db/schema.js +169 -0
  92. package/dist/orchestrator/db/schema.js.map +1 -0
  93. package/dist/orchestrator/db/tickets.d.ts +147 -0
  94. package/dist/orchestrator/db/tickets.d.ts.map +1 -0
  95. package/dist/orchestrator/db/tickets.js +238 -0
  96. package/dist/orchestrator/db/tickets.js.map +1 -0
  97. package/dist/orchestrator/db/verdicts.d.ts +187 -0
  98. package/dist/orchestrator/db/verdicts.d.ts.map +1 -0
  99. package/dist/orchestrator/db/verdicts.js +197 -0
  100. package/dist/orchestrator/db/verdicts.js.map +1 -0
  101. package/dist/orchestrator/events.d.ts +69 -0
  102. package/dist/orchestrator/events.d.ts.map +1 -0
  103. package/dist/orchestrator/events.js +20 -0
  104. package/dist/orchestrator/events.js.map +1 -0
  105. package/dist/orchestrator/github-credential-anchor-sender.d.ts +159 -0
  106. package/dist/orchestrator/github-credential-anchor-sender.d.ts.map +1 -0
  107. package/dist/orchestrator/github-credential-anchor-sender.js +313 -0
  108. package/dist/orchestrator/github-credential-anchor-sender.js.map +1 -0
  109. package/dist/orchestrator/hub-dispatch.d.ts +120 -0
  110. package/dist/orchestrator/hub-dispatch.d.ts.map +1 -0
  111. package/dist/orchestrator/hub-dispatch.js +257 -0
  112. package/dist/orchestrator/hub-dispatch.js.map +1 -0
  113. package/dist/orchestrator/hub-observer.d.ts +201 -0
  114. package/dist/orchestrator/hub-observer.d.ts.map +1 -0
  115. package/dist/orchestrator/hub-observer.js +474 -0
  116. package/dist/orchestrator/hub-observer.js.map +1 -0
  117. package/dist/orchestrator/journal-writer.d.ts +80 -0
  118. package/dist/orchestrator/journal-writer.d.ts.map +1 -0
  119. package/dist/orchestrator/journal-writer.js +113 -0
  120. package/dist/orchestrator/journal-writer.js.map +1 -0
  121. package/dist/orchestrator/mcp/server.d.ts +136 -0
  122. package/dist/orchestrator/mcp/server.d.ts.map +1 -0
  123. package/dist/orchestrator/mcp/server.js +582 -0
  124. package/dist/orchestrator/mcp/server.js.map +1 -0
  125. package/dist/orchestrator/mcp/stdio.d.ts +22 -0
  126. package/dist/orchestrator/mcp/stdio.d.ts.map +1 -0
  127. package/dist/orchestrator/mcp/stdio.js +51 -0
  128. package/dist/orchestrator/mcp/stdio.js.map +1 -0
  129. package/dist/orchestrator/review.d.ts +131 -0
  130. package/dist/orchestrator/review.d.ts.map +1 -0
  131. package/dist/orchestrator/review.js +322 -0
  132. package/dist/orchestrator/review.js.map +1 -0
  133. package/dist/tui/app.d.ts +33 -0
  134. package/dist/tui/app.d.ts.map +1 -0
  135. package/dist/tui/app.js +71 -0
  136. package/dist/tui/app.js.map +1 -0
  137. package/dist/tui/components.d.ts +110 -0
  138. package/dist/tui/components.d.ts.map +1 -0
  139. package/dist/tui/components.js +118 -0
  140. package/dist/tui/components.js.map +1 -0
  141. package/dist/tui/index.d.ts +30 -0
  142. package/dist/tui/index.d.ts.map +1 -0
  143. package/dist/tui/index.js +95 -0
  144. package/dist/tui/index.js.map +1 -0
  145. package/dist/tui/keymap.d.ts +33 -0
  146. package/dist/tui/keymap.d.ts.map +1 -0
  147. package/dist/tui/keymap.js +49 -0
  148. package/dist/tui/keymap.js.map +1 -0
  149. package/dist/tui/nav.d.ts +29 -0
  150. package/dist/tui/nav.d.ts.map +1 -0
  151. package/dist/tui/nav.js +39 -0
  152. package/dist/tui/nav.js.map +1 -0
  153. package/dist/tui/sanitize.d.ts +25 -0
  154. package/dist/tui/sanitize.d.ts.map +1 -0
  155. package/dist/tui/sanitize.js +36 -0
  156. package/dist/tui/sanitize.js.map +1 -0
  157. package/dist/tui/theme.d.ts +32 -0
  158. package/dist/tui/theme.d.ts.map +1 -0
  159. package/dist/tui/theme.js +63 -0
  160. package/dist/tui/theme.js.map +1 -0
  161. package/dist/tui/views/agents.d.ts +67 -0
  162. package/dist/tui/views/agents.d.ts.map +1 -0
  163. package/dist/tui/views/agents.js +231 -0
  164. package/dist/tui/views/agents.js.map +1 -0
  165. package/dist/tui/views/index.d.ts +93 -0
  166. package/dist/tui/views/index.d.ts.map +1 -0
  167. package/dist/tui/views/index.js +150 -0
  168. package/dist/tui/views/index.js.map +1 -0
  169. package/dist/tui/views/registry.d.ts +22 -0
  170. package/dist/tui/views/registry.d.ts.map +1 -0
  171. package/dist/tui/views/registry.js +110 -0
  172. package/dist/tui/views/registry.js.map +1 -0
  173. package/dist/utils/agent/backoff.d.ts +31 -0
  174. package/dist/utils/agent/backoff.d.ts.map +1 -0
  175. package/dist/utils/agent/backoff.js +51 -0
  176. package/dist/utils/agent/backoff.js.map +1 -0
  177. package/dist/utils/agent/markers.d.ts +87 -0
  178. package/dist/utils/agent/markers.d.ts.map +1 -0
  179. package/dist/utils/agent/markers.js +147 -0
  180. package/dist/utils/agent/markers.js.map +1 -0
  181. package/dist/utils/agent/review.d.ts +67 -0
  182. package/dist/utils/agent/review.d.ts.map +1 -0
  183. package/dist/utils/agent/review.js +305 -0
  184. package/dist/utils/agent/review.js.map +1 -0
  185. package/dist/utils/agent/spawn-agent.d.ts +117 -0
  186. package/dist/utils/agent/spawn-agent.d.ts.map +1 -0
  187. package/dist/utils/agent/spawn-agent.js +177 -0
  188. package/dist/utils/agent/spawn-agent.js.map +1 -0
  189. package/dist/utils/agent/task.d.ts +101 -0
  190. package/dist/utils/agent/task.d.ts.map +1 -0
  191. package/dist/utils/agent/task.js +357 -0
  192. package/dist/utils/agent/task.js.map +1 -0
  193. package/dist/utils/agent/verify.d.ts +47 -0
  194. package/dist/utils/agent/verify.d.ts.map +1 -0
  195. package/dist/utils/agent/verify.js +144 -0
  196. package/dist/utils/agent/verify.js.map +1 -0
  197. package/dist/utils/agent-detector.d.ts +48 -0
  198. package/dist/utils/agent-detector.d.ts.map +1 -0
  199. package/dist/utils/agent-detector.js +74 -0
  200. package/dist/utils/agent-detector.js.map +1 -0
  201. package/dist/utils/agent-profile-stage.d.ts +70 -0
  202. package/dist/utils/agent-profile-stage.d.ts.map +1 -0
  203. package/dist/utils/agent-profile-stage.js +153 -0
  204. package/dist/utils/agent-profile-stage.js.map +1 -0
  205. package/dist/utils/agent-profiles.d.ts +27 -0
  206. package/dist/utils/agent-profiles.d.ts.map +1 -0
  207. package/dist/utils/agent-profiles.js +61 -0
  208. package/dist/utils/agent-profiles.js.map +1 -0
  209. package/dist/utils/checkpoint-api.d.ts +1 -1
  210. package/dist/utils/checkpoint-api.js +1 -1
  211. package/dist/utils/checkpoint-env.d.ts +1 -1
  212. package/dist/utils/checkpoint-env.js +2 -2
  213. package/dist/utils/checkpoint-env.js.map +1 -1
  214. package/dist/utils/checkpoint-scaffold.d.ts +1 -1
  215. package/dist/utils/checkpoint-scaffold.js +1 -1
  216. package/dist/utils/cli-kit/browser.d.ts +24 -0
  217. package/dist/utils/cli-kit/browser.d.ts.map +1 -0
  218. package/dist/utils/cli-kit/browser.js +58 -0
  219. package/dist/utils/cli-kit/browser.js.map +1 -0
  220. package/dist/utils/cli-kit/claim-polling.d.ts +18 -0
  221. package/dist/utils/cli-kit/claim-polling.d.ts.map +1 -0
  222. package/dist/utils/{claim-polling.js → cli-kit/claim-polling.js} +19 -26
  223. package/dist/utils/cli-kit/claim-polling.js.map +1 -0
  224. package/dist/utils/cli-kit/diagnostics.d.ts +9 -0
  225. package/dist/utils/cli-kit/diagnostics.d.ts.map +1 -0
  226. package/dist/utils/cli-kit/diagnostics.js +11 -0
  227. package/dist/utils/cli-kit/diagnostics.js.map +1 -0
  228. package/dist/utils/cli-kit/fs-safe.d.ts +14 -0
  229. package/dist/utils/cli-kit/fs-safe.d.ts.map +1 -0
  230. package/dist/utils/cli-kit/fs-safe.js +20 -0
  231. package/dist/utils/cli-kit/fs-safe.js.map +1 -0
  232. package/dist/utils/cli-kit/index.d.ts +15 -0
  233. package/dist/utils/cli-kit/index.d.ts.map +1 -0
  234. package/dist/utils/cli-kit/index.js +10 -0
  235. package/dist/utils/cli-kit/index.js.map +1 -0
  236. package/dist/utils/cli-kit/json-file.d.ts +21 -0
  237. package/dist/utils/cli-kit/json-file.d.ts.map +1 -0
  238. package/dist/utils/cli-kit/json-file.js +51 -0
  239. package/dist/utils/cli-kit/json-file.js.map +1 -0
  240. package/dist/utils/cli-kit/marker-block.d.ts +26 -0
  241. package/dist/utils/cli-kit/marker-block.d.ts.map +1 -0
  242. package/dist/utils/cli-kit/marker-block.js +61 -0
  243. package/dist/utils/cli-kit/marker-block.js.map +1 -0
  244. package/dist/utils/cli-kit/paths.d.ts +15 -0
  245. package/dist/utils/cli-kit/paths.d.ts.map +1 -0
  246. package/dist/utils/cli-kit/paths.js +21 -0
  247. package/dist/utils/cli-kit/paths.js.map +1 -0
  248. package/dist/utils/cli-kit/secure-storage.d.ts +14 -0
  249. package/dist/utils/cli-kit/secure-storage.d.ts.map +1 -0
  250. package/dist/utils/cli-kit/secure-storage.js +20 -0
  251. package/dist/utils/cli-kit/secure-storage.js.map +1 -0
  252. package/dist/utils/cli-kit/step-report.d.ts +16 -0
  253. package/dist/utils/cli-kit/step-report.d.ts.map +1 -0
  254. package/dist/utils/cli-kit/step-report.js +36 -0
  255. package/dist/utils/cli-kit/step-report.js.map +1 -0
  256. package/dist/utils/dco/agent-metadata.d.ts +1 -1
  257. package/dist/utils/dco/agent-metadata.js +1 -1
  258. package/dist/utils/dco/agent-metadata.js.map +1 -1
  259. package/dist/utils/dco/claude-config.d.ts +18 -14
  260. package/dist/utils/dco/claude-config.d.ts.map +1 -1
  261. package/dist/utils/dco/claude-config.js +31 -97
  262. package/dist/utils/dco/claude-config.js.map +1 -1
  263. package/dist/utils/dco/dispatch.d.ts +134 -0
  264. package/dist/utils/dco/dispatch.d.ts.map +1 -0
  265. package/dist/utils/dco/dispatch.js +399 -0
  266. package/dist/utils/dco/dispatch.js.map +1 -0
  267. package/dist/utils/dco/fix.d.ts +122 -0
  268. package/dist/utils/dco/fix.d.ts.map +1 -0
  269. package/dist/utils/dco/fix.js +560 -0
  270. package/dist/utils/dco/fix.js.map +1 -0
  271. package/dist/utils/dco/git-config.d.ts.map +1 -1
  272. package/dist/utils/dco/git-config.js +5 -3
  273. package/dist/utils/dco/git-config.js.map +1 -1
  274. package/dist/utils/dco/github.d.ts +101 -0
  275. package/dist/utils/dco/github.d.ts.map +1 -1
  276. package/dist/utils/dco/github.js +133 -0
  277. package/dist/utils/dco/github.js.map +1 -1
  278. package/dist/utils/dco/paths.d.ts +1 -8
  279. package/dist/utils/dco/paths.d.ts.map +1 -1
  280. package/dist/utils/dco/paths.js +3 -12
  281. package/dist/utils/dco/paths.js.map +1 -1
  282. package/dist/utils/dco/render.d.ts +1 -1
  283. package/dist/utils/dco/render.d.ts.map +1 -1
  284. package/dist/utils/dco/render.js +4 -21
  285. package/dist/utils/dco/render.js.map +1 -1
  286. package/dist/utils/dco/resolve-agent.d.ts +54 -0
  287. package/dist/utils/dco/resolve-agent.d.ts.map +1 -0
  288. package/dist/utils/dco/resolve-agent.js +164 -0
  289. package/dist/utils/dco/resolve-agent.js.map +1 -0
  290. package/dist/utils/dco/setup.d.ts +10 -7
  291. package/dist/utils/dco/setup.d.ts.map +1 -1
  292. package/dist/utils/dco/setup.js +264 -200
  293. package/dist/utils/dco/setup.js.map +1 -1
  294. package/dist/utils/dco/signing-key-writer.d.ts +40 -0
  295. package/dist/utils/dco/signing-key-writer.d.ts.map +1 -0
  296. package/dist/utils/dco/signing-key-writer.js +76 -0
  297. package/dist/utils/dco/signing-key-writer.js.map +1 -0
  298. package/dist/utils/dco/ssh-key.d.ts +50 -0
  299. package/dist/utils/dco/ssh-key.d.ts.map +1 -1
  300. package/dist/utils/dco/ssh-key.js +129 -8
  301. package/dist/utils/dco/ssh-key.js.map +1 -1
  302. package/dist/utils/dco/status.d.ts +1 -1
  303. package/dist/utils/dco/status.d.ts.map +1 -1
  304. package/dist/utils/dco/status.js +3 -3
  305. package/dist/utils/dco/status.js.map +1 -1
  306. package/dist/utils/dco/verify.d.ts +170 -0
  307. package/dist/utils/dco/verify.d.ts.map +1 -0
  308. package/dist/utils/dco/verify.js +550 -0
  309. package/dist/utils/dco/verify.js.map +1 -0
  310. package/dist/utils/dependency-installer.d.ts +37 -0
  311. package/dist/utils/dependency-installer.d.ts.map +1 -0
  312. package/dist/utils/dependency-installer.js +32 -0
  313. package/dist/utils/dependency-installer.js.map +1 -0
  314. package/dist/utils/github-credential-stage.d.ts +87 -0
  315. package/dist/utils/github-credential-stage.d.ts.map +1 -0
  316. package/dist/utils/github-credential-stage.js +168 -0
  317. package/dist/utils/github-credential-stage.js.map +1 -0
  318. package/dist/utils/github-credential.d.ts +160 -0
  319. package/dist/utils/github-credential.d.ts.map +1 -0
  320. package/dist/utils/github-credential.js +308 -0
  321. package/dist/utils/github-credential.js.map +1 -0
  322. package/dist/utils/gitignore.d.ts +17 -0
  323. package/dist/utils/gitignore.d.ts.map +1 -0
  324. package/dist/utils/gitignore.js +40 -0
  325. package/dist/utils/gitignore.js.map +1 -0
  326. package/dist/utils/hub-config.d.ts +21 -0
  327. package/dist/utils/hub-config.d.ts.map +1 -0
  328. package/dist/utils/hub-config.js +28 -0
  329. package/dist/utils/hub-config.js.map +1 -0
  330. package/dist/utils/identity-heal.d.ts +16 -0
  331. package/dist/utils/identity-heal.d.ts.map +1 -0
  332. package/dist/utils/identity-heal.js +37 -0
  333. package/dist/utils/identity-heal.js.map +1 -0
  334. package/dist/utils/init/pipeline.d.ts +74 -0
  335. package/dist/utils/init/pipeline.d.ts.map +1 -0
  336. package/dist/utils/init/pipeline.js +96 -0
  337. package/dist/utils/init/pipeline.js.map +1 -0
  338. package/dist/utils/poll.d.ts +15 -1
  339. package/dist/utils/poll.d.ts.map +1 -1
  340. package/dist/utils/poll.js +6 -3
  341. package/dist/utils/poll.js.map +1 -1
  342. package/dist/utils/register-agent-identity.d.ts +67 -0
  343. package/dist/utils/register-agent-identity.d.ts.map +1 -0
  344. package/dist/utils/register-agent-identity.js +34 -0
  345. package/dist/utils/register-agent-identity.js.map +1 -0
  346. package/dist/utils/review/did-web-key.d.ts +34 -0
  347. package/dist/utils/review/did-web-key.d.ts.map +1 -0
  348. package/dist/utils/review/did-web-key.js +104 -0
  349. package/dist/utils/review/did-web-key.js.map +1 -0
  350. package/dist/utils/review/load-registry.d.ts +33 -0
  351. package/dist/utils/review/load-registry.d.ts.map +1 -0
  352. package/dist/utils/review/load-registry.js +62 -0
  353. package/dist/utils/review/load-registry.js.map +1 -0
  354. package/dist/utils/review/verdict-verify.d.ts +43 -0
  355. package/dist/utils/review/verdict-verify.d.ts.map +1 -0
  356. package/dist/utils/review/verdict-verify.js +53 -0
  357. package/dist/utils/review/verdict-verify.js.map +1 -0
  358. package/dist/utils/review-registry-writer.d.ts +52 -0
  359. package/dist/utils/review-registry-writer.d.ts.map +1 -0
  360. package/dist/utils/review-registry-writer.js +79 -0
  361. package/dist/utils/review-registry-writer.js.map +1 -0
  362. package/dist/utils/should-install-dependency.d.ts +17 -0
  363. package/dist/utils/should-install-dependency.d.ts.map +1 -0
  364. package/dist/utils/should-install-dependency.js +25 -0
  365. package/dist/utils/should-install-dependency.js.map +1 -0
  366. package/dist/utils/tool-readiness.d.ts +57 -0
  367. package/dist/utils/tool-readiness.d.ts.map +1 -0
  368. package/dist/utils/tool-readiness.js +114 -0
  369. package/dist/utils/tool-readiness.js.map +1 -0
  370. package/dist/utils/which.d.ts +2 -0
  371. package/dist/utils/which.d.ts.map +1 -0
  372. package/dist/utils/which.js +22 -0
  373. package/dist/utils/which.js.map +1 -0
  374. package/dist/version.d.ts +15 -0
  375. package/dist/version.d.ts.map +1 -0
  376. package/dist/version.js +29 -0
  377. package/dist/version.js.map +1 -0
  378. package/package.json +19 -6
  379. package/dist/utils/claim-polling.d.ts +0 -21
  380. package/dist/utils/claim-polling.d.ts.map +0 -1
  381. package/dist/utils/claim-polling.js.map +0 -1
  382. package/dist/utils/dco/fs-safe.d.ts +0 -14
  383. package/dist/utils/dco/fs-safe.d.ts.map +0 -1
  384. package/dist/utils/dco/fs-safe.js +0 -20
  385. package/dist/utils/dco/fs-safe.js.map +0 -1
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Ticket store (ORC-W1 PR-1).
3
+ *
4
+ * The two load-bearing operations live here, and both encode their invariant
5
+ * in SQL rather than in a caller's discipline.
6
+ *
7
+ * @module orchestrator/db/tickets
8
+ */
9
+ import { z } from "zod";
10
+ import { type Ledger } from "./index.js";
11
+ export declare const TicketStatusSchema: z.ZodEnum<["open", "claimed", "in-progress", "in-review", "blocked", "ready", "closed"]>;
12
+ export type TicketStatus = z.infer<typeof TicketStatusSchema>;
13
+ /**
14
+ * The statuses `setTicketStatus` is allowed to write.
15
+ *
16
+ * `closed` and `claimed` each carry something a bare status write cannot -- a
17
+ * recorded reason, and a claimant set in the same statement -- so each has a
18
+ * dedicated function here and neither is reachable through the generic setter.
19
+ *
20
+ * Defined in the STORE and not at the MCP boundary, because the boundary is
21
+ * only one of the entrances. The daemon, the CLI and any consumer of the built
22
+ * package call these functions directly, and a rule that holds at one door is
23
+ * not an invariant, it is a convention with good manners.
24
+ */
25
+ export declare const SettableTicketStatusSchema: z.ZodEnum<["open", "in-progress", "in-review", "blocked", "ready"]>;
26
+ export type SettableTicketStatus = z.infer<typeof SettableTicketStatusSchema>;
27
+ export declare const SETTABLE_TICKET_STATUSES: ["open", "in-progress", "in-review", "blocked", "ready"];
28
+ export declare const TicketSeveritySchema: z.ZodEnum<["blocking", "major", "minor", "nit"]>;
29
+ export type TicketSeverity = z.infer<typeof TicketSeveritySchema>;
30
+ export declare const TicketSourceSchema: z.ZodEnum<["linear", "log_scan", "review_finding", "manual"]>;
31
+ export type TicketSource = z.infer<typeof TicketSourceSchema>;
32
+ /**
33
+ * Shape of a `tickets` row.
34
+ *
35
+ * Rows are parsed rather than cast. better-sqlite3's `.get()` is typed `any`,
36
+ * so `as Ticket` would not merely be an unchecked assumption, it would switch
37
+ * off checking for everything downstream of it — the repo bans exactly that.
38
+ * Parsing also means a schema drift (a migration that renames a column, a
39
+ * hand-edited ledger) fails loudly at the read instead of surfacing as
40
+ * `undefined` three layers away.
41
+ */
42
+ export declare const TicketRowSchema: z.ZodObject<{
43
+ id: z.ZodString;
44
+ linear_id: z.ZodNullable<z.ZodString>;
45
+ title: z.ZodString;
46
+ body: z.ZodNullable<z.ZodString>;
47
+ status: z.ZodEnum<["open", "claimed", "in-progress", "in-review", "blocked", "ready", "closed"]>;
48
+ severity: z.ZodNullable<z.ZodEnum<["blocking", "major", "minor", "nit"]>>;
49
+ source: z.ZodEnum<["linear", "log_scan", "review_finding", "manual"]>;
50
+ claimed_by: z.ZodNullable<z.ZodString>;
51
+ claimed_at: z.ZodNullable<z.ZodString>;
52
+ closed_reason: z.ZodNullable<z.ZodString>;
53
+ superseded_by: z.ZodNullable<z.ZodString>;
54
+ created_at: z.ZodString;
55
+ updated_at: z.ZodString;
56
+ }, "strip", z.ZodTypeAny, {
57
+ id: string;
58
+ status: "open" | "closed" | "ready" | "claimed" | "in-progress" | "in-review" | "blocked";
59
+ body: string | null;
60
+ source: "linear" | "log_scan" | "review_finding" | "manual";
61
+ linear_id: string | null;
62
+ title: string;
63
+ severity: "blocking" | "major" | "minor" | "nit" | null;
64
+ claimed_by: string | null;
65
+ claimed_at: string | null;
66
+ closed_reason: string | null;
67
+ superseded_by: string | null;
68
+ created_at: string;
69
+ updated_at: string;
70
+ }, {
71
+ id: string;
72
+ status: "open" | "closed" | "ready" | "claimed" | "in-progress" | "in-review" | "blocked";
73
+ body: string | null;
74
+ source: "linear" | "log_scan" | "review_finding" | "manual";
75
+ linear_id: string | null;
76
+ title: string;
77
+ severity: "blocking" | "major" | "minor" | "nit" | null;
78
+ claimed_by: string | null;
79
+ claimed_at: string | null;
80
+ closed_reason: string | null;
81
+ superseded_by: string | null;
82
+ created_at: string;
83
+ updated_at: string;
84
+ }>;
85
+ export type Ticket = z.infer<typeof TicketRowSchema>;
86
+ export interface CreateTicketInput {
87
+ title: string;
88
+ source: TicketSource;
89
+ body?: string;
90
+ severity?: TicketSeverity;
91
+ linearId?: string;
92
+ id?: string;
93
+ }
94
+ /** Insert a ticket in the `open` state. */
95
+ export declare function createTicket(db: Ledger, input: CreateTicketInput): Ticket;
96
+ export declare function getTicket(db: Ledger, id: string): Ticket | undefined;
97
+ /**
98
+ * Claim the oldest open ticket, atomically.
99
+ *
100
+ * The claim and the mark are ONE statement. A read-then-write pair here is a
101
+ * review-blocking defect, not a style preference: two orchestrator ticks, or
102
+ * two orchestrators pointed at one ledger, would both read the same open
103
+ * ticket and both staff it, producing two workers on one ticket in two
104
+ * checkouts. With a single UPDATE the losing caller changes zero rows and
105
+ * moves on.
106
+ *
107
+ * Returns null when nothing was claimable, which is an ordinary outcome and
108
+ * never an error.
109
+ */
110
+ export declare function claimNextTicket(db: Ledger, workerDid: string): Ticket | null;
111
+ /**
112
+ * Close a ticket by marking it, never by deleting it.
113
+ *
114
+ * There is deliberately no delete path anywhere in this package. Once a row is
115
+ * gone, a bad autonomous close and a clean backlog look identical, and the
116
+ * evidence needed to tell them apart went with it.
117
+ */
118
+ export declare function closeTicket(db: Ledger, id: string, reason: string, supersededBy?: string): Ticket;
119
+ /**
120
+ * Move a ticket to one of the statuses a plain status write can express.
121
+ *
122
+ * `closed` and `claimed` are refused: see `SettableTicketStatusSchema`. The
123
+ * check is made at RUNTIME and not left to the parameter type, because the
124
+ * callers it guards are the ones TypeScript never sees -- JavaScript consumers
125
+ * of the built package, and anything arriving through an `unknown`. A type
126
+ * cannot stop a caller that was never type-checked.
127
+ */
128
+ export declare function setTicketStatus(db: Ledger, id: string, status: SettableTicketStatus): Ticket;
129
+ /**
130
+ * Read tickets, optionally filtered, optionally capped.
131
+ *
132
+ * The cap is applied HERE, to the newest rows, not by the caller slicing an
133
+ * oldest-first list. Tickets soft-close and are never deleted, so closed
134
+ * history accumulates at the front of `created_at` order: capping afterwards
135
+ * meant that once the ledger outgrew the cap, an unfiltered read could be
136
+ * entirely closed rows with every open ticket invisible behind them. The
137
+ * journal and dispatch readers already ordered newest-first; this one was the
138
+ * outlier.
139
+ *
140
+ * The window is taken newest-first and then handed back oldest-first, so the
141
+ * result reads in the natural direction while still being the recent end of the
142
+ * ledger. `id` breaks ties because `created_at` alone is not unique -- two
143
+ * tickets made in the same millisecond would otherwise order arbitrarily, and
144
+ * an arbitrary order at the cap boundary decides which row is visible at all.
145
+ */
146
+ export declare function listTickets(db: Ledger, status?: TicketStatus, limit?: number): Ticket[];
147
+ //# sourceMappingURL=tickets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tickets.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/db/tickets.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAEjD,eAAO,MAAM,kBAAkB,0FAQ7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,qEAAoD,CAAC;AAC5F,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,eAAO,MAAM,wBAAwB,0DAAqC,CAAC;AAgB3E,eAAO,MAAM,oBAAoB,kDAAgD,CAAC;AAClF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,kBAAkB,+DAA6D,CAAC;AAC7F,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAc1B,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAQrD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAiBzE;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgB5E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CA4CR;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAqC5F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBvF"}
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Ticket store (ORC-W1 PR-1).
3
+ *
4
+ * The two load-bearing operations live here, and both encode their invariant
5
+ * in SQL rather than in a caller's discipline.
6
+ *
7
+ * @module orchestrator/db/tickets
8
+ */
9
+ import { randomUUID } from "node:crypto";
10
+ import { z } from "zod";
11
+ import { rowCap } from "./index.js";
12
+ export const TicketStatusSchema = z.enum([
13
+ "open",
14
+ "claimed",
15
+ "in-progress",
16
+ "in-review",
17
+ "blocked",
18
+ "ready",
19
+ "closed",
20
+ ]);
21
+ /**
22
+ * The statuses `setTicketStatus` is allowed to write.
23
+ *
24
+ * `closed` and `claimed` each carry something a bare status write cannot -- a
25
+ * recorded reason, and a claimant set in the same statement -- so each has a
26
+ * dedicated function here and neither is reachable through the generic setter.
27
+ *
28
+ * Defined in the STORE and not at the MCP boundary, because the boundary is
29
+ * only one of the entrances. The daemon, the CLI and any consumer of the built
30
+ * package call these functions directly, and a rule that holds at one door is
31
+ * not an invariant, it is a convention with good manners.
32
+ */
33
+ export const SettableTicketStatusSchema = TicketStatusSchema.exclude(["closed", "claimed"]);
34
+ export const SETTABLE_TICKET_STATUSES = SettableTicketStatusSchema.options;
35
+ /**
36
+ * Why each excluded status is excluded, so a refusal names its replacement
37
+ * rather than just saying no.
38
+ *
39
+ * Null-prototyped, so a lookup answers for its OWN keys only. As a plain object
40
+ * literal every inherited name resolved -- `toString`, `constructor`,
41
+ * `__proto__` -- and `?? fallback` never fired, so a caller could steer the
42
+ * refusal into printing a native function body instead of the settable list.
43
+ */
44
+ const UNSETTABLE_STATUS_REASON = Object.assign(Object.create(null), {
45
+ closed: "closing must record a reason, use closeTicket",
46
+ claimed: "claiming must set a claimant in the same statement, use claimNextTicket",
47
+ });
48
+ export const TicketSeveritySchema = z.enum(["blocking", "major", "minor", "nit"]);
49
+ export const TicketSourceSchema = z.enum(["linear", "log_scan", "review_finding", "manual"]);
50
+ /**
51
+ * Shape of a `tickets` row.
52
+ *
53
+ * Rows are parsed rather than cast. better-sqlite3's `.get()` is typed `any`,
54
+ * so `as Ticket` would not merely be an unchecked assumption, it would switch
55
+ * off checking for everything downstream of it — the repo bans exactly that.
56
+ * Parsing also means a schema drift (a migration that renames a column, a
57
+ * hand-edited ledger) fails loudly at the read instead of surfacing as
58
+ * `undefined` three layers away.
59
+ */
60
+ export const TicketRowSchema = z.object({
61
+ id: z.string(),
62
+ linear_id: z.string().nullable(),
63
+ title: z.string(),
64
+ body: z.string().nullable(),
65
+ status: TicketStatusSchema,
66
+ severity: TicketSeveritySchema.nullable(),
67
+ source: TicketSourceSchema,
68
+ claimed_by: z.string().nullable(),
69
+ claimed_at: z.string().nullable(),
70
+ closed_reason: z.string().nullable(),
71
+ superseded_by: z.string().nullable(),
72
+ created_at: z.string(),
73
+ updated_at: z.string(),
74
+ });
75
+ /** Parse one row, or undefined when the query matched nothing. */
76
+ function parseRow(row) {
77
+ if (row === undefined || row === null)
78
+ return undefined;
79
+ return TicketRowSchema.parse(row);
80
+ }
81
+ /** Insert a ticket in the `open` state. */
82
+ export function createTicket(db, input) {
83
+ const now = new Date().toISOString();
84
+ const id = input.id ?? randomUUID();
85
+ db.prepare(`INSERT INTO tickets (id, linear_id, title, body, status, severity, source, created_at, updated_at)
86
+ VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?)`).run(id, input.linearId ?? null, input.title, input.body ?? null, input.severity ?? null, input.source, now, now);
87
+ return getTicket(db, id);
88
+ }
89
+ export function getTicket(db, id) {
90
+ return parseRow(db.prepare(`SELECT * FROM tickets WHERE id = ?`).get(id));
91
+ }
92
+ /**
93
+ * Claim the oldest open ticket, atomically.
94
+ *
95
+ * The claim and the mark are ONE statement. A read-then-write pair here is a
96
+ * review-blocking defect, not a style preference: two orchestrator ticks, or
97
+ * two orchestrators pointed at one ledger, would both read the same open
98
+ * ticket and both staff it, producing two workers on one ticket in two
99
+ * checkouts. With a single UPDATE the losing caller changes zero rows and
100
+ * moves on.
101
+ *
102
+ * Returns null when nothing was claimable, which is an ordinary outcome and
103
+ * never an error.
104
+ */
105
+ export function claimNextTicket(db, workerDid) {
106
+ const now = new Date().toISOString();
107
+ const row = db
108
+ .prepare(`UPDATE tickets
109
+ SET status = 'claimed', claimed_by = ?, claimed_at = ?, updated_at = ?
110
+ WHERE id = (
111
+ SELECT id FROM tickets
112
+ WHERE status = 'open'
113
+ ORDER BY created_at, id
114
+ LIMIT 1
115
+ )
116
+ RETURNING *`)
117
+ .get(workerDid, now, now);
118
+ return parseRow(row) ?? null;
119
+ }
120
+ /**
121
+ * Close a ticket by marking it, never by deleting it.
122
+ *
123
+ * There is deliberately no delete path anywhere in this package. Once a row is
124
+ * gone, a bad autonomous close and a clean backlog look identical, and the
125
+ * evidence needed to tell them apart went with it.
126
+ */
127
+ export function closeTicket(db, id, reason, supersededBy) {
128
+ // Enforced here and not only at the tool, for the reason the whole module
129
+ // exists: "nothing is ever deleted" buys an audit trail only if the surviving
130
+ // row says WHY it closed, and a blank reason produces the unexplained closed
131
+ // row permanently, since a second close is refused.
132
+ if (reason.trim() === "") {
133
+ throw new Error(`orchestrator: closing ticket ${id} needs a non-empty reason`);
134
+ }
135
+ const info = db
136
+ .prepare(`UPDATE tickets
137
+ SET status = 'closed',
138
+ closed_reason = ?,
139
+ superseded_by = ?,
140
+ updated_at = ?,
141
+ -- Closing LEAVES claimed, so it releases the claim too. The rule
142
+ -- lived only in setTicketStatus, so a closed row kept naming a
143
+ -- live worker and answered "who holds this" in flat contradiction
144
+ -- of its own status. In the same statement, so the release cannot
145
+ -- be separated from the close by a failure between them.
146
+ -- If a third writer ever leaves claimed, move this to a trigger
147
+ -- rather than writing the rule a third time.
148
+ claimed_by = NULL,
149
+ claimed_at = NULL
150
+ WHERE id = ?
151
+ AND status <> 'closed'`)
152
+ .run(reason, supersededBy ?? null, new Date().toISOString(), id);
153
+ if (info.changes === 0) {
154
+ const existing = getTicket(db, id);
155
+ if (existing === undefined) {
156
+ throw new Error(`orchestrator: cannot close unknown ticket ${id}`);
157
+ }
158
+ // Closing twice used to overwrite the original reason and NULL out
159
+ // superseded_by, which reduces "soft, auditable close" to one mutable
160
+ // column: the record of WHY something closed is the point of not deleting
161
+ // it, and a second close silently replaces that record.
162
+ throw new Error(`orchestrator: ticket ${id} is already closed (${existing.closed_reason ?? "no reason recorded"})`);
163
+ }
164
+ return getTicket(db, id);
165
+ }
166
+ /**
167
+ * Move a ticket to one of the statuses a plain status write can express.
168
+ *
169
+ * `closed` and `claimed` are refused: see `SettableTicketStatusSchema`. The
170
+ * check is made at RUNTIME and not left to the parameter type, because the
171
+ * callers it guards are the ones TypeScript never sees -- JavaScript consumers
172
+ * of the built package, and anything arriving through an `unknown`. A type
173
+ * cannot stop a caller that was never type-checked.
174
+ */
175
+ export function setTicketStatus(db, id, status) {
176
+ if (!SettableTicketStatusSchema.safeParse(status).success) {
177
+ const because = UNSETTABLE_STATUS_REASON[status] ??
178
+ `settable statuses are ${SETTABLE_TICKET_STATUSES.join(", ")}`;
179
+ throw new Error(`orchestrator: setTicketStatus cannot set '${status}'; ${because}`);
180
+ }
181
+ const info = db
182
+ .prepare(`UPDATE tickets
183
+ SET status = ?,
184
+ updated_at = ?,
185
+ -- Any transition AWAY from claimed releases the claim, in the same
186
+ -- statement so the release cannot be separated from the status
187
+ -- change by a failure between them. Unconditional because the
188
+ -- guard above makes 'claimed' unreachable here: every status this
189
+ -- statement can write is a status that leaves it.
190
+ claimed_by = NULL,
191
+ claimed_at = NULL
192
+ WHERE id = ?
193
+ AND status <> 'closed'`)
194
+ .run(status, new Date().toISOString(), id);
195
+ if (info.changes === 0) {
196
+ // Distinguish the two ways to change nothing, because they mean opposite
197
+ // things to a caller: one is a bad id, the other is a refused transition.
198
+ const existing = getTicket(db, id);
199
+ if (existing === undefined) {
200
+ throw new Error(`orchestrator: cannot update unknown ticket ${id}`);
201
+ }
202
+ throw new Error(`orchestrator: ticket ${id} is closed; reopening is a human decision, not a status write`);
203
+ }
204
+ return getTicket(db, id);
205
+ }
206
+ /**
207
+ * Read tickets, optionally filtered, optionally capped.
208
+ *
209
+ * The cap is applied HERE, to the newest rows, not by the caller slicing an
210
+ * oldest-first list. Tickets soft-close and are never deleted, so closed
211
+ * history accumulates at the front of `created_at` order: capping afterwards
212
+ * meant that once the ledger outgrew the cap, an unfiltered read could be
213
+ * entirely closed rows with every open ticket invisible behind them. The
214
+ * journal and dispatch readers already ordered newest-first; this one was the
215
+ * outlier.
216
+ *
217
+ * The window is taken newest-first and then handed back oldest-first, so the
218
+ * result reads in the natural direction while still being the recent end of the
219
+ * ledger. `id` breaks ties because `created_at` alone is not unique -- two
220
+ * tickets made in the same millisecond would otherwise order arbitrarily, and
221
+ * an arbitrary order at the cap boundary decides which row is visible at all.
222
+ */
223
+ export function listTickets(db, status, limit) {
224
+ const cap = rowCap(limit);
225
+ const rows = status
226
+ ? db
227
+ .prepare(`SELECT * FROM (
228
+ SELECT * FROM tickets WHERE status = ? ORDER BY created_at DESC, id DESC LIMIT ?
229
+ ) ORDER BY created_at, id`)
230
+ .all(status, cap)
231
+ : db
232
+ .prepare(`SELECT * FROM (
233
+ SELECT * FROM tickets ORDER BY created_at DESC, id DESC LIMIT ?
234
+ ) ORDER BY created_at, id`)
235
+ .all(cap);
236
+ return z.array(TicketRowSchema).parse(rows);
237
+ }
238
+ //# sourceMappingURL=tickets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tickets.js","sourceRoot":"","sources":["../../../src/orchestrator/db/tickets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Verdict and quorum store.
3
+ *
4
+ * The point of this module is that both writes are idempotent by NATURAL key,
5
+ * not by a hash of the event that produced them:
6
+ *
7
+ * - a verdict is unique per (repo, pr, head_sha, reviewer_did)
8
+ * - quorum is unique per (repo, pr, head_sha)
9
+ *
10
+ * Those keys are what the review protocol already means, so "have we processed
11
+ * this?" is answered by asking whether the row exists. The previous approach
12
+ * derived a content hash of the hub event and stored a synthetic marker beside
13
+ * the ticket, which needed its own scoping, its own lookup path, and its own
14
+ * durability guarantees -- three review findings' worth of them. A UNIQUE
15
+ * constraint the schema already declared does the same job and cannot expire,
16
+ * collide across tickets, or be looked for in the wrong window.
17
+ *
18
+ * `verdicts` was in the schema from the start with exactly this shape and no
19
+ * reader; this is that reader.
20
+ *
21
+ * @module cli/orchestrator/db/verdicts
22
+ */
23
+ import { z } from "zod";
24
+ import type { Ledger } from "./index.js";
25
+ export declare const VerdictKindSchema: z.ZodEnum<["approve", "request-changes", "comment"]>;
26
+ export type VerdictKind = z.infer<typeof VerdictKindSchema>;
27
+ export declare const VerdictRowSchema: z.ZodObject<{
28
+ id: z.ZodString;
29
+ ticket_id: z.ZodNullable<z.ZodString>;
30
+ repo: z.ZodString;
31
+ pr_number: z.ZodNumber;
32
+ head_sha: z.ZodString;
33
+ reviewer_did: z.ZodString;
34
+ verdict: z.ZodEnum<["approve", "request-changes", "comment"]>;
35
+ findings: z.ZodNullable<z.ZodString>;
36
+ counted: z.ZodNumber;
37
+ received_at: z.ZodString;
38
+ }, "strip", z.ZodTypeAny, {
39
+ id: string;
40
+ repo: string;
41
+ ticket_id: string | null;
42
+ pr_number: number;
43
+ head_sha: string;
44
+ reviewer_did: string;
45
+ verdict: "comment" | "approve" | "request-changes";
46
+ findings: string | null;
47
+ counted: number;
48
+ received_at: string;
49
+ }, {
50
+ id: string;
51
+ repo: string;
52
+ ticket_id: string | null;
53
+ pr_number: number;
54
+ head_sha: string;
55
+ reviewer_did: string;
56
+ verdict: "comment" | "approve" | "request-changes";
57
+ findings: string | null;
58
+ counted: number;
59
+ received_at: string;
60
+ }>;
61
+ export type VerdictRow = z.infer<typeof VerdictRowSchema>;
62
+ export interface RecordVerdictInput {
63
+ ticketId: string | null;
64
+ repo: string;
65
+ prNumber: number;
66
+ headSha: string;
67
+ reviewerDid: string;
68
+ verdict: VerdictKind;
69
+ /** The hub's own validity flag; false means it failed verdict validation. */
70
+ counted: boolean;
71
+ findings?: unknown;
72
+ /**
73
+ * PROTOCOL time -- the hub event's own timestamp -- not the wall clock at
74
+ * insert. Head ranking is derived from these, and consecutive better-sqlite3
75
+ * inserts land in the same millisecond, so a wall-clock stamp made ties the
76
+ * normal case on a cold-start replay and handed the decision to a lexicographic
77
+ * SHA comparison. Protocol time is the order things actually happened in, which
78
+ * is the order the ranking is trying to recover.
79
+ */
80
+ observedAt: number;
81
+ }
82
+ /**
83
+ * Record one reviewer's verdict on one head SHA.
84
+ *
85
+ * Returns true when something CHANGED: the verdict is new, or the same reviewer
86
+ * revised it on the same head. False means this exact verdict was already
87
+ * recorded, which is a replay, a re-delivered event, or a boot reconcile of a
88
+ * window already processed.
89
+ *
90
+ * `received_at` is NEVER rewritten on conflict: it is the FIRST sighting of this
91
+ * head, which head ranking depends on, and letting a late revision move it
92
+ * contradicted the very function that reads it. A revision updates the verdict,
93
+ * not when the head was first seen.
94
+ *
95
+ * The mind-change case is why this is an upsert rather than INSERT OR IGNORE.
96
+ * The hub explicitly permits a reviewer to follow an approval with
97
+ * request-changes on the SAME head and emits a second review_verdict for it. On
98
+ * a plain OR IGNORE that second verdict is dropped as "already handled" and the
99
+ * ticket never goes back to in-progress -- a reviewer withdrawing approval would
100
+ * be silently overruled by a uniqueness constraint.
101
+ *
102
+ * The guarded UPDATE is what keeps false meaning "nothing to do": re-delivering
103
+ * an identical verdict fails the WHERE, changes no rows, and reports false.
104
+ * `findings` is part of that comparison so a revision that only changes its
105
+ * reasons is still stored -- otherwise the recorded findings silently went stale
106
+ * while the verdict itself looked current.
107
+ *
108
+ * The id is a readable composite of the natural key rather than a hash, so a row
109
+ * can be found by hand in a debugging session.
110
+ */
111
+ export declare function recordVerdict(db: Ledger, input: RecordVerdictInput): boolean;
112
+ export interface RecordQuorumInput {
113
+ ticketId: string | null;
114
+ repo: string;
115
+ prNumber: number;
116
+ headSha: string;
117
+ quorumN?: number;
118
+ /** Protocol time, for the same reason as {@link RecordVerdictInput.observedAt}. */
119
+ observedAt: number;
120
+ }
121
+ /**
122
+ * Record that the hub declared quorum on one head SHA.
123
+ *
124
+ * Returns true when it was new. Quorum is stored rather than recomputed because
125
+ * the hub owns verdict validation, and a second implementation of the threshold
126
+ * here could disagree with the one that actually gated the decision.
127
+ */
128
+ export declare function recordQuorum(db: Ledger, input: RecordQuorumInput): boolean;
129
+ /** Every verdict on one PR head, newest first. */
130
+ export declare function listVerdictsForPr(db: Ledger, repo: string, prNumber: number, headSha?: string): VerdictRow[];
131
+ /** Has the hub already declared quorum on this head? */
132
+ export declare function quorumReached(db: Ledger, repo: string, prNumber: number, headSha: string): boolean;
133
+ /**
134
+ * The most recently seen head SHA for a pull request.
135
+ *
136
+ * Which revision the ledger currently believes is live. A push invalidates every
137
+ * prior verdict (the review protocol's settled rule), so status has to be derived
138
+ * from the newest head rather than from whichever head the event in hand names --
139
+ * otherwise a late or replayed quorum for superseded code moves current work.
140
+ * `counted: false` marks a stale VERDICT; quorum has no such flag.
141
+ *
142
+ * Ranked by when each head was FIRST seen, not when it was last touched. This is
143
+ * the whole correctness of the function. Ranking by last-touched let any newly
144
+ * recorded row for an older SHA promote it to "latest" -- including an uncounted
145
+ * stale verdict kept purely as evidence. Historical quorum on that superseded
146
+ * head would then clear a live objection on the real one, defeating the
147
+ * uncounted guard this derivation depends on. A head's first sighting cannot be
148
+ * moved by a late arrival, because the upsert never rewrites `received_at`.
149
+ *
150
+ * "When" is PROTOCOL time -- the hub event's own timestamp, carried in on
151
+ * `observedAt` -- not the wall clock at insert. Insert time made this a coin
152
+ * flip in the one case that matters most: on a cold start, `reconcileReviewState`
153
+ * replays the window fast enough that consecutive better-sqlite3 inserts land in
154
+ * the same millisecond, so every head tied and the winner fell to the SHA
155
+ * tiebreak. Half the time that elected the OLD head, derived a historical quorum
156
+ * against it, and moved a ticket to `ready` straight past a live counted
157
+ * request-changes on the new one.
158
+ *
159
+ * Ties still break on head_sha, for genuinely simultaneous protocol timestamps:
160
+ * an arbitrary-but-stable answer beats a fresh coin flip per query, and truly
161
+ * simultaneous revisions are ambiguous under any rule.
162
+ */
163
+ export declare function latestHeadForPr(db: Ledger, repo: string, prNumber: number): string | undefined;
164
+ /**
165
+ * The same ranking as {@link latestHeadForPr}, blind to uncounted verdicts.
166
+ *
167
+ * `latestHeadForPr` deliberately ranks EVERY verdict, counted or not -- a
168
+ * verdict naming a stale or malformed SHA still proves the hub saw that SHA,
169
+ * which is what that function's contract promises. But "a SHA was mentioned"
170
+ * and "a SHA was genuinely reviewed" are different questions, and DERIVING
171
+ * status needs the second one: a verdict the hub itself flagged invalid must
172
+ * not be able to outrank a real counted verdict or quorum recorded on a
173
+ * different head just because it happened to arrive with a later protocol
174
+ * timestamp. Left unfiltered, that lets review noise on a throwaway SHA
175
+ * occlude a real objection sitting under the head that actually matters --
176
+ * the ticket keeps whatever status the occluded head implied, forever,
177
+ * because nothing ever asks about that head again.
178
+ *
179
+ * Quorum rows carry no `counted` column and are never filtered here, the same
180
+ * way {@link latestHeadForPr} treats them: the hub is the sole authority for
181
+ * quorum, so a recorded quorum is trusted unconditionally.
182
+ *
183
+ * Returns undefined when no head has ANY trusted evidence yet -- distinct
184
+ * from "no evidence at all," which only {@link latestHeadForPr} can answer.
185
+ */
186
+ export declare function latestTrustedHeadForPr(db: Ledger, repo: string, prNumber: number): string | undefined;
187
+ //# sourceMappingURL=verdicts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdicts.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/db/verdicts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,eAAO,MAAM,iBAAiB,sDAAoD,CAAC;AACnF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;OAOG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CA6B5E;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAe1E;AAED,kDAAkD;AAClD,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,UAAU,EAAE,CAcd;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAMT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAe9F;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAerG"}