hungry-ghost-hive 0.48.0 → 0.49.0

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 (472) hide show
  1. package/dist/agents/base-agent.d.ts +11 -11
  2. package/dist/agents/base-agent.d.ts.map +1 -1
  3. package/dist/agents/base-agent.js +25 -25
  4. package/dist/agents/base-agent.js.map +1 -1
  5. package/dist/agents/base-agent.test.js +2 -1
  6. package/dist/agents/base-agent.test.js.map +1 -1
  7. package/dist/agents/intermediate.d.ts +2 -0
  8. package/dist/agents/intermediate.d.ts.map +1 -1
  9. package/dist/agents/intermediate.js +25 -18
  10. package/dist/agents/intermediate.js.map +1 -1
  11. package/dist/agents/junior.d.ts +2 -0
  12. package/dist/agents/junior.d.ts.map +1 -1
  13. package/dist/agents/junior.js +25 -18
  14. package/dist/agents/junior.js.map +1 -1
  15. package/dist/agents/qa.d.ts +2 -0
  16. package/dist/agents/qa.d.ts.map +1 -1
  17. package/dist/agents/qa.js +47 -38
  18. package/dist/agents/qa.js.map +1 -1
  19. package/dist/agents/senior.d.ts +2 -0
  20. package/dist/agents/senior.d.ts.map +1 -1
  21. package/dist/agents/senior.js +40 -27
  22. package/dist/agents/senior.js.map +1 -1
  23. package/dist/agents/tech-lead.d.ts +2 -0
  24. package/dist/agents/tech-lead.d.ts.map +1 -1
  25. package/dist/agents/tech-lead.js +37 -31
  26. package/dist/agents/tech-lead.js.map +1 -1
  27. package/dist/cli/commands/add-repo.js +2 -2
  28. package/dist/cli/commands/add-repo.js.map +1 -1
  29. package/dist/cli/commands/add-repo.test.js +1 -1
  30. package/dist/cli/commands/add-repo.test.js.map +1 -1
  31. package/dist/cli/commands/agents.d.ts.map +1 -1
  32. package/dist/cli/commands/agents.js +12 -10
  33. package/dist/cli/commands/agents.js.map +1 -1
  34. package/dist/cli/commands/agents.test.js +7 -7
  35. package/dist/cli/commands/agents.test.js.map +1 -1
  36. package/dist/cli/commands/approach.js +2 -2
  37. package/dist/cli/commands/approach.js.map +1 -1
  38. package/dist/cli/commands/approvals.js +7 -7
  39. package/dist/cli/commands/approvals.js.map +1 -1
  40. package/dist/cli/commands/approvals.test.js +8 -8
  41. package/dist/cli/commands/approvals.test.js.map +1 -1
  42. package/dist/cli/commands/assign.js +4 -4
  43. package/dist/cli/commands/assign.js.map +1 -1
  44. package/dist/cli/commands/assign.test.js +18 -16
  45. package/dist/cli/commands/assign.test.js.map +1 -1
  46. package/dist/cli/commands/cleanup.d.ts.map +1 -1
  47. package/dist/cli/commands/cleanup.js +8 -8
  48. package/dist/cli/commands/cleanup.js.map +1 -1
  49. package/dist/cli/commands/cleanup.test.js +5 -1
  50. package/dist/cli/commands/cleanup.test.js.map +1 -1
  51. package/dist/cli/commands/escalations.js +9 -7
  52. package/dist/cli/commands/escalations.js.map +1 -1
  53. package/dist/cli/commands/escalations.test.js +2 -2
  54. package/dist/cli/commands/escalations.test.js.map +1 -1
  55. package/dist/cli/commands/init.d.ts.map +1 -1
  56. package/dist/cli/commands/init.js +48 -5
  57. package/dist/cli/commands/init.js.map +1 -1
  58. package/dist/cli/commands/init.test.js +4 -0
  59. package/dist/cli/commands/init.test.js.map +1 -1
  60. package/dist/cli/commands/manager/agent-monitoring.d.ts +2 -2
  61. package/dist/cli/commands/manager/agent-monitoring.d.ts.map +1 -1
  62. package/dist/cli/commands/manager/agent-monitoring.js +1 -1
  63. package/dist/cli/commands/manager/agent-monitoring.js.map +1 -1
  64. package/dist/cli/commands/manager/auditor-lifecycle.js +3 -3
  65. package/dist/cli/commands/manager/auditor-lifecycle.js.map +1 -1
  66. package/dist/cli/commands/manager/auditor-lifecycle.test.js +21 -14
  67. package/dist/cli/commands/manager/auditor-lifecycle.test.js.map +1 -1
  68. package/dist/cli/commands/manager/auto-reject-comment-only-reviews.test.js +28 -23
  69. package/dist/cli/commands/manager/auto-reject-comment-only-reviews.test.js.map +1 -1
  70. package/dist/cli/commands/manager/escalation-handler.d.ts +2 -2
  71. package/dist/cli/commands/manager/escalation-handler.d.ts.map +1 -1
  72. package/dist/cli/commands/manager/escalation-handler.js +11 -10
  73. package/dist/cli/commands/manager/escalation-handler.js.map +1 -1
  74. package/dist/cli/commands/manager/escalation-handler.test.js +8 -8
  75. package/dist/cli/commands/manager/escalation-handler.test.js.map +1 -1
  76. package/dist/cli/commands/manager/feature-sign-off.js +7 -7
  77. package/dist/cli/commands/manager/feature-sign-off.js.map +1 -1
  78. package/dist/cli/commands/manager/feature-sign-off.test.js +40 -31
  79. package/dist/cli/commands/manager/feature-sign-off.test.js.map +1 -1
  80. package/dist/cli/commands/manager/feature-test-result.d.ts.map +1 -1
  81. package/dist/cli/commands/manager/feature-test-result.js +12 -13
  82. package/dist/cli/commands/manager/feature-test-result.js.map +1 -1
  83. package/dist/cli/commands/manager/handoff-recovery.d.ts.map +1 -1
  84. package/dist/cli/commands/manager/handoff-recovery.js +14 -15
  85. package/dist/cli/commands/manager/handoff-recovery.js.map +1 -1
  86. package/dist/cli/commands/manager/index.d.ts.map +1 -1
  87. package/dist/cli/commands/manager/index.js +26 -26
  88. package/dist/cli/commands/manager/index.js.map +1 -1
  89. package/dist/cli/commands/manager/index.test.js +3 -3
  90. package/dist/cli/commands/manager/index.test.js.map +1 -1
  91. package/dist/cli/commands/manager/merged-story-cleanup.d.ts +2 -2
  92. package/dist/cli/commands/manager/merged-story-cleanup.d.ts.map +1 -1
  93. package/dist/cli/commands/manager/merged-story-cleanup.js +6 -7
  94. package/dist/cli/commands/manager/merged-story-cleanup.js.map +1 -1
  95. package/dist/cli/commands/manager/merged-story-cleanup.test.js +27 -18
  96. package/dist/cli/commands/manager/merged-story-cleanup.test.js.map +1 -1
  97. package/dist/cli/commands/manager/pr-sync-orchestrator.d.ts.map +1 -1
  98. package/dist/cli/commands/manager/pr-sync-orchestrator.js +46 -38
  99. package/dist/cli/commands/manager/pr-sync-orchestrator.js.map +1 -1
  100. package/dist/cli/commands/manager/qa-review-handler.d.ts.map +1 -1
  101. package/dist/cli/commands/manager/qa-review-handler.js +25 -22
  102. package/dist/cli/commands/manager/qa-review-handler.js.map +1 -1
  103. package/dist/cli/commands/manager/spin-down.d.ts.map +1 -1
  104. package/dist/cli/commands/manager/spin-down.js +23 -19
  105. package/dist/cli/commands/manager/spin-down.js.map +1 -1
  106. package/dist/cli/commands/manager/stale-escalations.d.ts +2 -3
  107. package/dist/cli/commands/manager/stale-escalations.d.ts.map +1 -1
  108. package/dist/cli/commands/manager/stale-escalations.js.map +1 -1
  109. package/dist/cli/commands/manager/stuck-story-helpers.js +8 -8
  110. package/dist/cli/commands/manager/stuck-story-helpers.js.map +1 -1
  111. package/dist/cli/commands/manager/stuck-story-processor.d.ts +2 -2
  112. package/dist/cli/commands/manager/stuck-story-processor.d.ts.map +1 -1
  113. package/dist/cli/commands/manager/stuck-story-processor.js +23 -22
  114. package/dist/cli/commands/manager/stuck-story-processor.js.map +1 -1
  115. package/dist/cli/commands/manager/tech-lead-lifecycle.js +6 -6
  116. package/dist/cli/commands/manager/tech-lead-lifecycle.js.map +1 -1
  117. package/dist/cli/commands/manager/types.d.ts +2 -3
  118. package/dist/cli/commands/manager/types.d.ts.map +1 -1
  119. package/dist/cli/commands/manager/types.js.map +1 -1
  120. package/dist/cli/commands/msg.test.js +2 -2
  121. package/dist/cli/commands/msg.test.js.map +1 -1
  122. package/dist/cli/commands/my-stories.d.ts.map +1 -1
  123. package/dist/cli/commands/my-stories.js +17 -18
  124. package/dist/cli/commands/my-stories.js.map +1 -1
  125. package/dist/cli/commands/my-stories.test.js +2 -2
  126. package/dist/cli/commands/my-stories.test.js.map +1 -1
  127. package/dist/cli/commands/nuke.test.js +1 -1
  128. package/dist/cli/commands/nuke.test.js.map +1 -1
  129. package/dist/cli/commands/pr.js +32 -32
  130. package/dist/cli/commands/pr.js.map +1 -1
  131. package/dist/cli/commands/pr.test.js +10 -6
  132. package/dist/cli/commands/pr.test.js.map +1 -1
  133. package/dist/cli/commands/progress.d.ts.map +1 -1
  134. package/dist/cli/commands/progress.js +4 -5
  135. package/dist/cli/commands/progress.js.map +1 -1
  136. package/dist/cli/commands/progress.test.js +1 -1
  137. package/dist/cli/commands/progress.test.js.map +1 -1
  138. package/dist/cli/commands/req-headless.test.d.ts +2 -0
  139. package/dist/cli/commands/req-headless.test.d.ts.map +1 -0
  140. package/dist/cli/commands/req-headless.test.js +128 -0
  141. package/dist/cli/commands/req-headless.test.js.map +1 -0
  142. package/dist/cli/commands/req-spawn.test.js +5 -1
  143. package/dist/cli/commands/req-spawn.test.js.map +1 -1
  144. package/dist/cli/commands/req.d.ts.map +1 -1
  145. package/dist/cli/commands/req.js +13 -14
  146. package/dist/cli/commands/req.js.map +1 -1
  147. package/dist/cli/commands/resume.d.ts.map +1 -1
  148. package/dist/cli/commands/resume.js +7 -8
  149. package/dist/cli/commands/resume.js.map +1 -1
  150. package/dist/cli/commands/resume.test.js +1 -1
  151. package/dist/cli/commands/resume.test.js.map +1 -1
  152. package/dist/cli/commands/status.d.ts.map +1 -1
  153. package/dist/cli/commands/status.js +42 -40
  154. package/dist/cli/commands/status.js.map +1 -1
  155. package/dist/cli/commands/status.test.js +1 -1
  156. package/dist/cli/commands/status.test.js.map +1 -1
  157. package/dist/cli/commands/stories.js +9 -9
  158. package/dist/cli/commands/stories.js.map +1 -1
  159. package/dist/cli/commands/stories.test.js +2 -2
  160. package/dist/cli/commands/stories.test.js.map +1 -1
  161. package/dist/cli/commands/teams.js +11 -11
  162. package/dist/cli/commands/teams.js.map +1 -1
  163. package/dist/cli/commands/teams.test.js +2 -2
  164. package/dist/cli/commands/teams.test.js.map +1 -1
  165. package/dist/cli/dashboard/index.d.ts +2 -2
  166. package/dist/cli/dashboard/index.d.ts.map +1 -1
  167. package/dist/cli/dashboard/index.js +29 -20
  168. package/dist/cli/dashboard/index.js.map +1 -1
  169. package/dist/cli/dashboard/index.test.js +34 -32
  170. package/dist/cli/dashboard/index.test.js.map +1 -1
  171. package/dist/cli/dashboard/panels/activity.d.ts +3 -3
  172. package/dist/cli/dashboard/panels/activity.d.ts.map +1 -1
  173. package/dist/cli/dashboard/panels/activity.js +1 -1
  174. package/dist/cli/dashboard/panels/activity.js.map +1 -1
  175. package/dist/cli/dashboard/panels/agents.d.ts +3 -3
  176. package/dist/cli/dashboard/panels/agents.d.ts.map +1 -1
  177. package/dist/cli/dashboard/panels/agents.js +2 -2
  178. package/dist/cli/dashboard/panels/agents.js.map +1 -1
  179. package/dist/cli/dashboard/panels/escalations.d.ts +3 -3
  180. package/dist/cli/dashboard/panels/escalations.d.ts.map +1 -1
  181. package/dist/cli/dashboard/panels/escalations.js +1 -1
  182. package/dist/cli/dashboard/panels/escalations.js.map +1 -1
  183. package/dist/cli/dashboard/panels/merge-queue.d.ts +3 -3
  184. package/dist/cli/dashboard/panels/merge-queue.d.ts.map +1 -1
  185. package/dist/cli/dashboard/panels/merge-queue.js +1 -1
  186. package/dist/cli/dashboard/panels/merge-queue.js.map +1 -1
  187. package/dist/cli/dashboard/panels/pipeline.d.ts +3 -3
  188. package/dist/cli/dashboard/panels/pipeline.d.ts.map +1 -1
  189. package/dist/cli/dashboard/panels/pipeline.js +1 -1
  190. package/dist/cli/dashboard/panels/pipeline.js.map +1 -1
  191. package/dist/config/schema.d.ts +85 -82
  192. package/dist/config/schema.d.ts.map +1 -1
  193. package/dist/config/schema.js +1 -0
  194. package/dist/config/schema.js.map +1 -1
  195. package/dist/connectors/project-management/operations.d.ts +7 -7
  196. package/dist/connectors/project-management/operations.d.ts.map +1 -1
  197. package/dist/connectors/project-management/operations.js +2 -3
  198. package/dist/connectors/project-management/operations.js.map +1 -1
  199. package/dist/context-files/index.test.js +1 -0
  200. package/dist/context-files/index.test.js.map +1 -1
  201. package/dist/db/client.d.ts +6 -0
  202. package/dist/db/client.d.ts.map +1 -1
  203. package/dist/db/client.js +7 -0
  204. package/dist/db/client.js.map +1 -1
  205. package/dist/db/postgres-provider.d.ts +43 -0
  206. package/dist/db/postgres-provider.d.ts.map +1 -0
  207. package/dist/db/postgres-provider.integration.test.d.ts +2 -0
  208. package/dist/db/postgres-provider.integration.test.d.ts.map +1 -0
  209. package/dist/db/postgres-provider.integration.test.js +399 -0
  210. package/dist/db/postgres-provider.integration.test.js.map +1 -0
  211. package/dist/db/postgres-provider.js +315 -0
  212. package/dist/db/postgres-provider.js.map +1 -0
  213. package/dist/db/postgres-provider.test.d.ts +2 -0
  214. package/dist/db/postgres-provider.test.d.ts.map +1 -0
  215. package/dist/db/postgres-provider.test.js +72 -0
  216. package/dist/db/postgres-provider.test.js.map +1 -0
  217. package/dist/db/provider.d.ts +59 -0
  218. package/dist/db/provider.d.ts.map +1 -0
  219. package/dist/db/provider.js +121 -0
  220. package/dist/db/provider.js.map +1 -0
  221. package/dist/db/provider.test.d.ts +2 -0
  222. package/dist/db/provider.test.d.ts.map +1 -0
  223. package/dist/db/provider.test.js +226 -0
  224. package/dist/db/provider.test.js.map +1 -0
  225. package/dist/db/queries/agents.d.ts +13 -13
  226. package/dist/db/queries/agents.d.ts.map +1 -1
  227. package/dist/db/queries/agents.js +27 -28
  228. package/dist/db/queries/agents.js.map +1 -1
  229. package/dist/db/queries/agents.test.js +113 -111
  230. package/dist/db/queries/agents.test.js.map +1 -1
  231. package/dist/db/queries/escalations.d.ts +16 -16
  232. package/dist/db/queries/escalations.d.ts.map +1 -1
  233. package/dist/db/queries/escalations.js +34 -35
  234. package/dist/db/queries/escalations.js.map +1 -1
  235. package/dist/db/queries/escalations.test.js +133 -131
  236. package/dist/db/queries/escalations.test.js.map +1 -1
  237. package/dist/db/queries/heartbeat.d.ts +5 -5
  238. package/dist/db/queries/heartbeat.d.ts.map +1 -1
  239. package/dist/db/queries/heartbeat.js +7 -23
  240. package/dist/db/queries/heartbeat.js.map +1 -1
  241. package/dist/db/queries/heartbeat.test.js +76 -76
  242. package/dist/db/queries/heartbeat.test.js.map +1 -1
  243. package/dist/db/queries/integration-sync.d.ts +7 -7
  244. package/dist/db/queries/integration-sync.d.ts.map +1 -1
  245. package/dist/db/queries/integration-sync.js +13 -14
  246. package/dist/db/queries/integration-sync.js.map +1 -1
  247. package/dist/db/queries/logs.d.ts +10 -10
  248. package/dist/db/queries/logs.d.ts.map +1 -1
  249. package/dist/db/queries/logs.js +44 -42
  250. package/dist/db/queries/logs.js.map +1 -1
  251. package/dist/db/queries/logs.test.js +149 -146
  252. package/dist/db/queries/logs.test.js.map +1 -1
  253. package/dist/db/queries/messages.d.ts +6 -6
  254. package/dist/db/queries/messages.d.ts.map +1 -1
  255. package/dist/db/queries/messages.js +12 -11
  256. package/dist/db/queries/messages.js.map +1 -1
  257. package/dist/db/queries/messages.test.js +47 -46
  258. package/dist/db/queries/messages.test.js.map +1 -1
  259. package/dist/db/queries/pull-requests.d.ts +18 -18
  260. package/dist/db/queries/pull-requests.d.ts.map +1 -1
  261. package/dist/db/queries/pull-requests.js +50 -48
  262. package/dist/db/queries/pull-requests.js.map +1 -1
  263. package/dist/db/queries/pull-requests.test.js +195 -198
  264. package/dist/db/queries/pull-requests.test.js.map +1 -1
  265. package/dist/db/queries/requirements.d.ts +8 -8
  266. package/dist/db/queries/requirements.d.ts.map +1 -1
  267. package/dist/db/queries/requirements.js +17 -18
  268. package/dist/db/queries/requirements.js.map +1 -1
  269. package/dist/db/queries/requirements.test.js +83 -81
  270. package/dist/db/queries/requirements.test.js.map +1 -1
  271. package/dist/db/queries/stories.d.ts +29 -29
  272. package/dist/db/queries/stories.d.ts.map +1 -1
  273. package/dist/db/queries/stories.js +58 -64
  274. package/dist/db/queries/stories.js.map +1 -1
  275. package/dist/db/queries/stories.test.js +172 -170
  276. package/dist/db/queries/stories.test.js.map +1 -1
  277. package/dist/db/queries/teams.d.ts +6 -6
  278. package/dist/db/queries/teams.d.ts.map +1 -1
  279. package/dist/db/queries/teams.js +11 -12
  280. package/dist/db/queries/teams.js.map +1 -1
  281. package/dist/db/queries/teams.test.js +36 -34
  282. package/dist/db/queries/teams.test.js.map +1 -1
  283. package/dist/integrations/jira/repair.test.js +26 -24
  284. package/dist/integrations/jira/repair.test.js.map +1 -1
  285. package/dist/integrations/jira/stories.d.ts +3 -3
  286. package/dist/integrations/jira/stories.d.ts.map +1 -1
  287. package/dist/integrations/jira/stories.js +12 -12
  288. package/dist/integrations/jira/stories.js.map +1 -1
  289. package/dist/integrations/jira/stories.test.js +10 -8
  290. package/dist/integrations/jira/stories.test.js.map +1 -1
  291. package/dist/integrations/jira/sync.d.ts +7 -7
  292. package/dist/integrations/jira/sync.d.ts.map +1 -1
  293. package/dist/integrations/jira/sync.js +17 -20
  294. package/dist/integrations/jira/sync.js.map +1 -1
  295. package/dist/integrations/jira/sync.test.js +63 -62
  296. package/dist/integrations/jira/sync.test.js.map +1 -1
  297. package/dist/integrations/jira/transitions.d.ts +3 -3
  298. package/dist/integrations/jira/transitions.d.ts.map +1 -1
  299. package/dist/integrations/jira/transitions.js +3 -3
  300. package/dist/integrations/jira/transitions.js.map +1 -1
  301. package/dist/orchestrator/agent-selector.d.ts +3 -3
  302. package/dist/orchestrator/agent-selector.d.ts.map +1 -1
  303. package/dist/orchestrator/agent-selector.js +5 -6
  304. package/dist/orchestrator/agent-selector.js.map +1 -1
  305. package/dist/orchestrator/dependency-resolver.d.ts +4 -4
  306. package/dist/orchestrator/dependency-resolver.d.ts.map +1 -1
  307. package/dist/orchestrator/dependency-resolver.js +6 -6
  308. package/dist/orchestrator/dependency-resolver.js.map +1 -1
  309. package/dist/orchestrator/feature-branch.d.ts +3 -3
  310. package/dist/orchestrator/feature-branch.d.ts.map +1 -1
  311. package/dist/orchestrator/feature-branch.js +9 -10
  312. package/dist/orchestrator/feature-branch.js.map +1 -1
  313. package/dist/orchestrator/feature-branch.test.js +80 -78
  314. package/dist/orchestrator/feature-branch.test.js.map +1 -1
  315. package/dist/orchestrator/orphan-recovery.d.ts +2 -2
  316. package/dist/orchestrator/orphan-recovery.d.ts.map +1 -1
  317. package/dist/orchestrator/orphan-recovery.js +10 -10
  318. package/dist/orchestrator/orphan-recovery.js.map +1 -1
  319. package/dist/orchestrator/scheduler.d.ts +4 -4
  320. package/dist/orchestrator/scheduler.d.ts.map +1 -1
  321. package/dist/orchestrator/scheduler.js +90 -76
  322. package/dist/orchestrator/scheduler.js.map +1 -1
  323. package/dist/orchestrator/scheduler.test.js +496 -374
  324. package/dist/orchestrator/scheduler.test.js.map +1 -1
  325. package/dist/utils/auto-merge.d.ts.map +1 -1
  326. package/dist/utils/auto-merge.js +74 -56
  327. package/dist/utils/auto-merge.js.map +1 -1
  328. package/dist/utils/auto-merge.test.js +101 -66
  329. package/dist/utils/auto-merge.test.js.map +1 -1
  330. package/dist/utils/cli-helpers.d.ts +5 -5
  331. package/dist/utils/cli-helpers.d.ts.map +1 -1
  332. package/dist/utils/cli-helpers.js +8 -9
  333. package/dist/utils/cli-helpers.js.map +1 -1
  334. package/dist/utils/cli-helpers.test.js +28 -30
  335. package/dist/utils/cli-helpers.test.js.map +1 -1
  336. package/dist/utils/paths.d.ts +6 -0
  337. package/dist/utils/paths.d.ts.map +1 -1
  338. package/dist/utils/paths.js +12 -1
  339. package/dist/utils/paths.js.map +1 -1
  340. package/dist/utils/paths.test.js +1 -0
  341. package/dist/utils/paths.test.js.map +1 -1
  342. package/dist/utils/pr-sync.d.ts +10 -10
  343. package/dist/utils/pr-sync.d.ts.map +1 -1
  344. package/dist/utils/pr-sync.js +20 -21
  345. package/dist/utils/pr-sync.js.map +1 -1
  346. package/dist/utils/pr-sync.test.js +52 -50
  347. package/dist/utils/pr-sync.test.js.map +1 -1
  348. package/dist/utils/with-hive-context.d.ts.map +1 -1
  349. package/dist/utils/with-hive-context.js +70 -1
  350. package/dist/utils/with-hive-context.js.map +1 -1
  351. package/package.json +3 -1
  352. package/src/agents/base-agent.test.ts +2 -1
  353. package/src/agents/base-agent.ts +32 -28
  354. package/src/agents/intermediate.ts +27 -18
  355. package/src/agents/junior.ts +27 -18
  356. package/src/agents/qa.ts +54 -40
  357. package/src/agents/senior.ts +42 -27
  358. package/src/agents/tech-lead.ts +42 -32
  359. package/src/cli/commands/add-repo.test.ts +1 -1
  360. package/src/cli/commands/add-repo.ts +2 -2
  361. package/src/cli/commands/agents.test.ts +7 -7
  362. package/src/cli/commands/agents.ts +12 -10
  363. package/src/cli/commands/approach.ts +2 -2
  364. package/src/cli/commands/approvals.test.ts +8 -8
  365. package/src/cli/commands/approvals.ts +9 -7
  366. package/src/cli/commands/assign.test.ts +19 -18
  367. package/src/cli/commands/assign.ts +4 -4
  368. package/src/cli/commands/cleanup.test.ts +5 -1
  369. package/src/cli/commands/cleanup.ts +11 -9
  370. package/src/cli/commands/escalations.test.ts +2 -2
  371. package/src/cli/commands/escalations.ts +9 -7
  372. package/src/cli/commands/init.test.ts +5 -0
  373. package/src/cli/commands/init.ts +53 -5
  374. package/src/cli/commands/manager/agent-monitoring.ts +3 -3
  375. package/src/cli/commands/manager/auditor-lifecycle.test.ts +21 -14
  376. package/src/cli/commands/manager/auditor-lifecycle.ts +3 -3
  377. package/src/cli/commands/manager/auto-reject-comment-only-reviews.test.ts +28 -23
  378. package/src/cli/commands/manager/escalation-handler.test.ts +13 -13
  379. package/src/cli/commands/manager/escalation-handler.ts +19 -12
  380. package/src/cli/commands/manager/feature-sign-off.test.ts +40 -31
  381. package/src/cli/commands/manager/feature-sign-off.ts +7 -7
  382. package/src/cli/commands/manager/feature-test-result.ts +13 -16
  383. package/src/cli/commands/manager/handoff-recovery.ts +20 -20
  384. package/src/cli/commands/manager/index.test.ts +4 -4
  385. package/src/cli/commands/manager/index.ts +58 -59
  386. package/src/cli/commands/manager/merged-story-cleanup.test.ts +28 -19
  387. package/src/cli/commands/manager/merged-story-cleanup.ts +11 -14
  388. package/src/cli/commands/manager/pr-sync-orchestrator.ts +115 -110
  389. package/src/cli/commands/manager/qa-review-handler.ts +50 -63
  390. package/src/cli/commands/manager/spin-down.ts +27 -25
  391. package/src/cli/commands/manager/stale-escalations.ts +2 -3
  392. package/src/cli/commands/manager/stuck-story-helpers.ts +10 -10
  393. package/src/cli/commands/manager/stuck-story-processor.ts +56 -62
  394. package/src/cli/commands/manager/tech-lead-lifecycle.ts +6 -6
  395. package/src/cli/commands/manager/types.ts +2 -3
  396. package/src/cli/commands/msg.test.ts +2 -2
  397. package/src/cli/commands/my-stories.test.ts +4 -2
  398. package/src/cli/commands/my-stories.ts +22 -27
  399. package/src/cli/commands/nuke.test.ts +1 -1
  400. package/src/cli/commands/pr.test.ts +10 -6
  401. package/src/cli/commands/pr.ts +41 -32
  402. package/src/cli/commands/progress.test.ts +1 -1
  403. package/src/cli/commands/progress.ts +11 -6
  404. package/src/cli/commands/req-headless.test.ts +170 -0
  405. package/src/cli/commands/req-spawn.test.ts +12 -2
  406. package/src/cli/commands/req.ts +13 -14
  407. package/src/cli/commands/resume.test.ts +1 -1
  408. package/src/cli/commands/resume.ts +7 -8
  409. package/src/cli/commands/status.test.ts +1 -1
  410. package/src/cli/commands/status.ts +52 -40
  411. package/src/cli/commands/stories.test.ts +4 -2
  412. package/src/cli/commands/stories.ts +11 -11
  413. package/src/cli/commands/teams.test.ts +2 -2
  414. package/src/cli/commands/teams.ts +11 -11
  415. package/src/cli/dashboard/index.test.ts +35 -34
  416. package/src/cli/dashboard/index.ts +34 -23
  417. package/src/cli/dashboard/panels/activity.ts +10 -4
  418. package/src/cli/dashboard/panels/agents.ts +8 -5
  419. package/src/cli/dashboard/panels/escalations.ts +4 -4
  420. package/src/cli/dashboard/panels/merge-queue.ts +4 -4
  421. package/src/cli/dashboard/panels/pipeline.ts +10 -4
  422. package/src/config/schema.ts +1 -0
  423. package/src/connectors/project-management/operations.ts +9 -10
  424. package/src/context-files/index.test.ts +1 -0
  425. package/src/db/client.ts +17 -0
  426. package/src/db/pg-migrations/001-full-schema.sql +209 -0
  427. package/src/db/postgres-provider.integration.test.ts +574 -0
  428. package/src/db/postgres-provider.test.ts +97 -0
  429. package/src/db/postgres-provider.ts +364 -0
  430. package/src/db/provider.test.ts +283 -0
  431. package/src/db/provider.ts +161 -0
  432. package/src/db/queries/agents.test.ts +114 -113
  433. package/src/db/queries/agents.ts +50 -36
  434. package/src/db/queries/escalations.test.ts +134 -133
  435. package/src/db/queries/escalations.ts +72 -57
  436. package/src/db/queries/heartbeat.test.ts +77 -78
  437. package/src/db/queries/heartbeat.ts +24 -46
  438. package/src/db/queries/integration-sync.ts +26 -26
  439. package/src/db/queries/logs.test.ts +151 -148
  440. package/src/db/queries/logs.ts +78 -53
  441. package/src/db/queries/messages.test.ts +48 -50
  442. package/src/db/queries/messages.ts +26 -18
  443. package/src/db/queries/pull-requests.test.ts +194 -199
  444. package/src/db/queries/pull-requests.ts +117 -88
  445. package/src/db/queries/requirements.test.ts +84 -83
  446. package/src/db/queries/requirements.ts +33 -28
  447. package/src/db/queries/stories.test.ts +173 -172
  448. package/src/db/queries/stories.ts +141 -110
  449. package/src/db/queries/teams.test.ts +37 -36
  450. package/src/db/queries/teams.ts +22 -14
  451. package/src/integrations/jira/repair.test.ts +27 -26
  452. package/src/integrations/jira/stories.test.ts +15 -16
  453. package/src/integrations/jira/stories.ts +15 -15
  454. package/src/integrations/jira/sync.test.ts +68 -68
  455. package/src/integrations/jira/sync.ts +29 -39
  456. package/src/integrations/jira/transitions.ts +6 -6
  457. package/src/orchestrator/agent-selector.ts +9 -8
  458. package/src/orchestrator/dependency-resolver.ts +16 -7
  459. package/src/orchestrator/feature-branch.test.ts +85 -80
  460. package/src/orchestrator/feature-branch.ts +13 -14
  461. package/src/orchestrator/orphan-recovery.ts +14 -13
  462. package/src/orchestrator/scheduler.test.ts +536 -394
  463. package/src/orchestrator/scheduler.ts +129 -115
  464. package/src/utils/auto-merge.test.ts +102 -68
  465. package/src/utils/auto-merge.ts +161 -168
  466. package/src/utils/cli-helpers.test.ts +30 -32
  467. package/src/utils/cli-helpers.ts +15 -11
  468. package/src/utils/paths.test.ts +1 -0
  469. package/src/utils/paths.ts +14 -1
  470. package/src/utils/pr-sync.test.ts +55 -52
  471. package/src/utils/pr-sync.ts +27 -32
  472. package/src/utils/with-hive-context.ts +89 -1
