@amsterdamdatalabs/enact-factory 0.1.1

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 (644) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +566 -0
  3. package/dist/adapters/agenticLoop.d.ts +90 -0
  4. package/dist/adapters/agenticLoop.d.ts.map +1 -0
  5. package/dist/adapters/agenticLoop.js +219 -0
  6. package/dist/adapters/agenticLoop.js.map +1 -0
  7. package/dist/adapters/base.d.ts +16 -0
  8. package/dist/adapters/base.d.ts.map +1 -0
  9. package/dist/adapters/base.js +135 -0
  10. package/dist/adapters/base.js.map +1 -0
  11. package/dist/adapters/claude.d.ts +13 -0
  12. package/dist/adapters/claude.d.ts.map +1 -0
  13. package/dist/adapters/claude.js +318 -0
  14. package/dist/adapters/claude.js.map +1 -0
  15. package/dist/adapters/codex.d.ts +14 -0
  16. package/dist/adapters/codex.d.ts.map +1 -0
  17. package/dist/adapters/codex.js +366 -0
  18. package/dist/adapters/codex.js.map +1 -0
  19. package/dist/adapters/cryptoQuantAdapter.d.ts +85 -0
  20. package/dist/adapters/cryptoQuantAdapter.d.ts.map +1 -0
  21. package/dist/adapters/cryptoQuantAdapter.js +238 -0
  22. package/dist/adapters/cryptoQuantAdapter.js.map +1 -0
  23. package/dist/adapters/cursor.d.ts +13 -0
  24. package/dist/adapters/cursor.d.ts.map +1 -0
  25. package/dist/adapters/cursor.js +300 -0
  26. package/dist/adapters/cursor.js.map +1 -0
  27. package/dist/adapters/envPath.d.ts +20 -0
  28. package/dist/adapters/envPath.d.ts.map +1 -0
  29. package/dist/adapters/envPath.js +49 -0
  30. package/dist/adapters/envPath.js.map +1 -0
  31. package/dist/adapters/hermes.d.ts +13 -0
  32. package/dist/adapters/hermes.d.ts.map +1 -0
  33. package/dist/adapters/hermes.js +283 -0
  34. package/dist/adapters/hermes.js.map +1 -0
  35. package/dist/adapters/index.d.ts +18 -0
  36. package/dist/adapters/index.d.ts.map +1 -0
  37. package/dist/adapters/index.js +56 -0
  38. package/dist/adapters/index.js.map +1 -0
  39. package/dist/adapters/opencode.d.ts +13 -0
  40. package/dist/adapters/opencode.d.ts.map +1 -0
  41. package/dist/adapters/opencode.js +282 -0
  42. package/dist/adapters/opencode.js.map +1 -0
  43. package/dist/adapters/processRegistry.d.ts +38 -0
  44. package/dist/adapters/processRegistry.d.ts.map +1 -0
  45. package/dist/adapters/processRegistry.js +147 -0
  46. package/dist/adapters/processRegistry.js.map +1 -0
  47. package/dist/adapters/responses.d.ts +16 -0
  48. package/dist/adapters/responses.d.ts.map +1 -0
  49. package/dist/adapters/responses.js +244 -0
  50. package/dist/adapters/responses.js.map +1 -0
  51. package/dist/adapters/streamBuffer.d.ts +59 -0
  52. package/dist/adapters/streamBuffer.d.ts.map +1 -0
  53. package/dist/adapters/streamBuffer.js +123 -0
  54. package/dist/adapters/streamBuffer.js.map +1 -0
  55. package/dist/adapters/tools.d.ts +30 -0
  56. package/dist/adapters/tools.d.ts.map +1 -0
  57. package/dist/adapters/tools.js +219 -0
  58. package/dist/adapters/tools.js.map +1 -0
  59. package/dist/adapters/types.d.ts +82 -0
  60. package/dist/adapters/types.d.ts.map +1 -0
  61. package/dist/adapters/types.js +6 -0
  62. package/dist/adapters/types.js.map +1 -0
  63. package/dist/agents/agentBus.d.ts +160 -0
  64. package/dist/agents/agentBus.d.ts.map +1 -0
  65. package/dist/agents/agentBus.js +350 -0
  66. package/dist/agents/agentBus.js.map +1 -0
  67. package/dist/agents/agentPair.d.ts +215 -0
  68. package/dist/agents/agentPair.d.ts.map +1 -0
  69. package/dist/agents/agentPair.js +456 -0
  70. package/dist/agents/agentPair.js.map +1 -0
  71. package/dist/agents/auditor.d.ts +27 -0
  72. package/dist/agents/auditor.d.ts.map +1 -0
  73. package/dist/agents/auditor.js +238 -0
  74. package/dist/agents/auditor.js.map +1 -0
  75. package/dist/agents/cliStreamParser.d.ts +18 -0
  76. package/dist/agents/cliStreamParser.d.ts.map +1 -0
  77. package/dist/agents/cliStreamParser.js +156 -0
  78. package/dist/agents/cliStreamParser.js.map +1 -0
  79. package/dist/agents/documenter.d.ts +31 -0
  80. package/dist/agents/documenter.d.ts.map +1 -0
  81. package/dist/agents/documenter.js +286 -0
  82. package/dist/agents/documenter.js.map +1 -0
  83. package/dist/agents/draftAnalyzer.d.ts +50 -0
  84. package/dist/agents/draftAnalyzer.d.ts.map +1 -0
  85. package/dist/agents/draftAnalyzer.js +289 -0
  86. package/dist/agents/draftAnalyzer.js.map +1 -0
  87. package/dist/agents/evaluator.d.ts +61 -0
  88. package/dist/agents/evaluator.d.ts.map +1 -0
  89. package/dist/agents/evaluator.js +338 -0
  90. package/dist/agents/evaluator.js.map +1 -0
  91. package/dist/agents/executor.d.ts +33 -0
  92. package/dist/agents/executor.d.ts.map +1 -0
  93. package/dist/agents/executor.js +130 -0
  94. package/dist/agents/executor.js.map +1 -0
  95. package/dist/agents/index.d.ts +10 -0
  96. package/dist/agents/index.d.ts.map +1 -0
  97. package/dist/agents/index.js +10 -0
  98. package/dist/agents/index.js.map +1 -0
  99. package/dist/agents/pairMetrics.d.ts +63 -0
  100. package/dist/agents/pairMetrics.d.ts.map +1 -0
  101. package/dist/agents/pairMetrics.js +232 -0
  102. package/dist/agents/pairMetrics.js.map +1 -0
  103. package/dist/agents/pairPipeline.d.ts +184 -0
  104. package/dist/agents/pairPipeline.d.ts.map +1 -0
  105. package/dist/agents/pairPipeline.js +934 -0
  106. package/dist/agents/pairPipeline.js.map +1 -0
  107. package/dist/agents/pairWebhook.d.ts +59 -0
  108. package/dist/agents/pairWebhook.d.ts.map +1 -0
  109. package/dist/agents/pairWebhook.js +242 -0
  110. package/dist/agents/pairWebhook.js.map +1 -0
  111. package/dist/agents/pipelineFormat.d.ts +8 -0
  112. package/dist/agents/pipelineFormat.d.ts.map +1 -0
  113. package/dist/agents/pipelineFormat.js +65 -0
  114. package/dist/agents/pipelineFormat.js.map +1 -0
  115. package/dist/agents/pipelineGuards.d.ts +23 -0
  116. package/dist/agents/pipelineGuards.d.ts.map +1 -0
  117. package/dist/agents/pipelineGuards.js +257 -0
  118. package/dist/agents/pipelineGuards.js.map +1 -0
  119. package/dist/agents/reviewer.d.ts +37 -0
  120. package/dist/agents/reviewer.d.ts.map +1 -0
  121. package/dist/agents/reviewer.js +214 -0
  122. package/dist/agents/reviewer.js.map +1 -0
  123. package/dist/agents/skillDocumenter.d.ts +23 -0
  124. package/dist/agents/skillDocumenter.d.ts.map +1 -0
  125. package/dist/agents/skillDocumenter.js +219 -0
  126. package/dist/agents/skillDocumenter.js.map +1 -0
  127. package/dist/agents/tester.d.ts +37 -0
  128. package/dist/agents/tester.d.ts.map +1 -0
  129. package/dist/agents/tester.js +309 -0
  130. package/dist/agents/tester.js.map +1 -0
  131. package/dist/automation/autonomousRunner.d.ts +145 -0
  132. package/dist/automation/autonomousRunner.d.ts.map +1 -0
  133. package/dist/automation/autonomousRunner.js +1272 -0
  134. package/dist/automation/autonomousRunner.js.map +1 -0
  135. package/dist/automation/dailyReporter.d.ts +26 -0
  136. package/dist/automation/dailyReporter.d.ts.map +1 -0
  137. package/dist/automation/dailyReporter.js +130 -0
  138. package/dist/automation/dailyReporter.js.map +1 -0
  139. package/dist/automation/index.d.ts +5 -0
  140. package/dist/automation/index.d.ts.map +1 -0
  141. package/dist/automation/index.js +5 -0
  142. package/dist/automation/index.js.map +1 -0
  143. package/dist/automation/longRunningMonitor.d.ts +26 -0
  144. package/dist/automation/longRunningMonitor.d.ts.map +1 -0
  145. package/dist/automation/longRunningMonitor.js +356 -0
  146. package/dist/automation/longRunningMonitor.js.map +1 -0
  147. package/dist/automation/prOwnership.d.ts +18 -0
  148. package/dist/automation/prOwnership.d.ts.map +1 -0
  149. package/dist/automation/prOwnership.js +61 -0
  150. package/dist/automation/prOwnership.js.map +1 -0
  151. package/dist/automation/runnerExecution.d.ts +57 -0
  152. package/dist/automation/runnerExecution.d.ts.map +1 -0
  153. package/dist/automation/runnerExecution.js +701 -0
  154. package/dist/automation/runnerExecution.js.map +1 -0
  155. package/dist/automation/runnerState.d.ts +170 -0
  156. package/dist/automation/runnerState.d.ts.map +1 -0
  157. package/dist/automation/runnerState.js +496 -0
  158. package/dist/automation/runnerState.js.map +1 -0
  159. package/dist/automation/runnerTypes.d.ts +57 -0
  160. package/dist/automation/runnerTypes.d.ts.map +1 -0
  161. package/dist/automation/runnerTypes.js +5 -0
  162. package/dist/automation/runnerTypes.js.map +1 -0
  163. package/dist/automation/scheduler.d.ts +75 -0
  164. package/dist/automation/scheduler.d.ts.map +1 -0
  165. package/dist/automation/scheduler.js +402 -0
  166. package/dist/automation/scheduler.js.map +1 -0
  167. package/dist/azdo/azdo.d.ts +70 -0
  168. package/dist/azdo/azdo.d.ts.map +1 -0
  169. package/dist/azdo/azdo.js +328 -0
  170. package/dist/azdo/azdo.js.map +1 -0
  171. package/dist/azdo/index.d.ts +3 -0
  172. package/dist/azdo/index.d.ts.map +1 -0
  173. package/dist/azdo/index.js +3 -0
  174. package/dist/azdo/index.js.map +1 -0
  175. package/dist/azdo/projectUpdater.d.ts +13 -0
  176. package/dist/azdo/projectUpdater.d.ts.map +1 -0
  177. package/dist/azdo/projectUpdater.js +155 -0
  178. package/dist/azdo/projectUpdater.js.map +1 -0
  179. package/dist/azureDevOps/client.d.ts +75 -0
  180. package/dist/azureDevOps/client.d.ts.map +1 -0
  181. package/dist/azureDevOps/client.js +150 -0
  182. package/dist/azureDevOps/client.js.map +1 -0
  183. package/dist/azureDevOps/hierarchy.d.ts +119 -0
  184. package/dist/azureDevOps/hierarchy.d.ts.map +1 -0
  185. package/dist/azureDevOps/hierarchy.js +470 -0
  186. package/dist/azureDevOps/hierarchy.js.map +1 -0
  187. package/dist/azureDevOps/mapper.d.ts +101 -0
  188. package/dist/azureDevOps/mapper.d.ts.map +1 -0
  189. package/dist/azureDevOps/mapper.js +438 -0
  190. package/dist/azureDevOps/mapper.js.map +1 -0
  191. package/dist/azureDevOps/stateMapping.d.ts +15 -0
  192. package/dist/azureDevOps/stateMapping.d.ts.map +1 -0
  193. package/dist/azureDevOps/stateMapping.js +141 -0
  194. package/dist/azureDevOps/stateMapping.js.map +1 -0
  195. package/dist/cli/authHandler.d.ts +13 -0
  196. package/dist/cli/authHandler.d.ts.map +1 -0
  197. package/dist/cli/authHandler.js +70 -0
  198. package/dist/cli/authHandler.js.map +1 -0
  199. package/dist/cli/checkHandler.d.ts +27 -0
  200. package/dist/cli/checkHandler.d.ts.map +1 -0
  201. package/dist/cli/checkHandler.js +560 -0
  202. package/dist/cli/checkHandler.js.map +1 -0
  203. package/dist/cli/daemon.d.ts +30 -0
  204. package/dist/cli/daemon.d.ts.map +1 -0
  205. package/dist/cli/daemon.js +141 -0
  206. package/dist/cli/daemon.js.map +1 -0
  207. package/dist/cli/factoryCommands.d.ts +3 -0
  208. package/dist/cli/factoryCommands.d.ts.map +1 -0
  209. package/dist/cli/factoryCommands.js +165 -0
  210. package/dist/cli/factoryCommands.js.map +1 -0
  211. package/dist/cli/promptHandler.d.ts +13 -0
  212. package/dist/cli/promptHandler.d.ts.map +1 -0
  213. package/dist/cli/promptHandler.js +193 -0
  214. package/dist/cli/promptHandler.js.map +1 -0
  215. package/dist/cli.d.ts +3 -0
  216. package/dist/cli.d.ts.map +1 -0
  217. package/dist/cli.js +320 -0
  218. package/dist/cli.js.map +1 -0
  219. package/dist/core/agentLifecycle.d.ts +322 -0
  220. package/dist/core/agentLifecycle.d.ts.map +1 -0
  221. package/dist/core/agentLifecycle.js +230 -0
  222. package/dist/core/agentLifecycle.js.map +1 -0
  223. package/dist/core/areaMapping.d.ts +9 -0
  224. package/dist/core/areaMapping.d.ts.map +1 -0
  225. package/dist/core/areaMapping.js +37 -0
  226. package/dist/core/areaMapping.js.map +1 -0
  227. package/dist/core/config.d.ts +469 -0
  228. package/dist/core/config.d.ts.map +1 -0
  229. package/dist/core/config.js +780 -0
  230. package/dist/core/config.js.map +1 -0
  231. package/dist/core/dashboardContract.d.ts +204 -0
  232. package/dist/core/dashboardContract.d.ts.map +1 -0
  233. package/dist/core/dashboardContract.js +205 -0
  234. package/dist/core/dashboardContract.js.map +1 -0
  235. package/dist/core/devopsModel.d.ts +138 -0
  236. package/dist/core/devopsModel.d.ts.map +1 -0
  237. package/dist/core/devopsModel.js +137 -0
  238. package/dist/core/devopsModel.js.map +1 -0
  239. package/dist/core/envFile.d.ts +11 -0
  240. package/dist/core/envFile.d.ts.map +1 -0
  241. package/dist/core/envFile.js +104 -0
  242. package/dist/core/envFile.js.map +1 -0
  243. package/dist/core/eventHub.d.ts +220 -0
  244. package/dist/core/eventHub.d.ts.map +1 -0
  245. package/dist/core/eventHub.js +136 -0
  246. package/dist/core/eventHub.js.map +1 -0
  247. package/dist/core/index.d.ts +8 -0
  248. package/dist/core/index.d.ts.map +1 -0
  249. package/dist/core/index.js +7 -0
  250. package/dist/core/index.js.map +1 -0
  251. package/dist/core/laneExecutionState.d.ts +29 -0
  252. package/dist/core/laneExecutionState.d.ts.map +1 -0
  253. package/dist/core/laneExecutionState.js +18 -0
  254. package/dist/core/laneExecutionState.js.map +1 -0
  255. package/dist/core/laneStatus.d.ts +49 -0
  256. package/dist/core/laneStatus.d.ts.map +1 -0
  257. package/dist/core/laneStatus.js +153 -0
  258. package/dist/core/laneStatus.js.map +1 -0
  259. package/dist/core/prSidecar.d.ts +96 -0
  260. package/dist/core/prSidecar.d.ts.map +1 -0
  261. package/dist/core/prSidecar.js +33 -0
  262. package/dist/core/prSidecar.js.map +1 -0
  263. package/dist/core/runtimeConfig.d.ts +6 -0
  264. package/dist/core/runtimeConfig.d.ts.map +1 -0
  265. package/dist/core/runtimeConfig.js +24 -0
  266. package/dist/core/runtimeConfig.js.map +1 -0
  267. package/dist/core/scmProvider.d.ts +19 -0
  268. package/dist/core/scmProvider.d.ts.map +1 -0
  269. package/dist/core/scmProvider.js +38 -0
  270. package/dist/core/scmProvider.js.map +1 -0
  271. package/dist/core/service.d.ts +10 -0
  272. package/dist/core/service.d.ts.map +1 -0
  273. package/dist/core/service.js +297 -0
  274. package/dist/core/service.js.map +1 -0
  275. package/dist/core/traceCollector.d.ts +105 -0
  276. package/dist/core/traceCollector.d.ts.map +1 -0
  277. package/dist/core/traceCollector.js +141 -0
  278. package/dist/core/traceCollector.js.map +1 -0
  279. package/dist/core/types.d.ts +432 -0
  280. package/dist/core/types.d.ts.map +1 -0
  281. package/dist/core/types.js +2 -0
  282. package/dist/core/types.js.map +1 -0
  283. package/dist/core/workItemMapper.d.ts +39 -0
  284. package/dist/core/workItemMapper.d.ts.map +1 -0
  285. package/dist/core/workItemMapper.js +427 -0
  286. package/dist/core/workItemMapper.js.map +1 -0
  287. package/dist/core/workItemModel.d.ts +120 -0
  288. package/dist/core/workItemModel.d.ts.map +1 -0
  289. package/dist/core/workItemModel.js +104 -0
  290. package/dist/core/workItemModel.js.map +1 -0
  291. package/dist/core/workItemPayload.d.ts +195 -0
  292. package/dist/core/workItemPayload.d.ts.map +1 -0
  293. package/dist/core/workItemPayload.js +24 -0
  294. package/dist/core/workItemPayload.js.map +1 -0
  295. package/dist/core/workspaceConfig.d.ts +57 -0
  296. package/dist/core/workspaceConfig.d.ts.map +1 -0
  297. package/dist/core/workspaceConfig.js +184 -0
  298. package/dist/core/workspaceConfig.js.map +1 -0
  299. package/dist/doctor.d.ts +18 -0
  300. package/dist/doctor.d.ts.map +1 -0
  301. package/dist/doctor.js +34 -0
  302. package/dist/doctor.js.map +1 -0
  303. package/dist/factory/activeSkill.d.ts +11 -0
  304. package/dist/factory/activeSkill.d.ts.map +1 -0
  305. package/dist/factory/activeSkill.js +44 -0
  306. package/dist/factory/activeSkill.js.map +1 -0
  307. package/dist/factory/assignment.d.ts +54 -0
  308. package/dist/factory/assignment.d.ts.map +1 -0
  309. package/dist/factory/assignment.js +94 -0
  310. package/dist/factory/assignment.js.map +1 -0
  311. package/dist/factory/auditLog.d.ts +10 -0
  312. package/dist/factory/auditLog.d.ts.map +1 -0
  313. package/dist/factory/auditLog.js +38 -0
  314. package/dist/factory/auditLog.js.map +1 -0
  315. package/dist/factory/closureRequirements.d.ts +12 -0
  316. package/dist/factory/closureRequirements.d.ts.map +1 -0
  317. package/dist/factory/closureRequirements.js +30 -0
  318. package/dist/factory/closureRequirements.js.map +1 -0
  319. package/dist/factory/delegationPrompt.d.ts +3 -0
  320. package/dist/factory/delegationPrompt.d.ts.map +1 -0
  321. package/dist/factory/delegationPrompt.js +16 -0
  322. package/dist/factory/delegationPrompt.js.map +1 -0
  323. package/dist/factory/http.d.ts +3 -0
  324. package/dist/factory/http.d.ts.map +1 -0
  325. package/dist/factory/http.js +555 -0
  326. package/dist/factory/http.js.map +1 -0
  327. package/dist/factory/lifecyclePushMap.d.ts +4 -0
  328. package/dist/factory/lifecyclePushMap.d.ts.map +1 -0
  329. package/dist/factory/lifecyclePushMap.js +7 -0
  330. package/dist/factory/lifecyclePushMap.js.map +1 -0
  331. package/dist/factory/missions.d.ts +125 -0
  332. package/dist/factory/missions.d.ts.map +1 -0
  333. package/dist/factory/missions.js +304 -0
  334. package/dist/factory/missions.js.map +1 -0
  335. package/dist/factory/mode.d.ts +9 -0
  336. package/dist/factory/mode.d.ts.map +1 -0
  337. package/dist/factory/mode.js +30 -0
  338. package/dist/factory/mode.js.map +1 -0
  339. package/dist/factory/operatorActiveSkill.d.ts +15 -0
  340. package/dist/factory/operatorActiveSkill.d.ts.map +1 -0
  341. package/dist/factory/operatorActiveSkill.js +95 -0
  342. package/dist/factory/operatorActiveSkill.js.map +1 -0
  343. package/dist/factory/paseoDispatcher.d.ts +52 -0
  344. package/dist/factory/paseoDispatcher.d.ts.map +1 -0
  345. package/dist/factory/paseoDispatcher.js +122 -0
  346. package/dist/factory/paseoDispatcher.js.map +1 -0
  347. package/dist/factory/paseoLifecycle.d.ts +32 -0
  348. package/dist/factory/paseoLifecycle.d.ts.map +1 -0
  349. package/dist/factory/paseoLifecycle.js +260 -0
  350. package/dist/factory/paseoLifecycle.js.map +1 -0
  351. package/dist/factory/paths.d.ts +31 -0
  352. package/dist/factory/paths.d.ts.map +1 -0
  353. package/dist/factory/paths.js +139 -0
  354. package/dist/factory/paths.js.map +1 -0
  355. package/dist/factory/progressWatchdog.d.ts +58 -0
  356. package/dist/factory/progressWatchdog.d.ts.map +1 -0
  357. package/dist/factory/progressWatchdog.js +160 -0
  358. package/dist/factory/progressWatchdog.js.map +1 -0
  359. package/dist/factory/roster.d.ts +59 -0
  360. package/dist/factory/roster.d.ts.map +1 -0
  361. package/dist/factory/roster.js +116 -0
  362. package/dist/factory/roster.js.map +1 -0
  363. package/dist/factory/runtime.d.ts +44 -0
  364. package/dist/factory/runtime.d.ts.map +1 -0
  365. package/dist/factory/runtime.js +238 -0
  366. package/dist/factory/runtime.js.map +1 -0
  367. package/dist/factory/sync.d.ts +29 -0
  368. package/dist/factory/sync.d.ts.map +1 -0
  369. package/dist/factory/sync.js +77 -0
  370. package/dist/factory/sync.js.map +1 -0
  371. package/dist/factory/workitemQueues.d.ts +37 -0
  372. package/dist/factory/workitemQueues.d.ts.map +1 -0
  373. package/dist/factory/workitemQueues.js +99 -0
  374. package/dist/factory/workitemQueues.js.map +1 -0
  375. package/dist/factory/workitemTriage.d.ts +9 -0
  376. package/dist/factory/workitemTriage.d.ts.map +1 -0
  377. package/dist/factory/workitemTriage.js +81 -0
  378. package/dist/factory/workitemTriage.js.map +1 -0
  379. package/dist/hooks.d.ts +18 -0
  380. package/dist/hooks.d.ts.map +1 -0
  381. package/dist/hooks.js +96 -0
  382. package/dist/hooks.js.map +1 -0
  383. package/dist/index.d.ts +3 -0
  384. package/dist/index.d.ts.map +1 -0
  385. package/dist/index.js +90 -0
  386. package/dist/index.js.map +1 -0
  387. package/dist/install/agentCatalog.d.ts +7 -0
  388. package/dist/install/agentCatalog.d.ts.map +1 -0
  389. package/dist/install/agentCatalog.js +28 -0
  390. package/dist/install/agentCatalog.js.map +1 -0
  391. package/dist/install/bundlePaths.d.ts +10 -0
  392. package/dist/install/bundlePaths.d.ts.map +1 -0
  393. package/dist/install/bundlePaths.js +30 -0
  394. package/dist/install/bundlePaths.js.map +1 -0
  395. package/dist/install/codex.d.ts +43 -0
  396. package/dist/install/codex.d.ts.map +1 -0
  397. package/dist/install/codex.js +207 -0
  398. package/dist/install/codex.js.map +1 -0
  399. package/dist/install/enactHome.d.ts +37 -0
  400. package/dist/install/enactHome.d.ts.map +1 -0
  401. package/dist/install/enactHome.js +152 -0
  402. package/dist/install/enactHome.js.map +1 -0
  403. package/dist/install/plugins.d.ts +115 -0
  404. package/dist/install/plugins.d.ts.map +1 -0
  405. package/dist/install/plugins.js +259 -0
  406. package/dist/install/plugins.js.map +1 -0
  407. package/dist/install/setup.d.ts +33 -0
  408. package/dist/install/setup.d.ts.map +1 -0
  409. package/dist/install/setup.js +167 -0
  410. package/dist/install/setup.js.map +1 -0
  411. package/dist/locale/en.d.ts +3 -0
  412. package/dist/locale/en.d.ts.map +1 -0
  413. package/dist/locale/en.js +435 -0
  414. package/dist/locale/en.js.map +1 -0
  415. package/dist/locale/index.d.ts +28 -0
  416. package/dist/locale/index.d.ts.map +1 -0
  417. package/dist/locale/index.js +84 -0
  418. package/dist/locale/index.js.map +1 -0
  419. package/dist/locale/prompts/en.d.ts +3 -0
  420. package/dist/locale/prompts/en.d.ts.map +1 -0
  421. package/dist/locale/prompts/en.js +254 -0
  422. package/dist/locale/prompts/en.js.map +1 -0
  423. package/dist/locale/types.d.ts +433 -0
  424. package/dist/locale/types.d.ts.map +1 -0
  425. package/dist/locale/types.js +5 -0
  426. package/dist/locale/types.js.map +1 -0
  427. package/dist/mcp/server.d.ts +489 -0
  428. package/dist/mcp/server.d.ts.map +1 -0
  429. package/dist/mcp/server.js +597 -0
  430. package/dist/mcp/server.js.map +1 -0
  431. package/dist/orchestration/decisionEngine.d.ts +175 -0
  432. package/dist/orchestration/decisionEngine.d.ts.map +1 -0
  433. package/dist/orchestration/decisionEngine.js +471 -0
  434. package/dist/orchestration/decisionEngine.js.map +1 -0
  435. package/dist/orchestration/index.d.ts +5 -0
  436. package/dist/orchestration/index.d.ts.map +1 -0
  437. package/dist/orchestration/index.js +5 -0
  438. package/dist/orchestration/index.js.map +1 -0
  439. package/dist/orchestration/workItemParser.d.ts +67 -0
  440. package/dist/orchestration/workItemParser.d.ts.map +1 -0
  441. package/dist/orchestration/workItemParser.js +560 -0
  442. package/dist/orchestration/workItemParser.js.map +1 -0
  443. package/dist/orchestration/workItemScheduler.d.ts +141 -0
  444. package/dist/orchestration/workItemScheduler.d.ts.map +1 -0
  445. package/dist/orchestration/workItemScheduler.js +317 -0
  446. package/dist/orchestration/workItemScheduler.js.map +1 -0
  447. package/dist/orchestration/workflow.d.ts +145 -0
  448. package/dist/orchestration/workflow.d.ts.map +1 -0
  449. package/dist/orchestration/workflow.js +301 -0
  450. package/dist/orchestration/workflow.js.map +1 -0
  451. package/dist/providers/codexSessions.d.ts +93 -0
  452. package/dist/providers/codexSessions.d.ts.map +1 -0
  453. package/dist/providers/codexSessions.js +366 -0
  454. package/dist/providers/codexSessions.js.map +1 -0
  455. package/dist/registry/bsDetector.d.ts +24 -0
  456. package/dist/registry/bsDetector.d.ts.map +1 -0
  457. package/dist/registry/bsDetector.js +276 -0
  458. package/dist/registry/bsDetector.js.map +1 -0
  459. package/dist/registry/entityScanner.d.ts +36 -0
  460. package/dist/registry/entityScanner.d.ts.map +1 -0
  461. package/dist/registry/entityScanner.js +693 -0
  462. package/dist/registry/entityScanner.js.map +1 -0
  463. package/dist/registry/index.d.ts +9 -0
  464. package/dist/registry/index.d.ts.map +1 -0
  465. package/dist/registry/index.js +13 -0
  466. package/dist/registry/index.js.map +1 -0
  467. package/dist/registry/schema.d.ts +307 -0
  468. package/dist/registry/schema.d.ts.map +1 -0
  469. package/dist/registry/schema.js +139 -0
  470. package/dist/registry/schema.js.map +1 -0
  471. package/dist/registry/sqliteStore.d.ts +101 -0
  472. package/dist/registry/sqliteStore.d.ts.map +1 -0
  473. package/dist/registry/sqliteStore.js +688 -0
  474. package/dist/registry/sqliteStore.js.map +1 -0
  475. package/dist/registry/workItemBridge.d.ts +8 -0
  476. package/dist/registry/workItemBridge.d.ts.map +1 -0
  477. package/dist/registry/workItemBridge.js +30 -0
  478. package/dist/registry/workItemBridge.js.map +1 -0
  479. package/dist/runners/cliRunner.d.ts +11 -0
  480. package/dist/runners/cliRunner.d.ts.map +1 -0
  481. package/dist/runners/cliRunner.js +193 -0
  482. package/dist/runners/cliRunner.js.map +1 -0
  483. package/dist/support/apiCache.d.ts +85 -0
  484. package/dist/support/apiCache.d.ts.map +1 -0
  485. package/dist/support/apiCache.js +163 -0
  486. package/dist/support/apiCache.js.map +1 -0
  487. package/dist/support/chat.d.ts +3 -0
  488. package/dist/support/chat.d.ts.map +1 -0
  489. package/dist/support/chat.js +305 -0
  490. package/dist/support/chat.js.map +1 -0
  491. package/dist/support/chatBackend.d.ts +25 -0
  492. package/dist/support/chatBackend.d.ts.map +1 -0
  493. package/dist/support/chatBackend.js +289 -0
  494. package/dist/support/chatBackend.js.map +1 -0
  495. package/dist/support/chatTui.d.ts +3 -0
  496. package/dist/support/chatTui.d.ts.map +1 -0
  497. package/dist/support/chatTui.js +1082 -0
  498. package/dist/support/chatTui.js.map +1 -0
  499. package/dist/support/costTracker.d.ts +29 -0
  500. package/dist/support/costTracker.d.ts.map +1 -0
  501. package/dist/support/costTracker.js +113 -0
  502. package/dist/support/costTracker.js.map +1 -0
  503. package/dist/support/dashboardHtml.d.ts +5 -0
  504. package/dist/support/dashboardHtml.d.ts.map +1 -0
  505. package/dist/support/dashboardHtml.js +2629 -0
  506. package/dist/support/dashboardHtml.js.map +1 -0
  507. package/dist/support/dev.d.ts +55 -0
  508. package/dist/support/dev.d.ts.map +1 -0
  509. package/dist/support/dev.js +298 -0
  510. package/dist/support/dev.js.map +1 -0
  511. package/dist/support/editParser.d.ts +37 -0
  512. package/dist/support/editParser.d.ts.map +1 -0
  513. package/dist/support/editParser.js +365 -0
  514. package/dist/support/editParser.js.map +1 -0
  515. package/dist/support/ghosttyThemeCatalog.generated.d.ts +2 -0
  516. package/dist/support/ghosttyThemeCatalog.generated.d.ts.map +1 -0
  517. package/dist/support/ghosttyThemeCatalog.generated.js +11116 -0
  518. package/dist/support/ghosttyThemeCatalog.generated.js.map +1 -0
  519. package/dist/support/gitStatus.d.ts +21 -0
  520. package/dist/support/gitStatus.d.ts.map +1 -0
  521. package/dist/support/gitStatus.js +108 -0
  522. package/dist/support/gitStatus.js.map +1 -0
  523. package/dist/support/gitTracker.d.ts +30 -0
  524. package/dist/support/gitTracker.d.ts.map +1 -0
  525. package/dist/support/gitTracker.js +143 -0
  526. package/dist/support/gitTracker.js.map +1 -0
  527. package/dist/support/index.d.ts +12 -0
  528. package/dist/support/index.d.ts.map +1 -0
  529. package/dist/support/index.js +12 -0
  530. package/dist/support/index.js.map +1 -0
  531. package/dist/support/planner.d.ts +64 -0
  532. package/dist/support/planner.d.ts.map +1 -0
  533. package/dist/support/planner.js +396 -0
  534. package/dist/support/planner.js.map +1 -0
  535. package/dist/support/projectMapper.d.ts +46 -0
  536. package/dist/support/projectMapper.d.ts.map +1 -0
  537. package/dist/support/projectMapper.js +273 -0
  538. package/dist/support/projectMapper.js.map +1 -0
  539. package/dist/support/pty-helper.py +117 -0
  540. package/dist/support/quotaTracker.d.ts +29 -0
  541. package/dist/support/quotaTracker.d.ts.map +1 -0
  542. package/dist/support/quotaTracker.js +89 -0
  543. package/dist/support/quotaTracker.js.map +1 -0
  544. package/dist/support/rateLimiter.d.ts +101 -0
  545. package/dist/support/rateLimiter.d.ts.map +1 -0
  546. package/dist/support/rateLimiter.js +219 -0
  547. package/dist/support/rateLimiter.js.map +1 -0
  548. package/dist/support/rollback.d.ts +61 -0
  549. package/dist/support/rollback.d.ts.map +1 -0
  550. package/dist/support/rollback.js +329 -0
  551. package/dist/support/rollback.js.map +1 -0
  552. package/dist/support/sharedShell.d.ts +17 -0
  553. package/dist/support/sharedShell.d.ts.map +1 -0
  554. package/dist/support/sharedShell.js +439 -0
  555. package/dist/support/sharedShell.js.map +1 -0
  556. package/dist/support/stuckDetector.d.ts +68 -0
  557. package/dist/support/stuckDetector.d.ts.map +1 -0
  558. package/dist/support/stuckDetector.js +174 -0
  559. package/dist/support/stuckDetector.js.map +1 -0
  560. package/dist/support/terminalBridge.d.ts +18 -0
  561. package/dist/support/terminalBridge.d.ts.map +1 -0
  562. package/dist/support/terminalBridge.js +553 -0
  563. package/dist/support/terminalBridge.js.map +1 -0
  564. package/dist/support/timeWindow.d.ts +60 -0
  565. package/dist/support/timeWindow.d.ts.map +1 -0
  566. package/dist/support/timeWindow.js +236 -0
  567. package/dist/support/timeWindow.js.map +1 -0
  568. package/dist/support/uiThemes.d.ts +44 -0
  569. package/dist/support/uiThemes.d.ts.map +1 -0
  570. package/dist/support/uiThemes.js +290 -0
  571. package/dist/support/uiThemes.js.map +1 -0
  572. package/dist/support/web.d.ts +29 -0
  573. package/dist/support/web.d.ts.map +1 -0
  574. package/dist/support/web.js +1097 -0
  575. package/dist/support/web.js.map +1 -0
  576. package/dist/support/worktreeManager.d.ts +20 -0
  577. package/dist/support/worktreeManager.d.ts.map +1 -0
  578. package/dist/support/worktreeManager.js +140 -0
  579. package/dist/support/worktreeManager.js.map +1 -0
  580. package/dist/task_state_model.py +55 -0
  581. package/dist/workItemState/store.d.ts +122 -0
  582. package/dist/workItemState/store.d.ts.map +1 -0
  583. package/dist/workItemState/store.js +438 -0
  584. package/dist/workItemState/store.js.map +1 -0
  585. package/dist/workItems/azdoBridge.d.ts +42 -0
  586. package/dist/workItems/azdoBridge.d.ts.map +1 -0
  587. package/dist/workItems/azdoBridge.js +143 -0
  588. package/dist/workItems/azdoBridge.js.map +1 -0
  589. package/dist/workItems/azdoSyncRuntime.d.ts +28 -0
  590. package/dist/workItems/azdoSyncRuntime.d.ts.map +1 -0
  591. package/dist/workItems/azdoSyncRuntime.js +158 -0
  592. package/dist/workItems/azdoSyncRuntime.js.map +1 -0
  593. package/dist/workItems/azureDevOpsSync.d.ts +128 -0
  594. package/dist/workItems/azureDevOpsSync.d.ts.map +1 -0
  595. package/dist/workItems/azureDevOpsSync.js +748 -0
  596. package/dist/workItems/azureDevOpsSync.js.map +1 -0
  597. package/dist/workItems/helpers.d.ts +11 -0
  598. package/dist/workItems/helpers.d.ts.map +1 -0
  599. package/dist/workItems/helpers.js +17 -0
  600. package/dist/workItems/helpers.js.map +1 -0
  601. package/dist/workItems/index.d.ts +21 -0
  602. package/dist/workItems/index.d.ts.map +1 -0
  603. package/dist/workItems/index.js +89 -0
  604. package/dist/workItems/index.js.map +1 -0
  605. package/dist/workItems/localWorkItemFetcher.d.ts +55 -0
  606. package/dist/workItems/localWorkItemFetcher.d.ts.map +1 -0
  607. package/dist/workItems/localWorkItemFetcher.js +209 -0
  608. package/dist/workItems/localWorkItemFetcher.js.map +1 -0
  609. package/dist/workItems/migrations/001_rename_workItem_to_work_item.sql +10 -0
  610. package/dist/workItems/postgresStore.d.ts +78 -0
  611. package/dist/workItems/postgresStore.d.ts.map +1 -0
  612. package/dist/workItems/postgresStore.js +937 -0
  613. package/dist/workItems/postgresStore.js.map +1 -0
  614. package/dist/workItems/schema.d.ts +257 -0
  615. package/dist/workItems/schema.d.ts.map +1 -0
  616. package/dist/workItems/schema.js +176 -0
  617. package/dist/workItems/schema.js.map +1 -0
  618. package/dist/workItems/sqliteStore.d.ts +124 -0
  619. package/dist/workItems/sqliteStore.d.ts.map +1 -0
  620. package/dist/workItems/sqliteStore.js +713 -0
  621. package/dist/workItems/sqliteStore.js.map +1 -0
  622. package/dist/workItems/workItemBoardHtml.d.ts +5 -0
  623. package/dist/workItems/workItemBoardHtml.d.ts.map +1 -0
  624. package/dist/workItems/workItemBoardHtml.js +2192 -0
  625. package/dist/workItems/workItemBoardHtml.js.map +1 -0
  626. package/package.json +99 -0
  627. package/templates/AGENTS.md +432 -0
  628. package/templates/BOOT.md +25 -0
  629. package/templates/BOOTSTRAP.md +50 -0
  630. package/templates/CHANGELOG_AUDIT.md +74 -0
  631. package/templates/HEARTBEAT.md +86 -0
  632. package/templates/IDENTITY.md +27 -0
  633. package/templates/PR_LAND.md +75 -0
  634. package/templates/PR_REVIEW.md +97 -0
  635. package/templates/SOUL.dev.md +52 -0
  636. package/templates/SOUL.md +81 -0
  637. package/templates/TOOLS.md +52 -0
  638. package/templates/USER.md +22 -0
  639. package/templates/WORKITEM_ANALYSIS.md +31 -0
  640. package/templates/agents/executor.md +26 -0
  641. package/templates/agents/plan.md +22 -0
  642. package/templates/agents/ralph.md +37 -0
  643. package/templates/agents/review.md +22 -0
  644. package/templates/agents/team.md +39 -0
