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
@@ -3,9 +3,9 @@
3
3
  import { existsSync, mkdirSync, rmSync } from 'fs';
4
4
  import { tmpdir } from 'os';
5
5
  import { join } from 'path';
6
- import type { Database } from 'sql.js';
7
6
  import initSqlJs from 'sql.js';
8
7
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
8
+ import { SqliteProvider } from '../db/provider.js';
9
9
 
10
10
  import { getLogsByEventType } from '../db/queries/logs.js';
11
11
  import { createPullRequest } from '../db/queries/pull-requests.js';
@@ -39,7 +39,7 @@ vi.mock('../git/worktree.js', () => ({
39
39
  removeWorktree: vi.fn().mockResolvedValue(true),
40
40
  }));
41
41
 
42
- let db: Database;
42
+ let db: SqliteProvider;
43
43
  let scheduler: Scheduler;
44
44
 
45
45
  const mockConfig = {
@@ -184,46 +184,67 @@ CREATE TABLE IF NOT EXISTS requirements (
184
184
 
185
185
  beforeEach(async () => {
186
186
  const SQL = await initSqlJs();
187
- db = new SQL.Database();
188
- db.run('PRAGMA foreign_keys = ON');
189
- db.run(INITIAL_MIGRATION);
190
- db.run("INSERT INTO migrations (name) VALUES ('001-initial.sql')");
187
+ const rawDb = new SQL.Database();
188
+ rawDb.run('PRAGMA foreign_keys = ON');
189
+ rawDb.run(INITIAL_MIGRATION);
190
+ rawDb.run("INSERT INTO migrations (name) VALUES ('001-initial.sql')");
191
+ db = new SqliteProvider(rawDb);
191
192
 
192
193
  scheduler = new Scheduler(db, mockConfig as any);
193
194
  });
194
195
 
195
196
  describe('Scheduler Topological Sort', () => {
196
- it('should handle stories with no dependencies', () => {
197
- const team = createTeam(db, {
197
+ it('should handle stories with no dependencies', async () => {
198
+ const team = await createTeam(db, {
198
199
  name: 'Test Team',
199
200
  repoUrl: 'https://github.com/test/repo',
200
201
  repoPath: 'test',
201
202
  });
202
- const story1 = createStory(db, { teamId: team.id, title: 'Story 1', description: 'Test' });
203
- const story2 = createStory(db, { teamId: team.id, title: 'Story 2', description: 'Test' });
203
+ const story1 = await createStory(db, {
204
+ teamId: team.id,
205
+ title: 'Story 1',
206
+ description: 'Test',
207
+ });
208
+ const story2 = await createStory(db, {
209
+ teamId: team.id,
210
+ title: 'Story 2',
211
+ description: 'Test',
212
+ });
204
213
 
205
214
  // Mock the private method by accessing it through reflection
206
- const sorted = topologicalSort(db, [story1, story2]);
215
+ const sorted = await topologicalSort(db, [story1, story2]);
207
216
 
208
217
  expect(sorted).not.toBeNull();
209
218
  expect(sorted).toHaveLength(2);
210
219
  });
211
220
 
212
- it('should respect linear dependencies (A -> B -> C)', () => {
213
- const team = createTeam(db, {
221
+ it('should respect linear dependencies (A -> B -> C)', async () => {
222
+ const team = await createTeam(db, {
214
223
  name: 'Test Team',
215
224
  repoUrl: 'https://github.com/test/repo',
216
225
  repoPath: 'test',
217
226
  });
218
- const storyA = createStory(db, { teamId: team.id, title: 'Story A', description: 'Test' });
219
- const storyB = createStory(db, { teamId: team.id, title: 'Story B', description: 'Test' });
220
- const storyC = createStory(db, { teamId: team.id, title: 'Story C', description: 'Test' });
227
+ const storyA = await createStory(db, {
228
+ teamId: team.id,
229
+ title: 'Story A',
230
+ description: 'Test',
231
+ });
232
+ const storyB = await createStory(db, {
233
+ teamId: team.id,
234
+ title: 'Story B',
235
+ description: 'Test',
236
+ });
237
+ const storyC = await createStory(db, {
238
+ teamId: team.id,
239
+ title: 'Story C',
240
+ description: 'Test',
241
+ });
221
242
 
222
243
  // B depends on A, C depends on B
223
- addStoryDependency(db, storyB.id, storyA.id);
224
- addStoryDependency(db, storyC.id, storyB.id);
244
+ await addStoryDependency(db, storyB.id, storyA.id);
245
+ await addStoryDependency(db, storyC.id, storyB.id);
225
246
 
226
- const sorted = topologicalSort(db, [storyC, storyA, storyB]);
247
+ const sorted = await topologicalSort(db, [storyC, storyA, storyB]);
227
248
 
228
249
  expect(sorted).not.toBeNull();
229
250
  expect(sorted).toHaveLength(3);
@@ -233,24 +254,40 @@ describe('Scheduler Topological Sort', () => {
233
254
  expect(ids.indexOf(storyB.id)).toBeLessThan(ids.indexOf(storyC.id));
234
255
  });
235
256
 
236
- it('should respect diamond dependencies (A -> B, A -> C, B -> D, C -> D)', () => {
237
- const team = createTeam(db, {
257
+ it('should respect diamond dependencies (A -> B, A -> C, B -> D, C -> D)', async () => {
258
+ const team = await createTeam(db, {
238
259
  name: 'Test Team',
239
260
  repoUrl: 'https://github.com/test/repo',
240
261
  repoPath: 'test',
241
262
  });
242
- const storyA = createStory(db, { teamId: team.id, title: 'Story A', description: 'Test' });
243
- const storyB = createStory(db, { teamId: team.id, title: 'Story B', description: 'Test' });
244
- const storyC = createStory(db, { teamId: team.id, title: 'Story C', description: 'Test' });
245
- const storyD = createStory(db, { teamId: team.id, title: 'Story D', description: 'Test' });
263
+ const storyA = await createStory(db, {
264
+ teamId: team.id,
265
+ title: 'Story A',
266
+ description: 'Test',
267
+ });
268
+ const storyB = await createStory(db, {
269
+ teamId: team.id,
270
+ title: 'Story B',
271
+ description: 'Test',
272
+ });
273
+ const storyC = await createStory(db, {
274
+ teamId: team.id,
275
+ title: 'Story C',
276
+ description: 'Test',
277
+ });
278
+ const storyD = await createStory(db, {
279
+ teamId: team.id,
280
+ title: 'Story D',
281
+ description: 'Test',
282
+ });
246
283
 
247
284
  // B and C depend on A, D depends on both B and C
248
- addStoryDependency(db, storyB.id, storyA.id);
249
- addStoryDependency(db, storyC.id, storyA.id);
250
- addStoryDependency(db, storyD.id, storyB.id);
251
- addStoryDependency(db, storyD.id, storyC.id);
285
+ await addStoryDependency(db, storyB.id, storyA.id);
286
+ await addStoryDependency(db, storyC.id, storyA.id);
287
+ await addStoryDependency(db, storyD.id, storyB.id);
288
+ await addStoryDependency(db, storyD.id, storyC.id);
252
289
 
253
- const sorted = topologicalSort(db, [storyD, storyB, storyA, storyC]);
290
+ const sorted = await topologicalSort(db, [storyD, storyB, storyA, storyC]);
254
291
 
255
292
  expect(sorted).not.toBeNull();
256
293
  expect(sorted).toHaveLength(4);
@@ -267,138 +304,170 @@ describe('Scheduler Topological Sort', () => {
267
304
  expect(ids.indexOf(storyC.id)).toBeLessThan(ids.indexOf(storyD.id));
268
305
  });
269
306
 
270
- it('should detect circular dependencies', () => {
271
- const team = createTeam(db, {
307
+ it('should detect circular dependencies', async () => {
308
+ const team = await createTeam(db, {
272
309
  name: 'Test Team',
273
310
  repoUrl: 'https://github.com/test/repo',
274
311
  repoPath: 'test',
275
312
  });
276
- const storyA = createStory(db, { teamId: team.id, title: 'Story A', description: 'Test' });
277
- const storyB = createStory(db, { teamId: team.id, title: 'Story B', description: 'Test' });
313
+ const storyA = await createStory(db, {
314
+ teamId: team.id,
315
+ title: 'Story A',
316
+ description: 'Test',
317
+ });
318
+ const storyB = await createStory(db, {
319
+ teamId: team.id,
320
+ title: 'Story B',
321
+ description: 'Test',
322
+ });
278
323
 
279
324
  // Create circular dependency: A -> B -> A
280
- addStoryDependency(db, storyB.id, storyA.id);
281
- addStoryDependency(db, storyA.id, storyB.id);
325
+ await addStoryDependency(db, storyB.id, storyA.id);
326
+ await addStoryDependency(db, storyA.id, storyB.id);
282
327
 
283
- const sorted = topologicalSort(db, [storyA, storyB]);
328
+ const sorted = await topologicalSort(db, [storyA, storyB]);
284
329
 
285
330
  expect(sorted).toBeNull();
286
331
  });
287
332
  });
288
333
 
289
334
  describe('Scheduler Dependency Satisfaction', () => {
290
- it('should consider merged stories as satisfying dependencies', () => {
291
- const team = createTeam(db, {
335
+ it('should consider merged stories as satisfying dependencies', async () => {
336
+ const team = await createTeam(db, {
292
337
  name: 'Test Team',
293
338
  repoUrl: 'https://github.com/test/repo',
294
339
  repoPath: 'test',
295
340
  });
296
- const depStory = createStory(db, { teamId: team.id, title: 'Dependency', description: 'Test' });
297
- const mainStory = createStory(db, {
341
+ const depStory = await createStory(db, {
342
+ teamId: team.id,
343
+ title: 'Dependency',
344
+ description: 'Test',
345
+ });
346
+ const mainStory = await createStory(db, {
298
347
  teamId: team.id,
299
348
  title: 'Main Story',
300
349
  description: 'Test',
301
350
  });
302
351
 
303
- addStoryDependency(db, mainStory.id, depStory.id);
352
+ await addStoryDependency(db, mainStory.id, depStory.id);
304
353
 
305
354
  // Initially, dependencies are not satisfied
306
- let isSatisfied = areDependenciesSatisfied(db, mainStory.id);
355
+ let isSatisfied = await areDependenciesSatisfied(db, mainStory.id);
307
356
  expect(isSatisfied).toBe(false);
308
357
 
309
358
  // Mark dependency as merged
310
- updateStory(db, depStory.id, { status: 'merged' });
311
- isSatisfied = areDependenciesSatisfied(db, mainStory.id);
359
+ await updateStory(db, depStory.id, { status: 'merged' });
360
+ isSatisfied = await areDependenciesSatisfied(db, mainStory.id);
312
361
  expect(isSatisfied).toBe(true);
313
362
  });
314
363
 
315
- it('should not consider in-progress stories as satisfying dependencies', () => {
316
- const team = createTeam(db, {
364
+ it('should not consider in-progress stories as satisfying dependencies', async () => {
365
+ const team = await createTeam(db, {
317
366
  name: 'Test Team',
318
367
  repoUrl: 'https://github.com/test/repo',
319
368
  repoPath: 'test',
320
369
  });
321
- const depStory = createStory(db, { teamId: team.id, title: 'Dependency', description: 'Test' });
322
- const mainStory = createStory(db, {
370
+ const depStory = await createStory(db, {
371
+ teamId: team.id,
372
+ title: 'Dependency',
373
+ description: 'Test',
374
+ });
375
+ const mainStory = await createStory(db, {
323
376
  teamId: team.id,
324
377
  title: 'Main Story',
325
378
  description: 'Test',
326
379
  });
327
380
 
328
- addStoryDependency(db, mainStory.id, depStory.id);
381
+ await addStoryDependency(db, mainStory.id, depStory.id);
329
382
 
330
383
  // Mark dependency as in_progress - this should NOT satisfy the dependency
331
- updateStory(db, depStory.id, { status: 'in_progress' });
332
- const isSatisfied = areDependenciesSatisfied(db, mainStory.id);
384
+ await updateStory(db, depStory.id, { status: 'in_progress' });
385
+ const isSatisfied = await areDependenciesSatisfied(db, mainStory.id);
333
386
  expect(isSatisfied).toBe(false);
334
387
  });
335
388
 
336
- it('should not consider planned stories as satisfying dependencies', () => {
337
- const team = createTeam(db, {
389
+ it('should not consider planned stories as satisfying dependencies', async () => {
390
+ const team = await createTeam(db, {
338
391
  name: 'Test Team',
339
392
  repoUrl: 'https://github.com/test/repo',
340
393
  repoPath: 'test',
341
394
  });
342
- const depStory = createStory(db, { teamId: team.id, title: 'Dependency', description: 'Test' });
343
- const mainStory = createStory(db, {
395
+ const depStory = await createStory(db, {
396
+ teamId: team.id,
397
+ title: 'Dependency',
398
+ description: 'Test',
399
+ });
400
+ const mainStory = await createStory(db, {
344
401
  teamId: team.id,
345
402
  title: 'Main Story',
346
403
  description: 'Test',
347
404
  });
348
405
 
349
- addStoryDependency(db, mainStory.id, depStory.id);
406
+ await addStoryDependency(db, mainStory.id, depStory.id);
350
407
 
351
408
  // Update main story status to planned (default)
352
- updateStory(db, mainStory.id, { status: 'planned' });
409
+ await updateStory(db, mainStory.id, { status: 'planned' });
353
410
 
354
- const isSatisfied = areDependenciesSatisfied(db, mainStory.id);
411
+ const isSatisfied = await areDependenciesSatisfied(db, mainStory.id);
355
412
  expect(isSatisfied).toBe(false);
356
413
  });
357
414
 
358
- it('should handle multiple dependencies', () => {
359
- const team = createTeam(db, {
415
+ it('should handle multiple dependencies', async () => {
416
+ const team = await createTeam(db, {
360
417
  name: 'Test Team',
361
418
  repoUrl: 'https://github.com/test/repo',
362
419
  repoPath: 'test',
363
420
  });
364
- const dep1 = createStory(db, { teamId: team.id, title: 'Dep 1', description: 'Test' });
365
- const dep2 = createStory(db, { teamId: team.id, title: 'Dep 2', description: 'Test' });
366
- const mainStory = createStory(db, {
421
+ const dep1 = await createStory(db, { teamId: team.id, title: 'Dep 1', description: 'Test' });
422
+ const dep2 = await createStory(db, { teamId: team.id, title: 'Dep 2', description: 'Test' });
423
+ const mainStory = await createStory(db, {
367
424
  teamId: team.id,
368
425
  title: 'Main Story',
369
426
  description: 'Test',
370
427
  });
371
428
 
372
- addStoryDependency(db, mainStory.id, dep1.id);
373
- addStoryDependency(db, mainStory.id, dep2.id);
429
+ await addStoryDependency(db, mainStory.id, dep1.id);
430
+ await addStoryDependency(db, mainStory.id, dep2.id);
374
431
 
375
432
  // Mark only first dependency as merged
376
- updateStory(db, dep1.id, { status: 'merged' });
377
- let isSatisfied = areDependenciesSatisfied(db, mainStory.id);
433
+ await updateStory(db, dep1.id, { status: 'merged' });
434
+ let isSatisfied = await areDependenciesSatisfied(db, mainStory.id);
378
435
  expect(isSatisfied).toBe(false);
379
436
 
380
437
  // Mark second dependency as merged too
381
- updateStory(db, dep2.id, { status: 'merged' });
382
- isSatisfied = areDependenciesSatisfied(db, mainStory.id);
438
+ await updateStory(db, dep2.id, { status: 'merged' });
439
+ isSatisfied = await areDependenciesSatisfied(db, mainStory.id);
383
440
  expect(isSatisfied).toBe(true);
384
441
  });
385
442
  });
386
443
 
387
444
  describe('Scheduler Build Dependency Graph', () => {
388
- it('should correctly build a dependency graph', () => {
389
- const team = createTeam(db, {
445
+ it('should correctly build a dependency graph', async () => {
446
+ const team = await createTeam(db, {
390
447
  name: 'Test Team',
391
448
  repoUrl: 'https://github.com/test/repo',
392
449
  repoPath: 'test',
393
450
  });
394
- const storyA = createStory(db, { teamId: team.id, title: 'Story A', description: 'Test' });
395
- const storyB = createStory(db, { teamId: team.id, title: 'Story B', description: 'Test' });
396
- const storyC = createStory(db, { teamId: team.id, title: 'Story C', description: 'Test' });
451
+ const storyA = await createStory(db, {
452
+ teamId: team.id,
453
+ title: 'Story A',
454
+ description: 'Test',
455
+ });
456
+ const storyB = await createStory(db, {
457
+ teamId: team.id,
458
+ title: 'Story B',
459
+ description: 'Test',
460
+ });
461
+ const storyC = await createStory(db, {
462
+ teamId: team.id,
463
+ title: 'Story C',
464
+ description: 'Test',
465
+ });
397
466
 
398
- addStoryDependency(db, storyB.id, storyA.id);
399
- addStoryDependency(db, storyC.id, storyA.id);
467
+ await addStoryDependency(db, storyB.id, storyA.id);
468
+ await addStoryDependency(db, storyC.id, storyA.id);
400
469
 
401
- const graph = buildDependencyGraph(db, [storyA, storyB, storyC]);
470
+ const graph = await buildDependencyGraph(db, [storyA, storyB, storyC]);
402
471
 
403
472
  expect(graph.has(storyA.id)).toBe(true);
404
473
  expect(graph.has(storyB.id)).toBe(true);
@@ -409,21 +478,33 @@ describe('Scheduler Build Dependency Graph', () => {
409
478
  expect(graph.get(storyC.id)).toEqual(new Set([storyA.id]));
410
479
  });
411
480
 
412
- it('should include only stories in the input list', () => {
413
- const team = createTeam(db, {
481
+ it('should include only stories in the input list', async () => {
482
+ const team = await createTeam(db, {
414
483
  name: 'Test Team',
415
484
  repoUrl: 'https://github.com/test/repo',
416
485
  repoPath: 'test',
417
486
  });
418
- const storyA = createStory(db, { teamId: team.id, title: 'Story A', description: 'Test' });
419
- const storyB = createStory(db, { teamId: team.id, title: 'Story B', description: 'Test' });
420
- const storyC = createStory(db, { teamId: team.id, title: 'Story C', description: 'Test' });
487
+ const storyA = await createStory(db, {
488
+ teamId: team.id,
489
+ title: 'Story A',
490
+ description: 'Test',
491
+ });
492
+ const storyB = await createStory(db, {
493
+ teamId: team.id,
494
+ title: 'Story B',
495
+ description: 'Test',
496
+ });
497
+ const storyC = await createStory(db, {
498
+ teamId: team.id,
499
+ title: 'Story C',
500
+ description: 'Test',
501
+ });
421
502
 
422
503
  // B depends on A (A is not in the filter list)
423
- addStoryDependency(db, storyB.id, storyA.id);
504
+ await addStoryDependency(db, storyB.id, storyA.id);
424
505
 
425
506
  // Only include B and C in the graph
426
- const graph = buildDependencyGraph(db, [storyB, storyC]);
507
+ const graph = await buildDependencyGraph(db, [storyB, storyC]);
427
508
 
428
509
  expect(graph.has(storyB.id)).toBe(true);
429
510
  expect(graph.has(storyC.id)).toBe(true);
@@ -432,7 +513,7 @@ describe('Scheduler Build Dependency Graph', () => {
432
513
  });
433
514
 
434
515
  describe('Scheduler Worktree Removal', () => {
435
- it('should remove worktrees with a short cleanup timeout', () => {
516
+ it('should remove worktrees with a short cleanup timeout', async () => {
436
517
  const removeSpy = vi.spyOn(worktreeModule, 'removeWorktree').mockReturnValue({
437
518
  success: true,
438
519
  fullWorktreePath: '/tmp/repos/test-agent-1',
@@ -446,7 +527,7 @@ describe('Scheduler Worktree Removal', () => {
446
527
  vi.restoreAllMocks();
447
528
  });
448
529
 
449
- it('should log worktree removal failures to the database', () => {
530
+ it('should log worktree removal failures to the database', async () => {
450
531
  // Mock the shared removeWorktree to simulate failure
451
532
  vi.spyOn(worktreeModule, 'removeWorktree').mockReturnValue({
452
533
  success: false,
@@ -455,10 +536,10 @@ describe('Scheduler Worktree Removal', () => {
455
536
  });
456
537
 
457
538
  const removeMethod = (scheduler as any).removeAgentWorktree;
458
- removeMethod.call(scheduler, 'repos/test-agent-1', 'agent-test-1');
539
+ await removeMethod.call(scheduler, 'repos/test-agent-1', 'agent-test-1');
459
540
 
460
541
  // Check that the failure was logged
461
- const logs = getLogsByEventType(db, 'WORKTREE_REMOVAL_FAILED');
542
+ const logs = await getLogsByEventType(db, 'WORKTREE_REMOVAL_FAILED');
462
543
  expect(logs).toHaveLength(1);
463
544
  expect(logs[0].agent_id).toBe('agent-test-1');
464
545
  expect(logs[0].event_type).toBe('WORKTREE_REMOVAL_FAILED');
@@ -468,14 +549,14 @@ describe('Scheduler Worktree Removal', () => {
468
549
  vi.restoreAllMocks();
469
550
  });
470
551
 
471
- it('should handle empty worktree paths gracefully', () => {
552
+ it('should handle empty worktree paths gracefully', async () => {
472
553
  const removeMethod = (scheduler as any).removeAgentWorktree;
473
554
 
474
555
  // Should return without error for empty path
475
556
  removeMethod.call(scheduler, '', 'agent-test-1');
476
557
 
477
558
  // Should not log anything
478
- const logs = getLogsByEventType(db, 'WORKTREE_REMOVAL_FAILED');
559
+ const logs = await getLogsByEventType(db, 'WORKTREE_REMOVAL_FAILED');
479
560
  expect(logs).toHaveLength(0);
480
561
  });
481
562
  });
@@ -483,7 +564,7 @@ describe('Scheduler Worktree Removal', () => {
483
564
  describe('Scheduler Orphaned Story Recovery', () => {
484
565
  it('should recover orphaned stories assigned to terminated agents', async () => {
485
566
  // Setup: Create team, agents, and a story
486
- const team = createTeam(db, {
567
+ const team = await createTeam(db, {
487
568
  name: 'Test Team',
488
569
  repoUrl: 'https://github.com/test/repo',
489
570
  repoPath: 'test',
@@ -491,32 +572,32 @@ describe('Scheduler Orphaned Story Recovery', () => {
491
572
 
492
573
  // Create a terminated agent in the database
493
574
  const terminatedAgentId = 'agent-terminated-1';
494
- db.run(
575
+ db.db.run(
495
576
  `INSERT INTO agents (id, type, team_id, status, created_at, updated_at)
496
577
  VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))`,
497
578
  [terminatedAgentId, 'intermediate', team.id, 'terminated']
498
579
  );
499
580
 
500
581
  // Create a story assigned to the terminated agent
501
- const story = createStory(db, {
582
+ const story = await createStory(db, {
502
583
  teamId: team.id,
503
584
  title: 'Orphaned Story',
504
585
  description: 'Test',
505
586
  });
506
- updateStory(db, story.id, {
587
+ await updateStory(db, story.id, {
507
588
  assignedAgentId: terminatedAgentId,
508
589
  status: 'in_progress',
509
590
  });
510
591
 
511
592
  // Get the recovery method
512
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp');
593
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp');
513
594
 
514
595
  // Verify the story was recovered
515
596
  expect(recovered).toContain(story.id);
516
597
  expect(recovered.length).toBe(1);
517
598
 
518
599
  // Verify the story's assignment was cleared and status changed
519
- const recoveredStory = db.exec(
600
+ const recoveredStory = db.db.exec(
520
601
  `SELECT assigned_agent_id, status FROM stories WHERE id = '${story.id}'`
521
602
  )[0]?.values[0];
522
603
 
@@ -525,7 +606,7 @@ describe('Scheduler Orphaned Story Recovery', () => {
525
606
  });
526
607
 
527
608
  it('should not affect stories assigned to active agents', async () => {
528
- const team = createTeam(db, {
609
+ const team = await createTeam(db, {
529
610
  name: 'Test Team',
530
611
  repoUrl: 'https://github.com/test/repo',
531
612
  repoPath: 'test',
@@ -533,28 +614,32 @@ describe('Scheduler Orphaned Story Recovery', () => {
533
614
 
534
615
  // Create an active (non-terminated) agent
535
616
  const activeAgentId = 'agent-active-1';
536
- db.run(
617
+ db.db.run(
537
618
  `INSERT INTO agents (id, type, team_id, status, created_at, updated_at)
538
619
  VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))`,
539
620
  [activeAgentId, 'intermediate', team.id, 'working']
540
621
  );
541
622
 
542
623
  // Create a story assigned to the active agent
543
- const story = createStory(db, { teamId: team.id, title: 'Active Story', description: 'Test' });
544
- updateStory(db, story.id, {
624
+ const story = await createStory(db, {
625
+ teamId: team.id,
626
+ title: 'Active Story',
627
+ description: 'Test',
628
+ });
629
+ await updateStory(db, story.id, {
545
630
  assignedAgentId: activeAgentId,
546
631
  status: 'in_progress',
547
632
  });
548
- db.run(`UPDATE agents SET current_story_id = ? WHERE id = ?`, [story.id, activeAgentId]);
633
+ db.db.run(`UPDATE agents SET current_story_id = ? WHERE id = ?`, [story.id, activeAgentId]);
549
634
 
550
635
  // Get the recovery method
551
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp');
636
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp');
552
637
 
553
638
  // Verify no stories were recovered
554
639
  expect(recovered.length).toBe(0);
555
640
 
556
641
  // Verify the story's assignment was NOT changed
557
- const unchangedStory = db.exec(
642
+ const unchangedStory = db.db.exec(
558
643
  `SELECT assigned_agent_id, status FROM stories WHERE id = '${story.id}'`
559
644
  )[0]?.values[0];
560
645
 
@@ -563,34 +648,34 @@ describe('Scheduler Orphaned Story Recovery', () => {
563
648
  });
564
649
 
565
650
  it('should recover in_progress stories assigned to idle agents with no current story', async () => {
566
- const team = createTeam(db, {
651
+ const team = await createTeam(db, {
567
652
  name: 'Inconsistent Team',
568
653
  repoUrl: 'https://github.com/test/repo',
569
654
  repoPath: 'test',
570
655
  });
571
656
 
572
657
  const idleAgentId = 'agent-idle-1';
573
- db.run(
658
+ db.db.run(
574
659
  `INSERT INTO agents (id, type, team_id, status, current_story_id, created_at, updated_at)
575
660
  VALUES (?, ?, ?, ?, NULL, datetime('now'), datetime('now'))`,
576
661
  [idleAgentId, 'intermediate', team.id, 'idle']
577
662
  );
578
663
 
579
- const story = createStory(db, {
664
+ const story = await createStory(db, {
580
665
  teamId: team.id,
581
666
  title: 'Inconsistent Assignment Story',
582
667
  description: 'Assigned to idle agent',
583
668
  });
584
- updateStory(db, story.id, {
669
+ await updateStory(db, story.id, {
585
670
  assignedAgentId: idleAgentId,
586
671
  status: 'in_progress',
587
672
  });
588
673
 
589
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp');
674
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp');
590
675
 
591
676
  expect(recovered).toContain(story.id);
592
677
 
593
- const recoveredStory = db.exec(
678
+ const recoveredStory = db.db.exec(
594
679
  `SELECT assigned_agent_id, status FROM stories WHERE id = '${story.id}'`
595
680
  )[0]?.values[0];
596
681
 
@@ -599,34 +684,34 @@ describe('Scheduler Orphaned Story Recovery', () => {
599
684
  });
600
685
 
601
686
  it('should recover in_progress stories when agent current_story_id points to a different story', async () => {
602
- const team = createTeam(db, {
687
+ const team = await createTeam(db, {
603
688
  name: 'Mismatched Team',
604
689
  repoUrl: 'https://github.com/test/repo',
605
690
  repoPath: 'test',
606
691
  });
607
692
 
608
693
  const workingAgentId = 'agent-working-mismatch-1';
609
- db.run(
694
+ db.db.run(
610
695
  `INSERT INTO agents (id, type, team_id, status, current_story_id, created_at, updated_at)
611
696
  VALUES (?, ?, ?, ?, ?, datetime('now'), datetime('now'))`,
612
697
  [workingAgentId, 'intermediate', team.id, 'working', 'STORY-OTHER']
613
698
  );
614
699
 
615
- const story = createStory(db, {
700
+ const story = await createStory(db, {
616
701
  teamId: team.id,
617
702
  title: 'Mismatched Assignment Story',
618
703
  description: 'Assigned story does not match agent current story',
619
704
  });
620
- updateStory(db, story.id, {
705
+ await updateStory(db, story.id, {
621
706
  assignedAgentId: workingAgentId,
622
707
  status: 'in_progress',
623
708
  });
624
709
 
625
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp');
710
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp');
626
711
 
627
712
  expect(recovered).toContain(story.id);
628
713
 
629
- const recoveredStory = db.exec(
714
+ const recoveredStory = db.db.exec(
630
715
  `SELECT assigned_agent_id, status FROM stories WHERE id = '${story.id}'`
631
716
  )[0]?.values[0];
632
717
 
@@ -635,33 +720,33 @@ describe('Scheduler Orphaned Story Recovery', () => {
635
720
  });
636
721
 
637
722
  it('should recover in_progress stories assigned to blocked agents even with matching current story', async () => {
638
- const team = createTeam(db, {
723
+ const team = await createTeam(db, {
639
724
  name: 'Blocked Team',
640
725
  repoUrl: 'https://github.com/test/repo',
641
726
  repoPath: 'test',
642
727
  });
643
728
 
644
729
  const blockedAgentId = 'agent-blocked-1';
645
- const story = createStory(db, {
730
+ const story = await createStory(db, {
646
731
  teamId: team.id,
647
732
  title: 'Blocked Assignment Story',
648
733
  description: 'Assigned to blocked agent',
649
734
  });
650
- db.run(
735
+ db.db.run(
651
736
  `INSERT INTO agents (id, type, team_id, status, current_story_id, created_at, updated_at)
652
737
  VALUES (?, ?, ?, ?, ?, datetime('now'), datetime('now'))`,
653
738
  [blockedAgentId, 'intermediate', team.id, 'blocked', story.id]
654
739
  );
655
- updateStory(db, story.id, {
740
+ await updateStory(db, story.id, {
656
741
  assignedAgentId: blockedAgentId,
657
742
  status: 'in_progress',
658
743
  });
659
744
 
660
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp');
745
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp');
661
746
 
662
747
  expect(recovered).toContain(story.id);
663
748
 
664
- const recoveredStory = db.exec(
749
+ const recoveredStory = db.db.exec(
665
750
  `SELECT assigned_agent_id, status FROM stories WHERE id = '${story.id}'`
666
751
  )[0]?.values[0];
667
752
 
@@ -670,34 +755,34 @@ describe('Scheduler Orphaned Story Recovery', () => {
670
755
  });
671
756
 
672
757
  it('should not recover non-in_progress stories with inconsistent assignment', async () => {
673
- const team = createTeam(db, {
758
+ const team = await createTeam(db, {
674
759
  name: 'Review Team',
675
760
  repoUrl: 'https://github.com/test/repo',
676
761
  repoPath: 'test',
677
762
  });
678
763
 
679
764
  const idleAgentId = 'agent-idle-review-1';
680
- db.run(
765
+ db.db.run(
681
766
  `INSERT INTO agents (id, type, team_id, status, current_story_id, created_at, updated_at)
682
767
  VALUES (?, ?, ?, ?, NULL, datetime('now'), datetime('now'))`,
683
768
  [idleAgentId, 'intermediate', team.id, 'idle']
684
769
  );
685
770
 
686
- const reviewStory = createStory(db, {
771
+ const reviewStory = await createStory(db, {
687
772
  teamId: team.id,
688
773
  title: 'Review Story',
689
774
  description: 'Should not be recovered by in_progress consistency check',
690
775
  });
691
- updateStory(db, reviewStory.id, {
776
+ await updateStory(db, reviewStory.id, {
692
777
  assignedAgentId: idleAgentId,
693
778
  status: 'review',
694
779
  });
695
780
 
696
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp');
781
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp');
697
782
 
698
783
  expect(recovered).not.toContain(reviewStory.id);
699
784
 
700
- const unchangedStory = db.exec(
785
+ const unchangedStory = db.db.exec(
701
786
  `SELECT assigned_agent_id, status FROM stories WHERE id = '${reviewStory.id}'`
702
787
  )[0]?.values[0];
703
788
 
@@ -706,27 +791,27 @@ describe('Scheduler Orphaned Story Recovery', () => {
706
791
  });
707
792
 
708
793
  it('should recover stale in_progress stories without assigned agents', async () => {
709
- const team = createTeam(db, {
794
+ const team = await createTeam(db, {
710
795
  name: 'Stale Team',
711
796
  repoUrl: 'https://github.com/test/repo',
712
797
  repoPath: 'test',
713
798
  });
714
799
 
715
- const staleStory = createStory(db, {
800
+ const staleStory = await createStory(db, {
716
801
  teamId: team.id,
717
802
  title: 'Stale In Progress Story',
718
803
  description: 'Lost assignment',
719
804
  });
720
- updateStory(db, staleStory.id, {
805
+ await updateStory(db, staleStory.id, {
721
806
  status: 'in_progress',
722
807
  assignedAgentId: null,
723
808
  });
724
809
 
725
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp');
810
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp');
726
811
 
727
812
  expect(recovered).toContain(staleStory.id);
728
813
 
729
- const recoveredStory = db.exec(
814
+ const recoveredStory = db.db.exec(
730
815
  `SELECT assigned_agent_id, status FROM stories WHERE id = '${staleStory.id}'`
731
816
  )[0]?.values[0];
732
817
 
@@ -735,29 +820,29 @@ describe('Scheduler Orphaned Story Recovery', () => {
735
820
  });
736
821
 
737
822
  it('should not recover planned stories that are unassigned', async () => {
738
- const team = createTeam(db, {
823
+ const team = await createTeam(db, {
739
824
  name: 'Planned Team',
740
825
  repoUrl: 'https://github.com/test/repo',
741
826
  repoPath: 'test',
742
827
  });
743
828
 
744
- const plannedStory = createStory(db, {
829
+ const plannedStory = await createStory(db, {
745
830
  teamId: team.id,
746
831
  title: 'Already Planned',
747
832
  description: 'Should stay planned',
748
833
  });
749
- updateStory(db, plannedStory.id, {
834
+ await updateStory(db, plannedStory.id, {
750
835
  status: 'planned',
751
836
  assignedAgentId: null,
752
837
  });
753
838
 
754
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp');
839
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp');
755
840
 
756
841
  expect(recovered).not.toContain(plannedStory.id);
757
842
  });
758
843
 
759
844
  it('should recover multiple orphaned stories', async () => {
760
- const team = createTeam(db, {
845
+ const team = await createTeam(db, {
761
846
  name: 'Test Team',
762
847
  repoUrl: 'https://github.com/test/repo',
763
848
  repoPath: 'test',
@@ -765,35 +850,35 @@ describe('Scheduler Orphaned Story Recovery', () => {
765
850
 
766
851
  // Create a terminated agent
767
852
  const terminatedAgentId = 'agent-terminated-2';
768
- db.run(
853
+ db.db.run(
769
854
  `INSERT INTO agents (id, type, team_id, status, created_at, updated_at)
770
855
  VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))`,
771
856
  [terminatedAgentId, 'intermediate', team.id, 'terminated']
772
857
  );
773
858
 
774
859
  // Create multiple stories assigned to the terminated agent
775
- const story1 = createStory(db, {
860
+ const story1 = await createStory(db, {
776
861
  teamId: team.id,
777
862
  title: 'Orphaned Story 1',
778
863
  description: 'Test',
779
864
  });
780
- const story2 = createStory(db, {
865
+ const story2 = await createStory(db, {
781
866
  teamId: team.id,
782
867
  title: 'Orphaned Story 2',
783
868
  description: 'Test',
784
869
  });
785
870
 
786
- updateStory(db, story1.id, {
871
+ await updateStory(db, story1.id, {
787
872
  assignedAgentId: terminatedAgentId,
788
873
  status: 'in_progress',
789
874
  });
790
- updateStory(db, story2.id, {
875
+ await updateStory(db, story2.id, {
791
876
  assignedAgentId: terminatedAgentId,
792
877
  status: 'review',
793
878
  });
794
879
 
795
880
  // Get the recovery method
796
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp');
881
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp');
797
882
 
798
883
  // Verify both stories were recovered
799
884
  expect(recovered.length).toBe(2);
@@ -801,12 +886,12 @@ describe('Scheduler Orphaned Story Recovery', () => {
801
886
  expect(recovered).toContain(story2.id);
802
887
  });
803
888
 
804
- it('should write markdown files when storiesDir is provided during orphan recovery', () => {
889
+ it('should write markdown files when storiesDir is provided during orphan recovery', async () => {
805
890
  const storiesDir = join(tmpdir(), `hive-test-stories-${Date.now()}`);
806
891
  mkdirSync(storiesDir, { recursive: true });
807
892
 
808
893
  try {
809
- const team = createTeam(db, {
894
+ const team = await createTeam(db, {
810
895
  name: 'MD Test Team',
811
896
  repoUrl: 'https://github.com/test/repo',
812
897
  repoPath: 'test',
@@ -819,17 +904,17 @@ describe('Scheduler Orphaned Story Recovery', () => {
819
904
  [terminatedAgentId, 'intermediate', team.id, 'terminated']
820
905
  );
821
906
 
822
- const story = createStory(db, {
907
+ const story = await createStory(db, {
823
908
  teamId: team.id,
824
909
  title: 'Story with Markdown',
825
910
  description: 'Should get a markdown file on recovery',
826
911
  });
827
- updateStory(db, story.id, {
912
+ await updateStory(db, story.id, {
828
913
  assignedAgentId: terminatedAgentId,
829
914
  status: 'in_progress',
830
915
  });
831
916
 
832
- const recovered = detectAndRecoverOrphanedStories(db, '/tmp', storiesDir);
917
+ const recovered = await detectAndRecoverOrphanedStories(db, '/tmp', storiesDir);
833
918
 
834
919
  expect(recovered).toContain(story.id);
835
920
 
@@ -838,7 +923,7 @@ describe('Scheduler Orphaned Story Recovery', () => {
838
923
  expect(existsSync(mdPath)).toBe(true);
839
924
 
840
925
  // Verify markdown_path was set in DB
841
- const updatedStory = getStoryById(db, story.id);
926
+ const updatedStory = await getStoryById(db, story.id);
842
927
  expect(updatedStory?.markdown_path).toBe(mdPath);
843
928
  } finally {
844
929
  rmSync(storiesDir, { recursive: true, force: true });
@@ -858,33 +943,33 @@ describe('Scheduler Refactor Capacity Policy', () => {
858
943
  } as any;
859
944
  }
860
945
 
861
- it('should enforce refactor budget based on feature workload', () => {
862
- const team = createTeam(db, {
946
+ it('should enforce refactor budget based on feature workload', async () => {
947
+ const team = await createTeam(db, {
863
948
  name: 'Refactor Team',
864
949
  repoUrl: 'https://github.com/test/repo',
865
950
  repoPath: 'test',
866
951
  });
867
952
 
868
- const feature = createStory(db, {
953
+ const feature = await createStory(db, {
869
954
  teamId: team.id,
870
955
  title: 'Add endpoint',
871
956
  description: 'Feature story',
872
957
  });
873
- updateStory(db, feature.id, { status: 'planned', storyPoints: 10, complexityScore: 10 });
958
+ await updateStory(db, feature.id, { status: 'planned', storyPoints: 10, complexityScore: 10 });
874
959
 
875
- const refactorA = createStory(db, {
960
+ const refactorA = await createStory(db, {
876
961
  teamId: team.id,
877
962
  title: 'Refactor: clean parser',
878
963
  description: 'Refactor A',
879
964
  });
880
- updateStory(db, refactorA.id, { status: 'planned', storyPoints: 1, complexityScore: 1 });
965
+ await updateStory(db, refactorA.id, { status: 'planned', storyPoints: 1, complexityScore: 1 });
881
966
 
882
- const refactorB = createStory(db, {
967
+ const refactorB = await createStory(db, {
883
968
  teamId: team.id,
884
969
  title: 'Refactor: simplify auth flow',
885
970
  description: 'Refactor B',
886
971
  });
887
- updateStory(db, refactorB.id, { status: 'planned', storyPoints: 2, complexityScore: 2 });
972
+ await updateStory(db, refactorB.id, { status: 'planned', storyPoints: 2, complexityScore: 2 });
888
973
 
889
974
  const scalingConfig = createRefactorScalingConfig({
890
975
  enabled: true,
@@ -892,32 +977,32 @@ describe('Scheduler Refactor Capacity Policy', () => {
892
977
  allow_without_feature_work: true,
893
978
  });
894
979
 
895
- const selected = selectStoriesForCapacity(
980
+ const selected = (await selectStoriesForCapacity(
896
981
  [
897
- getStoryById(db, feature.id)!,
898
- getStoryById(db, refactorA.id)!,
899
- getStoryById(db, refactorB.id)!,
982
+ (await getStoryById(db, feature.id))!,
983
+ (await getStoryById(db, refactorA.id))!,
984
+ (await getStoryById(db, refactorB.id))!,
900
985
  ],
901
986
  scalingConfig
902
- ) as StoryRow[];
987
+ )) as StoryRow[];
903
988
 
904
989
  expect(selected.map(s => s.id)).toContain(feature.id);
905
990
  expect(selected.map(s => s.id)).toContain(refactorA.id);
906
991
  expect(selected.map(s => s.id)).not.toContain(refactorB.id);
907
992
  });
908
993
 
909
- it('should allow refactor-only queues when policy permits', () => {
910
- const team = createTeam(db, {
994
+ it('should allow refactor-only queues when policy permits', async () => {
995
+ const team = await createTeam(db, {
911
996
  name: 'Maintenance Team',
912
997
  repoUrl: 'https://github.com/test/repo',
913
998
  repoPath: 'test',
914
999
  });
915
- const refactor = createStory(db, {
1000
+ const refactor = await createStory(db, {
916
1001
  teamId: team.id,
917
1002
  title: 'Refactor: remove dead code',
918
1003
  description: 'Maintenance',
919
1004
  });
920
- updateStory(db, refactor.id, { status: 'planned', storyPoints: 3, complexityScore: 3 });
1005
+ await updateStory(db, refactor.id, { status: 'planned', storyPoints: 3, complexityScore: 3 });
921
1006
 
922
1007
  const scalingConfig = createRefactorScalingConfig({
923
1008
  enabled: true,
@@ -925,27 +1010,27 @@ describe('Scheduler Refactor Capacity Policy', () => {
925
1010
  allow_without_feature_work: true,
926
1011
  });
927
1012
 
928
- const selected = selectStoriesForCapacity(
929
- [getStoryById(db, refactor.id)!],
1013
+ const selected = (await selectStoriesForCapacity(
1014
+ [(await getStoryById(db, refactor.id))!],
930
1015
  scalingConfig
931
- ) as StoryRow[];
1016
+ )) as StoryRow[];
932
1017
 
933
1018
  expect(selected).toHaveLength(1);
934
1019
  expect(selected[0].id).toBe(refactor.id);
935
1020
  });
936
1021
 
937
- it('should block refactor-only queues when policy disallows it', () => {
938
- const team = createTeam(db, {
1022
+ it('should block refactor-only queues when policy disallows it', async () => {
1023
+ const team = await createTeam(db, {
939
1024
  name: 'Strict Team',
940
1025
  repoUrl: 'https://github.com/test/repo',
941
1026
  repoPath: 'test',
942
1027
  });
943
- const refactor = createStory(db, {
1028
+ const refactor = await createStory(db, {
944
1029
  teamId: team.id,
945
1030
  title: 'Refactor: rename internals',
946
1031
  description: 'Maintenance',
947
1032
  });
948
- updateStory(db, refactor.id, { status: 'planned', storyPoints: 2, complexityScore: 2 });
1033
+ await updateStory(db, refactor.id, { status: 'planned', storyPoints: 2, complexityScore: 2 });
949
1034
 
950
1035
  const scalingConfig = createRefactorScalingConfig({
951
1036
  enabled: true,
@@ -953,10 +1038,10 @@ describe('Scheduler Refactor Capacity Policy', () => {
953
1038
  allow_without_feature_work: false,
954
1039
  });
955
1040
 
956
- const selected = selectStoriesForCapacity(
957
- [getStoryById(db, refactor.id)!],
1041
+ const selected = (await selectStoriesForCapacity(
1042
+ [(await getStoryById(db, refactor.id))!],
958
1043
  scalingConfig
959
- ) as StoryRow[];
1044
+ )) as StoryRow[];
960
1045
 
961
1046
  expect(selected).toHaveLength(0);
962
1047
  });
@@ -1044,36 +1129,36 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1044
1129
  });
1045
1130
 
1046
1131
  // 5 tests: capacity point calculation
1047
- it('should use story_points when both story_points and complexity_score exist', () => {
1132
+ it('should use story_points when both story_points and complexity_score exist', async () => {
1048
1133
  expect(getCapacityPoints(mkStory('Feature', 8, 3))).toBe(8);
1049
1134
  });
1050
1135
 
1051
- it('should use complexity_score when story_points is null', () => {
1136
+ it('should use complexity_score when story_points is null', async () => {
1052
1137
  expect(getCapacityPoints(mkStory('Feature', null, 5))).toBe(5);
1053
1138
  });
1054
1139
 
1055
- it('should default to 1 when both story_points and complexity_score are null', () => {
1140
+ it('should default to 1 when both story_points and complexity_score are null', async () => {
1056
1141
  expect(getCapacityPoints(mkStory('Feature', null, null))).toBe(1);
1057
1142
  });
1058
1143
 
1059
- it('should treat story_points 0 as missing and fall back to complexity_score', () => {
1144
+ it('should treat story_points 0 as missing and fall back to complexity_score', async () => {
1060
1145
  expect(getCapacityPoints(mkStory('Feature', 0, 4))).toBe(4);
1061
1146
  });
1062
1147
 
1063
- it('should treat 0/0 points as minimum 1 capacity unit', () => {
1148
+ it('should treat 0/0 points as minimum 1 capacity unit', async () => {
1064
1149
  expect(getCapacityPoints(mkStory('Feature', 0, 0))).toBe(1);
1065
1150
  });
1066
1151
 
1067
- it('should use story_points when complexity_score is null', () => {
1152
+ it('should use story_points when complexity_score is null', async () => {
1068
1153
  expect(getCapacityPoints(mkStory('Feature', 6, null))).toBe(6);
1069
1154
  });
1070
1155
 
1071
- it('should pass through non-integer capacity points as provided', () => {
1156
+ it('should pass through non-integer capacity points as provided', async () => {
1072
1157
  expect(getCapacityPoints(mkStory('Feature', 2.5, null))).toBe(2.5);
1073
1158
  });
1074
1159
 
1075
1160
  // 12 tests: capacity selection behavior
1076
- it('should filter out refactor stories when refactor policy is disabled', () => {
1161
+ it('should filter out refactor stories when refactor policy is disabled', async () => {
1077
1162
  const scalingConfig = mkScalingConfig({
1078
1163
  enabled: false,
1079
1164
  capacity_percent: 100,
@@ -1082,12 +1167,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1082
1167
 
1083
1168
  const feature = mkStory('Feature: add endpoint', 8, 8);
1084
1169
  const refactor = mkStory('Refactor: split parser', 2, 2);
1085
- const selected = selectStoriesForCapacity([feature, refactor], scalingConfig) as StoryRow[];
1170
+ const selected = (await selectStoriesForCapacity(
1171
+ [feature, refactor],
1172
+ scalingConfig
1173
+ )) as StoryRow[];
1086
1174
 
1087
1175
  expect(selected.map(s => s.id)).toEqual([feature.id]);
1088
1176
  });
1089
1177
 
1090
- it('should include all refactor stories when capacity percent is 100', () => {
1178
+ it('should include all refactor stories when capacity percent is 100', async () => {
1091
1179
  const scalingConfig = mkScalingConfig({
1092
1180
  enabled: true,
1093
1181
  capacity_percent: 100,
@@ -1097,15 +1185,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1097
1185
  const feature = mkStory('Feature: add endpoint', 10, 10);
1098
1186
  const refactorA = mkStory('Refactor: split parser', 3, 3);
1099
1187
  const refactorB = mkStory('Refactor: normalize naming', 4, 4);
1100
- const selected = selectStoriesForCapacity(
1188
+ const selected = (await selectStoriesForCapacity(
1101
1189
  [feature, refactorA, refactorB],
1102
1190
  scalingConfig
1103
- ) as StoryRow[];
1191
+ )) as StoryRow[];
1104
1192
 
1105
1193
  expect(selected.map(s => s.id)).toEqual([feature.id, refactorA.id, refactorB.id]);
1106
1194
  });
1107
1195
 
1108
- it('should include no refactor stories when capacity percent is 0 and feature work exists', () => {
1196
+ it('should include no refactor stories when capacity percent is 0 and feature work exists', async () => {
1109
1197
  const scalingConfig = mkScalingConfig({
1110
1198
  enabled: true,
1111
1199
  capacity_percent: 0,
@@ -1114,12 +1202,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1114
1202
 
1115
1203
  const feature = mkStory('Feature: add endpoint', 10, 10);
1116
1204
  const refactor = mkStory('Refactor: split parser', 1, 1);
1117
- const selected = selectStoriesForCapacity([feature, refactor], scalingConfig) as StoryRow[];
1205
+ const selected = (await selectStoriesForCapacity(
1206
+ [feature, refactor],
1207
+ scalingConfig
1208
+ )) as StoryRow[];
1118
1209
 
1119
1210
  expect(selected.map(s => s.id)).toEqual([feature.id]);
1120
1211
  });
1121
1212
 
1122
- it('should allow at least one refactor point when percent is positive but rounded budget is zero', () => {
1213
+ it('should allow at least one refactor point when percent is positive but rounded budget is zero', async () => {
1123
1214
  const scalingConfig = mkScalingConfig({
1124
1215
  enabled: true,
1125
1216
  capacity_percent: 10,
@@ -1128,12 +1219,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1128
1219
 
1129
1220
  const feature = mkStory('Feature: tiny patch', 5, 5); // floor(5 * 0.1) = 0 -> min 1
1130
1221
  const refactor = mkStory('Refactor: tighten types', 1, 1);
1131
- const selected = selectStoriesForCapacity([feature, refactor], scalingConfig) as StoryRow[];
1222
+ const selected = (await selectStoriesForCapacity(
1223
+ [feature, refactor],
1224
+ scalingConfig
1225
+ )) as StoryRow[];
1132
1226
 
1133
1227
  expect(selected.map(s => s.id)).toEqual([feature.id, refactor.id]);
1134
1228
  });
1135
1229
 
1136
- it('should compute budget from total feature story points across multiple stories', () => {
1230
+ it('should compute budget from total feature story points across multiple stories', async () => {
1137
1231
  const scalingConfig = mkScalingConfig({
1138
1232
  enabled: true,
1139
1233
  capacity_percent: 20,
@@ -1145,15 +1239,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1145
1239
  const refactorA = mkStory('Refactor: A', 1, 1);
1146
1240
  const refactorB = mkStory('Refactor: B', 1, 1);
1147
1241
  const refactorC = mkStory('Refactor: C', 1, 1);
1148
- const selected = selectStoriesForCapacity(
1242
+ const selected = (await selectStoriesForCapacity(
1149
1243
  [featureA, featureB, refactorA, refactorB, refactorC],
1150
1244
  scalingConfig
1151
- ) as StoryRow[];
1245
+ )) as StoryRow[];
1152
1246
 
1153
1247
  expect(selected.map(s => s.id)).toEqual([featureA.id, featureB.id, refactorA.id, refactorB.id]);
1154
1248
  });
1155
1249
 
1156
- it('should skip a refactor story that exceeds remaining budget', () => {
1250
+ it('should skip a refactor story that exceeds remaining budget', async () => {
1157
1251
  const scalingConfig = mkScalingConfig({
1158
1252
  enabled: true,
1159
1253
  capacity_percent: 20,
@@ -1162,15 +1256,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1162
1256
 
1163
1257
  const feature = mkStory('Feature: A', 10, 10); // budget = 2
1164
1258
  const refactorLarge = mkStory('Refactor: big cleanup', 3, 3);
1165
- const selected = selectStoriesForCapacity(
1259
+ const selected = (await selectStoriesForCapacity(
1166
1260
  [feature, refactorLarge],
1167
1261
  scalingConfig
1168
- ) as StoryRow[];
1262
+ )) as StoryRow[];
1169
1263
 
1170
1264
  expect(selected.map(s => s.id)).toEqual([feature.id]);
1171
1265
  });
1172
1266
 
1173
- it('should select a later smaller refactor story if an earlier one exceeds budget', () => {
1267
+ it('should select a later smaller refactor story if an earlier one exceeds budget', async () => {
1174
1268
  const scalingConfig = mkScalingConfig({
1175
1269
  enabled: true,
1176
1270
  capacity_percent: 20,
@@ -1180,15 +1274,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1180
1274
  const feature = mkStory('Feature: A', 10, 10); // budget = 2
1181
1275
  const refactorLarge = mkStory('Refactor: big cleanup', 3, 3); // skipped
1182
1276
  const refactorSmall = mkStory('Refactor: tiny cleanup', 2, 2); // fits
1183
- const selected = selectStoriesForCapacity(
1277
+ const selected = (await selectStoriesForCapacity(
1184
1278
  [feature, refactorLarge, refactorSmall],
1185
1279
  scalingConfig
1186
- ) as StoryRow[];
1280
+ )) as StoryRow[];
1187
1281
 
1188
1282
  expect(selected.map(s => s.id)).toEqual([feature.id, refactorSmall.id]);
1189
1283
  });
1190
1284
 
1191
- it('should allow refactor-only queues when configured to allow without feature work', () => {
1285
+ it('should allow refactor-only queues when configured to allow without feature work', async () => {
1192
1286
  const scalingConfig = mkScalingConfig({
1193
1287
  enabled: true,
1194
1288
  capacity_percent: 10,
@@ -1197,12 +1291,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1197
1291
 
1198
1292
  const refactorA = mkStory('Refactor: A', 3, 3);
1199
1293
  const refactorB = mkStory('Refactor: B', 5, 5);
1200
- const selected = selectStoriesForCapacity([refactorA, refactorB], scalingConfig) as StoryRow[];
1294
+ const selected = (await selectStoriesForCapacity(
1295
+ [refactorA, refactorB],
1296
+ scalingConfig
1297
+ )) as StoryRow[];
1201
1298
 
1202
1299
  expect(selected.map(s => s.id)).toEqual([refactorA.id, refactorB.id]);
1203
1300
  });
1204
1301
 
1205
- it('should block refactor-only queues when allow_without_feature_work is false', () => {
1302
+ it('should block refactor-only queues when allow_without_feature_work is false', async () => {
1206
1303
  const scalingConfig = mkScalingConfig({
1207
1304
  enabled: true,
1208
1305
  capacity_percent: 10,
@@ -1211,12 +1308,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1211
1308
 
1212
1309
  const refactorA = mkStory('Refactor: A', 3, 3);
1213
1310
  const refactorB = mkStory('Refactor: B', 5, 5);
1214
- const selected = selectStoriesForCapacity([refactorA, refactorB], scalingConfig) as StoryRow[];
1311
+ const selected = (await selectStoriesForCapacity(
1312
+ [refactorA, refactorB],
1313
+ scalingConfig
1314
+ )) as StoryRow[];
1215
1315
 
1216
1316
  expect(selected).toHaveLength(0);
1217
1317
  });
1218
1318
 
1219
- it('should preserve order of selected stories', () => {
1319
+ it('should preserve order of selected stories', async () => {
1220
1320
  const scalingConfig = mkScalingConfig({
1221
1321
  enabled: true,
1222
1322
  capacity_percent: 20,
@@ -1227,36 +1327,39 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1227
1327
  const refactorA = mkStory('Refactor: A', 1, 1);
1228
1328
  const featureB = mkStory('Feature: B', 5, 5);
1229
1329
  const refactorB = mkStory('Refactor: B', 1, 1);
1230
- const selected = selectStoriesForCapacity(
1330
+ const selected = (await selectStoriesForCapacity(
1231
1331
  [featureA, refactorA, featureB, refactorB],
1232
1332
  scalingConfig
1233
- ) as StoryRow[];
1333
+ )) as StoryRow[];
1234
1334
 
1235
1335
  expect(selected.map(s => s.id)).toEqual([featureA.id, refactorA.id, featureB.id, refactorB.id]);
1236
1336
  });
1237
1337
 
1238
- it('should default to disabled behavior when refactor config is missing', () => {
1338
+ it('should default to disabled behavior when refactor config is missing', async () => {
1239
1339
  const scalingConfig = mkScalingConfig();
1240
1340
 
1241
1341
  const feature = mkStory('Feature: A', 5, 5);
1242
1342
  const refactor = mkStory('Refactor: A', 1, 1);
1243
- const selected = selectStoriesForCapacity([feature, refactor], scalingConfig) as StoryRow[];
1343
+ const selected = (await selectStoriesForCapacity(
1344
+ [feature, refactor],
1345
+ scalingConfig
1346
+ )) as StoryRow[];
1244
1347
 
1245
1348
  expect(selected.map(s => s.id)).toEqual([feature.id]);
1246
1349
  });
1247
1350
 
1248
- it('should return an empty array when no stories are provided', () => {
1351
+ it('should return an empty array when no stories are provided', async () => {
1249
1352
  const scalingConfig = mkScalingConfig({
1250
1353
  enabled: true,
1251
1354
  capacity_percent: 50,
1252
1355
  allow_without_feature_work: true,
1253
1356
  });
1254
1357
 
1255
- const selected = selectStoriesForCapacity([], scalingConfig) as StoryRow[];
1358
+ const selected = (await selectStoriesForCapacity([], scalingConfig)) as StoryRow[];
1256
1359
  expect(selected).toEqual([]);
1257
1360
  });
1258
1361
 
1259
- it('should include refactor stories when cumulative points exactly match budget', () => {
1362
+ it('should include refactor stories when cumulative points exactly match budget', async () => {
1260
1363
  const scalingConfig = mkScalingConfig({
1261
1364
  enabled: true,
1262
1365
  capacity_percent: 30,
@@ -1266,15 +1369,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1266
1369
  const feature = mkStory('Feature: A', 10, 10); // budget = 3
1267
1370
  const refactorA = mkStory('Refactor: A', 1, 1);
1268
1371
  const refactorB = mkStory('Refactor: B', 2, 2);
1269
- const selected = selectStoriesForCapacity(
1372
+ const selected = (await selectStoriesForCapacity(
1270
1373
  [feature, refactorA, refactorB],
1271
1374
  scalingConfig
1272
- ) as StoryRow[];
1375
+ )) as StoryRow[];
1273
1376
 
1274
1377
  expect(selected.map(s => s.id)).toEqual([feature.id, refactorA.id, refactorB.id]);
1275
1378
  });
1276
1379
 
1277
- it('should continue selecting later refactors after partially consuming budget and skipping a too-large one', () => {
1380
+ it('should continue selecting later refactors after partially consuming budget and skipping a too-large one', async () => {
1278
1381
  const scalingConfig = mkScalingConfig({
1279
1382
  enabled: true,
1280
1383
  capacity_percent: 50,
@@ -1285,15 +1388,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1285
1388
  const refactorA = mkStory('Refactor: A', 2, 2); // used = 2
1286
1389
  const refactorLarge = mkStory('Refactor: Large', 4, 4); // skipped (2 + 4 > 5)
1287
1390
  const refactorB = mkStory('Refactor: B', 3, 3); // used = 5
1288
- const selected = selectStoriesForCapacity(
1391
+ const selected = (await selectStoriesForCapacity(
1289
1392
  [feature, refactorA, refactorLarge, refactorB],
1290
1393
  scalingConfig
1291
- ) as StoryRow[];
1394
+ )) as StoryRow[];
1292
1395
 
1293
1396
  expect(selected.map(s => s.id)).toEqual([feature.id, refactorA.id, refactorB.id]);
1294
1397
  });
1295
1398
 
1296
- it('should derive feature budget from complexity when story_points are not set', () => {
1399
+ it('should derive feature budget from complexity when story_points are not set', async () => {
1297
1400
  const scalingConfig = mkScalingConfig({
1298
1401
  enabled: true,
1299
1402
  capacity_percent: 20,
@@ -1304,15 +1407,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1304
1407
  const featureB = mkStory('Feature: B', null, 4); // feature total = 10, budget = 2
1305
1408
  const refactorA = mkStory('Refactor: A', 1, 1);
1306
1409
  const refactorB = mkStory('Refactor: B', 2, 2);
1307
- const selected = selectStoriesForCapacity(
1410
+ const selected = (await selectStoriesForCapacity(
1308
1411
  [featureA, featureB, refactorA, refactorB],
1309
1412
  scalingConfig
1310
- ) as StoryRow[];
1413
+ )) as StoryRow[];
1311
1414
 
1312
1415
  expect(selected.map(s => s.id)).toEqual([featureA.id, featureB.id, refactorA.id]);
1313
1416
  });
1314
1417
 
1315
- it('should allow one point of refactor work when feature stories have no explicit points', () => {
1418
+ it('should allow one point of refactor work when feature stories have no explicit points', async () => {
1316
1419
  const scalingConfig = mkScalingConfig({
1317
1420
  enabled: true,
1318
1421
  capacity_percent: 10,
@@ -1322,15 +1425,15 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1322
1425
  const feature = mkStory('Feature: A', null, null); // defaults to 1, floor(1 * 0.1)=0 -> min 1
1323
1426
  const refactorA = mkStory('Refactor: A', 1, 1);
1324
1427
  const refactorB = mkStory('Refactor: B', 1, 1);
1325
- const selected = selectStoriesForCapacity(
1428
+ const selected = (await selectStoriesForCapacity(
1326
1429
  [feature, refactorA, refactorB],
1327
1430
  scalingConfig
1328
- ) as StoryRow[];
1431
+ )) as StoryRow[];
1329
1432
 
1330
1433
  expect(selected.map(s => s.id)).toEqual([feature.id, refactorA.id]);
1331
1434
  });
1332
1435
 
1333
- it('should ignore capacity_percent for refactor-only queues when allow_without_feature_work is true', () => {
1436
+ it('should ignore capacity_percent for refactor-only queues when allow_without_feature_work is true', async () => {
1334
1437
  const scalingConfig = mkScalingConfig({
1335
1438
  enabled: true,
1336
1439
  capacity_percent: 0,
@@ -1339,38 +1442,53 @@ describe('Scheduler Refactor Policy Test Matrix', () => {
1339
1442
 
1340
1443
  const refactorA = mkStory('Refactor: A', 2, 2);
1341
1444
  const refactorB = mkStory('Refactor: B', 4, 4);
1342
- const selected = selectStoriesForCapacity([refactorA, refactorB], scalingConfig) as StoryRow[];
1445
+ const selected = (await selectStoriesForCapacity(
1446
+ [refactorA, refactorB],
1447
+ scalingConfig
1448
+ )) as StoryRow[];
1343
1449
 
1344
1450
  expect(selected.map(s => s.id)).toEqual([refactorA.id, refactorB.id]);
1345
1451
  });
1346
1452
  });
1347
1453
 
1348
1454
  describe('Scheduler Agent Selection', () => {
1349
- it('should select agent with least workload from multiple agents', () => {
1350
- const team = createTeam(db, {
1455
+ it('should select agent with least workload from multiple agents', async () => {
1456
+ const team = await createTeam(db, {
1351
1457
  name: 'Test Team',
1352
1458
  repoUrl: 'https://github.com/test/repo',
1353
1459
  repoPath: 'test',
1354
1460
  });
1355
1461
 
1356
1462
  // Create three junior agents with different workloads
1357
- db.run(
1463
+ db.db.run(
1358
1464
  `INSERT INTO agents (id, type, team_id, status) VALUES ('junior-1', 'junior', '${team.id}', 'idle')`
1359
1465
  );
1360
- db.run(
1466
+ db.db.run(
1361
1467
  `INSERT INTO agents (id, type, team_id, status) VALUES ('junior-2', 'junior', '${team.id}', 'idle')`
1362
1468
  );
1363
- db.run(
1469
+ db.db.run(
1364
1470
  `INSERT INTO agents (id, type, team_id, status) VALUES ('junior-3', 'junior', '${team.id}', 'idle')`
1365
1471
  );
1366
1472
 
1367
1473
  // Give junior-1 two stories, junior-2 one story, junior-3 zero stories
1368
- const story1 = createStory(db, { teamId: team.id, title: 'Story 1', description: 'Test' });
1369
- const story2 = createStory(db, { teamId: team.id, title: 'Story 2', description: 'Test' });
1370
- const story3 = createStory(db, { teamId: team.id, title: 'Story 3', description: 'Test' });
1371
- updateStory(db, story1.id, { assignedAgentId: 'junior-1', status: 'in_progress' });
1372
- updateStory(db, story2.id, { assignedAgentId: 'junior-1', status: 'in_progress' });
1373
- updateStory(db, story3.id, { assignedAgentId: 'junior-2', status: 'in_progress' });
1474
+ const story1 = await createStory(db, {
1475
+ teamId: team.id,
1476
+ title: 'Story 1',
1477
+ description: 'Test',
1478
+ });
1479
+ const story2 = await createStory(db, {
1480
+ teamId: team.id,
1481
+ title: 'Story 2',
1482
+ description: 'Test',
1483
+ });
1484
+ const story3 = await createStory(db, {
1485
+ teamId: team.id,
1486
+ title: 'Story 3',
1487
+ description: 'Test',
1488
+ });
1489
+ await updateStory(db, story1.id, { assignedAgentId: 'junior-1', status: 'in_progress' });
1490
+ await updateStory(db, story2.id, { assignedAgentId: 'junior-1', status: 'in_progress' });
1491
+ await updateStory(db, story3.id, { assignedAgentId: 'junior-2', status: 'in_progress' });
1374
1492
 
1375
1493
  const agents = [
1376
1494
  {
@@ -1420,14 +1538,14 @@ describe('Scheduler Agent Selection', () => {
1420
1538
  },
1421
1539
  ];
1422
1540
 
1423
- const selected = selectAgentWithLeastWorkload(db, agents);
1541
+ const selected = await selectAgentWithLeastWorkload(db, agents);
1424
1542
 
1425
1543
  // Should select junior-3 who has zero stories
1426
1544
  expect(selected.id).toBe('junior-3');
1427
1545
  });
1428
1546
 
1429
- it('should select first agent when all have equal workload', () => {
1430
- const team = createTeam(db, {
1547
+ it('should select first agent when all have equal workload', async () => {
1548
+ const team = await createTeam(db, {
1431
1549
  name: 'Test Team',
1432
1550
  repoUrl: 'https://github.com/test/repo',
1433
1551
  repoPath: 'test',
@@ -1466,86 +1584,94 @@ describe('Scheduler Agent Selection', () => {
1466
1584
  },
1467
1585
  ];
1468
1586
 
1469
- const selected = selectAgentWithLeastWorkload(db, agents);
1587
+ const selected = await selectAgentWithLeastWorkload(db, agents);
1470
1588
 
1471
1589
  expect(selected.id).toBe('agent-1');
1472
1590
  });
1473
1591
 
1474
- it('should calculate agent workload correctly', () => {
1475
- const team = createTeam(db, {
1592
+ it('should calculate agent workload correctly', async () => {
1593
+ const team = await createTeam(db, {
1476
1594
  name: 'Test Team',
1477
1595
  repoUrl: 'https://github.com/test/repo',
1478
1596
  repoPath: 'test',
1479
1597
  });
1480
- db.run(
1598
+ db.db.run(
1481
1599
  `INSERT INTO agents (id, type, team_id, status) VALUES ('agent-1', 'junior', '${team.id}', 'idle')`
1482
1600
  );
1483
1601
 
1484
- const story1 = createStory(db, { teamId: team.id, title: 'Story 1', description: 'Test' });
1485
- const story2 = createStory(db, { teamId: team.id, title: 'Story 2', description: 'Test' });
1486
- updateStory(db, story1.id, { assignedAgentId: 'agent-1', status: 'in_progress' });
1487
- updateStory(db, story2.id, { assignedAgentId: 'agent-1', status: 'in_progress' });
1602
+ const story1 = await createStory(db, {
1603
+ teamId: team.id,
1604
+ title: 'Story 1',
1605
+ description: 'Test',
1606
+ });
1607
+ const story2 = await createStory(db, {
1608
+ teamId: team.id,
1609
+ title: 'Story 2',
1610
+ description: 'Test',
1611
+ });
1612
+ await updateStory(db, story1.id, { assignedAgentId: 'agent-1', status: 'in_progress' });
1613
+ await updateStory(db, story2.id, { assignedAgentId: 'agent-1', status: 'in_progress' });
1488
1614
 
1489
- const workload = getAgentWorkload(db, 'agent-1');
1615
+ const workload = await getAgentWorkload(db, 'agent-1');
1490
1616
 
1491
1617
  expect(workload).toBe(2);
1492
1618
  });
1493
1619
 
1494
- it('should return zero workload for agent with no stories', () => {
1495
- const team = createTeam(db, {
1620
+ it('should return zero workload for agent with no stories', async () => {
1621
+ const team = await createTeam(db, {
1496
1622
  name: 'Test Team',
1497
1623
  repoUrl: 'https://github.com/test/repo',
1498
1624
  repoPath: 'test',
1499
1625
  });
1500
- db.run(
1626
+ db.db.run(
1501
1627
  `INSERT INTO agents (id, type, team_id, status) VALUES ('agent-1', 'junior', '${team.id}', 'idle')`
1502
1628
  );
1503
1629
 
1504
- const workload = getAgentWorkload(db, 'agent-1');
1630
+ const workload = await getAgentWorkload(db, 'agent-1');
1505
1631
 
1506
1632
  expect(workload).toBe(0);
1507
1633
  });
1508
1634
  });
1509
1635
 
1510
1636
  describe('Scheduler Complexity Routing', () => {
1511
- it('should route low complexity stories to junior agents', () => {
1637
+ it('should route low complexity stories to junior agents', async () => {
1512
1638
  // Test the routing logic: complexity <= junior_max_complexity goes to junior
1513
1639
  const complexity = 2;
1514
1640
  expect(complexity).toBeLessThanOrEqual(mockConfig.scaling.junior_max_complexity);
1515
1641
  });
1516
1642
 
1517
- it('should route medium complexity stories to intermediate agents', () => {
1643
+ it('should route medium complexity stories to intermediate agents', async () => {
1518
1644
  // Test the routing logic: complexity between junior and intermediate thresholds
1519
1645
  const complexity = 4;
1520
1646
  expect(complexity).toBeGreaterThan(mockConfig.scaling.junior_max_complexity);
1521
1647
  expect(complexity).toBeLessThanOrEqual(mockConfig.scaling.intermediate_max_complexity);
1522
1648
  });
1523
1649
 
1524
- it('should route high complexity stories to senior agents', () => {
1650
+ it('should route high complexity stories to senior agents', async () => {
1525
1651
  // Test the routing logic: complexity > intermediate_max_complexity goes to senior
1526
1652
  const complexity = 8;
1527
1653
  expect(complexity).toBeGreaterThan(mockConfig.scaling.intermediate_max_complexity);
1528
1654
  });
1529
1655
 
1530
- it('should handle edge case at junior boundary', () => {
1656
+ it('should handle edge case at junior boundary', async () => {
1531
1657
  // Complexity exactly at junior_max_complexity should still go to junior
1532
1658
  const complexity = 3;
1533
1659
  expect(complexity).toBeLessThanOrEqual(mockConfig.scaling.junior_max_complexity);
1534
1660
  });
1535
1661
 
1536
- it('should handle edge case at intermediate boundary', () => {
1662
+ it('should handle edge case at intermediate boundary', async () => {
1537
1663
  // Complexity exactly at intermediate_max_complexity should still go to intermediate
1538
1664
  const complexity = 5;
1539
1665
  expect(complexity).toBeLessThanOrEqual(mockConfig.scaling.intermediate_max_complexity);
1540
1666
  });
1541
1667
 
1542
- it('should use config values for routing thresholds', () => {
1668
+ it('should use config values for routing thresholds', async () => {
1543
1669
  // Verify config values are set correctly for routing logic
1544
1670
  expect(mockConfig.scaling.junior_max_complexity).toBe(3);
1545
1671
  expect(mockConfig.scaling.intermediate_max_complexity).toBe(5);
1546
1672
  });
1547
1673
 
1548
- it('should default to complexity 5 when not specified', () => {
1674
+ it('should default to complexity 5 when not specified', async () => {
1549
1675
  // Test default complexity value used in assignStories
1550
1676
  const complexity = null;
1551
1677
  const defaultComplexity = complexity || 5;
@@ -1554,115 +1680,131 @@ describe('Scheduler Complexity Routing', () => {
1554
1680
  });
1555
1681
 
1556
1682
  describe('Scheduler Story Assignment Prevention', () => {
1557
- it('should prevent duplicate story assignments', () => {
1558
- const team = createTeam(db, {
1683
+ it('should prevent duplicate story assignments', async () => {
1684
+ const team = await createTeam(db, {
1559
1685
  name: 'Test Team',
1560
1686
  repoUrl: 'https://github.com/test/repo',
1561
1687
  repoPath: 'test',
1562
1688
  });
1563
- db.run(
1689
+ db.db.run(
1564
1690
  `INSERT INTO agents (id, type, team_id, status) VALUES ('agent-1', 'junior', '${team.id}', 'idle')`
1565
1691
  );
1566
1692
 
1567
1693
  // Create a story and assign it
1568
- const story = createStory(db, {
1694
+ const story = await createStory(db, {
1569
1695
  teamId: team.id,
1570
1696
  title: 'Story',
1571
1697
  description: 'Test',
1572
1698
  });
1573
- updateStory(db, story.id, { complexityScore: 2, status: 'planned' });
1699
+ await updateStory(db, story.id, { complexityScore: 2, status: 'planned' });
1574
1700
 
1575
1701
  // First assignment
1576
- updateStory(db, story.id, { assignedAgentId: 'agent-1', status: 'in_progress' });
1702
+ await updateStory(db, story.id, { assignedAgentId: 'agent-1', status: 'in_progress' });
1577
1703
 
1578
1704
  // Verify the story is now assigned
1579
- const result = db.exec(`SELECT assigned_agent_id FROM stories WHERE id = '${story.id}'`);
1705
+ const result = db.db.exec(`SELECT assigned_agent_id FROM stories WHERE id = '${story.id}'`);
1580
1706
  expect(result[0].values[0][0]).toBe('agent-1');
1581
1707
  });
1582
1708
 
1583
- it('should verify story assignment changes status', () => {
1584
- const team = createTeam(db, {
1709
+ it('should verify story assignment changes status', async () => {
1710
+ const team = await createTeam(db, {
1585
1711
  name: 'Test Team',
1586
1712
  repoUrl: 'https://github.com/test/repo',
1587
1713
  repoPath: 'test',
1588
1714
  });
1589
1715
 
1590
- const story = createStory(db, {
1716
+ const story = await createStory(db, {
1591
1717
  teamId: team.id,
1592
1718
  title: 'Story',
1593
1719
  description: 'Test',
1594
1720
  });
1595
- updateStory(db, story.id, { status: 'planned' });
1721
+ await updateStory(db, story.id, { status: 'planned' });
1596
1722
 
1597
1723
  // Change status to in_progress
1598
- updateStory(db, story.id, { status: 'in_progress' });
1724
+ await updateStory(db, story.id, { status: 'in_progress' });
1599
1725
 
1600
1726
  // Verify status changed
1601
- const result = db.exec(`SELECT status FROM stories WHERE id = '${story.id}'`);
1727
+ const result = db.db.exec(`SELECT status FROM stories WHERE id = '${story.id}'`);
1602
1728
  expect(result[0].values[0][0]).toBe('in_progress');
1603
1729
  });
1604
1730
 
1605
- it('should skip stories with unsatisfied dependencies', () => {
1606
- const team = createTeam(db, {
1731
+ it('should skip stories with unsatisfied dependencies', async () => {
1732
+ const team = await createTeam(db, {
1607
1733
  name: 'Test Team',
1608
1734
  repoUrl: 'https://github.com/test/repo',
1609
1735
  repoPath: 'test',
1610
1736
  });
1611
- const storyA = createStory(db, { teamId: team.id, title: 'Story A', description: 'Test' });
1612
- updateStory(db, storyA.id, { status: 'planned' });
1613
- const storyB = createStory(db, { teamId: team.id, title: 'Story B', description: 'Test' });
1614
- updateStory(db, storyB.id, { status: 'planned' });
1737
+ const storyA = await createStory(db, {
1738
+ teamId: team.id,
1739
+ title: 'Story A',
1740
+ description: 'Test',
1741
+ });
1742
+ await updateStory(db, storyA.id, { status: 'planned' });
1743
+ const storyB = await createStory(db, {
1744
+ teamId: team.id,
1745
+ title: 'Story B',
1746
+ description: 'Test',
1747
+ });
1748
+ await updateStory(db, storyB.id, { status: 'planned' });
1615
1749
 
1616
1750
  // B depends on A, but A is still planned
1617
- addStoryDependency(db, storyB.id, storyA.id);
1751
+ await addStoryDependency(db, storyB.id, storyA.id);
1618
1752
 
1619
1753
  // B should not be ready for assignment because A is not merged yet
1620
- const satisfied = areDependenciesSatisfied(db, storyB.id);
1754
+ const satisfied = await areDependenciesSatisfied(db, storyB.id);
1621
1755
  expect(satisfied).toBe(false);
1622
1756
  });
1623
1757
 
1624
- it('should allow stories when dependencies are in terminal states', () => {
1625
- const team = createTeam(db, {
1758
+ it('should allow stories when dependencies are in terminal states', async () => {
1759
+ const team = await createTeam(db, {
1626
1760
  name: 'Test Team',
1627
1761
  repoUrl: 'https://github.com/test/repo',
1628
1762
  repoPath: 'test',
1629
1763
  });
1630
1764
 
1631
1765
  // Test with merged status (terminal state)
1632
- const storyA = createStory(db, { teamId: team.id, title: 'Story A', description: 'Test' });
1633
- const storyB = createStory(db, { teamId: team.id, title: 'Story B', description: 'Test' });
1766
+ const storyA = await createStory(db, {
1767
+ teamId: team.id,
1768
+ title: 'Story A',
1769
+ description: 'Test',
1770
+ });
1771
+ const storyB = await createStory(db, {
1772
+ teamId: team.id,
1773
+ title: 'Story B',
1774
+ description: 'Test',
1775
+ });
1634
1776
 
1635
1777
  // Update A to merged status
1636
- updateStory(db, storyA.id, { status: 'merged' });
1778
+ await updateStory(db, storyA.id, { status: 'merged' });
1637
1779
 
1638
1780
  // B depends on A, and A is merged
1639
- addStoryDependency(db, storyB.id, storyA.id);
1781
+ await addStoryDependency(db, storyB.id, storyA.id);
1640
1782
 
1641
1783
  // B should be ready for assignment
1642
- const satisfied = areDependenciesSatisfied(db, storyB.id);
1784
+ const satisfied = await areDependenciesSatisfied(db, storyB.id);
1643
1785
  expect(satisfied).toBe(true);
1644
1786
  });
1645
1787
 
1646
- it('should map claude model IDs to claude runtime shorthands', () => {
1788
+ it('should map claude model IDs to claude runtime shorthands', async () => {
1647
1789
  const runtimeModel = (scheduler as any).getRuntimeModel('claude-sonnet-4-5-20250929', 'claude');
1648
1790
  expect(runtimeModel).toBe('sonnet');
1649
1791
  });
1650
1792
 
1651
- it('should remap unsupported codex mini model and preserve gemini runtime model', () => {
1793
+ it('should remap unsupported codex mini model and preserve gemini runtime model', async () => {
1652
1794
  const codexModel = (scheduler as any).getRuntimeModel('gpt-4o-mini', 'codex');
1653
1795
  const geminiModel = (scheduler as any).getRuntimeModel('gemini-2.5-pro', 'gemini');
1654
1796
  expect(codexModel).toBe('gpt-5.2-codex');
1655
1797
  expect(geminiModel).toBe('gemini-2.5-pro');
1656
1798
  });
1657
1799
 
1658
- it('should not fallback unknown claude models to haiku', () => {
1800
+ it('should not fallback unknown claude models to haiku', async () => {
1659
1801
  const runtimeModel = (scheduler as any).getRuntimeModel('claude-custom-model', 'claude');
1660
1802
  expect(runtimeModel).toBe('claude-custom-model');
1661
1803
  });
1662
1804
 
1663
- it('should detect godmode is active when an active requirement has godmode enabled', () => {
1805
+ it('should detect godmode is active when an active requirement has godmode enabled', async () => {
1664
1806
  // Create a requirement with godmode and set it to planning status
1665
- const req = createRequirement(db, {
1807
+ const req = await createRequirement(db, {
1666
1808
  title: 'Godmode Requirement',
1667
1809
  description: 'Test requirement with godmode',
1668
1810
  godmode: true,
@@ -1670,19 +1812,19 @@ describe('Scheduler Story Assignment Prevention', () => {
1670
1812
  db.run(`UPDATE requirements SET status = 'planning' WHERE id = ?`, [req.id]);
1671
1813
 
1672
1814
  // Godmode should be detected as active
1673
- const isGodmodeActive = (scheduler as any).isGodmodeActive();
1815
+ const isGodmodeActive = await (scheduler as any).isGodmodeActive();
1674
1816
  expect(isGodmodeActive).toBe(true);
1675
1817
  });
1676
1818
 
1677
- it('should detect godmode even when all stories have moved to in_progress', () => {
1678
- const team = createTeam(db, {
1819
+ it('should detect godmode even when all stories have moved to in_progress', async () => {
1820
+ const team = await createTeam(db, {
1679
1821
  name: 'Test Team',
1680
1822
  repoUrl: 'https://github.com/test/repo',
1681
1823
  repoPath: 'test',
1682
1824
  });
1683
1825
 
1684
1826
  // Create a godmode requirement in in_progress status
1685
- const req = createRequirement(db, {
1827
+ const req = await createRequirement(db, {
1686
1828
  title: 'Godmode Requirement',
1687
1829
  description: 'Test requirement with godmode',
1688
1830
  godmode: true,
@@ -1690,22 +1832,22 @@ describe('Scheduler Story Assignment Prevention', () => {
1690
1832
  db.run(`UPDATE requirements SET status = 'in_progress' WHERE id = ?`, [req.id]);
1691
1833
 
1692
1834
  // Create a story that has moved to in_progress (no longer planned)
1693
- const story = createStory(db, {
1835
+ const story = await createStory(db, {
1694
1836
  requirementId: req.id,
1695
1837
  teamId: team.id,
1696
1838
  title: 'Godmode Story',
1697
1839
  description: 'Test',
1698
1840
  });
1699
- updateStory(db, story.id, { status: 'in_progress' });
1841
+ await updateStory(db, story.id, { status: 'in_progress' });
1700
1842
 
1701
1843
  // Godmode should still be active even though no stories are planned
1702
- const isGodmodeActive = (scheduler as any).isGodmodeActive();
1844
+ const isGodmodeActive = await (scheduler as any).isGodmodeActive();
1703
1845
  expect(isGodmodeActive).toBe(true);
1704
1846
  });
1705
1847
 
1706
- it('should not detect godmode when no requirements have godmode enabled', () => {
1848
+ it('should not detect godmode when no requirements have godmode enabled', async () => {
1707
1849
  // Create a normal requirement (without godmode) in planning status
1708
- const req = createRequirement(db, {
1850
+ const req = await createRequirement(db, {
1709
1851
  title: 'Normal Requirement',
1710
1852
  description: 'Test requirement without godmode',
1711
1853
  godmode: false,
@@ -1713,13 +1855,13 @@ describe('Scheduler Story Assignment Prevention', () => {
1713
1855
  db.run(`UPDATE requirements SET status = 'planning' WHERE id = ?`, [req.id]);
1714
1856
 
1715
1857
  // Godmode should not be detected as active
1716
- const isGodmodeActive = (scheduler as any).isGodmodeActive();
1858
+ const isGodmodeActive = await (scheduler as any).isGodmodeActive();
1717
1859
  expect(isGodmodeActive).toBe(false);
1718
1860
  });
1719
1861
 
1720
- it('should not detect godmode when godmode requirement is completed', () => {
1862
+ it('should not detect godmode when godmode requirement is completed', async () => {
1721
1863
  // Create a godmode requirement that is already completed
1722
- const req = createRequirement(db, {
1864
+ const req = await createRequirement(db, {
1723
1865
  title: 'Godmode Requirement',
1724
1866
  description: 'Test requirement with godmode',
1725
1867
  godmode: true,
@@ -1727,34 +1869,34 @@ describe('Scheduler Story Assignment Prevention', () => {
1727
1869
  db.run(`UPDATE requirements SET status = 'completed' WHERE id = ?`, [req.id]);
1728
1870
 
1729
1871
  // Godmode should not be active for completed requirements
1730
- const isGodmodeActive = (scheduler as any).isGodmodeActive();
1872
+ const isGodmodeActive = await (scheduler as any).isGodmodeActive();
1731
1873
  expect(isGodmodeActive).toBe(false);
1732
1874
  });
1733
1875
 
1734
- it('should not detect godmode when no requirements exist', () => {
1876
+ it('should not detect godmode when no requirements exist', async () => {
1735
1877
  // No requirements created, so godmode cannot be active
1736
- const isGodmodeActive = (scheduler as any).isGodmodeActive();
1878
+ const isGodmodeActive = await (scheduler as any).isGodmodeActive();
1737
1879
  expect(isGodmodeActive).toBe(false);
1738
1880
  });
1739
1881
  });
1740
1882
 
1741
1883
  describe('Scheduler Agent Reassignment for Working Agents with NULL currentStoryId', () => {
1742
- it('should consider working agents with null current_story_id as available for assignment', () => {
1743
- const team = createTeam(db, {
1884
+ it('should consider working agents with null current_story_id as available for assignment', async () => {
1885
+ const team = await createTeam(db, {
1744
1886
  name: 'Test Team',
1745
1887
  repoUrl: 'https://github.com/test/repo',
1746
1888
  repoPath: 'test',
1747
1889
  });
1748
1890
 
1749
1891
  // Create a working agent with no current story (effectively idle)
1750
- db.run(
1892
+ db.db.run(
1751
1893
  `INSERT INTO agents (id, type, team_id, status, current_story_id, created_at, updated_at)
1752
1894
  VALUES (?, ?, ?, ?, NULL, datetime('now'), datetime('now'))`,
1753
1895
  ['senior-orphan-1', 'senior', team.id, 'working']
1754
1896
  );
1755
1897
 
1756
1898
  // Query agents using the same filter logic from assignStories
1757
- const result = db.exec(
1899
+ const result = db.db.exec(
1758
1900
  `SELECT id, type, status, current_story_id FROM agents
1759
1901
  WHERE team_id = '${team.id}' AND type != 'qa'
1760
1902
  AND (status = 'idle' OR (status = 'working' AND current_story_id IS NULL))`
@@ -1764,24 +1906,24 @@ describe('Scheduler Agent Reassignment for Working Agents with NULL currentStory
1764
1906
  expect(result[0].values[0][0]).toBe('senior-orphan-1');
1765
1907
  });
1766
1908
 
1767
- it('should not consider working agents with a current story as available', () => {
1768
- const team = createTeam(db, {
1909
+ it('should not consider working agents with a current story as available', async () => {
1910
+ const team = await createTeam(db, {
1769
1911
  name: 'Test Team',
1770
1912
  repoUrl: 'https://github.com/test/repo',
1771
1913
  repoPath: 'test',
1772
1914
  });
1773
1915
 
1774
- const story = createStory(db, { teamId: team.id, title: 'Active', description: 'Test' });
1916
+ const story = await createStory(db, { teamId: team.id, title: 'Active', description: 'Test' });
1775
1917
 
1776
1918
  // Create a working agent with a current story
1777
- db.run(
1919
+ db.db.run(
1778
1920
  `INSERT INTO agents (id, type, team_id, status, current_story_id, created_at, updated_at)
1779
1921
  VALUES (?, ?, ?, ?, ?, datetime('now'), datetime('now'))`,
1780
1922
  ['senior-busy-1', 'senior', team.id, 'working', story.id]
1781
1923
  );
1782
1924
 
1783
1925
  // Query agents using the same filter logic from assignStories
1784
- const result = db.exec(
1926
+ const result = db.db.exec(
1785
1927
  `SELECT id, type, status, current_story_id FROM agents
1786
1928
  WHERE team_id = '${team.id}' AND type != 'qa'
1787
1929
  AND (status = 'idle' OR (status = 'working' AND current_story_id IS NULL))`
@@ -1818,19 +1960,19 @@ describe('Scheduler checkMergeQueue', () => {
1818
1960
  it('should spawn QA when a queued PR exists for an in_progress story', async () => {
1819
1961
  ensurePullRequestsTable();
1820
1962
 
1821
- const team = createTeam(db, {
1963
+ const team = await createTeam(db, {
1822
1964
  name: 'Test Team',
1823
1965
  repoUrl: 'https://github.com/test/repo',
1824
1966
  repoPath: 'test',
1825
1967
  });
1826
- const story = createStory(db, {
1968
+ const story = await createStory(db, {
1827
1969
  teamId: team.id,
1828
1970
  title: 'Queued PR Story',
1829
1971
  description: 'Story has queued PR but stale in_progress status',
1830
1972
  });
1831
- updateStory(db, story.id, { status: 'in_progress' });
1973
+ await updateStory(db, story.id, { status: 'in_progress' });
1832
1974
 
1833
- createPullRequest(db, {
1975
+ await createPullRequest(db, {
1834
1976
  storyId: story.id,
1835
1977
  teamId: team.id,
1836
1978
  branchName: 'feature/queued-pr-story',
@@ -1856,19 +1998,19 @@ describe('Scheduler checkMergeQueue', () => {
1856
1998
  it('should not spawn QA for merged stories even if PR row is still queued', async () => {
1857
1999
  ensurePullRequestsTable();
1858
2000
 
1859
- const team = createTeam(db, {
2001
+ const team = await createTeam(db, {
1860
2002
  name: 'Test Team',
1861
2003
  repoUrl: 'https://github.com/test/repo',
1862
2004
  repoPath: 'test',
1863
2005
  });
1864
- const story = createStory(db, {
2006
+ const story = await createStory(db, {
1865
2007
  teamId: team.id,
1866
2008
  title: 'Merged Story',
1867
2009
  description: 'Merged stories should not drive QA scaling',
1868
2010
  });
1869
- updateStory(db, story.id, { status: 'merged' });
2011
+ await updateStory(db, story.id, { status: 'merged' });
1870
2012
 
1871
- createPullRequest(db, {
2013
+ await createPullRequest(db, {
1872
2014
  storyId: story.id,
1873
2015
  teamId: team.id,
1874
2016
  branchName: 'feature/merged-story',
@@ -1893,24 +2035,24 @@ describe('Scheduler checkMergeQueue', () => {
1893
2035
 
1894
2036
  describe('Scheduler checkScaling', () => {
1895
2037
  it('should spawn a new indexed senior when the base senior is busy', async () => {
1896
- const team = createTeam(db, {
2038
+ const team = await createTeam(db, {
1897
2039
  name: 'Busy Senior Team',
1898
2040
  repoUrl: 'https://github.com/test/repo',
1899
2041
  repoPath: 'test',
1900
2042
  });
1901
2043
 
1902
- db.run(
2044
+ db.db.run(
1903
2045
  `INSERT INTO agents (id, type, team_id, status, current_story_id, created_at, updated_at)
1904
2046
  VALUES (?, ?, ?, ?, ?, datetime('now'), datetime('now'))`,
1905
2047
  ['senior-busy-1', 'senior', team.id, 'working', 'STORY-OLD']
1906
2048
  );
1907
2049
 
1908
- const story = createStory(db, {
2050
+ const story = await createStory(db, {
1909
2051
  teamId: team.id,
1910
2052
  title: 'Needs Senior',
1911
2053
  description: 'High complexity story',
1912
2054
  });
1913
- updateStory(db, story.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2055
+ await updateStory(db, story.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
1914
2056
 
1915
2057
  const spawnSeniorSpy = vi
1916
2058
  .spyOn(scheduler as any, 'spawnSenior')
@@ -1936,11 +2078,11 @@ describe('Scheduler checkScaling', () => {
1936
2078
  expect(result.assigned).toBe(1);
1937
2079
  expect(spawnSeniorSpy).toHaveBeenCalledTimes(1);
1938
2080
 
1939
- const updatedStory = getStoryById(db, story.id)!;
2081
+ const updatedStory = (await getStoryById(db, story.id))!;
1940
2082
  expect(updatedStory.status).toBe('in_progress');
1941
2083
  expect(updatedStory.assigned_agent_id).toBe('senior-spawned-2');
1942
2084
 
1943
- const busySeniorRow = db.exec(
2085
+ const busySeniorRow = db.db.exec(
1944
2086
  `SELECT status, current_story_id FROM agents WHERE id = 'senior-busy-1'`
1945
2087
  )[0]?.values[0];
1946
2088
  expect(busySeniorRow?.[0]).toBe('working');
@@ -1950,7 +2092,7 @@ describe('Scheduler checkScaling', () => {
1950
2092
  });
1951
2093
 
1952
2094
  it('should choose next senior index from max active index when index 1 is absent', async () => {
1953
- const team = createTeam(db, {
2095
+ const team = await createTeam(db, {
1954
2096
  name: 'Gap Index Team',
1955
2097
  repoUrl: 'https://github.com/test/repo',
1956
2098
  repoPath: 'test',
@@ -1974,12 +2116,12 @@ describe('Scheduler checkScaling', () => {
1974
2116
  );
1975
2117
  }
1976
2118
 
1977
- const story = createStory(db, {
2119
+ const story = await createStory(db, {
1978
2120
  teamId: team.id,
1979
2121
  title: 'Gap Index Story',
1980
2122
  description: 'Requires spawning the next indexed senior',
1981
2123
  });
1982
- updateStory(db, story.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2124
+ await updateStory(db, story.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
1983
2125
 
1984
2126
  const spawnSeniorSpy = vi
1985
2127
  .spyOn(scheduler as any, 'spawnSenior')
@@ -2005,37 +2147,37 @@ describe('Scheduler checkScaling', () => {
2005
2147
 
2006
2148
  expect(result.assigned).toBe(1);
2007
2149
  expect(spawnSeniorSpy).toHaveBeenCalledTimes(1);
2008
- expect(getStoryById(db, story.id)?.assigned_agent_id).toBe('senior-gap-6');
2150
+ expect((await getStoryById(db, story.id))?.assigned_agent_id).toBe('senior-gap-6');
2009
2151
 
2010
2152
  spawnSeniorSpy.mockRestore();
2011
2153
  });
2012
2154
 
2013
2155
  it('should not assign multiple stories to the same senior in one cycle', async () => {
2014
- const team = createTeam(db, {
2156
+ const team = await createTeam(db, {
2015
2157
  name: 'Single Senior Team',
2016
2158
  repoUrl: 'https://github.com/test/repo',
2017
2159
  repoPath: 'test',
2018
2160
  });
2019
2161
 
2020
- db.run(
2162
+ db.db.run(
2021
2163
  `INSERT INTO agents (id, type, team_id, status, current_story_id, created_at, updated_at)
2022
2164
  VALUES (?, ?, ?, ?, NULL, datetime('now'), datetime('now'))`,
2023
2165
  ['senior-single-1', 'senior', team.id, 'idle']
2024
2166
  );
2025
2167
 
2026
- const story1 = createStory(db, {
2168
+ const story1 = await createStory(db, {
2027
2169
  teamId: team.id,
2028
2170
  title: 'High Complexity 1',
2029
2171
  description: 'Needs senior',
2030
2172
  });
2031
- updateStory(db, story1.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2173
+ await updateStory(db, story1.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2032
2174
 
2033
- const story2 = createStory(db, {
2175
+ const story2 = await createStory(db, {
2034
2176
  teamId: team.id,
2035
2177
  title: 'High Complexity 2',
2036
2178
  description: 'Needs senior too',
2037
2179
  });
2038
- updateStory(db, story2.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2180
+ await updateStory(db, story2.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2039
2181
 
2040
2182
  const spawnSeniorSpy = vi
2041
2183
  .spyOn(scheduler as any, 'spawnSenior')
@@ -2047,45 +2189,45 @@ describe('Scheduler checkScaling', () => {
2047
2189
  expect(result.errors.some(e => e.includes('Failed to spawn Senior'))).toBe(true);
2048
2190
  expect(spawnSeniorSpy).toHaveBeenCalledTimes(1);
2049
2191
 
2050
- const updatedStory1 = getStoryById(db, story1.id)!;
2051
- const updatedStory2 = getStoryById(db, story2.id)!;
2052
- const inProgress = [updatedStory1, updatedStory2].filter(s => s.status === 'in_progress');
2053
- const planned = [updatedStory1, updatedStory2].filter(s => s.status === 'planned');
2192
+ const updatedStory1 = (await getStoryById(db, story1.id))!;
2193
+ const updatedStory2 = (await getStoryById(db, story2.id))!;
2194
+ const inProgress = [updatedStory1, updatedStory2].filter(s => s!.status === 'in_progress');
2195
+ const planned = [updatedStory1, updatedStory2].filter(s => s!.status === 'planned');
2054
2196
 
2055
2197
  expect(inProgress).toHaveLength(1);
2056
2198
  expect(planned).toHaveLength(1);
2057
- expect(inProgress[0].assigned_agent_id).toBe('senior-single-1');
2058
- expect(planned[0].assigned_agent_id).toBeNull();
2199
+ expect(inProgress[0]!.assigned_agent_id).toBe('senior-single-1');
2200
+ expect(planned[0]!.assigned_agent_id).toBeNull();
2059
2201
 
2060
- const seniorRow = db.exec(
2202
+ const seniorRow = db.db.exec(
2061
2203
  `SELECT status, current_story_id FROM agents WHERE id = 'senior-single-1'`
2062
2204
  )[0]?.values[0];
2063
2205
  expect(seniorRow?.[0]).toBe('working');
2064
- expect(seniorRow?.[1]).toBe(inProgress[0].id);
2206
+ expect(seniorRow?.[1]).toBe(inProgress[0]!.id);
2065
2207
 
2066
2208
  spawnSeniorSpy.mockRestore();
2067
2209
  });
2068
2210
 
2069
2211
  it('should send an explicit assignment handoff to the assigned tmux session', async () => {
2070
- const team = createTeam(db, {
2212
+ const team = await createTeam(db, {
2071
2213
  name: 'Handoff Team',
2072
2214
  repoUrl: 'https://github.com/test/repo',
2073
2215
  repoPath: 'test',
2074
2216
  });
2075
2217
 
2076
2218
  const sessionName = 'hive-senior-handoff-team';
2077
- db.run(
2219
+ db.db.run(
2078
2220
  `INSERT INTO agents (id, type, team_id, tmux_session, status, current_story_id, created_at, updated_at)
2079
2221
  VALUES (?, ?, ?, ?, ?, NULL, datetime('now'), datetime('now'))`,
2080
2222
  ['senior-handoff-1', 'senior', team.id, sessionName, 'idle']
2081
2223
  );
2082
2224
 
2083
- const story = createStory(db, {
2225
+ const story = await createStory(db, {
2084
2226
  teamId: team.id,
2085
2227
  title: 'Needs Context Reset',
2086
2228
  description: 'Verify assignment handoff message is sent',
2087
2229
  });
2088
- updateStory(db, story.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2230
+ await updateStory(db, story.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2089
2231
 
2090
2232
  const isRunningSpy = vi.spyOn(tmuxModule, 'isTmuxSessionRunning').mockResolvedValue(true);
2091
2233
  const sendSpy = vi.spyOn(tmuxModule, 'sendToTmuxSession').mockResolvedValue();
@@ -2104,7 +2246,7 @@ describe('Scheduler checkScaling', () => {
2104
2246
  });
2105
2247
 
2106
2248
  it('should reject spawning a senior on a busy existing session', async () => {
2107
- const team = createTeam(db, {
2249
+ const team = await createTeam(db, {
2108
2250
  name: 'Spawn Guard Team',
2109
2251
  repoUrl: 'https://github.com/test/repo',
2110
2252
  repoPath: 'test',
@@ -2113,7 +2255,7 @@ describe('Scheduler checkScaling', () => {
2113
2255
  const hiveDir = join(mockConfig.rootDir, '.hive');
2114
2256
  const expectedSession = generateSessionName('senior', team.name, undefined, hiveDir);
2115
2257
 
2116
- db.run(
2258
+ db.db.run(
2117
2259
  `INSERT INTO agents (id, type, team_id, tmux_session, status, current_story_id, created_at, updated_at)
2118
2260
  VALUES (?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))`,
2119
2261
  ['senior-guard-1', 'senior', team.id, expectedSession, 'working', 'STORY-ACTIVE']
@@ -2129,38 +2271,38 @@ describe('Scheduler checkScaling', () => {
2129
2271
  });
2130
2272
 
2131
2273
  it('should only spawn agents for assignable stories (unblocked dependencies)', async () => {
2132
- const team = createTeam(db, {
2274
+ const team = await createTeam(db, {
2133
2275
  name: 'Test Team',
2134
2276
  repoUrl: 'https://github.com/test/repo',
2135
2277
  repoPath: 'test',
2136
2278
  });
2137
2279
 
2138
2280
  // Create a blocker story that is not yet merged
2139
- const blockerStory = createStory(db, {
2281
+ const blockerStory = await createStory(db, {
2140
2282
  teamId: team.id,
2141
2283
  title: 'Blocker Story',
2142
2284
  description: 'Must be completed first',
2143
2285
  });
2144
- updateStory(db, blockerStory.id, { status: 'planned', storyPoints: 10 });
2286
+ await updateStory(db, blockerStory.id, { status: 'planned', storyPoints: 10 });
2145
2287
 
2146
2288
  // Create 4 stories that depend on the blocker (cannot be assigned yet)
2147
2289
  for (let i = 1; i <= 4; i++) {
2148
- const story = createStory(db, {
2290
+ const story = await createStory(db, {
2149
2291
  teamId: team.id,
2150
2292
  title: `Blocked Story ${i}`,
2151
2293
  description: 'Depends on blocker',
2152
2294
  });
2153
- updateStory(db, story.id, { status: 'planned', storyPoints: 10 });
2154
- addStoryDependency(db, story.id, blockerStory.id);
2295
+ await updateStory(db, story.id, { status: 'planned', storyPoints: 10 });
2296
+ await addStoryDependency(db, story.id, blockerStory.id);
2155
2297
  }
2156
2298
 
2157
2299
  // Create 1 story with no dependencies (can be assigned)
2158
- const unblockedStory = createStory(db, {
2300
+ const unblockedStory = await createStory(db, {
2159
2301
  teamId: team.id,
2160
2302
  title: 'Unblocked Story',
2161
2303
  description: 'No dependencies',
2162
2304
  });
2163
- updateStory(db, unblockedStory.id, { status: 'planned', storyPoints: 10 });
2305
+ await updateStory(db, unblockedStory.id, { status: 'planned', storyPoints: 10 });
2164
2306
 
2165
2307
  // Total: 50 story points, but only 10 are assignable
2166
2308
  // With senior_capacity: 50, this should spawn 1 senior (10/50 = 0.2, ceil = 1)
@@ -2184,29 +2326,29 @@ describe('Scheduler checkScaling', () => {
2184
2326
  });
2185
2327
 
2186
2328
  it('should not spawn agents when all stories are blocked', async () => {
2187
- const team = createTeam(db, {
2329
+ const team = await createTeam(db, {
2188
2330
  name: 'Test Team',
2189
2331
  repoUrl: 'https://github.com/test/repo',
2190
2332
  repoPath: 'test',
2191
2333
  });
2192
2334
 
2193
2335
  // Create a blocker story that is not yet merged
2194
- const blockerStory = createStory(db, {
2336
+ const blockerStory = await createStory(db, {
2195
2337
  teamId: team.id,
2196
2338
  title: 'Blocker Story',
2197
2339
  description: 'Must be completed first',
2198
2340
  });
2199
- updateStory(db, blockerStory.id, { status: 'planned', storyPoints: 10 });
2341
+ await updateStory(db, blockerStory.id, { status: 'planned', storyPoints: 10 });
2200
2342
 
2201
2343
  // Create stories that all depend on the blocker
2202
2344
  for (let i = 1; i <= 5; i++) {
2203
- const story = createStory(db, {
2345
+ const story = await createStory(db, {
2204
2346
  teamId: team.id,
2205
2347
  title: `Blocked Story ${i}`,
2206
2348
  description: 'Depends on blocker',
2207
2349
  });
2208
- updateStory(db, story.id, { status: 'planned', storyPoints: 10 });
2209
- addStoryDependency(db, story.id, blockerStory.id);
2350
+ await updateStory(db, story.id, { status: 'planned', storyPoints: 10 });
2351
+ await addStoryDependency(db, story.id, blockerStory.id);
2210
2352
  }
2211
2353
 
2212
2354
  // Mock spawnSenior to track calls
@@ -2244,25 +2386,25 @@ describe('Scheduler Markdown File Writing', () => {
2244
2386
  });
2245
2387
 
2246
2388
  it('should write markdown files when assigning stories via scheduler', async () => {
2247
- const team = createTeam(db, {
2389
+ const team = await createTeam(db, {
2248
2390
  name: 'MD Write Team',
2249
2391
  repoUrl: 'https://github.com/test/repo',
2250
2392
  repoPath: 'test',
2251
2393
  });
2252
2394
 
2253
2395
  // Create an idle senior agent
2254
- db.run(
2396
+ db.db.run(
2255
2397
  `INSERT INTO agents (id, type, team_id, status, created_at, updated_at)
2256
2398
  VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))`,
2257
2399
  ['senior-md-1', 'senior', team.id, 'idle']
2258
2400
  );
2259
2401
 
2260
- const story = createStory(db, {
2402
+ const story = await createStory(db, {
2261
2403
  teamId: team.id,
2262
2404
  title: 'Markdown Test Story',
2263
2405
  description: 'Should get a markdown file on assignment',
2264
2406
  });
2265
- updateStory(db, story.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2407
+ await updateStory(db, story.id, { status: 'planned', complexityScore: 10, storyPoints: 8 });
2266
2408
 
2267
2409
  // Create scheduler with rootDir pointing to a temp dir that has .hive/stories/
2268
2410
  const hiveRoot = join(tmpdir(), `hive-md-root-${Date.now()}`);
@@ -2286,7 +2428,7 @@ describe('Scheduler Markdown File Writing', () => {
2286
2428
  expect(existsSync(mdPath)).toBe(true);
2287
2429
 
2288
2430
  // Verify markdown_path was set in DB
2289
- const updatedStory = getStoryById(db, story.id);
2431
+ const updatedStory = await getStoryById(db, story.id);
2290
2432
  expect(updatedStory?.markdown_path).toBe(mdPath);
2291
2433
  expect(updatedStory?.status).toBe('in_progress');
2292
2434
 
@@ -2295,22 +2437,22 @@ describe('Scheduler Markdown File Writing', () => {
2295
2437
  });
2296
2438
 
2297
2439
  describe('Scheduler Target Branch Propagation', () => {
2298
- it('should retrieve target_branch from requirement when creating story', () => {
2299
- const team = createTeam(db, {
2440
+ it('should retrieve target_branch from requirement when creating story', async () => {
2441
+ const team = await createTeam(db, {
2300
2442
  name: 'Test Team',
2301
2443
  repoUrl: 'https://github.com/test/repo',
2302
2444
  repoPath: 'test',
2303
2445
  });
2304
2446
 
2305
2447
  // Create a requirement with custom target_branch
2306
- const requirement = createRequirement(db, {
2448
+ const requirement = await createRequirement(db, {
2307
2449
  title: 'Feature for Release Branch',
2308
2450
  description: 'Test feature',
2309
2451
  targetBranch: 'release/v2.0',
2310
2452
  });
2311
2453
 
2312
2454
  // Create a story linked to this requirement
2313
- const story = createStory(db, {
2455
+ const story = await createStory(db, {
2314
2456
  teamId: team.id,
2315
2457
  requirementId: requirement.id,
2316
2458
  title: 'Story for Release',
@@ -2322,55 +2464,55 @@ describe('Scheduler Target Branch Propagation', () => {
2322
2464
  expect(story.team_id).toBe(team.id);
2323
2465
 
2324
2466
  // Verify we can retrieve the requirement and its target_branch
2325
- const retrievedReq = db.exec(
2467
+ const retrievedReq = db.db.exec(
2326
2468
  `SELECT target_branch FROM requirements WHERE id = '${requirement.id}'`
2327
2469
  )[0]?.values[0];
2328
2470
  expect(retrievedReq?.[0]).toBe('release/v2.0');
2329
2471
  });
2330
2472
 
2331
- it('should use default target_branch (main) when requirement has no custom branch', () => {
2473
+ it('should use default target_branch (main) when requirement has no custom branch', async () => {
2332
2474
  // Create a requirement without specifying target_branch
2333
- const requirement = createRequirement(db, {
2475
+ const requirement = await createRequirement(db, {
2334
2476
  title: 'Feature for Main Branch',
2335
2477
  description: 'Test feature',
2336
2478
  });
2337
2479
 
2338
2480
  // Verify the requirement defaults to main branch
2339
- const retrievedReq = db.exec(
2481
+ const retrievedReq = db.db.exec(
2340
2482
  `SELECT target_branch FROM requirements WHERE id = '${requirement.id}'`
2341
2483
  )[0]?.values[0];
2342
2484
  expect(retrievedReq?.[0]).toBe('main');
2343
2485
  });
2344
2486
 
2345
- it('should handle stories with different target branches from different requirements', () => {
2346
- const team = createTeam(db, {
2487
+ it('should handle stories with different target branches from different requirements', async () => {
2488
+ const team = await createTeam(db, {
2347
2489
  name: 'Test Team',
2348
2490
  repoUrl: 'https://github.com/test/repo',
2349
2491
  repoPath: 'test',
2350
2492
  });
2351
2493
 
2352
2494
  // Create two requirements with different target branches
2353
- const req1 = createRequirement(db, {
2495
+ const req1 = await createRequirement(db, {
2354
2496
  title: 'Main Feature',
2355
2497
  description: 'Goes to main',
2356
2498
  targetBranch: 'main',
2357
2499
  });
2358
2500
 
2359
- const req2 = createRequirement(db, {
2501
+ const req2 = await createRequirement(db, {
2360
2502
  title: 'Staging Feature',
2361
2503
  description: 'Goes to staging',
2362
2504
  targetBranch: 'staging',
2363
2505
  });
2364
2506
 
2365
2507
  // Create stories for each requirement
2366
- const story1 = createStory(db, {
2508
+ const story1 = await createStory(db, {
2367
2509
  teamId: team.id,
2368
2510
  requirementId: req1.id,
2369
2511
  title: 'Story 1',
2370
2512
  description: 'Test',
2371
2513
  });
2372
2514
 
2373
- const story2 = createStory(db, {
2515
+ const story2 = await createStory(db, {
2374
2516
  teamId: team.id,
2375
2517
  requirementId: req2.id,
2376
2518
  title: 'Story 2',
@@ -2378,7 +2520,7 @@ describe('Scheduler Target Branch Propagation', () => {
2378
2520
  });
2379
2521
 
2380
2522
  // Verify each story can access its requirement's target_branch via JOIN
2381
- const result = db.exec(
2523
+ const result = db.db.exec(
2382
2524
  `SELECT s.id, r.target_branch
2383
2525
  FROM stories s
2384
2526
  LEFT JOIN requirements r ON s.requirement_id = r.id
@@ -2392,15 +2534,15 @@ describe('Scheduler Target Branch Propagation', () => {
2392
2534
  expect(branches).toContain('staging');
2393
2535
  });
2394
2536
 
2395
- it('should handle stories without a linked requirement (null requirement_id)', () => {
2396
- const team = createTeam(db, {
2537
+ it('should handle stories without a linked requirement (null requirement_id)', async () => {
2538
+ const team = await createTeam(db, {
2397
2539
  name: 'Test Team',
2398
2540
  repoUrl: 'https://github.com/test/repo',
2399
2541
  repoPath: 'test',
2400
2542
  });
2401
2543
 
2402
2544
  // Create a story without a requirement
2403
- const story = createStory(db, {
2545
+ const story = await createStory(db, {
2404
2546
  teamId: team.id,
2405
2547
  title: 'Standalone Story',
2406
2548
  description: 'No requirement',
@@ -2409,7 +2551,7 @@ describe('Scheduler Target Branch Propagation', () => {
2409
2551
  expect(story.requirement_id).toBeNull();
2410
2552
 
2411
2553
  // When joining with requirements, should get null for target_branch
2412
- const result = db.exec(
2554
+ const result = db.db.exec(
2413
2555
  `SELECT s.id, r.target_branch
2414
2556
  FROM stories s
2415
2557
  LEFT JOIN requirements r ON s.requirement_id = r.id