@@ -1,6 +1,6 @@
1
1
  // Licensed under the Hungry Ghost Hive License. See LICENSE.
2
2
 
3
- import { existsSync } from 'fs';
3
+ import { existsSync, readFileSync } from 'fs';
4
4
  import { join, resolve } from 'path';
5
5
 
6
6
  export const HIVE_DIR_NAME = '.hive';
@@ -14,6 +14,7 @@ export interface HivePaths {
14
14
  hiveDir: string;
15
15
  dbPath: string;
16
16
  configPath: string;
17
+ workspaceIdPath: string;
17
18
  agentsDir: string;
18
19
  logsDir: string;
19
20
  reposDir: string;
@@ -42,6 +43,7 @@ export function getHivePaths(rootDir: string): HivePaths {
42
43
  hiveDir,
43
44
  dbPath: join(hiveDir, 'hive.db'),
44
45
  configPath: join(hiveDir, 'hive.config.yaml'),
46
+ workspaceIdPath: join(hiveDir, 'workspace.id'),
45
47
  agentsDir: join(hiveDir, AGENTS_DIR_NAME),
46
48
  logsDir: join(hiveDir, LOGS_DIR_NAME),
47
49
  reposDir: join(rootDir, REPOS_DIR_NAME),
@@ -52,3 +54,14 @@ export function getHivePaths(rootDir: string): HivePaths {
52
54
  export function isHiveWorkspace(dir: string): boolean {
53
55
  return existsSync(join(dir, HIVE_DIR_NAME));
54
56
  }
57
+
58
+ /**
59
+ * Read the workspace ID from .hive/workspace.id.
60
+ * Returns null if the file does not exist (non-distributed mode).
61
+ */
62
+ export function getWorkspaceId(paths: HivePaths): string | null {
63
+ if (!existsSync(paths.workspaceIdPath)) {
64
+ return null;
65
+ }
66
+ return readFileSync(paths.workspaceIdPath, 'utf-8').trim();
67
+ }
@@ -1,7 +1,7 @@
1
1
  // Licensed under the Hungry Ghost Hive License. See LICENSE.
2
2
 
3
- import type { Database } from 'sql.js';
4
3
  import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+ import { SqliteProvider } from '../db/provider.js';
5
5
  import { createPullRequest } from '../db/queries/pull-requests.js';
6
6
  import { createTestDatabase } from '../db/queries/test-helpers.js';
7
7
  import { closeStaleGitHubPRs, getExistingPRIdentifiers, syncOpenGitHubPRs } from './pr-sync.js';
@@ -14,64 +14,65 @@ import { execa } from 'execa';
14
14
 
15
15
  const mockExeca = vi.mocked(execa);
16
16
 
17
- let db: Database;
17
+ let db: SqliteProvider;
18
18
 
19
19
  beforeEach(async () => {
20
20
  vi.clearAllMocks();
21
- db = await createTestDatabase();
21
+ const rawDb = await createTestDatabase();
22
+ db = new SqliteProvider(rawDb);
22
23
  // Create a 'manager' agent for logging (required by foreign key constraint)
23
- db.run("INSERT INTO agents (id, type, status) VALUES ('manager', 'tech_lead', 'idle')");
24
+ db.db.run("INSERT INTO agents (id, type, status) VALUES ('manager', 'tech_lead', 'idle')");
24
25
  });
25
26
 
26
27
  describe('getExistingPRIdentifiers', () => {
27
- it('should return empty sets when no PRs exist', () => {
28
- const { existingBranches, existingPrNumbers } = getExistingPRIdentifiers(db);
28
+ it('should return empty sets when no PRs exist', async () => {
29
+ const { existingBranches, existingPrNumbers } = await getExistingPRIdentifiers(db);
29
30
 
30
31
  expect(existingBranches.size).toBe(0);
31
32
  expect(existingPrNumbers.size).toBe(0);
32
33
  });
33
34
 
34
- it('should include all branch names when includeTerminalBranches is true', () => {
35
- createPullRequest(db, { branchName: 'feature/open', githubPrNumber: 1 });
36
- const mergedPR = createPullRequest(db, {
35
+ it('should include all branch names when includeTerminalBranches is true', async () => {
36
+ await createPullRequest(db, { branchName: 'feature/open', githubPrNumber: 1 });
37
+ const mergedPR = await createPullRequest(db, {
37
38
  branchName: 'feature/merged',
38
39
  githubPrNumber: 2,
39
40
  });
40
41
  // Manually set status to merged
41
- db.run("UPDATE pull_requests SET status = 'merged' WHERE id = ?", [mergedPR.id]);
42
+ db.db.run("UPDATE pull_requests SET status = 'merged' WHERE id = ?", [mergedPR.id]);
42
43
 
43
- const { existingBranches } = getExistingPRIdentifiers(db, true);
44
+ const { existingBranches } = await getExistingPRIdentifiers(db, true);
44
45
 
45
46
  expect(existingBranches.has('feature/open')).toBe(true);
46
47
  expect(existingBranches.has('feature/merged')).toBe(true);
47
48
  });
48
49
 
49
- it('should exclude terminal branch names when includeTerminalBranches is false', () => {
50
- createPullRequest(db, { branchName: 'feature/open', githubPrNumber: 1 });
51
- const mergedPR = createPullRequest(db, {
50
+ it('should exclude terminal branch names when includeTerminalBranches is false', async () => {
51
+ await createPullRequest(db, { branchName: 'feature/open', githubPrNumber: 1 });
52
+ const mergedPR = await createPullRequest(db, {
52
53
  branchName: 'feature/merged',
53
54
  githubPrNumber: 2,
54
55
  });
55
- const closedPR = createPullRequest(db, {
56
+ const closedPR = await createPullRequest(db, {
56
57
  branchName: 'feature/closed',
57
58
  githubPrNumber: 3,
58
59
  });
59
- db.run("UPDATE pull_requests SET status = 'merged' WHERE id = ?", [mergedPR.id]);
60
- db.run("UPDATE pull_requests SET status = 'closed' WHERE id = ?", [closedPR.id]);
60
+ db.db.run("UPDATE pull_requests SET status = 'merged' WHERE id = ?", [mergedPR.id]);
61
+ db.db.run("UPDATE pull_requests SET status = 'closed' WHERE id = ?", [closedPR.id]);
61
62
 
62
- const { existingBranches } = getExistingPRIdentifiers(db, false);
63
+ const { existingBranches } = await getExistingPRIdentifiers(db, false);
63
64
 
64
65
  expect(existingBranches.has('feature/open')).toBe(true);
65
66
  expect(existingBranches.has('feature/merged')).toBe(false);
66
67
  expect(existingBranches.has('feature/closed')).toBe(false);
67
68
  });
68
69
 
69
- it('should collect PR numbers and filter out nulls', () => {
70
- createPullRequest(db, { branchName: 'feature/a', githubPrNumber: 42 });
71
- createPullRequest(db, { branchName: 'feature/b', githubPrNumber: null });
72
- createPullRequest(db, { branchName: 'feature/c', githubPrNumber: 99 });
70
+ it('should collect PR numbers and filter out nulls', async () => {
71
+ await createPullRequest(db, { branchName: 'feature/a', githubPrNumber: 42 });
72
+ await createPullRequest(db, { branchName: 'feature/b', githubPrNumber: null });
73
+ await createPullRequest(db, { branchName: 'feature/c', githubPrNumber: 99 });
73
74
 
74
- const { existingPrNumbers } = getExistingPRIdentifiers(db);
75
+ const { existingPrNumbers } = await getExistingPRIdentifiers(db);
75
76
 
76
77
  expect(existingPrNumbers.has(42)).toBe(true);
77
78
  expect(existingPrNumbers.has(99)).toBe(true);
@@ -200,7 +201,7 @@ describe('syncOpenGitHubPRs', () => {
200
201
  expect(existingBranches.has('feature/shared')).toBe(true);
201
202
  expect(existingPrNumbers.has(10)).toBe(true);
202
203
 
203
- const countResult = db.exec('SELECT COUNT(*) as count FROM pull_requests');
204
+ const countResult = db.db.exec('SELECT COUNT(*) as count FROM pull_requests');
204
205
  expect(countResult[0].values[0][0]).toBe(1);
205
206
  });
206
207
 
@@ -238,7 +239,7 @@ describe('syncOpenGitHubPRs', () => {
238
239
  } as any);
239
240
 
240
241
  // Create a team so foreign key is satisfied
241
- db.run(
242
+ db.db.run(
242
243
  "INSERT INTO teams (id, repo_url, repo_path, name) VALUES ('team-1', 'https://test', 'repo', 'Test')"
243
244
  );
244
245
 
@@ -246,13 +247,13 @@ describe('syncOpenGitHubPRs', () => {
246
247
 
247
248
  expect(result.synced).toBe(1);
248
249
  // Verify the PR was created with the team ID
249
- const prs = db.exec('SELECT team_id FROM pull_requests');
250
+ const prs = db.db.exec('SELECT team_id FROM pull_requests');
250
251
  expect(prs[0].values[0][0]).toBe('team-1');
251
252
  });
252
253
 
253
254
  it('should extract story IDs from branch names that match the story ID pattern', async () => {
254
255
  // Create a story so the FK constraint is satisfied
255
- db.run(
256
+ db.db.run(
256
257
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-GOD-001', 'Test', 'Test', 'planned')"
257
258
  );
258
259
 
@@ -270,7 +271,7 @@ describe('syncOpenGitHubPRs', () => {
270
271
 
271
272
  await syncOpenGitHubPRs(db, '/repo', null, new Set(), new Set());
272
273
 
273
- const prs = db.exec('SELECT story_id FROM pull_requests');
274
+ const prs = db.db.exec('SELECT story_id FROM pull_requests');
274
275
  expect(prs[0].values[0][0]).toBe('STORY-GOD-001');
275
276
  });
276
277
 
@@ -293,7 +294,7 @@ describe('syncOpenGitHubPRs', () => {
293
294
  expect(result.imported).toHaveLength(1);
294
295
 
295
296
  // Verify the PR was created with null story_id
296
- const prs = db.exec('SELECT story_id FROM pull_requests');
297
+ const prs = db.db.exec('SELECT story_id FROM pull_requests');
297
298
  expect(prs[0].values[0][0]).toBeNull();
298
299
  });
299
300
 
@@ -318,7 +319,7 @@ describe('syncOpenGitHubPRs', () => {
318
319
 
319
320
  it('should skip PRs where story status is merged', async () => {
320
321
  // Create a merged story
321
- db.run(
322
+ db.db.run(
322
323
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-MERGED-001', 'Merged Story', 'Test', 'merged')"
323
324
  );
324
325
 
@@ -342,7 +343,7 @@ describe('syncOpenGitHubPRs', () => {
342
343
 
343
344
  it('should import PRs with active (non-merged) stories', async () => {
344
345
  // Create an active story
345
- db.run(
346
+ db.db.run(
346
347
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-ACTIVE-001', 'Active Story', 'Test', 'in_progress')"
347
348
  );
348
349
 
@@ -367,10 +368,10 @@ describe('syncOpenGitHubPRs', () => {
367
368
 
368
369
  it('should filter mixed PRs - import active stories and PRs without story IDs', async () => {
369
370
  // Create stories with different statuses
370
- db.run(
371
+ db.db.run(
371
372
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-ACTIVE-001', 'Active', 'Test', 'planned')"
372
373
  );
373
- db.run(
374
+ db.db.run(
374
375
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-MERGED-001', 'Merged', 'Test', 'merged')"
375
376
  );
376
377
 
@@ -491,7 +492,7 @@ describe('syncOpenGitHubPRs', () => {
491
492
  await syncOpenGitHubPRs(db, '/repo', null, new Set(), new Set(), null, maxAgeHours);
492
493
 
493
494
  // Check that a log entry was created
494
- const logs = db.exec("SELECT * FROM agent_logs WHERE event_type = 'PR_SYNC_SKIPPED'");
495
+ const logs = db.db.exec("SELECT * FROM agent_logs WHERE event_type = 'PR_SYNC_SKIPPED'");
495
496
  expect(logs.length).toBeGreaterThan(0);
496
497
  expect(logs[0].values.length).toBeGreaterThan(0);
497
498
  });
@@ -512,7 +513,7 @@ describe('syncOpenGitHubPRs', () => {
512
513
  await syncOpenGitHubPRs(db, '/repo', null, new Set(), new Set());
513
514
 
514
515
  // Check that a log entry was created
515
- const logs = db.exec("SELECT * FROM agent_logs WHERE event_type = 'PR_SYNC_SKIPPED'");
516
+ const logs = db.db.exec("SELECT * FROM agent_logs WHERE event_type = 'PR_SYNC_SKIPPED'");
516
517
  expect(logs.length).toBeGreaterThan(0);
517
518
  expect(logs[0].values.length).toBeGreaterThan(0);
518
519
  });
@@ -521,14 +522,14 @@ describe('syncOpenGitHubPRs', () => {
521
522
  describe('closeStaleGitHubPRs', () => {
522
523
  beforeEach(() => {
523
524
  // Insert a team so the function can iterate teams
524
- db.run(
525
+ db.db.run(
525
526
  "INSERT INTO teams (id, repo_url, repo_path, name) VALUES ('team-1', 'https://github.com/test/repo', 'repos/test', 'Test')"
526
527
  );
527
528
  });
528
529
 
529
530
  it('should return empty array when no teams exist', async () => {
530
531
  // Remove the team inserted in beforeEach
531
- db.run("DELETE FROM teams WHERE id = 'team-1'");
532
+ db.db.run("DELETE FROM teams WHERE id = 'team-1'");
532
533
 
533
534
  const result = await closeStaleGitHubPRs('/root', db);
534
535
 
@@ -564,10 +565,10 @@ describe('closeStaleGitHubPRs', () => {
564
565
  });
565
566
 
566
567
  it('should skip a GitHub PR that is already in the queue', async () => {
567
- db.run(
568
+ db.db.run(
568
569
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-001', 'Test', 'Test', 'in_progress')"
569
570
  );
570
- const pr = createPullRequest(db, {
571
+ const pr = await createPullRequest(db, {
571
572
  storyId: 'STORY-TST-001',
572
573
  branchName: 'feature/STORY-TST-001-work',
573
574
  githubPrNumber: 10,
@@ -598,11 +599,11 @@ describe('closeStaleGitHubPRs', () => {
598
599
  });
599
600
 
600
601
  it('should close a stale GitHub PR and return ClosedPRInfo', async () => {
601
- db.run(
602
+ db.db.run(
602
603
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-002', 'Test', 'Test', 'in_progress')"
603
604
  );
604
605
  // Queue PR has github_pr_number 20 (the newer one)
605
- createPullRequest(db, {
606
+ await createPullRequest(db, {
606
607
  storyId: 'STORY-TST-002',
607
608
  branchName: 'feature/STORY-TST-002-v2',
608
609
  githubPrNumber: 20,
@@ -634,10 +635,10 @@ describe('closeStaleGitHubPRs', () => {
634
635
  });
635
636
 
636
637
  it('should include superseding PR number in the log message', async () => {
637
- db.run(
638
+ db.db.run(
638
639
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-003', 'Test', 'Test', 'in_progress')"
639
640
  );
640
- createPullRequest(db, {
641
+ await createPullRequest(db, {
641
642
  storyId: 'STORY-TST-003',
642
643
  branchName: 'feature/STORY-TST-003-v2',
643
644
  githubPrNumber: 30,
@@ -660,7 +661,9 @@ describe('closeStaleGitHubPRs', () => {
660
661
 
661
662
  await closeStaleGitHubPRs('/root', db);
662
663
 
663
- const logs = db.exec("SELECT message, metadata FROM agent_logs WHERE event_type = 'PR_CLOSED'");
664
+ const logs = db.db.exec(
665
+ "SELECT message, metadata FROM agent_logs WHERE event_type = 'PR_CLOSED'"
666
+ );
664
667
  expect(logs.length).toBeGreaterThan(0);
665
668
  const message = logs[0].values[0][0] as string;
666
669
  expect(message).toContain('#15');
@@ -671,10 +674,10 @@ describe('closeStaleGitHubPRs', () => {
671
674
  });
672
675
 
673
676
  it('should not close if gh CLI throws and should not include in result', async () => {
674
- db.run(
677
+ db.db.run(
675
678
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-004', 'Test', 'Test', 'in_progress')"
676
679
  );
677
- createPullRequest(db, {
680
+ await createPullRequest(db, {
678
681
  storyId: 'STORY-TST-004',
679
682
  branchName: 'feature/STORY-TST-004-v2',
680
683
  githubPrNumber: 40,
@@ -702,10 +705,10 @@ describe('closeStaleGitHubPRs', () => {
702
705
  });
703
706
 
704
707
  it('should skip PRs not targeting the configured base branch', async () => {
705
- db.run(
708
+ db.db.run(
706
709
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-005', 'Test', 'Test', 'in_progress')"
707
710
  );
708
- createPullRequest(db, {
711
+ await createPullRequest(db, {
709
712
  storyId: 'STORY-TST-005',
710
713
  branchName: 'feature/STORY-TST-005-v2',
711
714
  githubPrNumber: 50,
@@ -736,10 +739,10 @@ describe('closeStaleGitHubPRs', () => {
736
739
  });
737
740
 
738
741
  it('should only close PRs targeting the configured base branch when it is non-main', async () => {
739
- db.run(
742
+ db.db.run(
740
743
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-006', 'Test', 'Test', 'in_progress')"
741
744
  );
742
- createPullRequest(db, {
745
+ await createPullRequest(db, {
743
746
  storyId: 'STORY-TST-006',
744
747
  branchName: 'feature/STORY-TST-006-v2',
745
748
  githubPrNumber: 60,
@@ -768,10 +771,10 @@ describe('closeStaleGitHubPRs', () => {
768
771
  });
769
772
 
770
773
  it('should not close PRs targeting main when configured base branch is feat/memento-refactor', async () => {
771
- db.run(
774
+ db.db.run(
772
775
  "INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-007', 'Test', 'Test', 'in_progress')"
773
776
  );
774
- createPullRequest(db, {
777
+ await createPullRequest(db, {
775
778
  storyId: 'STORY-TST-007',
776
779
  branchName: 'feature/STORY-TST-007-v2',
777
780
  githubPrNumber: 70,
@@ -1,9 +1,8 @@
1
1
  // Licensed under the Hungry Ghost Hive License. See LICENSE.
2
2
 
3
3
  import { execa } from 'execa';
4
- import type { Database } from 'sql.js';
5
4
  import { syncStatusForStory } from '../connectors/project-management/operations.js';
6
- import { queryAll, withTransaction } from '../db/client.js';
5
+ import type { DatabaseProvider } from '../db/provider.js';
7
6
  import { createLog } from '../db/queries/logs.js';
8
7
  import { createPullRequest } from '../db/queries/pull-requests.js';
9
8
  import { updateStory } from '../db/queries/stories.js';
@@ -53,23 +52,22 @@ interface ExistingPRNumberRow {
53
52
  /**
54
53
  * Build sets of existing branch names and PR numbers from the database.
55
54
  *
56
- * @param db - sql.js Database instance
55
+ * @param db - DatabaseProvider instance
57
56
  * @param includeTerminalBranches - If true, include merged/closed PR branches
58
57
  * in the returned set (prevents re-importing previously synced PRs).
59
58
  * Defaults to true.
60
59
  */
61
- export function getExistingPRIdentifiers(
62
- db: Database,
60
+ export async function getExistingPRIdentifiers(
61
+ db: DatabaseProvider,
63
62
  includeTerminalBranches = true
64
- ): { existingBranches: Set<string>; existingPrNumbers: Set<number> } {
63
+ ): Promise<{ existingBranches: Set<string>; existingPrNumbers: Set<number> }> {
65
64
  const branchQuery = includeTerminalBranches
66
65
  ? 'SELECT branch_name FROM pull_requests'
67
66
  : "SELECT branch_name FROM pull_requests WHERE status NOT IN ('merged', 'closed')";
68
- const branchRows = queryAll<ExistingPRBranchRow>(db, branchQuery);
67
+ const branchRows = await db.queryAll<ExistingPRBranchRow>(branchQuery);
69
68
  const existingBranches = new Set(branchRows.map(row => row.branch_name));
70
69
 
71
- const numberRows = queryAll<ExistingPRNumberRow>(
72
- db,
70
+ const numberRows = await db.queryAll<ExistingPRNumberRow>(
73
71
  `
74
72
  SELECT DISTINCT github_pr_number
75
73
  FROM pull_requests
@@ -111,7 +109,7 @@ export async function fetchOpenGitHubPRs(
111
109
  * - PRs with story IDs are only imported if the story exists and is not merged
112
110
  * - PRs older than maxAgeHours are skipped (age-based filtering)
113
111
  *
114
- * @param db - sql.js Database instance
112
+ * @param db - DatabaseProvider instance
115
113
  * @param repoDir - Absolute path to the git repository
116
114
  * @param teamId - Team ID to associate with created PRs (null for CLI usage)
117
115
  * @param existingBranches - Set of branch names already in the queue
@@ -120,7 +118,7 @@ export async function fetchOpenGitHubPRs(
120
118
  * @param maxAgeHours - Optional max age in hours for PRs (default: no limit)
121
119
  */
122
120
  export async function syncOpenGitHubPRs(
123
- db: Database,
121
+ db: DatabaseProvider,
124
122
  repoDir: string,
125
123
  teamId: string | null,
126
124
  existingBranches: Set<string>,
@@ -142,7 +140,7 @@ export async function syncOpenGitHubPRs(
142
140
  const ageHours = (Date.now() - prCreatedAt.getTime()) / (1000 * 60 * 60);
143
141
 
144
142
  if (ageHours > maxAgeHours) {
145
- createLog(db, {
143
+ await createLog(db, {
146
144
  agentId: 'manager',
147
145
  eventType: 'PR_SYNC_SKIPPED',
148
146
  status: 'info',
@@ -164,15 +162,14 @@ export async function syncOpenGitHubPRs(
164
162
  // If the PR has a story ID, check if the story is active
165
163
  if (storyId) {
166
164
  // Check if the story exists and is active (not merged)
167
- const storyRows = queryAll<{ id: string; status: string }>(
168
- db,
165
+ const storyRows = await db.queryAll<{ id: string; status: string }>(
169
166
  `SELECT id, status FROM stories WHERE id = ? COLLATE NOCASE AND status != 'merged'`,
170
167
  [storyId]
171
168
  );
172
169
 
173
170
  // Skip PRs where story doesn't exist or is merged
174
171
  if (storyRows.length === 0) {
175
- createLog(db, {
172
+ await createLog(db, {
176
173
  agentId: 'manager',
177
174
  eventType: 'PR_SYNC_SKIPPED',
178
175
  status: 'info',
@@ -188,7 +185,7 @@ export async function syncOpenGitHubPRs(
188
185
  }
189
186
  }
190
187
 
191
- const pr = createPullRequest(db, {
188
+ const pr = await createPullRequest(db, {
192
189
  storyId,
193
190
  teamId,
194
191
  branchName: ghPR.headRefName,
@@ -222,14 +219,14 @@ export async function syncOpenGitHubPRs(
222
219
  */
223
220
  export async function syncAllTeamOpenPRs(
224
221
  root: string,
225
- db: Database,
222
+ db: DatabaseProvider,
226
223
  saveFn: () => void,
227
224
  maxAgeHours?: number
228
225
  ): Promise<number> {
229
- const teams = getAllTeams(db);
226
+ const teams = await getAllTeams(db);
230
227
  if (teams.length === 0) return 0;
231
228
 
232
- const { existingBranches, existingPrNumbers } = getExistingPRIdentifiers(db, true);
229
+ const { existingBranches, existingPrNumbers } = await getExistingPRIdentifiers(db, true);
233
230
  let totalSynced = 0;
234
231
 
235
232
  for (const team of teams) {
@@ -265,10 +262,10 @@ export async function syncAllTeamOpenPRs(
265
262
  */
266
263
  export async function syncMergedPRsFromGitHub(
267
264
  root: string,
268
- db: Database,
265
+ db: DatabaseProvider,
269
266
  saveFn: () => void
270
267
  ): Promise<number> {
271
- const teams = getAllTeams(db);
268
+ const teams = await getAllTeams(db);
272
269
  if (teams.length === 0) return 0;
273
270
 
274
271
  let storiesUpdated = 0;
@@ -308,8 +305,7 @@ export async function syncMergedPRsFromGitHub(
308
305
  }
309
306
 
310
307
  const placeholders = candidateStoryIds.map(() => '?').join(',');
311
- const updatableStories = queryAll<{ id: string }>(
312
- db,
308
+ const updatableStories = await db.queryAll<{ id: string }>(
313
309
  `
314
310
  SELECT id
315
311
  FROM stories
@@ -333,10 +329,10 @@ export async function syncMergedPRsFromGitHub(
333
329
  continue;
334
330
  }
335
331
 
336
- await withTransaction(db, () => {
332
+ await db.withTransaction(async () => {
337
333
  for (const update of toUpdate) {
338
- updateStory(db, update.storyId, { status: 'merged', assignedAgentId: null });
339
- createLog(db, {
334
+ await updateStory(db, update.storyId, { status: 'merged', assignedAgentId: null });
335
+ await createLog(db, {
340
336
  agentId: 'manager',
341
337
  storyId: update.storyId,
342
338
  eventType: 'STORY_MERGED',
@@ -378,15 +374,15 @@ export interface ClosedPRInfo {
378
374
  * in the hive merge queue (i.e., the GitHub PR is stale/orphaned).
379
375
  *
380
376
  * @param root - Root directory
381
- * @param db - sql.js Database instance
377
+ * @param db - DatabaseProvider instance
382
378
  * @returns Array of ClosedPRInfo for each PR that was closed.
383
379
  */
384
380
  export async function closeStaleGitHubPRs(
385
381
  root: string,
386
- db: Database,
382
+ db: DatabaseProvider,
387
383
  baseBranch = 'main'
388
384
  ): Promise<ClosedPRInfo[]> {
389
- const teams = getAllTeams(db);
385
+ const teams = await getAllTeams(db);
390
386
  if (teams.length === 0) return [];
391
387
 
392
388
  const closed: ClosedPRInfo[] = [];
@@ -408,8 +404,7 @@ export async function closeStaleGitHubPRs(
408
404
  if (!storyId) continue;
409
405
 
410
406
  // Check if there are other PRs for this story in the queue
411
- const prsForStory = queryAll<{ id: string; github_pr_number: number | null }>(
412
- db,
407
+ const prsForStory = await db.queryAll<{ id: string; github_pr_number: number | null }>(
413
408
  `
414
409
  SELECT id, github_pr_number
415
410
  FROM pull_requests
@@ -444,7 +439,7 @@ export async function closeStaleGitHubPRs(
444
439
  cwd: repoDir,
445
440
  timeout: GH_CLI_TIMEOUT_MS,
446
441
  });
447
- createLog(db, {
442
+ await createLog(db, {
448
443
  agentId: 'manager',
449
444
  storyId,
450
445
  eventType: 'PR_CLOSED',
@@ -2,6 +2,7 @@
2
2
 
3
3
  import chalk from 'chalk';
4
4
  import { join } from 'path';
5
+ import { loadConfig } from '../config/loader.js';
5
6
  import {
6
7
  getDatabase,
7
8
  getReadOnlyDatabase,
@@ -9,7 +10,8 @@ import {
9
10
  type ReadOnlyDatabaseClient,
10
11
  } from '../db/client.js';
11
12
  import { acquireLock } from '../db/lock.js';
12
- import { findHiveRoot, getHivePaths, type HivePaths } from './paths.js';
13
+ import { createPostgresProvider } from '../db/postgres-provider.js';
14
+ import { findHiveRoot, getHivePaths, getWorkspaceId, type HivePaths } from './paths.js';
13
15
 
14
16
  export interface HiveContext {
15
17
  root: string;
@@ -38,8 +40,25 @@ function resolveRoot(): { root: string; paths: HivePaths } {
38
40
  return { root, paths };
39
41
  }
40
42
 
43
+ /**
44
+ * Check if this workspace is running in distributed (Postgres) mode.
45
+ */
46
+ function isDistributedMode(paths: HivePaths): boolean {
47
+ try {
48
+ const config = loadConfig(paths.hiveDir);
49
+ return config.distributed === true;
50
+ } catch {
51
+ return false;
52
+ }
53
+ }
54
+
41
55
  export async function withHiveContext<T>(fn: (ctx: HiveContext) => Promise<T> | T): Promise<T> {
42
56
  const { root, paths } = resolveRoot();
57
+
58
+ if (isDistributedMode(paths)) {
59
+ return withDistributedHiveContext(root, paths, fn);
60
+ }
61
+
43
62
  const dbLockPath = join(paths.hiveDir, 'db');
44
63
 
45
64
  // Acquire database lock to prevent concurrent access and race conditions
@@ -93,11 +112,51 @@ export async function withHiveContext<T>(fn: (ctx: HiveContext) => Promise<T> |
93
112
  }
94
113
  }
95
114
 
115
+ async function withDistributedHiveContext<T>(
116
+ root: string,
117
+ paths: HivePaths,
118
+ fn: (ctx: HiveContext) => Promise<T> | T
119
+ ): Promise<T> {
120
+ const workspaceId = getWorkspaceId(paths);
121
+ if (!workspaceId) {
122
+ throw new Error(
123
+ 'Distributed mode is enabled but workspace.id file is missing. ' +
124
+ 'Re-run "hive init --distributed" to fix.'
125
+ );
126
+ }
127
+
128
+ const provider = await createPostgresProvider(workspaceId);
129
+ // Create a DatabaseClient-compatible wrapper around the Postgres provider
130
+ const db: DatabaseClient = {
131
+ db: null as never, // No sql.js database in distributed mode
132
+ provider,
133
+ close: () => {
134
+ provider.close();
135
+ },
136
+ save: () => {
137
+ provider.save();
138
+ },
139
+ runMigrations: () => {
140
+ provider.runMigrations();
141
+ },
142
+ };
143
+
144
+ try {
145
+ return await fn({ root, paths, db });
146
+ } finally {
147
+ await provider.close();
148
+ }
149
+ }
150
+
96
151
  export async function withReadOnlyHiveContext<T>(
97
152
  fn: (ctx: ReadOnlyHiveContext) => Promise<T> | T
98
153
  ): Promise<T> {
99
154
  const { root, paths } = resolveRoot();
100
155
 
156
+ if (isDistributedMode(paths)) {
157
+ return withDistributedReadOnlyHiveContext(root, paths, fn);
158
+ }
159
+
101
160
  const db = await getReadOnlyDatabase(paths.hiveDir);
102
161
  try {
103
162
  return await fn({ root, paths, db });
@@ -106,6 +165,35 @@ export async function withReadOnlyHiveContext<T>(
106
165
  }
107
166
  }
108
167
 
168
+ async function withDistributedReadOnlyHiveContext<T>(
169
+ root: string,
170
+ paths: HivePaths,
171
+ fn: (ctx: ReadOnlyHiveContext) => Promise<T> | T
172
+ ): Promise<T> {
173
+ const workspaceId = getWorkspaceId(paths);
174
+ if (!workspaceId) {
175
+ throw new Error(
176
+ 'Distributed mode is enabled but workspace.id file is missing. ' +
177
+ 'Re-run "hive init --distributed" to fix.'
178
+ );
179
+ }
180
+
181
+ const provider = await createPostgresProvider(workspaceId);
182
+ const db: ReadOnlyDatabaseClient = {
183
+ db: null as never, // No sql.js database in distributed mode
184
+ provider,
185
+ close: () => {
186
+ provider.close();
187
+ },
188
+ };
189
+
190
+ try {
191
+ return await fn({ root, paths, db });
192
+ } finally {
193
+ await provider.close();
194
+ }
195
+ }
196
+
109
197
  export function withHiveRoot<T>(fn: (ctx: HiveRootContext) => T): T {
110
198
  const { root, paths } = resolveRoot();
111
199
  return fn({ root, paths });