@telora/daemon 0.12.33

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 (473) hide show
  1. package/.env.example +64 -0
  2. package/README.md +229 -0
  3. package/build-info.json +4 -0
  4. package/dist/activity-tracker.d.ts +13 -0
  5. package/dist/activity-tracker.d.ts.map +1 -0
  6. package/dist/activity-tracker.js +19 -0
  7. package/dist/activity-tracker.js.map +1 -0
  8. package/dist/agent-state.d.ts +45 -0
  9. package/dist/agent-state.d.ts.map +1 -0
  10. package/dist/agent-state.js +61 -0
  11. package/dist/agent-state.js.map +1 -0
  12. package/dist/audit-hooks.d.ts +12 -0
  13. package/dist/audit-hooks.d.ts.map +1 -0
  14. package/dist/audit-hooks.js +45 -0
  15. package/dist/audit-hooks.js.map +1 -0
  16. package/dist/auto-update.d.ts +42 -0
  17. package/dist/auto-update.d.ts.map +1 -0
  18. package/dist/auto-update.js +96 -0
  19. package/dist/auto-update.js.map +1 -0
  20. package/dist/branch-status.d.ts +40 -0
  21. package/dist/branch-status.d.ts.map +1 -0
  22. package/dist/branch-status.js +107 -0
  23. package/dist/branch-status.js.map +1 -0
  24. package/dist/completion-detector.d.ts +87 -0
  25. package/dist/completion-detector.d.ts.map +1 -0
  26. package/dist/completion-detector.js +160 -0
  27. package/dist/completion-detector.js.map +1 -0
  28. package/dist/completion-handler.d.ts +48 -0
  29. package/dist/completion-handler.d.ts.map +1 -0
  30. package/dist/completion-handler.js +200 -0
  31. package/dist/completion-handler.js.map +1 -0
  32. package/dist/condition-evaluators.d.ts +31 -0
  33. package/dist/condition-evaluators.d.ts.map +1 -0
  34. package/dist/condition-evaluators.js +416 -0
  35. package/dist/condition-evaluators.js.map +1 -0
  36. package/dist/config.d.ts +55 -0
  37. package/dist/config.d.ts.map +1 -0
  38. package/dist/config.js +311 -0
  39. package/dist/config.js.map +1 -0
  40. package/dist/control-state.d.ts +41 -0
  41. package/dist/control-state.d.ts.map +1 -0
  42. package/dist/control-state.js +204 -0
  43. package/dist/control-state.js.map +1 -0
  44. package/dist/crash-recovery-cleanup.d.ts +21 -0
  45. package/dist/crash-recovery-cleanup.d.ts.map +1 -0
  46. package/dist/crash-recovery-cleanup.js +198 -0
  47. package/dist/crash-recovery-cleanup.js.map +1 -0
  48. package/dist/crash-recovery-scan.d.ts +19 -0
  49. package/dist/crash-recovery-scan.d.ts.map +1 -0
  50. package/dist/crash-recovery-scan.js +145 -0
  51. package/dist/crash-recovery-scan.js.map +1 -0
  52. package/dist/crash-recovery-types.d.ts +54 -0
  53. package/dist/crash-recovery-types.d.ts.map +1 -0
  54. package/dist/crash-recovery-types.js +13 -0
  55. package/dist/crash-recovery-types.js.map +1 -0
  56. package/dist/crash-recovery.d.ts +88 -0
  57. package/dist/crash-recovery.d.ts.map +1 -0
  58. package/dist/crash-recovery.js +448 -0
  59. package/dist/crash-recovery.js.map +1 -0
  60. package/dist/daemon-logs.d.ts +19 -0
  61. package/dist/daemon-logs.d.ts.map +1 -0
  62. package/dist/daemon-logs.js +81 -0
  63. package/dist/daemon-logs.js.map +1 -0
  64. package/dist/daemon-process.d.ts +154 -0
  65. package/dist/daemon-process.d.ts.map +1 -0
  66. package/dist/daemon-process.js +427 -0
  67. package/dist/daemon-process.js.map +1 -0
  68. package/dist/dag-validator.d.ts +52 -0
  69. package/dist/dag-validator.d.ts.map +1 -0
  70. package/dist/dag-validator.js +199 -0
  71. package/dist/dag-validator.js.map +1 -0
  72. package/dist/delivery-guards.d.ts +41 -0
  73. package/dist/delivery-guards.d.ts.map +1 -0
  74. package/dist/delivery-guards.js +195 -0
  75. package/dist/delivery-guards.js.map +1 -0
  76. package/dist/delivery-lifecycle.d.ts +110 -0
  77. package/dist/delivery-lifecycle.d.ts.map +1 -0
  78. package/dist/delivery-lifecycle.js +353 -0
  79. package/dist/delivery-lifecycle.js.map +1 -0
  80. package/dist/delivery-merge.d.ts +17 -0
  81. package/dist/delivery-merge.d.ts.map +1 -0
  82. package/dist/delivery-merge.js +89 -0
  83. package/dist/delivery-merge.js.map +1 -0
  84. package/dist/dependency-resolver.d.ts +77 -0
  85. package/dist/dependency-resolver.d.ts.map +1 -0
  86. package/dist/dependency-resolver.js +337 -0
  87. package/dist/dependency-resolver.js.map +1 -0
  88. package/dist/evaluation-context.d.ts +49 -0
  89. package/dist/evaluation-context.d.ts.map +1 -0
  90. package/dist/evaluation-context.js +98 -0
  91. package/dist/evaluation-context.js.map +1 -0
  92. package/dist/git-activity.d.ts +24 -0
  93. package/dist/git-activity.d.ts.map +1 -0
  94. package/dist/git-activity.js +97 -0
  95. package/dist/git-activity.js.map +1 -0
  96. package/dist/git-branch.d.ts +33 -0
  97. package/dist/git-branch.d.ts.map +1 -0
  98. package/dist/git-branch.js +88 -0
  99. package/dist/git-branch.js.map +1 -0
  100. package/dist/git-integration.d.ts +27 -0
  101. package/dist/git-integration.d.ts.map +1 -0
  102. package/dist/git-integration.js +82 -0
  103. package/dist/git-integration.js.map +1 -0
  104. package/dist/git-merge-helpers.d.ts +48 -0
  105. package/dist/git-merge-helpers.d.ts.map +1 -0
  106. package/dist/git-merge-helpers.js +105 -0
  107. package/dist/git-merge-helpers.js.map +1 -0
  108. package/dist/git-merge-lock.d.ts +67 -0
  109. package/dist/git-merge-lock.d.ts.map +1 -0
  110. package/dist/git-merge-lock.js +157 -0
  111. package/dist/git-merge-lock.js.map +1 -0
  112. package/dist/git-merge-strategies.d.ts +39 -0
  113. package/dist/git-merge-strategies.d.ts.map +1 -0
  114. package/dist/git-merge-strategies.js +127 -0
  115. package/dist/git-merge-strategies.js.map +1 -0
  116. package/dist/git-merge.d.ts +80 -0
  117. package/dist/git-merge.d.ts.map +1 -0
  118. package/dist/git-merge.js +373 -0
  119. package/dist/git-merge.js.map +1 -0
  120. package/dist/git-state-detector.d.ts +24 -0
  121. package/dist/git-state-detector.d.ts.map +1 -0
  122. package/dist/git-state-detector.js +122 -0
  123. package/dist/git-state-detector.js.map +1 -0
  124. package/dist/git-types.d.ts +40 -0
  125. package/dist/git-types.d.ts.map +1 -0
  126. package/dist/git-types.js +23 -0
  127. package/dist/git-types.js.map +1 -0
  128. package/dist/git-utils.d.ts +28 -0
  129. package/dist/git-utils.d.ts.map +1 -0
  130. package/dist/git-utils.js +57 -0
  131. package/dist/git-utils.js.map +1 -0
  132. package/dist/git.d.ts +24 -0
  133. package/dist/git.d.ts.map +1 -0
  134. package/dist/git.js +64 -0
  135. package/dist/git.js.map +1 -0
  136. package/dist/guard-engine.d.ts +19 -0
  137. package/dist/guard-engine.d.ts.map +1 -0
  138. package/dist/guard-engine.js +21 -0
  139. package/dist/guard-engine.js.map +1 -0
  140. package/dist/guard-evaluator.d.ts +47 -0
  141. package/dist/guard-evaluator.d.ts.map +1 -0
  142. package/dist/guard-evaluator.js +193 -0
  143. package/dist/guard-evaluator.js.map +1 -0
  144. package/dist/heartbeat.d.ts +73 -0
  145. package/dist/heartbeat.d.ts.map +1 -0
  146. package/dist/heartbeat.js +306 -0
  147. package/dist/heartbeat.js.map +1 -0
  148. package/dist/index.d.ts +32 -0
  149. package/dist/index.d.ts.map +1 -0
  150. package/dist/index.js +493 -0
  151. package/dist/index.js.map +1 -0
  152. package/dist/listener-auto-advance.d.ts +29 -0
  153. package/dist/listener-auto-advance.d.ts.map +1 -0
  154. package/dist/listener-auto-advance.js +172 -0
  155. package/dist/listener-auto-advance.js.map +1 -0
  156. package/dist/listener-review.d.ts +37 -0
  157. package/dist/listener-review.d.ts.map +1 -0
  158. package/dist/listener-review.js +217 -0
  159. package/dist/listener-review.js.map +1 -0
  160. package/dist/listener.d.ts +57 -0
  161. package/dist/listener.d.ts.map +1 -0
  162. package/dist/listener.js +361 -0
  163. package/dist/listener.js.map +1 -0
  164. package/dist/log-manager.d.ts +18 -0
  165. package/dist/log-manager.d.ts.map +1 -0
  166. package/dist/log-manager.js +18 -0
  167. package/dist/log-manager.js.map +1 -0
  168. package/dist/otlp-log-parser.d.ts +21 -0
  169. package/dist/otlp-log-parser.d.ts.map +1 -0
  170. package/dist/otlp-log-parser.js +143 -0
  171. package/dist/otlp-log-parser.js.map +1 -0
  172. package/dist/otlp-metric-parser.d.ts +20 -0
  173. package/dist/otlp-metric-parser.d.ts.map +1 -0
  174. package/dist/otlp-metric-parser.js +113 -0
  175. package/dist/otlp-metric-parser.js.map +1 -0
  176. package/dist/otlp-port-manager.d.ts +26 -0
  177. package/dist/otlp-port-manager.d.ts.map +1 -0
  178. package/dist/otlp-port-manager.js +130 -0
  179. package/dist/otlp-port-manager.js.map +1 -0
  180. package/dist/otlp-receiver.d.ts +51 -0
  181. package/dist/otlp-receiver.d.ts.map +1 -0
  182. package/dist/otlp-receiver.js +663 -0
  183. package/dist/otlp-receiver.js.map +1 -0
  184. package/dist/otlp-types.d.ts +92 -0
  185. package/dist/otlp-types.d.ts.map +1 -0
  186. package/dist/otlp-types.js +133 -0
  187. package/dist/otlp-types.js.map +1 -0
  188. package/dist/output-monitor.d.ts +33 -0
  189. package/dist/output-monitor.d.ts.map +1 -0
  190. package/dist/output-monitor.js +67 -0
  191. package/dist/output-monitor.js.map +1 -0
  192. package/dist/planning-prompt-builder.d.ts +67 -0
  193. package/dist/planning-prompt-builder.d.ts.map +1 -0
  194. package/dist/planning-prompt-builder.js +515 -0
  195. package/dist/planning-prompt-builder.js.map +1 -0
  196. package/dist/prompt-builder.d.ts +14 -0
  197. package/dist/prompt-builder.d.ts.map +1 -0
  198. package/dist/prompt-builder.js +174 -0
  199. package/dist/prompt-builder.js.map +1 -0
  200. package/dist/qa-crash-recovery.d.ts +77 -0
  201. package/dist/qa-crash-recovery.d.ts.map +1 -0
  202. package/dist/qa-crash-recovery.js +243 -0
  203. package/dist/qa-crash-recovery.js.map +1 -0
  204. package/dist/qa-dev-server.d.ts +73 -0
  205. package/dist/qa-dev-server.d.ts.map +1 -0
  206. package/dist/qa-dev-server.js +279 -0
  207. package/dist/qa-dev-server.js.map +1 -0
  208. package/dist/qa-orchestrator.d.ts +79 -0
  209. package/dist/qa-orchestrator.d.ts.map +1 -0
  210. package/dist/qa-orchestrator.js +349 -0
  211. package/dist/qa-orchestrator.js.map +1 -0
  212. package/dist/qa-port-allocator.d.ts +34 -0
  213. package/dist/qa-port-allocator.d.ts.map +1 -0
  214. package/dist/qa-port-allocator.js +75 -0
  215. package/dist/qa-port-allocator.js.map +1 -0
  216. package/dist/qa-provisioner.d.ts +33 -0
  217. package/dist/qa-provisioner.d.ts.map +1 -0
  218. package/dist/qa-provisioner.js +141 -0
  219. package/dist/qa-provisioner.js.map +1 -0
  220. package/dist/qa-state.d.ts +93 -0
  221. package/dist/qa-state.d.ts.map +1 -0
  222. package/dist/qa-state.js +74 -0
  223. package/dist/qa-state.js.map +1 -0
  224. package/dist/queries/control-state.d.ts +25 -0
  225. package/dist/queries/control-state.d.ts.map +1 -0
  226. package/dist/queries/control-state.js +34 -0
  227. package/dist/queries/control-state.js.map +1 -0
  228. package/dist/queries/daemon-connection.d.ts +25 -0
  229. package/dist/queries/daemon-connection.d.ts.map +1 -0
  230. package/dist/queries/daemon-connection.js +28 -0
  231. package/dist/queries/daemon-connection.js.map +1 -0
  232. package/dist/queries/deliveries.d.ts +100 -0
  233. package/dist/queries/deliveries.d.ts.map +1 -0
  234. package/dist/queries/deliveries.js +184 -0
  235. package/dist/queries/deliveries.js.map +1 -0
  236. package/dist/queries/git-activity.d.ts +20 -0
  237. package/dist/queries/git-activity.d.ts.map +1 -0
  238. package/dist/queries/git-activity.js +22 -0
  239. package/dist/queries/git-activity.js.map +1 -0
  240. package/dist/queries/guards.d.ts +47 -0
  241. package/dist/queries/guards.d.ts.map +1 -0
  242. package/dist/queries/guards.js +138 -0
  243. package/dist/queries/guards.js.map +1 -0
  244. package/dist/queries/index.d.ts +19 -0
  245. package/dist/queries/index.d.ts.map +1 -0
  246. package/dist/queries/index.js +17 -0
  247. package/dist/queries/index.js.map +1 -0
  248. package/dist/queries/issues.d.ts +41 -0
  249. package/dist/queries/issues.d.ts.map +1 -0
  250. package/dist/queries/issues.js +67 -0
  251. package/dist/queries/issues.js.map +1 -0
  252. package/dist/queries/qa.d.ts +79 -0
  253. package/dist/queries/qa.d.ts.map +1 -0
  254. package/dist/queries/qa.js +85 -0
  255. package/dist/queries/qa.js.map +1 -0
  256. package/dist/queries/roles.d.ts +13 -0
  257. package/dist/queries/roles.d.ts.map +1 -0
  258. package/dist/queries/roles.js +39 -0
  259. package/dist/queries/roles.js.map +1 -0
  260. package/dist/queries/schemas.d.ts +777 -0
  261. package/dist/queries/schemas.d.ts.map +1 -0
  262. package/dist/queries/schemas.js +391 -0
  263. package/dist/queries/schemas.js.map +1 -0
  264. package/dist/queries/sessions.d.ts +64 -0
  265. package/dist/queries/sessions.d.ts.map +1 -0
  266. package/dist/queries/sessions.js +100 -0
  267. package/dist/queries/sessions.js.map +1 -0
  268. package/dist/queries/shared.d.ts +61 -0
  269. package/dist/queries/shared.d.ts.map +1 -0
  270. package/dist/queries/shared.js +187 -0
  271. package/dist/queries/shared.js.map +1 -0
  272. package/dist/queries/strategies.d.ts +69 -0
  273. package/dist/queries/strategies.d.ts.map +1 -0
  274. package/dist/queries/strategies.js +80 -0
  275. package/dist/queries/strategies.js.map +1 -0
  276. package/dist/queries/workflows.d.ts +17 -0
  277. package/dist/queries/workflows.d.ts.map +1 -0
  278. package/dist/queries/workflows.js +49 -0
  279. package/dist/queries/workflows.js.map +1 -0
  280. package/dist/queries/worktrees.d.ts +38 -0
  281. package/dist/queries/worktrees.d.ts.map +1 -0
  282. package/dist/queries/worktrees.js +37 -0
  283. package/dist/queries/worktrees.js.map +1 -0
  284. package/dist/self-update.d.ts +94 -0
  285. package/dist/self-update.d.ts.map +1 -0
  286. package/dist/self-update.js +438 -0
  287. package/dist/self-update.js.map +1 -0
  288. package/dist/session-lifecycle.d.ts +77 -0
  289. package/dist/session-lifecycle.d.ts.map +1 -0
  290. package/dist/session-lifecycle.js +379 -0
  291. package/dist/session-lifecycle.js.map +1 -0
  292. package/dist/shutdown-state.d.ts +17 -0
  293. package/dist/shutdown-state.d.ts.map +1 -0
  294. package/dist/shutdown-state.js +22 -0
  295. package/dist/shutdown-state.js.map +1 -0
  296. package/dist/spawn-cooldown.d.ts +14 -0
  297. package/dist/spawn-cooldown.d.ts.map +1 -0
  298. package/dist/spawn-cooldown.js +34 -0
  299. package/dist/spawn-cooldown.js.map +1 -0
  300. package/dist/spawn-environment.d.ts +35 -0
  301. package/dist/spawn-environment.d.ts.map +1 -0
  302. package/dist/spawn-environment.js +48 -0
  303. package/dist/spawn-environment.js.map +1 -0
  304. package/dist/spawner-liveness.d.ts +23 -0
  305. package/dist/spawner-liveness.d.ts.map +1 -0
  306. package/dist/spawner-liveness.js +99 -0
  307. package/dist/spawner-liveness.js.map +1 -0
  308. package/dist/spawner-resolution.d.ts +27 -0
  309. package/dist/spawner-resolution.d.ts.map +1 -0
  310. package/dist/spawner-resolution.js +99 -0
  311. package/dist/spawner-resolution.js.map +1 -0
  312. package/dist/spawner-timeout.d.ts +32 -0
  313. package/dist/spawner-timeout.d.ts.map +1 -0
  314. package/dist/spawner-timeout.js +124 -0
  315. package/dist/spawner-timeout.js.map +1 -0
  316. package/dist/spawner.d.ts +77 -0
  317. package/dist/spawner.d.ts.map +1 -0
  318. package/dist/spawner.js +734 -0
  319. package/dist/spawner.js.map +1 -0
  320. package/dist/strategy-completion.d.ts +110 -0
  321. package/dist/strategy-completion.d.ts.map +1 -0
  322. package/dist/strategy-completion.js +434 -0
  323. package/dist/strategy-completion.js.map +1 -0
  324. package/dist/strategy-engine.d.ts +47 -0
  325. package/dist/strategy-engine.d.ts.map +1 -0
  326. package/dist/strategy-engine.js +419 -0
  327. package/dist/strategy-engine.js.map +1 -0
  328. package/dist/strategy-executor.d.ts +93 -0
  329. package/dist/strategy-executor.d.ts.map +1 -0
  330. package/dist/strategy-executor.js +775 -0
  331. package/dist/strategy-executor.js.map +1 -0
  332. package/dist/strategy-lifecycle.d.ts +61 -0
  333. package/dist/strategy-lifecycle.d.ts.map +1 -0
  334. package/dist/strategy-lifecycle.js +516 -0
  335. package/dist/strategy-lifecycle.js.map +1 -0
  336. package/dist/strategy-merge.d.ts +72 -0
  337. package/dist/strategy-merge.d.ts.map +1 -0
  338. package/dist/strategy-merge.js +371 -0
  339. package/dist/strategy-merge.js.map +1 -0
  340. package/dist/strategy-prompt-builder.d.ts +62 -0
  341. package/dist/strategy-prompt-builder.d.ts.map +1 -0
  342. package/dist/strategy-prompt-builder.js +538 -0
  343. package/dist/strategy-prompt-builder.js.map +1 -0
  344. package/dist/strategy-provisioning.d.ts +16 -0
  345. package/dist/strategy-provisioning.d.ts.map +1 -0
  346. package/dist/strategy-provisioning.js +119 -0
  347. package/dist/strategy-provisioning.js.map +1 -0
  348. package/dist/strategy-team-state.d.ts +24 -0
  349. package/dist/strategy-team-state.d.ts.map +1 -0
  350. package/dist/strategy-team-state.js +43 -0
  351. package/dist/strategy-team-state.js.map +1 -0
  352. package/dist/strategy-teardown.d.ts +24 -0
  353. package/dist/strategy-teardown.d.ts.map +1 -0
  354. package/dist/strategy-teardown.js +158 -0
  355. package/dist/strategy-teardown.js.map +1 -0
  356. package/dist/strategy-worktree-state.d.ts +47 -0
  357. package/dist/strategy-worktree-state.d.ts.map +1 -0
  358. package/dist/strategy-worktree-state.js +104 -0
  359. package/dist/strategy-worktree-state.js.map +1 -0
  360. package/dist/supabase.d.ts +36 -0
  361. package/dist/supabase.d.ts.map +1 -0
  362. package/dist/supabase.js +50 -0
  363. package/dist/supabase.js.map +1 -0
  364. package/dist/task-converter.d.ts +61 -0
  365. package/dist/task-converter.d.ts.map +1 -0
  366. package/dist/task-converter.js +286 -0
  367. package/dist/task-converter.js.map +1 -0
  368. package/dist/task-dag-builder.d.ts +14 -0
  369. package/dist/task-dag-builder.d.ts.map +1 -0
  370. package/dist/task-dag-builder.js +17 -0
  371. package/dist/task-dag-builder.js.map +1 -0
  372. package/dist/team-prompt-base.d.ts +114 -0
  373. package/dist/team-prompt-base.d.ts.map +1 -0
  374. package/dist/team-prompt-base.js +531 -0
  375. package/dist/team-prompt-base.js.map +1 -0
  376. package/dist/team-prompt-variants.d.ts +27 -0
  377. package/dist/team-prompt-variants.d.ts.map +1 -0
  378. package/dist/team-prompt-variants.js +134 -0
  379. package/dist/team-prompt-variants.js.map +1 -0
  380. package/dist/team-spawner.d.ts +50 -0
  381. package/dist/team-spawner.d.ts.map +1 -0
  382. package/dist/team-spawner.js +410 -0
  383. package/dist/team-spawner.js.map +1 -0
  384. package/dist/telemetry-writer.d.ts +66 -0
  385. package/dist/telemetry-writer.d.ts.map +1 -0
  386. package/dist/telemetry-writer.js +96 -0
  387. package/dist/telemetry-writer.js.map +1 -0
  388. package/dist/trigger-executor.d.ts +56 -0
  389. package/dist/trigger-executor.d.ts.map +1 -0
  390. package/dist/trigger-executor.js +313 -0
  391. package/dist/trigger-executor.js.map +1 -0
  392. package/dist/types/config.d.ts +60 -0
  393. package/dist/types/config.d.ts.map +1 -0
  394. package/dist/types/config.js +5 -0
  395. package/dist/types/config.js.map +1 -0
  396. package/dist/types/dag.d.ts +53 -0
  397. package/dist/types/dag.d.ts.map +1 -0
  398. package/dist/types/dag.js +5 -0
  399. package/dist/types/dag.js.map +1 -0
  400. package/dist/types/delivery.d.ts +71 -0
  401. package/dist/types/delivery.d.ts.map +1 -0
  402. package/dist/types/delivery.js +5 -0
  403. package/dist/types/delivery.js.map +1 -0
  404. package/dist/types/index.d.ts +15 -0
  405. package/dist/types/index.d.ts.map +1 -0
  406. package/dist/types/index.js +15 -0
  407. package/dist/types/index.js.map +1 -0
  408. package/dist/types/issue.d.ts +22 -0
  409. package/dist/types/issue.d.ts.map +1 -0
  410. package/dist/types/issue.js +5 -0
  411. package/dist/types/issue.js.map +1 -0
  412. package/dist/types/merge.d.ts +28 -0
  413. package/dist/types/merge.d.ts.map +1 -0
  414. package/dist/types/merge.js +5 -0
  415. package/dist/types/merge.js.map +1 -0
  416. package/dist/types/session.d.ts +98 -0
  417. package/dist/types/session.d.ts.map +1 -0
  418. package/dist/types/session.js +5 -0
  419. package/dist/types/session.js.map +1 -0
  420. package/dist/types/strategy.d.ts +175 -0
  421. package/dist/types/strategy.d.ts.map +1 -0
  422. package/dist/types/strategy.js +5 -0
  423. package/dist/types/strategy.js.map +1 -0
  424. package/dist/types/workflow.d.ts +34 -0
  425. package/dist/types/workflow.d.ts.map +1 -0
  426. package/dist/types/workflow.js +9 -0
  427. package/dist/types/workflow.js.map +1 -0
  428. package/dist/types.d.ts +9 -0
  429. package/dist/types.d.ts.map +1 -0
  430. package/dist/types.js +9 -0
  431. package/dist/types.js.map +1 -0
  432. package/dist/unified-init.d.ts +16 -0
  433. package/dist/unified-init.d.ts.map +1 -0
  434. package/dist/unified-init.js +183 -0
  435. package/dist/unified-init.js.map +1 -0
  436. package/dist/unified-shell-config.d.ts +34 -0
  437. package/dist/unified-shell-config.d.ts.map +1 -0
  438. package/dist/unified-shell-config.js +238 -0
  439. package/dist/unified-shell-config.js.map +1 -0
  440. package/dist/unified-shell-status.d.ts +15 -0
  441. package/dist/unified-shell-status.d.ts.map +1 -0
  442. package/dist/unified-shell-status.js +100 -0
  443. package/dist/unified-shell-status.js.map +1 -0
  444. package/dist/unified-shell.d.ts +50 -0
  445. package/dist/unified-shell.d.ts.map +1 -0
  446. package/dist/unified-shell.js +682 -0
  447. package/dist/unified-shell.js.map +1 -0
  448. package/dist/version-check.d.ts +19 -0
  449. package/dist/version-check.d.ts.map +1 -0
  450. package/dist/version-check.js +67 -0
  451. package/dist/version-check.js.map +1 -0
  452. package/dist/workflow-engine.d.ts +95 -0
  453. package/dist/workflow-engine.d.ts.map +1 -0
  454. package/dist/workflow-engine.js +165 -0
  455. package/dist/workflow-engine.js.map +1 -0
  456. package/dist/worktree-merge.d.ts +23 -0
  457. package/dist/worktree-merge.d.ts.map +1 -0
  458. package/dist/worktree-merge.js +57 -0
  459. package/dist/worktree-merge.js.map +1 -0
  460. package/dist/worktree-safety.d.ts +48 -0
  461. package/dist/worktree-safety.d.ts.map +1 -0
  462. package/dist/worktree-safety.js +113 -0
  463. package/dist/worktree-safety.js.map +1 -0
  464. package/dist/worktree-strategy.d.ts +69 -0
  465. package/dist/worktree-strategy.d.ts.map +1 -0
  466. package/dist/worktree-strategy.js +214 -0
  467. package/dist/worktree-strategy.js.map +1 -0
  468. package/dist/worktree.d.ts +159 -0
  469. package/dist/worktree.d.ts.map +1 -0
  470. package/dist/worktree.js +512 -0
  471. package/dist/worktree.js.map +1 -0
  472. package/package.json +76 -0
  473. package/scripts/telora-daemon-wrapper.sh +31 -0
