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
@@ -63,8 +63,10 @@ approvalsCommand
63
63
  .action(async (options: { all?: boolean; json?: boolean }) => {
64
64
  await withHiveContext(async ({ db }) => {
65
65
  const approvals = options.all
66
- ? getAllEscalations(db.db).filter(escalation => escalation.to_agent_id === null)
67
- : getPendingHumanEscalations(db.db);
66
+ ? (await getAllEscalations(db.provider)).filter(
67
+ escalation => escalation.to_agent_id === null
68
+ )
69
+ : await getPendingHumanEscalations(db.provider);
68
70
 
69
71
  if (options.json) {
70
72
  console.log(JSON.stringify(approvals, null, 2));
@@ -107,7 +109,7 @@ approvalsCommand
107
109
  .description('Show a human approval request')
108
110
  .action(async (id: string) => {
109
111
  await withHiveContext(async ({ db }) => {
110
- const approval = ensureHumanApprovalEscalation(getEscalationById(db.db, id), id);
112
+ const approval = ensureHumanApprovalEscalation(await getEscalationById(db.provider, id), id);
111
113
  const type = classifyApproval(approval.reason);
112
114
 
113
115
  console.log(chalk.bold(`\nApproval: ${approval.id}\n`));
@@ -132,14 +134,14 @@ approvalsCommand
132
134
  .option('-m, --message <message>', 'Optional guidance sent as approval context')
133
135
  .action(async (id: string, options: { message?: string }) => {
134
136
  await withHiveContext(async ({ db }) => {
135
- const approval = ensureHumanApprovalEscalation(getEscalationById(db.db, id), id);
137
+ const approval = ensureHumanApprovalEscalation(await getEscalationById(db.provider, id), id);
136
138
  if (approval.status === 'resolved') {
137
139
  console.log(chalk.yellow(`Approval ${id} is already resolved.`));
138
140
  return;
139
141
  }
140
142
 
141
143
  const note = options.message?.trim() || 'Approved by human reviewer.';
142
- resolveEscalation(db.db, id, `APPROVED: ${note}`);
144
+ await resolveEscalation(db.provider, id, `APPROVED: ${note}`);
143
145
  console.log(chalk.green(`Approved ${id}.`));
144
146
  });
145
147
  });
@@ -150,13 +152,13 @@ approvalsCommand
150
152
  .requiredOption('-m, --message <message>', 'Reason/guidance for denial')
151
153
  .action(async (id: string, options: { message: string }) => {
152
154
  await withHiveContext(async ({ db }) => {
153
- const approval = ensureHumanApprovalEscalation(getEscalationById(db.db, id), id);
155
+ const approval = ensureHumanApprovalEscalation(await getEscalationById(db.provider, id), id);
154
156
  if (approval.status === 'resolved') {
155
157
  console.log(chalk.yellow(`Approval ${id} is already resolved.`));
156
158
  return;
157
159
  }
158
160
 
159
- resolveEscalation(db.db, id, `DENIED: ${options.message}`);
161
+ await resolveEscalation(db.provider, id, `DENIED: ${options.message}`);
160
162
  console.log(chalk.green(`Denied ${id}.`));
161
163
  });
162
164
  });
@@ -1,8 +1,8 @@
1
1
  // Licensed under the Hungry Ghost Hive License. See LICENSE.
2
2
 
3
- import type { Database } from 'sql.js';
4
3
  import initSqlJs from 'sql.js';
5
4
  import { beforeEach, describe, expect, it, vi } from 'vitest';
5
+ import { SqliteProvider } from '../../db/provider.js';
6
6
  import { getPlannedStories } from '../../db/queries/stories.js';
7
7
  import { getTeamById } from '../../db/queries/teams.js';
8
8
 
@@ -16,7 +16,7 @@ vi.mock('../../db/queries/stories.js');
16
16
  vi.mock('../../db/queries/teams.js');
17
17
 
18
18
  describe('Assign Command', () => {
19
- let db: Database;
19
+ let db: SqliteProvider;
20
20
 
21
21
  const mockConfig = {
22
22
  scaling: {
@@ -90,22 +90,23 @@ CREATE TABLE IF NOT EXISTS stories (
90
90
 
91
91
  beforeEach(async () => {
92
92
  const SQL = await initSqlJs();
93
- db = new SQL.Database();
94
- db.run('PRAGMA foreign_keys = ON');
95
- db.run(INITIAL_MIGRATION);
93
+ const rawDb = new SQL.Database();
94
+ rawDb.run('PRAGMA foreign_keys = ON');
95
+ rawDb.run(INITIAL_MIGRATION);
96
+ db = new SqliteProvider(rawDb);
96
97
  vi.clearAllMocks();
97
98
  });
98
99
 
99
100
  describe('--dry-run flag', () => {
100
- it('should return empty when no stories are planned', () => {
101
+ it('should return empty when no stories are planned', async () => {
101
102
  // Mock empty planned stories
102
- vi.mocked(getPlannedStories).mockReturnValue([]);
103
+ vi.mocked(getPlannedStories).mockResolvedValue([]);
103
104
 
104
- const plannedStories = getPlannedStories(db);
105
+ const plannedStories = await getPlannedStories(db);
105
106
  expect(plannedStories).toEqual([]);
106
107
  });
107
108
 
108
- it('should show stories grouped by team without making assignments', () => {
109
+ it('should show stories grouped by team without making assignments', async () => {
109
110
  // Mock planned stories with team association
110
111
  const mockStories = [
111
112
  {
@@ -168,8 +169,8 @@ CREATE TABLE IF NOT EXISTS stories (
168
169
  },
169
170
  ];
170
171
 
171
- vi.mocked(getPlannedStories).mockReturnValue(mockStories);
172
- vi.mocked(getTeamById).mockReturnValue({
172
+ vi.mocked(getPlannedStories).mockResolvedValue(mockStories);
173
+ vi.mocked(getTeamById).mockResolvedValue({
173
174
  id: 'team-1',
174
175
  repo_url: 'https://github.com/test/repo',
175
176
  repo_path: '/path/to/repo',
@@ -177,7 +178,7 @@ CREATE TABLE IF NOT EXISTS stories (
177
178
  created_at: new Date().toISOString(),
178
179
  });
179
180
 
180
- const plannedStories = getPlannedStories(db);
181
+ const plannedStories = await getPlannedStories(db);
181
182
  expect(plannedStories).toHaveLength(2);
182
183
  expect(plannedStories[0].team_id).toBe('team-1');
183
184
  });
@@ -220,7 +221,7 @@ CREATE TABLE IF NOT EXISTS stories (
220
221
  expect(targetLevel).toBe('Senior');
221
222
  });
222
223
 
223
- it('should not make database changes during dry-run', () => {
224
+ it('should not make database changes during dry-run', async () => {
224
225
  // The dry-run option should only call getPlannedStories without making any changes
225
226
  const mockStories = [
226
227
  {
@@ -254,17 +255,17 @@ CREATE TABLE IF NOT EXISTS stories (
254
255
  },
255
256
  ];
256
257
 
257
- vi.mocked(getPlannedStories).mockReturnValue(mockStories);
258
+ vi.mocked(getPlannedStories).mockResolvedValue(mockStories);
258
259
 
259
260
  // In dry-run mode, we should only read data, not write
260
- const plannedStories = getPlannedStories(db);
261
+ const plannedStories = await getPlannedStories(db);
261
262
  expect(plannedStories).toHaveLength(1);
262
263
 
263
264
  // Verify that no assignment operations were performed
264
265
  // (This would be verified by checking that Scheduler.assignStories was not called)
265
266
  });
266
267
 
267
- it('should handle multiple teams in planned stories', () => {
268
+ it('should handle multiple teams in planned stories', async () => {
268
269
  const mockStories = [
269
270
  {
270
271
  id: 'STORY-001',
@@ -326,9 +327,9 @@ CREATE TABLE IF NOT EXISTS stories (
326
327
  },
327
328
  ];
328
329
 
329
- vi.mocked(getPlannedStories).mockReturnValue(mockStories);
330
+ vi.mocked(getPlannedStories).mockResolvedValue(mockStories);
330
331
 
331
- const plannedStories = getPlannedStories(db);
332
+ const plannedStories = await getPlannedStories(db);
332
333
  expect(plannedStories).toHaveLength(2);
333
334
 
334
335
  // Verify stories are grouped by team
@@ -48,11 +48,11 @@ export const assignCommand = new Command('assign')
48
48
  }
49
49
 
50
50
  // Check if godmode is active
51
- const plannedStories = getPlannedStories(db.db);
51
+ const plannedStories = await getPlannedStories(db.provider);
52
52
  let godmodeActive = false;
53
53
  for (const story of plannedStories) {
54
54
  if (story.requirement_id) {
55
- const requirement = getRequirementById(db.db, story.requirement_id);
55
+ const requirement = await getRequirementById(db.provider, story.requirement_id);
56
56
  if (requirement && requirement.godmode) {
57
57
  godmodeActive = true;
58
58
  break;
@@ -85,7 +85,7 @@ export const assignCommand = new Command('assign')
85
85
 
86
86
  // Display planned assignments
87
87
  for (const [teamId, stories] of storiesByTeam) {
88
- const team = getTeamById(db.db, teamId);
88
+ const team = await getTeamById(db.provider, teamId);
89
89
  if (!team) continue;
90
90
 
91
91
  console.log(chalk.cyan(`\n📦 Team: ${team.name}\n`));
@@ -114,7 +114,7 @@ export const assignCommand = new Command('assign')
114
114
  console.log(chalk.yellow('⚡ GODMODE is active - all agents will use Opus 4.6\n'));
115
115
  }
116
116
 
117
- const scheduler = new Scheduler(db.db, {
117
+ const scheduler = new Scheduler(db.provider, {
118
118
  scaling: config.scaling,
119
119
  models: config.models,
120
120
  qa: config.qa,
@@ -19,7 +19,11 @@ vi.mock('../../tmux/manager.js', () => ({
19
19
 
20
20
  vi.mock('../../utils/with-hive-context.js', () => ({
21
21
  withHiveContext: vi.fn(callback =>
22
- callback({ db: { db: {}, save: vi.fn() }, root: '/tmp', paths: { hiveDir: '/tmp/.hive' } })
22
+ callback({
23
+ db: { db: {}, provider: {}, save: vi.fn() },
24
+ root: '/tmp',
25
+ paths: { hiveDir: '/tmp/.hive' },
26
+ })
23
27
  ),
24
28
  }));
25
29
 
@@ -47,7 +47,7 @@ async function findOrphanedWorktrees(root: string, db: DatabaseClient): Promise<
47
47
 
48
48
  try {
49
49
  const entries = await fs.readdir(reposDir, { withFileTypes: true });
50
- const allAgents = getAllAgents(db.db);
50
+ const allAgents = await getAllAgents(db.provider);
51
51
  const agentWorktrees = new Set(
52
52
  allAgents.filter(a => a.worktree_path).map(a => a.worktree_path)
53
53
  );
@@ -110,7 +110,7 @@ async function findDeadTmuxSessions(db: DatabaseClient): Promise<string[]> {
110
110
 
111
111
  try {
112
112
  const hiveSessions = await getHiveSessions();
113
- const allAgents = getAllAgents(db.db);
113
+ const allAgents = await getAllAgents(db.provider);
114
114
  const agentSessionNames = new Set(
115
115
  allAgents.filter(a => a.tmux_session).map(a => a.tmux_session)
116
116
  );
@@ -132,9 +132,11 @@ async function findDeadTmuxSessions(db: DatabaseClient): Promise<string[]> {
132
132
  return deadSessions;
133
133
  }
134
134
 
135
- function findOrphanedAssignments(db: DatabaseClient): Array<{ id: string; agent_id: string }> {
135
+ async function findOrphanedAssignments(
136
+ db: DatabaseClient
137
+ ): Promise<Array<{ id: string; agent_id: string }>> {
136
138
  try {
137
- return getStoriesWithOrphanedAssignments(db.db);
139
+ return await getStoriesWithOrphanedAssignments(db.provider);
138
140
  } catch (err) {
139
141
  console.error(
140
142
  chalk.yellow(
@@ -225,11 +227,11 @@ async function cleanupDeadTmuxSessions(deadSessions: string[], dryRun: boolean):
225
227
  return cleaned;
226
228
  }
227
229
 
228
- function cleanupOrphanedAssignments(
230
+ async function cleanupOrphanedAssignments(
229
231
  db: DatabaseClient,
230
232
  orphaned: Array<{ id: string; agent_id: string }>,
231
233
  dryRun: boolean
232
- ): number {
234
+ ): Promise<number> {
233
235
  let cleaned = 0;
234
236
 
235
237
  for (const assignment of orphaned) {
@@ -237,7 +239,7 @@ function cleanupOrphanedAssignments(
237
239
  if (dryRun) {
238
240
  console.log(chalk.gray(` Would unassign: ${assignment.id} from ${assignment.agent_id}`));
239
241
  } else {
240
- updateStoryAssignment(db.db, assignment.id, null);
242
+ await updateStoryAssignment(db.provider, assignment.id, null);
241
243
  console.log(chalk.gray(` ✓ Unassigned: ${assignment.id}`));
242
244
  cleaned++;
243
245
  }
@@ -300,7 +302,7 @@ export const cleanupCommand = new Command('cleanup')
300
302
  stats.deadTmuxSessions = await findDeadTmuxSessions(db);
301
303
  }
302
304
  if (shouldCleanupAssignments) {
303
- stats.orphanedStories = findOrphanedAssignments(db);
305
+ stats.orphanedStories = await findOrphanedAssignments(db);
304
306
  }
305
307
 
306
308
  stats.totalIssuesFound =
@@ -395,7 +397,7 @@ export const cleanupCommand = new Command('cleanup')
395
397
 
396
398
  if (stats.orphanedStories.length > 0) {
397
399
  console.log(chalk.cyan('Unassigning orphaned stories:'));
398
- const cleaned = cleanupOrphanedAssignments(db, stats.orphanedStories, false);
400
+ const cleaned = await cleanupOrphanedAssignments(db, stats.orphanedStories, false);
399
401
  totalCleaned += cleaned;
400
402
  db.save();
401
403
  console.log();
@@ -16,8 +16,8 @@ vi.mock('../../db/queries/logs.js', () => ({
16
16
  }));
17
17
 
18
18
  vi.mock('../../utils/with-hive-context.js', () => ({
19
- withHiveContext: vi.fn(callback => callback({ db: { db: {} } })),
20
- withReadOnlyHiveContext: vi.fn(callback => callback({ db: { db: {} } })),
19
+ withHiveContext: vi.fn(callback => callback({ db: { db: {}, provider: {} } })),
20
+ withReadOnlyHiveContext: vi.fn(callback => callback({ db: { db: {}, provider: {} } })),
21
21
  }));
22
22
 
23
23
  import { escalationsCommand } from './escalations.js';
@@ -21,7 +21,9 @@ escalationsCommand
21
21
  .option('--json', 'Output as JSON')
22
22
  .action(async (options: { all?: boolean; json?: boolean }) => {
23
23
  await withReadOnlyHiveContext(async ({ db }) => {
24
- const escalations = options.all ? getAllEscalations(db.db) : getPendingEscalations(db.db);
24
+ const escalations = options.all
25
+ ? await getAllEscalations(db.provider)
26
+ : await getPendingEscalations(db.provider);
25
27
 
26
28
  if (options.json) {
27
29
  console.log(JSON.stringify(escalations, null, 2));
@@ -64,7 +66,7 @@ escalationsCommand
64
66
  .description('Show escalation details')
65
67
  .action(async (id: string) => {
66
68
  await withReadOnlyHiveContext(async ({ db }) => {
67
- const escalation = getEscalationById(db.db, id);
69
+ const escalation = await getEscalationById(db.provider, id);
68
70
  if (!escalation) {
69
71
  console.error(chalk.red(`Escalation not found: ${id}`));
70
72
  process.exit(1);
@@ -95,7 +97,7 @@ escalationsCommand
95
97
  .requiredOption('-m, --message <message>', 'Resolution message/guidance')
96
98
  .action(async (id: string, options: { message: string }) => {
97
99
  await withHiveContext(async ({ db }) => {
98
- const escalation = getEscalationById(db.db, id);
100
+ const escalation = await getEscalationById(db.provider, id);
99
101
  if (!escalation) {
100
102
  console.error(chalk.red(`Escalation not found: ${id}`));
101
103
  process.exit(1);
@@ -106,11 +108,11 @@ escalationsCommand
106
108
  return;
107
109
  }
108
110
 
109
- const resolved = resolveEscalation(db.db, id, options.message);
111
+ const resolved = await resolveEscalation(db.provider, id, options.message);
110
112
 
111
113
  // Log the resolution
112
114
  if (escalation.from_agent_id) {
113
- createLog(db.db, {
115
+ await createLog(db.provider, {
114
116
  agentId: escalation.from_agent_id,
115
117
  storyId: escalation.story_id,
116
118
  eventType: 'ESCALATION_RESOLVED',
@@ -129,7 +131,7 @@ escalationsCommand
129
131
  .description('Acknowledge an escalation (mark as being worked on)')
130
132
  .action(async (id: string) => {
131
133
  await withHiveContext(async ({ db }) => {
132
- const escalation = getEscalationById(db.db, id);
134
+ const escalation = await getEscalationById(db.provider, id);
133
135
  if (!escalation) {
134
136
  console.error(chalk.red(`Escalation not found: ${id}`));
135
137
  process.exit(1);
@@ -140,7 +142,7 @@ escalationsCommand
140
142
  return;
141
143
  }
142
144
 
143
- acknowledgeEscalation(db.db, id);
145
+ await acknowledgeEscalation(db.provider, id);
144
146
  console.log(chalk.green(`Escalation ${id} acknowledged.`));
145
147
  });
146
148
  });
@@ -85,5 +85,10 @@ describe('init command', () => {
85
85
  const jiraOpt = initCommand.options.find(opt => opt.long === '--jira-project');
86
86
  expect(jiraOpt).toBeDefined();
87
87
  });
88
+
89
+ it('should have --distributed option', () => {
90
+ const distributedOpt = initCommand.options.find(opt => opt.long === '--distributed');
91
+ expect(distributedOpt).toBeDefined();
92
+ });
88
93
  });
89
94
  });
@@ -3,12 +3,14 @@
3
3
  import chalk from 'chalk';
4
4
  import { Command } from 'commander';
5
5
  import { execa } from 'execa';
6
- import { existsSync, mkdirSync } from 'fs';
6
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
7
+ import { nanoid } from 'nanoid';
7
8
  import ora from 'ora';
8
9
  import { join } from 'path';
9
10
  import { createDefaultConfig, loadConfig, saveConfig } from '../../config/loader.js';
10
11
  import type { HiveConfig } from '../../config/schema.js';
11
12
  import { createDatabase } from '../../db/client.js';
13
+ import { createPostgresProvider } from '../../db/postgres-provider.js';
12
14
  import { getHivePaths, isHiveWorkspace } from '../../utils/paths.js';
13
15
  import type { AgentRuntime } from '../wizard/init-wizard.js';
14
16
  import { runInitWizard } from '../wizard/init-wizard.js';
@@ -23,6 +25,7 @@ export const initCommand = new Command('init')
23
25
  .option('--agent-runtime <runtime>', 'Agent runtime (claude, codex)')
24
26
  .option('--jira-project <key>', 'Jira project key (for non-interactive mode)')
25
27
  .option('--e2e-test-path <path>', 'Path to E2E tests directory')
28
+ .option('--distributed', 'Use Postgres for distributed multi-workspace mode')
26
29
  .action(
27
30
  async (options: {
28
31
  force?: boolean;
@@ -33,6 +36,7 @@ export const initCommand = new Command('init')
33
36
  agentRuntime?: string;
34
37
  jiraProject?: string;
35
38
  e2eTestPath?: string;
39
+ distributed?: boolean;
36
40
  }) => {
37
41
  const rootDir = process.cwd();
38
42
  const paths = getHivePaths(rootDir);
@@ -59,10 +63,15 @@ export const initCommand = new Command('init')
59
63
  createDefaultConfig(paths.hiveDir);
60
64
 
61
65
  // Initialize database
62
- spinner.text = 'Initializing database...';
63
- const db = await createDatabase(paths.dbPath);
64
- db.runMigrations();
65
- db.close();
66
+ if (options.distributed) {
67
+ spinner.text = 'Validating Postgres connection...';
68
+ await initDistributedDatabase(paths.workspaceIdPath);
69
+ } else {
70
+ spinner.text = 'Initializing database...';
71
+ const db = await createDatabase(paths.dbPath);
72
+ db.runMigrations();
73
+ db.close();
74
+ }
66
75
 
67
76
  // Initialize git repository if not already in one
68
77
  spinner.text = 'Initializing git repository...';
@@ -106,6 +115,9 @@ export const initCommand = new Command('init')
106
115
  }
107
116
  }
108
117
  }
118
+ if (options.distributed) {
119
+ config.distributed = true;
120
+ }
109
121
  saveConfig(paths.hiveDir, config);
110
122
 
111
123
  console.log();
@@ -116,6 +128,11 @@ export const initCommand = new Command('init')
116
128
  console.log(chalk.cyan(' hive req "Your requirement here"'));
117
129
  console.log(chalk.gray(' 3. View dashboard:'));
118
130
  console.log(chalk.cyan(' hive dashboard'));
131
+ if (options.distributed) {
132
+ console.log();
133
+ console.log(chalk.gray(' Distributed mode enabled. Database: Postgres'));
134
+ console.log(chalk.gray(` Workspace ID stored in: ${paths.workspaceIdPath}`));
135
+ }
119
136
  console.log();
120
137
  } catch (err) {
121
138
  spinner.fail(chalk.red('Failed to initialize Hive workspace'));
@@ -125,6 +142,37 @@ export const initCommand = new Command('init')
125
142
  }
126
143
  );
127
144
 
145
+ /**
146
+ * Initialize distributed mode: validate HIVE_DATABASE_URL, test connection,
147
+ * generate workspace_id, and run Postgres migrations.
148
+ */
149
+ async function initDistributedDatabase(workspaceIdPath: string): Promise<void> {
150
+ // Load .env if available
151
+ try {
152
+ const dotenv = await import('dotenv');
153
+ dotenv.config();
154
+ } catch {
155
+ // dotenv not available
156
+ }
157
+
158
+ const connectionString = process.env.HIVE_DATABASE_URL;
159
+ if (!connectionString) {
160
+ throw new Error(
161
+ 'HIVE_DATABASE_URL environment variable is not set.\n' +
162
+ 'Set it in your environment or in a .env file before running hive init --distributed.\n' +
163
+ 'Example: HIVE_DATABASE_URL=postgres://user:pass@host:5432/hive'
164
+ );
165
+ }
166
+
167
+ // Generate unique workspace ID
168
+ const workspaceId = nanoid();
169
+ writeFileSync(workspaceIdPath, workspaceId, 'utf-8');
170
+
171
+ // Test connection and run migrations
172
+ const provider = await createPostgresProvider(workspaceId);
173
+ await provider.close();
174
+ }
175
+
128
176
  function applyAgentRuntimePreset(config: HiveConfig, agentRuntime: AgentRuntime): void {
129
177
  const provider = agentRuntime === 'codex' ? 'openai' : 'anthropic';
130
178
  const cliTool = agentRuntime;
@@ -3,7 +3,7 @@
3
3
  import chalk from 'chalk';
4
4
  import { randomUUID } from 'crypto';
5
5
  import type { HiveConfig } from '../../../config/schema.js';
6
- import type { getAllAgents } from '../../../db/queries/agents.js';
6
+ import type { AgentRow } from '../../../db/queries/agents.js';
7
7
  import { createLog } from '../../../db/queries/logs.js';
8
8
  import { getStateDetector, type StateDetectionResult } from '../../../state-detectors/index.js';
9
9
  import { AgentState } from '../../../state-detectors/types.js';
@@ -189,7 +189,7 @@ export function describeAgentState(state: AgentState, cliTool: CLITool): string
189
189
 
190
190
  export function getAgentSafetyMode(
191
191
  config: HiveConfig,
192
- agent: ReturnType<typeof getAllAgents>[number] | undefined
192
+ agent: AgentRow | undefined
193
193
  ): 'safe' | 'unsafe' {
194
194
  if (!agent) return 'unsafe';
195
195
  return config.models[agent.type].safety_mode;
@@ -252,7 +252,7 @@ export async function handlePermissionPrompt(
252
252
  const approved = await autoApprovePermission(sessionName);
253
253
  if (approved) {
254
254
  await ctx.withDb(async db => {
255
- createLog(db.db, {
255
+ createLog(db.provider, {
256
256
  agentId: 'manager',
257
257
  eventType: 'STORY_PROGRESS_UPDATE',
258
258
  message: `Auto-approved permission prompt for ${sessionName}`,
@@ -52,7 +52,14 @@ function makeCtx(
52
52
  overrides: Partial<ManagerCheckContext> = {},
53
53
  schedulerOverrides: Record<string, unknown> = {}
54
54
  ): ManagerCheckContext {
55
- const mockDb = { db: {} as never, save: vi.fn(), close: vi.fn(), runMigrations: vi.fn() };
55
+ const mockProvider = {} as never;
56
+ const mockDb = {
57
+ db: {} as never,
58
+ provider: mockProvider,
59
+ save: vi.fn(),
60
+ close: vi.fn(),
61
+ runMigrations: vi.fn(),
62
+ };
56
63
  const mockScheduler = {
57
64
  spawnAuditor: vi.fn().mockResolvedValue({ id: 'auditor-abc123' }),
58
65
  ...schedulerOverrides,
@@ -118,8 +125,8 @@ describe('spawnAuditorIfNeeded', () => {
118
125
  });
119
126
 
120
127
  it('spawns auditor when interval elapsed and no active auditor', async () => {
121
- mockGetAgentsByType.mockReturnValue([]);
122
- mockGetAllTeams.mockReturnValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
128
+ mockGetAgentsByType.mockResolvedValue([]);
129
+ mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
123
130
 
124
131
  const ctx = makeCtx();
125
132
  const result = await spawnAuditorIfNeeded(ctx);
@@ -135,8 +142,8 @@ describe('spawnAuditorIfNeeded', () => {
135
142
  });
136
143
 
137
144
  it('skips spawn when interval has not elapsed', async () => {
138
- mockGetAgentsByType.mockReturnValue([]);
139
- mockGetAllTeams.mockReturnValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
145
+ mockGetAgentsByType.mockResolvedValue([]);
146
+ mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
140
147
 
141
148
  const ctx = makeCtx();
142
149
 
@@ -151,7 +158,7 @@ describe('spawnAuditorIfNeeded', () => {
151
158
  });
152
159
 
153
160
  it('skips spawn when an active auditor is running', async () => {
154
- mockGetAgentsByType.mockReturnValue([
161
+ mockGetAgentsByType.mockResolvedValue([
155
162
  { id: 'auditor-existing', type: 'auditor', status: 'working' },
156
163
  ]);
157
164
 
@@ -166,8 +173,8 @@ describe('spawnAuditorIfNeeded', () => {
166
173
  });
167
174
 
168
175
  it('skips spawn when no teams exist', async () => {
169
- mockGetAgentsByType.mockReturnValue([]);
170
- mockGetAllTeams.mockReturnValue([]);
176
+ mockGetAgentsByType.mockResolvedValue([]);
177
+ mockGetAllTeams.mockResolvedValue([]);
171
178
 
172
179
  const ctx = makeCtx();
173
180
  const result = await spawnAuditorIfNeeded(ctx);
@@ -177,8 +184,8 @@ describe('spawnAuditorIfNeeded', () => {
177
184
  });
178
185
 
179
186
  it('handles spawn errors gracefully', async () => {
180
- mockGetAgentsByType.mockReturnValue([]);
181
- mockGetAllTeams.mockReturnValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
187
+ mockGetAgentsByType.mockResolvedValue([]);
188
+ mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
182
189
 
183
190
  const ctx = makeCtx(
184
191
  {},
@@ -193,10 +200,10 @@ describe('spawnAuditorIfNeeded', () => {
193
200
  });
194
201
 
195
202
  it('does not count terminated auditors as active', async () => {
196
- mockGetAgentsByType.mockReturnValue([
203
+ mockGetAgentsByType.mockResolvedValue([
197
204
  { id: 'auditor-old', type: 'auditor', status: 'terminated' },
198
205
  ]);
199
- mockGetAllTeams.mockReturnValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
206
+ mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
200
207
 
201
208
  const ctx = makeCtx();
202
209
  const result = await spawnAuditorIfNeeded(ctx);
@@ -206,8 +213,8 @@ describe('spawnAuditorIfNeeded', () => {
206
213
  });
207
214
 
208
215
  it('updates lastAuditorSpawnTime after successful spawn', async () => {
209
- mockGetAgentsByType.mockReturnValue([]);
210
- mockGetAllTeams.mockReturnValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
216
+ mockGetAgentsByType.mockResolvedValue([]);
217
+ mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
211
218
 
212
219
  expect(getLastAuditorSpawnTime()).toBe(0);
213
220
 
@@ -55,7 +55,7 @@ export async function spawnAuditorIfNeeded(ctx: ManagerCheckContext): Promise<bo
55
55
 
56
56
  // Check if a previous auditor is still running
57
57
  const hasActiveAuditor = await ctx.withDb(async db => {
58
- const auditors = getAgentsByType(db.db, 'auditor');
58
+ const auditors = await getAgentsByType(db.provider, 'auditor');
59
59
  return auditors.some(a => a.status === 'idle' || a.status === 'working');
60
60
  });
61
61
 
@@ -67,7 +67,7 @@ export async function spawnAuditorIfNeeded(ctx: ManagerCheckContext): Promise<bo
67
67
  // Spawn a new auditor agent
68
68
  try {
69
69
  const agent = await ctx.withDb(async (db, scheduler) => {
70
- const teams = getAllTeams(db.db);
70
+ const teams = await getAllTeams(db.provider);
71
71
  if (teams.length === 0) {
72
72
  verboseLogCtx(ctx, 'spawnAuditorIfNeeded: skip=no_teams');
73
73
  return null;
@@ -76,7 +76,7 @@ export async function spawnAuditorIfNeeded(ctx: ManagerCheckContext): Promise<bo
76
76
  const team = teams[0];
77
77
  const spawned = await scheduler.spawnAuditor(team.id, team.name, team.repo_path);
78
78
 
79
- createLog(db.db, {
79
+ await createLog(db.provider, {
80
80
  agentId: spawned.id,
81
81
  eventType: 'AGENT_SPAWNED',
82
82
  message: `Spawned auditor agent ${spawned.id} for team ${team.name}`,