@@ -0,0 +1,937 @@
1
+ // ============================================
2
+ // Enact Factory - PostgreSQL WorkItem Store
3
+ // Alternative to SQLite for multi-instance deployments
4
+ // ============================================
5
+ import { Pool } from 'pg';
6
+ import { nanoid } from 'nanoid';
7
+ export class PostgresWorkItemStore {
8
+ pool;
9
+ schema;
10
+ constructor(config) {
11
+ const defaultPort = 45432;
12
+ const defaultDatabase = 'enact_factory_dev';
13
+ const poolConfig = config.connectionString
14
+ ? { connectionString: config.connectionString }
15
+ : {
16
+ host: config.host ?? 'localhost',
17
+ port: config.port ?? defaultPort,
18
+ database: config.database ?? defaultDatabase,
19
+ user: config.user ?? 'postgres',
20
+ password: config.password ?? '',
21
+ max: config.maxConnections ?? 10,
22
+ };
23
+ this.pool = new Pool(poolConfig);
24
+ this.schema = config.schema ?? 'public';
25
+ // Handle pool errors
26
+ this.pool.on('error', (err) => {
27
+ console.error('[PostgresStore] Unexpected pool error:', err);
28
+ });
29
+ }
30
+ async init() {
31
+ await this.migrate();
32
+ }
33
+ async close() {
34
+ await this.pool.end();
35
+ }
36
+ async migrate() {
37
+ const client = await this.pool.connect();
38
+ try {
39
+ // Create schema if not exists
40
+ await client.query(`CREATE SCHEMA IF NOT EXISTS ${this.schema}`);
41
+ // Create workItems table
42
+ await client.query(`
43
+ CREATE TABLE IF NOT EXISTS ${this.schema}.work_items (
44
+ id TEXT PRIMARY KEY,
45
+ project_id TEXT NOT NULL,
46
+ title TEXT NOT NULL,
47
+ description TEXT DEFAULT '',
48
+ status TEXT,
49
+ priority TEXT,
50
+ source TEXT,
51
+ kind TEXT,
52
+ area TEXT,
53
+ review_state TEXT,
54
+ resolution TEXT,
55
+ assignee TEXT,
56
+ milestone TEXT,
57
+ estimate_minutes INTEGER,
58
+ complexity TEXT,
59
+ parent_id TEXT REFERENCES ${this.schema}.work_items(id) ON DELETE SET NULL,
60
+ azdo_id TEXT,
61
+ azdo_identifier TEXT,
62
+ azdo_url TEXT,
63
+ payload_json JSONB,
64
+ operator_session_id TEXT,
65
+ operator_lane TEXT,
66
+ is_session_root BOOLEAN DEFAULT FALSE,
67
+ external_work_item_id TEXT,
68
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
69
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
70
+ closed_at TIMESTAMPTZ
71
+ )
72
+ `);
73
+ // Add azdo columns if they don't exist (idempotent migration for existing schemas)
74
+ await client.query(`ALTER TABLE ${this.schema}.work_items ADD COLUMN IF NOT EXISTS azdo_id TEXT`);
75
+ await client.query(`ALTER TABLE ${this.schema}.work_items ADD COLUMN IF NOT EXISTS azdo_identifier TEXT`);
76
+ await client.query(`ALTER TABLE ${this.schema}.work_items ADD COLUMN IF NOT EXISTS azdo_url TEXT`);
77
+ await client.query(`ALTER TABLE ${this.schema}.work_items ADD COLUMN IF NOT EXISTS operator_session_id TEXT`);
78
+ await client.query(`ALTER TABLE ${this.schema}.work_items ADD COLUMN IF NOT EXISTS operator_lane TEXT`);
79
+ await client.query(`ALTER TABLE ${this.schema}.work_items ADD COLUMN IF NOT EXISTS is_session_root BOOLEAN DEFAULT FALSE`);
80
+ await client.query(`ALTER TABLE ${this.schema}.work_items ADD COLUMN IF NOT EXISTS external_work_item_id TEXT`);
81
+ // Drop content-field DEFAULTs on existing DBs so real Azure DevOps values (or NULL) persist
82
+ // instead of being silently replaced by fabricated literals. DROP DEFAULT is idempotent.
83
+ await client.query(`ALTER TABLE ${this.schema}.work_items ALTER COLUMN status DROP DEFAULT`);
84
+ await client.query(`ALTER TABLE ${this.schema}.work_items ALTER COLUMN priority DROP DEFAULT`);
85
+ await client.query(`ALTER TABLE ${this.schema}.work_items ALTER COLUMN source DROP DEFAULT`);
86
+ await client.query(`ALTER TABLE ${this.schema}.work_items ALTER COLUMN kind DROP DEFAULT`);
87
+ await client.query(`ALTER TABLE ${this.schema}.work_items ALTER COLUMN area DROP DEFAULT`);
88
+ await client.query(`ALTER TABLE ${this.schema}.work_items ALTER COLUMN review_state DROP DEFAULT`);
89
+ await client.query(`ALTER TABLE ${this.schema}.work_items ALTER COLUMN resolution DROP DEFAULT`);
90
+ // Create sync_meta KV table for sync watermarks
91
+ await client.query(`
92
+ CREATE TABLE IF NOT EXISTS ${this.schema}.sync_meta (
93
+ key TEXT PRIMARY KEY,
94
+ value TEXT NOT NULL,
95
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
96
+ )
97
+ `);
98
+ await client.query(`
99
+ CREATE TABLE IF NOT EXISTS ${this.schema}.projects (
100
+ name TEXT PRIMARY KEY,
101
+ path TEXT NOT NULL UNIQUE,
102
+ heartbeat_ms INTEGER NOT NULL,
103
+ azdo_label TEXT,
104
+ enabled BOOLEAN NOT NULL DEFAULT TRUE,
105
+ paused BOOLEAN NOT NULL DEFAULT FALSE,
106
+ operators JSONB NOT NULL DEFAULT '[]'::jsonb
107
+ )
108
+ `);
109
+ // Create labels table
110
+ await client.query(`
111
+ CREATE TABLE IF NOT EXISTS ${this.schema}.labels (
112
+ id TEXT PRIMARY KEY,
113
+ name TEXT NOT NULL UNIQUE,
114
+ color TEXT DEFAULT '#6B7280',
115
+ description TEXT
116
+ )
117
+ `);
118
+ // Create work_item_labels junction table
119
+ await client.query(`
120
+ CREATE TABLE IF NOT EXISTS ${this.schema}.work_item_labels (
121
+ work_item_id TEXT NOT NULL REFERENCES ${this.schema}.work_items(id) ON DELETE CASCADE,
122
+ label_id TEXT NOT NULL REFERENCES ${this.schema}.labels(id) ON DELETE CASCADE,
123
+ PRIMARY KEY (work_item_id, label_id)
124
+ )
125
+ `);
126
+ // Create work_item_dependencies table
127
+ await client.query(`
128
+ CREATE TABLE IF NOT EXISTS ${this.schema}.work_item_dependencies (
129
+ work_item_id TEXT NOT NULL REFERENCES ${this.schema}.work_items(id) ON DELETE CASCADE,
130
+ depends_on_id TEXT NOT NULL REFERENCES ${this.schema}.work_items(id) ON DELETE CASCADE,
131
+ PRIMARY KEY (work_item_id, depends_on_id)
132
+ )
133
+ `);
134
+ // Create work_item_relevant_files table
135
+ await client.query(`
136
+ CREATE TABLE IF NOT EXISTS ${this.schema}.work_item_relevant_files (
137
+ work_item_id TEXT NOT NULL REFERENCES ${this.schema}.work_items(id) ON DELETE CASCADE,
138
+ file_path TEXT NOT NULL,
139
+ PRIMARY KEY (work_item_id, file_path)
140
+ )
141
+ `);
142
+ // Create work_item_acceptance_criteria table
143
+ await client.query(`
144
+ CREATE TABLE IF NOT EXISTS ${this.schema}.work_item_acceptance_criteria (
145
+ work_item_id TEXT NOT NULL REFERENCES ${this.schema}.work_items(id) ON DELETE CASCADE,
146
+ criterion TEXT NOT NULL,
147
+ sort_order INTEGER DEFAULT 0
148
+ )
149
+ `);
150
+ // Create work_item_memory_links table
151
+ await client.query(`
152
+ CREATE TABLE IF NOT EXISTS ${this.schema}.work_item_memory_links (
153
+ work_item_id TEXT NOT NULL REFERENCES ${this.schema}.work_items(id) ON DELETE CASCADE,
154
+ memory_id TEXT NOT NULL,
155
+ linked_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
156
+ PRIMARY KEY (work_item_id, memory_id)
157
+ )
158
+ `);
159
+ // Create work_item_events table
160
+ await client.query(`
161
+ CREATE TABLE IF NOT EXISTS ${this.schema}.work_item_events (
162
+ id TEXT PRIMARY KEY,
163
+ work_item_id TEXT NOT NULL REFERENCES ${this.schema}.work_items(id) ON DELETE CASCADE,
164
+ type TEXT NOT NULL,
165
+ old_value TEXT,
166
+ new_value TEXT,
167
+ content TEXT,
168
+ memory_id TEXT,
169
+ actor TEXT DEFAULT 'system',
170
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
171
+ )
172
+ `);
173
+ // Create milestones table
174
+ await client.query(`
175
+ CREATE TABLE IF NOT EXISTS ${this.schema}.milestones (
176
+ id TEXT PRIMARY KEY,
177
+ name TEXT NOT NULL,
178
+ description TEXT,
179
+ due_date TIMESTAMPTZ,
180
+ status TEXT DEFAULT 'active',
181
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
182
+ )
183
+ `);
184
+ // Create indexes
185
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_work_items_project ON ${this.schema}.work_items(project_id)`);
186
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_work_items_status ON ${this.schema}.work_items(status)`);
187
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_work_items_priority ON ${this.schema}.work_items(priority)`);
188
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_work_items_parent ON ${this.schema}.work_items(parent_id)`);
189
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_work_items_azdo ON ${this.schema}.work_items(azdo_id)`);
190
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_work_item_events_item ON ${this.schema}.work_item_events(work_item_id)`);
191
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_work_item_events_created ON ${this.schema}.work_item_events(created_at)`);
192
+ // Create full-text search index (using tsvector for Postgres)
193
+ await client.query(`
194
+ CREATE INDEX IF NOT EXISTS idx_work_items_fts ON ${this.schema}.work_items
195
+ USING gin(to_tsvector('english', title || ' ' || COALESCE(description, '')))
196
+ `);
197
+ // Drop the legacy updated_at auto-update trigger. It force-overwrote updated_at = NOW()
198
+ // on every UPDATE, which made persisting a real System.ChangedDate impossible.
199
+ // updated_at is now written explicitly by each write path.
200
+ await client.query(`DROP TRIGGER IF EXISTS update_work_items_updated_at ON ${this.schema}.work_items`);
201
+ }
202
+ finally {
203
+ client.release();
204
+ }
205
+ }
206
+ // ============ WorkItem CRUD ============
207
+ async createWorkItem(input) {
208
+ const id = input.id ?? nanoid(12);
209
+ const now = new Date().toISOString();
210
+ const workItem = {
211
+ id,
212
+ projectId: input.projectId,
213
+ title: input.title,
214
+ description: input.description ?? '',
215
+ // No content-field fabrication: the caller's value (or undefined → SQL NULL) passes
216
+ // straight through. WorkItemRecord types these as required, so we assert here; a missing
217
+ // value surfaces as NULL in the DB and fails loudly at any call site that assumes a value.
218
+ status: input.status,
219
+ priority: input.priority,
220
+ source: input.source,
221
+ kind: input.kind,
222
+ area: input.area,
223
+ reviewState: input.reviewState,
224
+ resolution: input.resolution,
225
+ assignee: input.assignee ?? undefined,
226
+ milestone: input.milestone,
227
+ labels: input.labels ?? [],
228
+ dependencies: input.dependencies ?? [],
229
+ relevantFiles: input.relevantFiles ?? [],
230
+ acceptanceCriteria: input.acceptanceCriteria ?? [],
231
+ estimateMinutes: input.estimateMinutes,
232
+ complexity: input.complexity,
233
+ parentId: input.parentId,
234
+ azdoId: input.azdoId,
235
+ azdoIdentifier: input.azdoIdentifier,
236
+ azdoUrl: input.azdoUrl,
237
+ memoryIds: [],
238
+ childIds: [],
239
+ operatorLane: input.operatorLane,
240
+ isSessionRoot: input.isSessionRoot ?? false,
241
+ externalWorkItemId: input.externalWorkItemId,
242
+ createdAt: input.createdAt ?? now,
243
+ updatedAt: input.updatedAt ?? now,
244
+ closedAt: input.closedAt ?? undefined,
245
+ };
246
+ await this.createWorkItemAsync(workItem, input);
247
+ return workItem;
248
+ }
249
+ async createWorkItemAsync(workItem, input) {
250
+ const client = await this.pool.connect();
251
+ try {
252
+ await client.query('BEGIN');
253
+ // Insert workItem
254
+ await client.query(`
255
+ INSERT INTO ${this.schema}.work_items (id, project_id, title, description, status, priority, source,
256
+ kind, area, review_state, resolution, assignee, milestone, estimate_minutes, complexity,
257
+ parent_id, azdo_id, azdo_identifier, azdo_url,
258
+ operator_lane, is_session_root, external_work_item_id,
259
+ created_at, updated_at, closed_at)
260
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)
261
+ `, [
262
+ workItem.id, workItem.projectId, workItem.title, workItem.description, workItem.status ?? null,
263
+ workItem.priority ?? null, workItem.source ?? null, workItem.kind ?? null, workItem.area ?? null,
264
+ workItem.reviewState ?? null, workItem.resolution ?? null, workItem.assignee, workItem.milestone,
265
+ workItem.estimateMinutes, workItem.complexity, workItem.parentId, workItem.azdoId, workItem.azdoIdentifier, workItem.azdoUrl,
266
+ workItem.operatorLane ?? null,
267
+ workItem.isSessionRoot ?? false,
268
+ workItem.externalWorkItemId ?? null,
269
+ workItem.createdAt, workItem.updatedAt, workItem.closedAt ?? null,
270
+ ]);
271
+ // Insert labels
272
+ if (input.labels?.length) {
273
+ for (const labelId of input.labels) {
274
+ await client.query(`
275
+ INSERT INTO ${this.schema}.work_item_labels (work_item_id, label_id)
276
+ VALUES ($1, $2)
277
+ ON CONFLICT DO NOTHING
278
+ `, [workItem.id, labelId]);
279
+ }
280
+ }
281
+ // Insert dependencies
282
+ if (input.dependencies?.length) {
283
+ for (const depId of input.dependencies) {
284
+ await client.query(`
285
+ INSERT INTO ${this.schema}.work_item_dependencies (work_item_id, depends_on_id)
286
+ VALUES ($1, $2)
287
+ ON CONFLICT DO NOTHING
288
+ `, [workItem.id, depId]);
289
+ }
290
+ }
291
+ // Insert relevant files
292
+ if (input.relevantFiles?.length) {
293
+ for (const file of input.relevantFiles) {
294
+ await client.query(`
295
+ INSERT INTO ${this.schema}.work_item_relevant_files (work_item_id, file_path)
296
+ VALUES ($1, $2)
297
+ ON CONFLICT DO NOTHING
298
+ `, [workItem.id, file]);
299
+ }
300
+ }
301
+ // Insert acceptance criteria
302
+ if (input.acceptanceCriteria?.length) {
303
+ for (const [idx, criterion] of input.acceptanceCriteria.entries()) {
304
+ await client.query(`
305
+ INSERT INTO ${this.schema}.work_item_acceptance_criteria (work_item_id, criterion, sort_order)
306
+ VALUES ($1, $2, $3)
307
+ `, [workItem.id, criterion, idx]);
308
+ }
309
+ }
310
+ await client.query('COMMIT');
311
+ }
312
+ catch (err) {
313
+ await client.query('ROLLBACK');
314
+ throw err;
315
+ }
316
+ finally {
317
+ client.release();
318
+ }
319
+ }
320
+ async getWorkItem(id) {
321
+ return this.getWorkItemAsync(id);
322
+ }
323
+ async getWorkItemAsync(id) {
324
+ const result = await this.pool.query(`
325
+ SELECT * FROM ${this.schema}.work_items WHERE id = $1
326
+ `, [id]);
327
+ if (result.rows.length === 0)
328
+ return null;
329
+ const row = result.rows[0];
330
+ return this.rowToWorkItem(row);
331
+ }
332
+ async updateWorkItem(id, patch) {
333
+ return this.updateWorkItemAsync(id, patch);
334
+ }
335
+ async updateWorkItemAsync(id, patch) {
336
+ const client = await this.pool.connect();
337
+ try {
338
+ await client.query('BEGIN');
339
+ // Build update query dynamically
340
+ const updates = [];
341
+ const values = [];
342
+ let paramIdx = 1;
343
+ if (patch.title !== undefined) {
344
+ updates.push(`title = $${paramIdx++}`);
345
+ values.push(patch.title);
346
+ }
347
+ if (patch.description !== undefined) {
348
+ updates.push(`description = $${paramIdx++}`);
349
+ values.push(patch.description);
350
+ }
351
+ if (patch.status !== undefined) {
352
+ updates.push(`status = $${paramIdx++}`);
353
+ values.push(patch.status);
354
+ }
355
+ if (patch.priority !== undefined) {
356
+ updates.push(`priority = $${paramIdx++}`);
357
+ values.push(patch.priority);
358
+ }
359
+ if (patch.source !== undefined) {
360
+ updates.push(`source = $${paramIdx++}`);
361
+ values.push(patch.source);
362
+ }
363
+ if (patch.kind !== undefined) {
364
+ updates.push(`kind = $${paramIdx++}`);
365
+ values.push(patch.kind);
366
+ }
367
+ if (patch.area !== undefined) {
368
+ updates.push(`area = $${paramIdx++}`);
369
+ values.push(patch.area);
370
+ }
371
+ if (patch.reviewState !== undefined) {
372
+ updates.push(`review_state = $${paramIdx++}`);
373
+ values.push(patch.reviewState);
374
+ }
375
+ if (patch.resolution !== undefined) {
376
+ updates.push(`resolution = $${paramIdx++}`);
377
+ values.push(patch.resolution);
378
+ }
379
+ if (patch.assignee !== undefined) {
380
+ updates.push(`assignee = $${paramIdx++}`);
381
+ values.push(patch.assignee);
382
+ }
383
+ if (patch.milestone !== undefined) {
384
+ updates.push(`milestone = $${paramIdx++}`);
385
+ values.push(patch.milestone);
386
+ }
387
+ if (patch.estimateMinutes !== undefined) {
388
+ updates.push(`estimate_minutes = $${paramIdx++}`);
389
+ values.push(patch.estimateMinutes);
390
+ }
391
+ if (patch.complexity !== undefined) {
392
+ updates.push(`complexity = $${paramIdx++}`);
393
+ values.push(patch.complexity);
394
+ }
395
+ if (patch.parentId !== undefined) {
396
+ updates.push(`parent_id = $${paramIdx++}`);
397
+ values.push(patch.parentId);
398
+ }
399
+ if (patch.operatorLane !== undefined) {
400
+ updates.push(`operator_lane = $${paramIdx++}`);
401
+ values.push(patch.operatorLane);
402
+ }
403
+ if (patch.isSessionRoot !== undefined) {
404
+ updates.push(`is_session_root = $${paramIdx++}`);
405
+ values.push(patch.isSessionRoot);
406
+ }
407
+ if (patch.externalWorkItemId !== undefined) {
408
+ updates.push(`external_work_item_id = $${paramIdx++}`);
409
+ values.push(patch.externalWorkItemId);
410
+ }
411
+ if (patch.createdAt !== undefined) {
412
+ updates.push(`created_at = $${paramIdx++}`);
413
+ values.push(patch.createdAt);
414
+ }
415
+ if (patch.closedAt !== undefined) {
416
+ updates.push(`closed_at = $${paramIdx++}`);
417
+ values.push(patch.closedAt);
418
+ }
419
+ // The legacy trigger that auto-bumped updated_at is gone, so write it explicitly here.
420
+ // A caller-supplied updatedAt (e.g. a real System.ChangedDate from sync) wins; otherwise
421
+ // a normal local edit bumps to NOW(). updated_at is always written on update.
422
+ if (patch.updatedAt !== undefined) {
423
+ updates.push(`updated_at = $${paramIdx++}`);
424
+ values.push(patch.updatedAt);
425
+ }
426
+ else {
427
+ updates.push(`updated_at = NOW()`);
428
+ }
429
+ if (updates.length > 0) {
430
+ values.push(id);
431
+ await client.query(`
432
+ UPDATE ${this.schema}.work_items
433
+ SET ${updates.join(', ')}
434
+ WHERE id = $${paramIdx}
435
+ `, values);
436
+ }
437
+ await client.query('COMMIT');
438
+ return this.getWorkItemAsync(id);
439
+ }
440
+ catch (err) {
441
+ await client.query('ROLLBACK');
442
+ throw err;
443
+ }
444
+ finally {
445
+ client.release();
446
+ }
447
+ }
448
+ async deleteWorkItem(id) {
449
+ return this.deleteWorkItemAsync(id);
450
+ }
451
+ async deleteWorkItemAsync(id) {
452
+ const result = await this.pool.query(`
453
+ DELETE FROM ${this.schema}.work_items WHERE id = $1
454
+ `, [id]);
455
+ return (result.rowCount ?? 0) > 0;
456
+ }
457
+ async listWorkItems(filter) {
458
+ return this.listWorkItemsAsync(filter);
459
+ }
460
+ async listWorkItemsAsync(filter) {
461
+ const where = ['1=1'];
462
+ const params = [];
463
+ let paramIdx = 1;
464
+ if (filter?.projectId) {
465
+ where.push(`project_id = $${paramIdx++}`);
466
+ params.push(filter.projectId);
467
+ }
468
+ if (filter?.status?.length) {
469
+ where.push(`status = ANY($${paramIdx++})`);
470
+ params.push(filter.status);
471
+ }
472
+ if (filter?.priority?.length) {
473
+ where.push(`priority = ANY($${paramIdx++})`);
474
+ params.push(filter.priority);
475
+ }
476
+ if (filter?.assignee) {
477
+ where.push(`assignee = $${paramIdx++}`);
478
+ params.push(filter.assignee);
479
+ }
480
+ if (filter?.source) {
481
+ where.push(`source = $${paramIdx++}`);
482
+ params.push(filter.source);
483
+ }
484
+ if (filter?.search) {
485
+ where.push(`(
486
+ to_tsvector('english', title || ' ' || COALESCE(description, '')) @@ plainto_tsquery('english', $${paramIdx++})
487
+ OR title ILIKE $${paramIdx++}
488
+ )`);
489
+ params.push(filter.search, `%${filter.search}%`);
490
+ }
491
+ const limit = filter?.limit ?? 50;
492
+ const offset = filter?.offset ?? 0;
493
+ // Get total count
494
+ const countResult = await this.pool.query(`
495
+ SELECT COUNT(*) as total FROM ${this.schema}.work_items WHERE ${where.join(' AND ')}
496
+ `, params);
497
+ const total = parseInt(countResult.rows[0].total, 10);
498
+ // Get workItems
499
+ const result = await this.pool.query(`
500
+ SELECT * FROM ${this.schema}.work_items
501
+ WHERE ${where.join(' AND ')}
502
+ ORDER BY created_at DESC
503
+ LIMIT $${paramIdx++} OFFSET $${paramIdx++}
504
+ `, [...params, limit, offset]);
505
+ const workItems = await Promise.all(result.rows.map((row) => this.loadWorkItemDetails(row)));
506
+ return { workItems, total };
507
+ }
508
+ async loadWorkItemDetails(row) {
509
+ const client = await this.pool.connect();
510
+ try {
511
+ const workItem = this.rowToWorkItem(row);
512
+ // Load labels
513
+ const labelsResult = await client.query(`
514
+ SELECT l.name FROM ${this.schema}.labels l
515
+ JOIN ${this.schema}.work_item_labels il ON l.id = il.label_id
516
+ WHERE il.work_item_id = $1
517
+ `, [workItem.id]);
518
+ workItem.labels = labelsResult.rows.map((r) => r.name);
519
+ // Load dependencies
520
+ const depsResult = await client.query(`
521
+ SELECT depends_on_id FROM ${this.schema}.work_item_dependencies WHERE work_item_id = $1
522
+ `, [workItem.id]);
523
+ workItem.dependencies = depsResult.rows.map((r) => r.depends_on_id);
524
+ // Load relevant files
525
+ const filesResult = await client.query(`
526
+ SELECT file_path FROM ${this.schema}.work_item_relevant_files WHERE work_item_id = $1
527
+ `, [workItem.id]);
528
+ workItem.relevantFiles = filesResult.rows.map((r) => r.file_path);
529
+ // Load acceptance criteria
530
+ const acResult = await client.query(`
531
+ SELECT criterion FROM ${this.schema}.work_item_acceptance_criteria
532
+ WHERE work_item_id = $1 ORDER BY sort_order
533
+ `, [workItem.id]);
534
+ workItem.acceptanceCriteria = acResult.rows.map((r) => r.criterion);
535
+ // Load memory links
536
+ const memResult = await client.query(`
537
+ SELECT memory_id FROM ${this.schema}.work_item_memory_links WHERE work_item_id = $1
538
+ `, [workItem.id]);
539
+ workItem.memoryIds = memResult.rows.map((r) => r.memory_id);
540
+ return workItem;
541
+ }
542
+ finally {
543
+ client.release();
544
+ }
545
+ }
546
+ rowToWorkItem(row) {
547
+ return {
548
+ id: row.id,
549
+ projectId: row.project_id,
550
+ title: row.title,
551
+ description: row.description ?? '',
552
+ status: row.status,
553
+ priority: row.priority,
554
+ source: row.source,
555
+ kind: row.kind ?? undefined,
556
+ area: row.area ?? undefined,
557
+ reviewState: row.review_state ?? undefined,
558
+ resolution: row.resolution ?? undefined,
559
+ labels: [],
560
+ assignee: row.assignee ?? undefined,
561
+ milestone: row.milestone ?? undefined,
562
+ relevantFiles: [],
563
+ acceptanceCriteria: [],
564
+ estimateMinutes: row.estimate_minutes ?? undefined,
565
+ complexity: row.complexity ?? undefined,
566
+ dependencies: [],
567
+ parentId: row.parent_id ?? undefined,
568
+ childIds: [],
569
+ azdoId: row.azdo_id ?? undefined,
570
+ azdoIdentifier: row.azdo_identifier ?? undefined,
571
+ azdoUrl: row.azdo_url ?? undefined,
572
+ operatorSessionId: row.operator_session_id ?? undefined,
573
+ operatorLane: row.operator_lane ?? undefined,
574
+ isSessionRoot: row.is_session_root === true || row.is_session_root === 't' || row.is_session_root === 1,
575
+ externalWorkItemId: row.external_work_item_id ?? undefined,
576
+ memoryIds: [],
577
+ createdAt: row.created_at instanceof Date
578
+ ? row.created_at.toISOString()
579
+ : row.created_at,
580
+ updatedAt: row.updated_at instanceof Date
581
+ ? row.updated_at.toISOString()
582
+ : row.updated_at,
583
+ closedAt: row.closed_at instanceof Date
584
+ ? row.closed_at.toISOString()
585
+ : (row.closed_at ?? undefined),
586
+ };
587
+ }
588
+ // ============ Status Changes ============
589
+ async changeStatus(id, status, actor) {
590
+ return this.changeStatusAsync(id, status, actor);
591
+ }
592
+ async changeStatusAsync(id, status, actor) {
593
+ const closedAt = status === 'done' || status === 'cancelled' ? new Date().toISOString() : null;
594
+ await this.pool.query(`
595
+ UPDATE ${this.schema}.work_items
596
+ SET status = $1, closed_at = $2, updated_at = NOW()
597
+ WHERE id = $3
598
+ `, [status, closedAt, id]);
599
+ // Add event
600
+ await this.addEvent(id, 'status_changed', {
601
+ newValue: status,
602
+ actor,
603
+ });
604
+ return this.getWorkItemAsync(id);
605
+ }
606
+ // ============ Events ============
607
+ async addEvent(workItemId, type, data) {
608
+ const event = {
609
+ id: nanoid(12),
610
+ workItemId,
611
+ type,
612
+ oldValue: data?.oldValue,
613
+ newValue: data?.newValue,
614
+ content: data?.content,
615
+ memoryId: data?.memoryId,
616
+ actor: data?.actor ?? 'system',
617
+ createdAt: new Date().toISOString(),
618
+ };
619
+ await this.addEventAsync(event);
620
+ return event;
621
+ }
622
+ async addEventAsync(event) {
623
+ await this.pool.query(`
624
+ INSERT INTO ${this.schema}.work_item_events (id, work_item_id, type, old_value, new_value, content, memory_id, actor, created_at)
625
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
626
+ `, [
627
+ event.id, event.workItemId, event.type, event.oldValue, event.newValue,
628
+ event.content, event.memoryId, event.actor, event.createdAt,
629
+ ]);
630
+ }
631
+ async getEvents(workItemId, limit) {
632
+ return this.getEventsAsync(workItemId, limit);
633
+ }
634
+ async getEventsAsync(workItemId, limit) {
635
+ const result = await this.pool.query(`
636
+ SELECT * FROM ${this.schema}.work_item_events
637
+ WHERE work_item_id = $1
638
+ ORDER BY created_at DESC
639
+ LIMIT $2
640
+ `, [workItemId, limit ?? 50]);
641
+ return result.rows.map((row) => ({
642
+ id: row.id,
643
+ workItemId: row.work_item_id,
644
+ type: row.type,
645
+ oldValue: row.old_value ?? undefined,
646
+ newValue: row.new_value ?? undefined,
647
+ content: row.content ?? undefined,
648
+ memoryId: row.memory_id ?? undefined,
649
+ actor: row.actor,
650
+ createdAt: row.created_at instanceof Date
651
+ ? row.created_at.toISOString()
652
+ : row.created_at,
653
+ }));
654
+ }
655
+ async getRecentEvents(limit) {
656
+ return this.getRecentEventsAsync(limit);
657
+ }
658
+ async getRecentEventsAsync(limit) {
659
+ const result = await this.pool.query(`
660
+ SELECT * FROM ${this.schema}.work_item_events
661
+ ORDER BY created_at DESC
662
+ LIMIT $1
663
+ `, [limit ?? 50]);
664
+ return result.rows.map((row) => ({
665
+ id: row.id,
666
+ workItemId: row.work_item_id,
667
+ type: row.type,
668
+ oldValue: row.old_value ?? undefined,
669
+ newValue: row.new_value ?? undefined,
670
+ content: row.content ?? undefined,
671
+ memoryId: row.memory_id ?? undefined,
672
+ actor: row.actor,
673
+ createdAt: row.created_at instanceof Date
674
+ ? row.created_at.toISOString()
675
+ : row.created_at,
676
+ }));
677
+ }
678
+ // ============ Labels ============
679
+ async createLabel(name, color, description) {
680
+ const label = {
681
+ id: nanoid(12),
682
+ name,
683
+ color: color ?? '#6B7280',
684
+ description,
685
+ };
686
+ await this.createLabelAsync(label);
687
+ return label;
688
+ }
689
+ async createLabelAsync(label) {
690
+ await this.pool.query(`
691
+ INSERT INTO ${this.schema}.labels (id, name, color, description)
692
+ VALUES ($1, $2, $3, $4)
693
+ ON CONFLICT (name) DO NOTHING
694
+ `, [label.id, label.name, label.color, label.description]);
695
+ }
696
+ async listLabels() {
697
+ return this.listLabelsAsync();
698
+ }
699
+ async listLabelsAsync() {
700
+ const result = await this.pool.query(`SELECT * FROM ${this.schema}.labels`);
701
+ return result.rows.map((row) => ({
702
+ id: row.id,
703
+ name: row.name,
704
+ color: row.color,
705
+ description: row.description ?? undefined,
706
+ }));
707
+ }
708
+ async deleteLabel(id) {
709
+ return this.deleteLabelAsync(id);
710
+ }
711
+ async deleteLabelAsync(id) {
712
+ const result = await this.pool.query(`
713
+ DELETE FROM ${this.schema}.labels WHERE id = $1
714
+ `, [id]);
715
+ return (result.rowCount ?? 0) > 0;
716
+ }
717
+ // ============ Milestones ============
718
+ async createMilestone(name, description, dueDate) {
719
+ const milestone = {
720
+ id: nanoid(12),
721
+ name,
722
+ description,
723
+ dueDate,
724
+ status: 'active',
725
+ createdAt: new Date().toISOString(),
726
+ };
727
+ await this.createMilestoneAsync(milestone);
728
+ return milestone;
729
+ }
730
+ async createMilestoneAsync(milestone) {
731
+ await this.pool.query(`
732
+ INSERT INTO ${this.schema}.milestones (id, name, description, due_date, status, created_at)
733
+ VALUES ($1, $2, $3, $4, $5, $6)
734
+ `, [
735
+ milestone.id, milestone.name, milestone.description,
736
+ milestone.dueDate, milestone.status, milestone.createdAt,
737
+ ]);
738
+ }
739
+ async listMilestones() {
740
+ return this.listMilestonesAsync();
741
+ }
742
+ async listMilestonesAsync() {
743
+ const result = await this.pool.query(`
744
+ SELECT * FROM ${this.schema}.milestones WHERE status = 'active'
745
+ `);
746
+ return result.rows.map((row) => ({
747
+ id: row.id,
748
+ name: row.name,
749
+ description: row.description ?? undefined,
750
+ dueDate: row.due_date ?? undefined,
751
+ status: row.status,
752
+ createdAt: row.created_at instanceof Date
753
+ ? row.created_at.toISOString()
754
+ : row.created_at,
755
+ }));
756
+ }
757
+ // ============ Memory Links ============
758
+ async linkMemory(workItemId, memoryId) {
759
+ await this.linkMemoryAsync(workItemId, memoryId);
760
+ }
761
+ async linkMemoryAsync(workItemId, memoryId) {
762
+ await this.pool.query(`
763
+ INSERT INTO ${this.schema}.work_item_memory_links (work_item_id, memory_id, linked_at)
764
+ VALUES ($1, $2, NOW())
765
+ ON CONFLICT DO NOTHING
766
+ `, [workItemId, memoryId]);
767
+ }
768
+ async getLinkedMemories(workItemId) {
769
+ return this.getLinkedMemoriesAsync(workItemId);
770
+ }
771
+ async getLinkedMemoriesAsync(workItemId) {
772
+ const result = await this.pool.query(`
773
+ SELECT memory_id FROM ${this.schema}.work_item_memory_links WHERE work_item_id = $1
774
+ `, [workItemId]);
775
+ return result.rows.map((r) => r.memory_id);
776
+ }
777
+ // ============ Stats ============
778
+ async getStats() {
779
+ return this.getStatsAsync();
780
+ }
781
+ async getStatsAsync() {
782
+ const client = await this.pool.connect();
783
+ try {
784
+ // Total count
785
+ const totalResult = await client.query(`SELECT COUNT(*) as count FROM ${this.schema}.work_items`);
786
+ const total = parseInt(totalResult.rows[0].count, 10);
787
+ // By status
788
+ const statusResult = await client.query(`
789
+ SELECT status, COUNT(*) as count FROM ${this.schema}.work_items GROUP BY status
790
+ `);
791
+ const byStatus = {};
792
+ for (const row of statusResult.rows) {
793
+ byStatus[row.status] = parseInt(row.count, 10);
794
+ }
795
+ // By priority
796
+ const priorityResult = await client.query(`
797
+ SELECT priority, COUNT(*) as count FROM ${this.schema}.work_items GROUP BY priority
798
+ `);
799
+ const byPriority = {};
800
+ for (const row of priorityResult.rows) {
801
+ byPriority[row.priority] = parseInt(row.count, 10);
802
+ }
803
+ // By project
804
+ const projectResult = await client.query(`
805
+ SELECT project_id, COUNT(*) as count FROM ${this.schema}.work_items GROUP BY project_id
806
+ `);
807
+ const byProject = {};
808
+ for (const row of projectResult.rows) {
809
+ byProject[row.project_id] = parseInt(row.count, 10);
810
+ }
811
+ // Recently created (7 days)
812
+ const createdResult = await client.query(`
813
+ SELECT COUNT(*) as count FROM ${this.schema}.work_items
814
+ WHERE created_at > NOW() - INTERVAL '7 days'
815
+ `);
816
+ const recentlyCreated = parseInt(createdResult.rows[0].count, 10);
817
+ // Recently closed (7 days)
818
+ const closedResult = await client.query(`
819
+ SELECT COUNT(*) as count FROM ${this.schema}.work_items
820
+ WHERE closed_at > NOW() - INTERVAL '7 days'
821
+ `);
822
+ const recentlyClosed = parseInt(closedResult.rows[0].count, 10);
823
+ return {
824
+ total,
825
+ byStatus,
826
+ byPriority,
827
+ byProject,
828
+ recentlyCreated,
829
+ recentlyClosed,
830
+ };
831
+ }
832
+ finally {
833
+ client.release();
834
+ }
835
+ }
836
+ // ============ AzDO mirror payload (sync stubs — not yet wired to pool) ============
837
+ async setPayloadJson(workItemId, json) {
838
+ await this.pool.query(`UPDATE ${this.schema}.work_items SET payload_json = $1::jsonb WHERE id = $2`, [json, workItemId]);
839
+ }
840
+ async getPayloadJson(workItemId) {
841
+ const result = await this.pool.query(`SELECT payload_json FROM ${this.schema}.work_items WHERE id = $1`, [workItemId]);
842
+ if (result.rows.length === 0)
843
+ return null;
844
+ const value = result.rows[0].payload_json;
845
+ return value == null ? null : JSON.stringify(value);
846
+ }
847
+ async updateOperatorSessionId(workItemId, sessionId) {
848
+ await this.pool.query(`UPDATE ${this.schema}.work_items SET operator_session_id = $1, updated_at = NOW() WHERE id = $2`, [sessionId, workItemId]);
849
+ }
850
+ async pruneOrphans(source, keepIds) {
851
+ const result = await this.pool.query(`SELECT id FROM ${this.schema}.work_items WHERE source = $1`, [source]);
852
+ const ids = result.rows.map((row) => row.id);
853
+ const toDelete = ids.filter((id) => !keepIds.has(id));
854
+ if (toDelete.length === 0)
855
+ return 0;
856
+ await this.pool.query(`DELETE FROM ${this.schema}.work_items WHERE id = ANY($1::text[])`, [toDelete]);
857
+ return toDelete.length;
858
+ }
859
+ // ============ Sync watermarks ============
860
+ async getSyncMeta(key) {
861
+ const result = await this.pool.query(`SELECT value FROM ${this.schema}.sync_meta WHERE key = $1`, [key]);
862
+ return result.rows[0]?.value ?? null;
863
+ }
864
+ async setSyncMeta(key, value) {
865
+ await this.pool.query(`INSERT INTO ${this.schema}.sync_meta (key, value)
866
+ VALUES ($1, $2)
867
+ ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()`, [key, value]);
868
+ }
869
+ async getProjectConfigs() {
870
+ const result = await this.pool.query(`SELECT name, path, heartbeat_ms, azdo_label, enabled, paused, operators
871
+ FROM ${this.schema}.projects
872
+ ORDER BY name ASC`);
873
+ return result.rows.map((row) => ({
874
+ name: String(row.name),
875
+ path: String(row.path),
876
+ heartbeatMs: Number(row.heartbeat_ms),
877
+ azdoLabel: row.azdo_label ? String(row.azdo_label) : undefined,
878
+ enabled: Boolean(row.enabled),
879
+ paused: Boolean(row.paused),
880
+ operators: Array.isArray(row.operators)
881
+ ? row.operators.map((value) => String(value))
882
+ : [],
883
+ }));
884
+ }
885
+ async seedProjectConfigsIfEmpty(projects) {
886
+ if (projects.length === 0) {
887
+ return this.getProjectConfigs();
888
+ }
889
+ const client = await this.pool.connect();
890
+ try {
891
+ await client.query('BEGIN');
892
+ const countResult = await client.query(`SELECT COUNT(*)::int AS count FROM ${this.schema}.projects`);
893
+ const count = Number(countResult.rows[0]?.count ?? 0);
894
+ if (count === 0) {
895
+ for (const project of projects) {
896
+ await client.query(`INSERT INTO ${this.schema}.projects
897
+ (name, path, heartbeat_ms, azdo_label, enabled, paused, operators)
898
+ VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`, [
899
+ project.name,
900
+ project.path,
901
+ project.heartbeatMs,
902
+ project.azdoLabel ?? null,
903
+ project.enabled,
904
+ project.paused,
905
+ JSON.stringify(project.operators ?? []),
906
+ ]);
907
+ }
908
+ }
909
+ await client.query('COMMIT');
910
+ }
911
+ catch (error) {
912
+ await client.query('ROLLBACK');
913
+ throw error;
914
+ }
915
+ finally {
916
+ client.release();
917
+ }
918
+ return this.getProjectConfigs();
919
+ }
920
+ // ============ Sync interface (compatibility) ============
921
+ // These methods ensure interface compatibility but log warnings
922
+ async syncListWorkItems(filter) {
923
+ return this.listWorkItemsAsync(filter);
924
+ }
925
+ async syncGetStats() {
926
+ return this.getStatsAsync();
927
+ }
928
+ }
929
+ // Factory function to create appropriate store based on config
930
+ export function createWorkItemStore(config) {
931
+ if (config.type === 'postgres') {
932
+ return new PostgresWorkItemStore(config.postgres ?? {});
933
+ }
934
+ // Return SQLite store via the config-aware index, not sqliteStore directly
935
+ throw new Error('Use openSqliteWorkItemStore() from sqliteStore.js for SQLite directly, or getWorkItemStore() from workItems/index.js');
936
+ }
937
+ //# sourceMappingURL=postgresStore.js.map