@@ -0,0 +1,349 @@
1
+ /**
2
+ * QA environment orchestration.
3
+ *
4
+ * Called by the daemon poll loop to process pending QA requests.
5
+ * Coordinates provisioning and teardown using the lower-level modules.
6
+ */
7
+ import { getQaRequests, updateQaStatus, getDeactivatedQaStrategies, getProductQaRequests, updateProductQaStatus } from './supabase.js';
8
+ import { symlinkEnvFiles, createQaWorktree, removeQaWorktree } from './qa-provisioner.js';
9
+ import { getStrategyWorktree as getStrategyWorktreeImpl } from './strategy-worktree-state.js';
10
+ import { allocatePort, buildQaUrl } from './qa-port-allocator.js';
11
+ import { startQaDevServer, stopQaDevServer } from './qa-dev-server.js';
12
+ import { getQaEnvironment, setQaEnvironment, removeQaEnvironment, hasActiveQaEnvironment, getProductQaEnvironment, setProductQaEnvironment, removeProductQaEnvironment, hasActiveProductQaEnvironment, } from './qa-state.js';
13
+ /** Default deps wired to real implementations. */
14
+ const defaultDeps = {
15
+ getQaRequests,
16
+ getDeactivatedQaStrategies,
17
+ updateQaStatus,
18
+ getStrategyWorktree: getStrategyWorktreeImpl,
19
+ symlinkEnvFiles,
20
+ allocatePort,
21
+ buildQaUrl,
22
+ startQaDevServer,
23
+ stopQaDevServer,
24
+ getQaEnvironment,
25
+ setQaEnvironment,
26
+ removeQaEnvironment,
27
+ hasActiveQaEnvironment,
28
+ };
29
+ /**
30
+ * Check for and process pending QA requests.
31
+ * Called each poll cycle from listener.ts.
32
+ */
33
+ export async function checkQaRequests(config, deps = defaultDeps) {
34
+ let requests;
35
+ try {
36
+ requests = await deps.getQaRequests(config.productId);
37
+ }
38
+ catch (err) {
39
+ console.warn(`[qa] Failed to fetch QA requests: ${err.message}`);
40
+ return;
41
+ }
42
+ if (requests.length === 0)
43
+ return;
44
+ for (const req of requests) {
45
+ try {
46
+ if (req.qa_status === 'requested') {
47
+ await handleQaProvision(config, req, deps);
48
+ }
49
+ else if (req.qa_status === 'stop_requested') {
50
+ await handleQaTeardown(config, req, deps);
51
+ }
52
+ }
53
+ catch (err) {
54
+ console.error(`[qa] Error processing QA request for strategy ${req.strategy_name}: ${err.message}`);
55
+ // Update DB to failed state
56
+ try {
57
+ await deps.updateQaStatus(req.strategy_id, {
58
+ qaStatus: 'failed',
59
+ qaError: err.message,
60
+ });
61
+ }
62
+ catch (updateErr) {
63
+ console.warn(`[qa] Failed to update error state: ${updateErr.message}`);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ /**
69
+ * Provision a QA environment for a strategy.
70
+ *
71
+ * 1. If already active (refresh case), tear down first.
72
+ * 2. Set DB status to 'provisioning'.
73
+ * 3. Allocate a port and create a worktree.
74
+ * 4. Install deps and start the dev server.
75
+ * 5. Update in-memory state and DB to 'ready'.
76
+ */
77
+ async function handleQaProvision(config, req, deps) {
78
+ const { strategy_id: strategyId, strategy_name: strategyName } = req;
79
+ // If already active (refresh), tear down first
80
+ if (deps.hasActiveQaEnvironment(strategyId)) {
81
+ console.log(`[qa] Refreshing QA environment for "${strategyName}"`);
82
+ await handleQaTeardown(config, req, deps);
83
+ }
84
+ // 1. Set provisioning in DB
85
+ await deps.updateQaStatus(strategyId, { qaStatus: 'provisioning' });
86
+ // 2. Allocate port
87
+ const port = await deps.allocatePort(config);
88
+ const url = deps.buildQaUrl(config, port);
89
+ // 3. Look up the persistent strategy worktree (QA runs inside it)
90
+ const worktreeInfo = deps.getStrategyWorktree(strategyId);
91
+ if (!worktreeInfo) {
92
+ throw new Error(`No persistent worktree found for strategy "${strategyName}" (${strategyId})`);
93
+ }
94
+ const worktreePath = worktreeInfo.worktreePath;
95
+ deps.symlinkEnvFiles(config.repoPath, worktreePath);
96
+ // 4. Track in memory (status provisioning, dev server not yet started)
97
+ const state = {
98
+ strategyId,
99
+ strategyName,
100
+ worktreePath,
101
+ pid: null,
102
+ port,
103
+ url,
104
+ status: 'provisioning',
105
+ createdAt: new Date(),
106
+ lastError: null,
107
+ };
108
+ deps.setQaEnvironment(strategyId, state);
109
+ // 5. Start dev server (npm install + npm run dev)
110
+ const result = deps.startQaDevServer({
111
+ config,
112
+ strategyId,
113
+ worktreePath,
114
+ port,
115
+ onUnexpectedExit: (error) => {
116
+ console.error(`[qa] Dev server crashed for "${strategyName}": ${error}`);
117
+ deps.setQaEnvironment(strategyId, { ...state, pid: null, status: 'failed', lastError: error });
118
+ deps.updateQaStatus(strategyId, { qaStatus: 'failed', qaError: error }).catch((e) => {
119
+ console.warn(`[qa] Failed to report dev server crash: ${e.message}`);
120
+ });
121
+ },
122
+ });
123
+ // 6. Update state with PID and mark ready
124
+ const readyState = {
125
+ ...state,
126
+ pid: result.pid,
127
+ status: 'ready',
128
+ };
129
+ deps.setQaEnvironment(strategyId, readyState);
130
+ // 7. Update DB to ready
131
+ await deps.updateQaStatus(strategyId, {
132
+ qaStatus: 'ready',
133
+ qaUrl: url,
134
+ qaPort: port,
135
+ qaWorktreePath: worktreePath,
136
+ qaReadyAt: new Date().toISOString(),
137
+ });
138
+ console.log(`[qa] QA environment ready for "${strategyName}" at ${url}`);
139
+ }
140
+ /**
141
+ * Tear down a QA environment for a strategy.
142
+ *
143
+ * 1. Kill the dev server process if running.
144
+ * 2. Remove the worktree.
145
+ * 3. Clear in-memory and DB state.
146
+ */
147
+ async function handleQaTeardown(config, req, deps) {
148
+ const { strategy_id: strategyId, strategy_name: strategyName } = req;
149
+ console.log(`[qa] Tearing down QA environment for "${strategyName}"`);
150
+ // Kill dev server if running
151
+ const state = deps.getQaEnvironment(strategyId);
152
+ if (state?.pid) {
153
+ await deps.stopQaDevServer(state.pid);
154
+ }
155
+ // Worktree is strategy-owned -- do NOT remove here.
156
+ // Removal happens via coordinated teardown when the strategy is deactivated.
157
+ // Clear in-memory state
158
+ deps.removeQaEnvironment(strategyId);
159
+ // Clear DB state
160
+ await deps.updateQaStatus(strategyId, {
161
+ qaStatus: null,
162
+ qaUrl: null,
163
+ qaPort: null,
164
+ qaWorktreePath: null,
165
+ qaReadyAt: null,
166
+ qaError: null,
167
+ });
168
+ console.log(`[qa] QA environment torn down for "${strategyName}"`);
169
+ }
170
+ /**
171
+ * Check for strategies that have been deactivated while QA was running.
172
+ * Tears down any QA environment whose strategy is no longer in 'active' status.
173
+ * Called each poll cycle from listener.ts.
174
+ */
175
+ export async function checkQaForDeactivatedStrategies(config, deps = defaultDeps) {
176
+ let deactivated;
177
+ try {
178
+ deactivated = await deps.getDeactivatedQaStrategies(config.productId);
179
+ }
180
+ catch (err) {
181
+ console.warn(`[qa] Failed to fetch deactivated QA strategies: ${err.message}`);
182
+ return;
183
+ }
184
+ if (deactivated.length === 0)
185
+ return;
186
+ for (const strategy of deactivated) {
187
+ console.log(`[qa] Strategy "${strategy.strategy_name}" is ${strategy.strategy_status} but has QA state "${strategy.qa_status}" -- tearing down`);
188
+ try {
189
+ await handleQaTeardown(config, {
190
+ strategy_id: strategy.strategy_id,
191
+ strategy_name: strategy.strategy_name,
192
+ qa_status: strategy.qa_status,
193
+ product_id: strategy.product_id,
194
+ }, deps);
195
+ }
196
+ catch (err) {
197
+ console.error(`[qa] Error tearing down QA for deactivated strategy "${strategy.strategy_name}": ${err.message}`);
198
+ }
199
+ }
200
+ }
201
+ /** Default deps wired to real implementations. */
202
+ const defaultProductDeps = {
203
+ getProductQaRequests,
204
+ updateProductQaStatus,
205
+ createQaWorktree,
206
+ removeQaWorktree,
207
+ symlinkEnvFiles,
208
+ allocatePort,
209
+ buildQaUrl,
210
+ startQaDevServer,
211
+ stopQaDevServer,
212
+ getProductQaEnvironment,
213
+ setProductQaEnvironment,
214
+ removeProductQaEnvironment,
215
+ hasActiveProductQaEnvironment,
216
+ };
217
+ /**
218
+ * Check for and process pending product QA requests.
219
+ * Called each poll cycle from listener.ts.
220
+ */
221
+ export async function checkProductQaRequests(config, deps = defaultProductDeps) {
222
+ let requests;
223
+ try {
224
+ requests = await deps.getProductQaRequests(config.productId);
225
+ }
226
+ catch (err) {
227
+ console.warn(`[product-qa] Failed to fetch product QA requests: ${err.message}`);
228
+ return;
229
+ }
230
+ if (requests.length === 0)
231
+ return;
232
+ for (const req of requests) {
233
+ try {
234
+ if (req.qa_status === 'requested') {
235
+ await handleProductQaProvision(config, req, deps);
236
+ }
237
+ else if (req.qa_status === 'stop_requested') {
238
+ await handleProductQaTeardown(config, req, deps);
239
+ }
240
+ }
241
+ catch (err) {
242
+ console.error(`[product-qa] Error processing product QA request for "${req.product_name}": ${err.message}`);
243
+ try {
244
+ await deps.updateProductQaStatus(req.product_id, {
245
+ qaStatus: 'failed',
246
+ qaError: err.message,
247
+ });
248
+ }
249
+ catch (updateErr) {
250
+ console.warn(`[product-qa] Failed to update error state: ${updateErr.message}`);
251
+ }
252
+ }
253
+ }
254
+ }
255
+ /**
256
+ * Provision a product-level QA environment.
257
+ *
258
+ * Creates a QA worktree on the integration branch so the dev server
259
+ * reflects the combined result of all merged strategy work.
260
+ */
261
+ async function handleProductQaProvision(config, req, deps) {
262
+ const { product_id: productId, product_name: productName } = req;
263
+ // If already active (refresh), tear down first
264
+ if (deps.hasActiveProductQaEnvironment(productId)) {
265
+ console.log(`[product-qa] Refreshing QA environment for product "${productName}"`);
266
+ await handleProductQaTeardown(config, req, deps);
267
+ }
268
+ // 1. Set provisioning in DB
269
+ await deps.updateProductQaStatus(productId, { qaStatus: 'provisioning' });
270
+ // 2. Allocate port
271
+ const port = await deps.allocatePort(config);
272
+ const url = deps.buildQaUrl(config, port);
273
+ // 3. Create QA worktree on integration branch
274
+ const worktreePath = deps.createQaWorktree(config, config.integrationBranch, `product-${productId}`);
275
+ deps.symlinkEnvFiles(config.repoPath, worktreePath);
276
+ // 4. Track in memory
277
+ const state = {
278
+ productId,
279
+ productName,
280
+ worktreePath,
281
+ pid: null,
282
+ port,
283
+ url,
284
+ status: 'provisioning',
285
+ createdAt: new Date(),
286
+ lastError: null,
287
+ };
288
+ deps.setProductQaEnvironment(productId, state);
289
+ // 5. Start dev server in integration worktree
290
+ const result = deps.startQaDevServer({
291
+ config,
292
+ strategyId: `product-${productId}`,
293
+ worktreePath,
294
+ port,
295
+ onUnexpectedExit: (error) => {
296
+ console.error(`[product-qa] Dev server crashed for product "${productName}": ${error}`);
297
+ deps.setProductQaEnvironment(productId, { ...state, pid: null, status: 'failed', lastError: error });
298
+ deps.updateProductQaStatus(productId, { qaStatus: 'failed', qaError: error }).catch((e) => {
299
+ console.warn(`[product-qa] Failed to report dev server crash: ${e.message}`);
300
+ });
301
+ },
302
+ });
303
+ // 6. Update state with PID and mark ready
304
+ const readyState = {
305
+ ...state,
306
+ pid: result.pid,
307
+ status: 'ready',
308
+ };
309
+ deps.setProductQaEnvironment(productId, readyState);
310
+ // 7. Update DB to ready
311
+ await deps.updateProductQaStatus(productId, {
312
+ qaStatus: 'ready',
313
+ qaUrl: url,
314
+ qaPort: port,
315
+ qaWorktreePath: worktreePath,
316
+ qaReadyAt: new Date().toISOString(),
317
+ });
318
+ console.log(`[product-qa] QA environment ready for product "${productName}" at ${url} (integration branch)`);
319
+ }
320
+ /**
321
+ * Tear down a product-level QA environment.
322
+ * Kills the dev server and removes the integration worktree.
323
+ */
324
+ async function handleProductQaTeardown(config, req, deps) {
325
+ const { product_id: productId, product_name: productName } = req;
326
+ console.log(`[product-qa] Tearing down QA environment for product "${productName}"`);
327
+ // Kill dev server if running
328
+ const state = deps.getProductQaEnvironment(productId);
329
+ if (state?.pid) {
330
+ await deps.stopQaDevServer(state.pid);
331
+ }
332
+ // Remove QA worktree (read-only checkout, no safety commits needed)
333
+ if (state?.worktreePath) {
334
+ deps.removeQaWorktree(config.repoPath, state.worktreePath);
335
+ }
336
+ // Clear in-memory state
337
+ deps.removeProductQaEnvironment(productId);
338
+ // Clear DB state
339
+ await deps.updateProductQaStatus(productId, {
340
+ qaStatus: null,
341
+ qaUrl: null,
342
+ qaPort: null,
343
+ qaWorktreePath: null,
344
+ qaReadyAt: null,
345
+ qaError: null,
346
+ });
347
+ console.log(`[product-qa] QA environment torn down for product "${productName}"`);
348
+ }
349
+ //# sourceMappingURL=qa-orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qa-orchestrator.js","sourceRoot":"","sources":["../src/qa-orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * QA environment port allocation and URL construction.
3
+ *
4
+ * Allocates ports from the configured range for QA dev servers,
5
+ * checking both in-memory state and OS-level availability.
6
+ */
7
+ import type { DaemonConfig } from './types.js';
8
+ /**
9
+ * Allocate an available port from the configured QA port range.
10
+ *
11
+ * 1. Collects ports already in use by active QA environments (in-memory).
12
+ * 2. Iterates through [qaPortRangeStart, qaPortRangeEnd].
13
+ * 3. For each port not already allocated, verifies OS-level availability.
14
+ * 4. Returns the first available port.
15
+ *
16
+ * @throws Error if no port is available in the configured range.
17
+ */
18
+ export declare function allocatePort(config: DaemonConfig): Promise<number>;
19
+ /**
20
+ * Release a port allocation.
21
+ *
22
+ * Currently a no-op: ports are tracked in qa-state.ts via QaEnvironmentState.
23
+ * When removeQaEnvironment() is called, the port is implicitly released.
24
+ * This is a placeholder for future explicit port reservation tracking.
25
+ */
26
+ export declare function releasePort(_port: number): void;
27
+ /**
28
+ * Build the full QA URL for a given port using the configured host.
29
+ *
30
+ * Uses qaHost from config, which is either an auto-detected LAN IP
31
+ * or an explicitly configured hostname.
32
+ */
33
+ export declare function buildQaUrl(config: DaemonConfig, port: number): string;
34
+ //# sourceMappingURL=qa-port-allocator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qa-port-allocator.d.ts","sourceRoot":"","sources":["../src/qa-port-allocator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAkB/C;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBxE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG/C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErE"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * QA environment port allocation and URL construction.
3
+ *
4
+ * Allocates ports from the configured range for QA dev servers,
5
+ * checking both in-memory state and OS-level availability.
6
+ */
7
+ import { createServer } from 'node:net';
8
+ import { getActiveQaEnvironments } from './qa-state.js';
9
+ /**
10
+ * Check whether a port is available by briefly binding to it.
11
+ * Returns true if the port can be bound, false if it is in use.
12
+ */
13
+ function isPortAvailable(port) {
14
+ return new Promise((resolve) => {
15
+ const server = createServer();
16
+ server.once('error', () => resolve(false));
17
+ server.once('listening', () => {
18
+ server.close(() => resolve(true));
19
+ });
20
+ server.listen(port, '0.0.0.0');
21
+ });
22
+ }
23
+ /**
24
+ * Allocate an available port from the configured QA port range.
25
+ *
26
+ * 1. Collects ports already in use by active QA environments (in-memory).
27
+ * 2. Iterates through [qaPortRangeStart, qaPortRangeEnd].
28
+ * 3. For each port not already allocated, verifies OS-level availability.
29
+ * 4. Returns the first available port.
30
+ *
31
+ * @throws Error if no port is available in the configured range.
32
+ */
33
+ export async function allocatePort(config) {
34
+ const { qaPortRangeStart: start, qaPortRangeEnd: end } = config;
35
+ // Collect ports already allocated to active QA environments
36
+ const activeEnvironments = getActiveQaEnvironments();
37
+ const allocatedPorts = new Set();
38
+ for (const env of activeEnvironments.values()) {
39
+ allocatedPorts.add(env.port);
40
+ }
41
+ // Iterate through the range looking for an available port
42
+ for (let port = start; port <= end; port++) {
43
+ // Skip ports already tracked in memory
44
+ if (allocatedPorts.has(port)) {
45
+ continue;
46
+ }
47
+ // Verify the port is actually free at the OS level
48
+ const available = await isPortAvailable(port);
49
+ if (available) {
50
+ return port;
51
+ }
52
+ }
53
+ throw new Error(`No available port in range ${start}-${end}`);
54
+ }
55
+ /**
56
+ * Release a port allocation.
57
+ *
58
+ * Currently a no-op: ports are tracked in qa-state.ts via QaEnvironmentState.
59
+ * When removeQaEnvironment() is called, the port is implicitly released.
60
+ * This is a placeholder for future explicit port reservation tracking.
61
+ */
62
+ export function releasePort(_port) {
63
+ // Port is released implicitly when QA environment state is removed.
64
+ // This is a placeholder for future explicit port reservation tracking.
65
+ }
66
+ /**
67
+ * Build the full QA URL for a given port using the configured host.
68
+ *
69
+ * Uses qaHost from config, which is either an auto-detected LAN IP
70
+ * or an explicitly configured hostname.
71
+ */
72
+ export function buildQaUrl(config, port) {
73
+ return `http://${config.qaHost}:${port}`;
74
+ }
75
+ //# sourceMappingURL=qa-port-allocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qa-port-allocator.js","sourceRoot":"","sources":["../src/qa-port-allocator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD;;;GAGG;AACH,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAoB;IACrD,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;IAEhE,4DAA4D;IAC5D,MAAM,kBAAkB,GAAG,uBAAuB,EAAE,CAAC;IACrD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,0DAA0D;IAC1D,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;QAC3C,uCAAuC;QACvC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,mDAAmD;QACnD,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,8BAA8B,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,oEAAoE;IACpE,uEAAuE;AACzE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAoB,EAAE,IAAY;IAC3D,OAAO,UAAU,MAAM,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * QA worktree provisioning and teardown.
3
+ *
4
+ * Manages git worktrees for QA environments. Unlike agent worktrees,
5
+ * QA worktrees are read-only checkouts of a strategy's integration branch
6
+ * used to run a dev server for manual QA verification.
7
+ */
8
+ import type { DaemonConfig } from './types.js';
9
+ /**
10
+ * Create (or update) a QA worktree for a strategy's integration branch.
11
+ *
12
+ * If the worktree already exists, checks out the correct branch and
13
+ * pulls the latest changes. Otherwise, creates a fresh worktree.
14
+ *
15
+ * @returns The absolute path to the QA worktree directory.
16
+ */
17
+ export declare function createQaWorktree(config: DaemonConfig, strategyBranchName: string, strategyId: string): string;
18
+ /**
19
+ * Remove a QA worktree.
20
+ *
21
+ * QA worktrees are read-only checkouts so no safety commits are needed.
22
+ * Falls back to recursive directory removal if `git worktree remove` fails.
23
+ */
24
+ export declare function removeQaWorktree(repoPath: string, worktreePath: string): void;
25
+ /**
26
+ * Symlink common environment/config files from the main repo into a QA worktree.
27
+ *
28
+ * Only creates symlinks for files that exist in the main repo and don't
29
+ * already exist (or aren't already correctly symlinked) in the worktree.
30
+ * Logs each action and warns (but does not throw) on failure.
31
+ */
32
+ export declare function symlinkEnvFiles(repoPath: string, worktreePath: string): void;
33
+ //# sourceMappingURL=qa-provisioner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qa-provisioner.d.ts","sourceRoot":"","sources":["../src/qa-provisioner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,EACpB,kBAAkB,EAAE,MAAM,EAC1B,UAAU,EAAE,MAAM,GACjB,MAAM,CAsER;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,IAAI,CAgCN;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,IAAI,CA6CN"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * QA worktree provisioning and teardown.
3
+ *
4
+ * Manages git worktrees for QA environments. Unlike agent worktrees,
5
+ * QA worktrees are read-only checkouts of a strategy's integration branch
6
+ * used to run a dev server for manual QA verification.
7
+ */
8
+ import { existsSync, mkdirSync, symlinkSync, unlinkSync, readlinkSync, rmSync } from 'node:fs';
9
+ import { join, resolve } from 'node:path';
10
+ import { runGitSync, branchExists } from './git.js';
11
+ /** File names to symlink from the main repo into QA worktrees. */
12
+ const ENV_FILES = ['.env', '.env.local', '.env.development.local'];
13
+ /**
14
+ * Create (or update) a QA worktree for a strategy's integration branch.
15
+ *
16
+ * If the worktree already exists, checks out the correct branch and
17
+ * pulls the latest changes. Otherwise, creates a fresh worktree.
18
+ *
19
+ * @returns The absolute path to the QA worktree directory.
20
+ */
21
+ export function createQaWorktree(config, strategyBranchName, strategyId) {
22
+ const worktreePath = join(config.worktreeDir, 'qa-' + strategyId.slice(0, 8));
23
+ // Ensure parent worktree directory exists
24
+ if (!existsSync(config.worktreeDir)) {
25
+ mkdirSync(config.worktreeDir, { recursive: true });
26
+ console.log(`[qa-provisioner] Created worktree directory: ${config.worktreeDir}`);
27
+ }
28
+ // If the worktree directory already exists, update in place (detached HEAD)
29
+ if (existsSync(worktreePath)) {
30
+ console.log(`[qa-provisioner] QA worktree already exists, updating: ${worktreePath}`);
31
+ // Fetch latest then reset to branch tip (detached HEAD, no branch lock)
32
+ runGitSync(['fetch', 'origin', strategyBranchName], config.repoPath);
33
+ const resetResult = runGitSync(['checkout', '--detach', strategyBranchName], worktreePath);
34
+ if (!resetResult.success) {
35
+ console.warn(`[qa-provisioner] Could not update detached HEAD to ${strategyBranchName}: ${resetResult.error}`);
36
+ }
37
+ symlinkEnvFiles(config.repoPath, worktreePath);
38
+ return worktreePath;
39
+ }
40
+ // Prune stale worktree entries before creating a new one
41
+ runGitSync(['worktree', 'prune'], config.repoPath);
42
+ // If the branch doesn't exist locally, try fetching from origin
43
+ if (!branchExists(strategyBranchName, config.repoPath)) {
44
+ console.log(`[qa-provisioner] Branch ${strategyBranchName} not found locally, fetching from origin...`);
45
+ const fetchResult = runGitSync(['fetch', 'origin', strategyBranchName], config.repoPath);
46
+ if (!fetchResult.success) {
47
+ throw new Error(`[qa-provisioner] Failed to fetch branch ${strategyBranchName} from origin: ${fetchResult.error}`);
48
+ }
49
+ }
50
+ // Create the worktree with detached HEAD to avoid locking the branch.
51
+ // Locking the branch prevents agent merges into integration while QA is running.
52
+ console.log(`[qa-provisioner] Creating QA worktree at ${worktreePath} (detached at ${strategyBranchName})`);
53
+ const addResult = runGitSync(['worktree', 'add', '--detach', worktreePath, strategyBranchName], config.repoPath);
54
+ if (!addResult.success) {
55
+ throw new Error(`[qa-provisioner] Failed to create QA worktree: ${addResult.error}`);
56
+ }
57
+ // Pull latest changes in the new worktree
58
+ const pullResult = runGitSync(['pull', '--ff-only'], worktreePath);
59
+ if (!pullResult.success) {
60
+ console.warn(`[qa-provisioner] Could not pull latest after worktree creation: ${pullResult.error}`);
61
+ }
62
+ symlinkEnvFiles(config.repoPath, worktreePath);
63
+ return worktreePath;
64
+ }
65
+ /**
66
+ * Remove a QA worktree.
67
+ *
68
+ * QA worktrees are read-only checkouts so no safety commits are needed.
69
+ * Falls back to recursive directory removal if `git worktree remove` fails.
70
+ */
71
+ export function removeQaWorktree(repoPath, worktreePath) {
72
+ try {
73
+ if (!existsSync(worktreePath)) {
74
+ console.log(`[qa-provisioner] QA worktree already removed: ${worktreePath}`);
75
+ runGitSync(['worktree', 'prune'], repoPath);
76
+ return;
77
+ }
78
+ console.log(`[qa-provisioner] Removing QA worktree: ${worktreePath}`);
79
+ const result = runGitSync(['worktree', 'remove', '--force', worktreePath], repoPath);
80
+ if (!result.success) {
81
+ console.warn(`[qa-provisioner] git worktree remove failed, falling back to rmSync: ${result.error}`);
82
+ rmSync(worktreePath, { recursive: true, force: true });
83
+ // Prune the now-stale worktree entry
84
+ runGitSync(['worktree', 'prune'], repoPath);
85
+ console.log(`[qa-provisioner] Removed QA worktree directory via rmSync: ${worktreePath}`);
86
+ }
87
+ else {
88
+ console.log(`[qa-provisioner] Removed QA worktree: ${worktreePath}`);
89
+ }
90
+ }
91
+ catch (err) {
92
+ console.error('[qa-provisioner] Error removing QA worktree:', err instanceof Error ? err.message : String(err));
93
+ }
94
+ }
95
+ /**
96
+ * Symlink common environment/config files from the main repo into a QA worktree.
97
+ *
98
+ * Only creates symlinks for files that exist in the main repo and don't
99
+ * already exist (or aren't already correctly symlinked) in the worktree.
100
+ * Logs each action and warns (but does not throw) on failure.
101
+ */
102
+ export function symlinkEnvFiles(repoPath, worktreePath) {
103
+ for (const fileName of ENV_FILES) {
104
+ const sourcePath = resolve(repoPath, fileName);
105
+ const targetPath = resolve(worktreePath, fileName);
106
+ if (!existsSync(sourcePath)) {
107
+ continue;
108
+ }
109
+ // If the target already exists, check if it's already a correct symlink
110
+ if (existsSync(targetPath)) {
111
+ try {
112
+ const linkTarget = readlinkSync(targetPath);
113
+ if (resolve(linkTarget) === sourcePath) {
114
+ // Already correctly symlinked
115
+ continue;
116
+ }
117
+ }
118
+ catch {
119
+ // Not a symlink (regular file) -- skip to avoid overwriting
120
+ console.log(`[qa-provisioner] Skipping ${fileName}: already exists in worktree as a regular file`);
121
+ continue;
122
+ }
123
+ // Symlink exists but points somewhere else -- remove and re-create
124
+ try {
125
+ unlinkSync(targetPath);
126
+ }
127
+ catch (unlinkErr) {
128
+ console.warn(`[qa-provisioner] Could not remove stale symlink for ${fileName}: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`);
129
+ continue;
130
+ }
131
+ }
132
+ try {
133
+ symlinkSync(sourcePath, targetPath);
134
+ console.log(`[qa-provisioner] Symlinked ${fileName} -> ${sourcePath}`);
135
+ }
136
+ catch (symlinkErr) {
137
+ console.warn(`[qa-provisioner] Failed to symlink ${fileName}: ${symlinkErr instanceof Error ? symlinkErr.message : String(symlinkErr)}`);
138
+ }
139
+ }
140
+ }
141
+ //# sourceMappingURL=qa-provisioner.js.map