@shepai/cli 1.66.3 → 1.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -1
  2. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.js +26 -11
  3. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
  4. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +16 -10
  5. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.d.ts.map +1 -1
  6. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +21 -1
  7. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.stories.d.ts +15 -1
  8. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.stories.d.ts.map +1 -1
  9. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.stories.js +16 -2
  10. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.d.ts +12 -0
  11. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.d.ts.map +1 -0
  12. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.js +284 -0
  13. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.d.ts +33 -0
  14. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.d.ts.map +1 -0
  15. package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.js +210 -0
  16. package/dist/src/presentation/web/components/common/control-center-drawer/drawer-view.d.ts +56 -0
  17. package/dist/src/presentation/web/components/common/control-center-drawer/drawer-view.d.ts.map +1 -0
  18. package/dist/src/presentation/web/components/common/control-center-drawer/drawer-view.js +32 -0
  19. package/dist/src/presentation/web/components/common/control-center-drawer/index.d.ts +3 -0
  20. package/dist/src/presentation/web/components/common/control-center-drawer/index.d.ts.map +1 -0
  21. package/dist/src/presentation/web/components/common/control-center-drawer/index.js +2 -0
  22. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts +0 -4
  23. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts.map +1 -1
  24. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts +1 -1
  25. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts.map +1 -1
  26. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.js +18 -12
  27. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.stories.d.ts +4 -6
  28. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.stories.d.ts.map +1 -1
  29. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.stories.js +5 -13
  30. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
  31. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +2 -13
  32. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts +2 -10
  33. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts.map +1 -1
  34. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.js +21 -1
  35. package/dist/src/presentation/web/components/common/feature-create-drawer/index.d.ts +1 -1
  36. package/dist/src/presentation/web/components/common/feature-create-drawer/index.d.ts.map +1 -1
  37. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.d.ts.map +1 -1
  38. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.js +14 -20
  39. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.d.ts +7 -1
  40. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.d.ts.map +1 -1
  41. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.js +37 -2
  42. package/dist/src/presentation/web/components/common/index.d.ts +1 -0
  43. package/dist/src/presentation/web/components/common/index.d.ts.map +1 -1
  44. package/dist/src/presentation/web/components/common/index.js +1 -0
  45. package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -1
  46. package/dist/src/presentation/web/components/common/merge-review/merge-review.js +2 -2
  47. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts.map +1 -1
  48. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.js +1 -2
  49. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.js +1 -1
  50. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts.map +1 -1
  51. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.js +1 -2
  52. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.d.ts.map +1 -1
  53. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.js +5 -1
  54. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.d.ts +2 -0
  55. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.d.ts.map +1 -1
  56. package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.js +13 -2
  57. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.d.ts.map +1 -1
  58. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.js +5 -2
  59. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.js +1 -1
  60. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts.map +1 -1
  61. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.js +1 -1
  62. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.d.ts.map +1 -1
  63. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.js +1 -2
  64. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  65. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +20 -215
  66. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  67. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +2 -1
  68. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
  69. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +1 -1
  70. package/dist/tsconfig.build.tsbuildinfo +1 -1
  71. package/package.json +1 -1
  72. package/web/.next/BUILD_ID +1 -1
  73. package/web/.next/build-manifest.json +5 -5
  74. package/web/.next/cache/.previewinfo +1 -1
  75. package/web/.next/cache/.rscinfo +1 -1
  76. package/web/.next/cache/.tsbuildinfo +1 -1
  77. package/web/.next/cache/config.json +3 -3
  78. package/web/.next/fallback-build-manifest.json +2 -2
  79. package/web/.next/prerender-manifest.json +3 -3
  80. package/web/.next/required-server-files.js +1 -1
  81. package/web/.next/required-server-files.json +1 -1
  82. package/web/.next/server/app/_global-error/page/build-manifest.json +3 -3
  83. package/web/.next/server/app/_global-error.html +2 -2
  84. package/web/.next/server/app/_global-error.rsc +1 -1
  85. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  86. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  87. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  88. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  89. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  90. package/web/.next/server/app/_not-found/page/build-manifest.json +3 -3
  91. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  92. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  93. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  94. package/web/.next/server/app/page/build-manifest.json +3 -3
  95. package/web/.next/server/app/page/server-reference-manifest.json +88 -88
  96. package/web/.next/server/app/page.js +1 -1
  97. package/web/.next/server/app/page.js.nft.json +1 -1
  98. package/web/.next/server/app/page_client-reference-manifest.js +1 -1
  99. package/web/.next/server/app/skills/page/build-manifest.json +3 -3
  100. package/web/.next/server/app/skills/page/server-reference-manifest.json +5 -5
  101. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  102. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  103. package/web/.next/server/app/tools/page/build-manifest.json +3 -3
  104. package/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
  105. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  106. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  107. package/web/.next/server/app/version/page/build-manifest.json +3 -3
  108. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  109. package/web/.next/server/app/version/page.js.nft.json +1 -1
  110. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  111. package/web/.next/server/chunks/ssr/403f9_next_dist_a53cb908._.js +3 -0
  112. package/web/.next/server/chunks/ssr/403f9_next_dist_a53cb908._.js.map +1 -0
  113. package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
  114. package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  116. package/web/.next/server/chunks/ssr/{[root-of-the-server]__f5830fa9._.js → [root-of-the-server]__2ffb27f1._.js} +2 -2
  117. package/web/.next/server/chunks/ssr/{[root-of-the-server]__f5830fa9._.js.map → [root-of-the-server]__2ffb27f1._.js.map} +1 -1
  118. package/web/.next/server/chunks/ssr/[root-of-the-server]__551fb7e1._.js +1 -1
  119. package/web/.next/server/chunks/ssr/[root-of-the-server]__551fb7e1._.js.map +1 -1
  120. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  121. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  122. package/web/.next/server/chunks/ssr/[root-of-the-server]__7f4180a1._.js +3 -0
  123. package/web/.next/server/chunks/ssr/[root-of-the-server]__7f4180a1._.js.map +1 -0
  124. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  125. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  126. package/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js +4 -4
  127. package/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js.map +1 -1
  128. package/web/.next/server/chunks/ssr/[root-of-the-server]__e41b5eec._.js +9 -0
  129. package/web/.next/server/chunks/ssr/{[root-of-the-server]__f648005b._.js.map → [root-of-the-server]__e41b5eec._.js.map} +1 -1
  130. package/web/.next/server/chunks/ssr/[root-of-the-server]__eaf6100f._.js +3 -0
  131. package/web/.next/server/chunks/ssr/[root-of-the-server]__eaf6100f._.js.map +1 -0
  132. package/web/.next/server/chunks/ssr/_23c92688._.js +6 -0
  133. package/web/.next/server/chunks/ssr/_23c92688._.js.map +1 -0
  134. package/web/.next/server/chunks/ssr/_28993370._.js +1 -1
  135. package/web/.next/server/chunks/ssr/_28993370._.js.map +1 -1
  136. package/web/.next/server/chunks/ssr/_49bf495c._.js +3 -0
  137. package/web/.next/server/chunks/ssr/_49bf495c._.js.map +1 -0
  138. package/web/.next/server/chunks/ssr/_690ea95f._.js +3 -0
  139. package/web/.next/server/chunks/ssr/{_2900ed94._.js.map → _690ea95f._.js.map} +1 -1
  140. package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/_c52cace8._.js → server/chunks/ssr/_725584e5._.js} +2 -2
  141. package/web/.next/server/chunks/ssr/_725584e5._.js.map +1 -0
  142. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  143. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  144. package/web/.next/server/middleware-build-manifest.js +3 -3
  145. package/web/.next/server/pages/500.html +2 -2
  146. package/web/.next/server/server-reference-manifest.js +1 -1
  147. package/web/.next/server/server-reference-manifest.json +115 -115
  148. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  149. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +5 -5
  150. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  151. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  152. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error/page/build-manifest.json +3 -3
  153. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  154. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  155. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  156. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  157. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  158. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  159. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  160. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/build-manifest.json +3 -3
  161. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  162. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  163. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  164. package/web/.next/standalone/src/presentation/web/.next/server/app/page/build-manifest.json +3 -3
  165. package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +88 -88
  166. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js +1 -1
  167. package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
  168. package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
  169. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/build-manifest.json +3 -3
  170. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +5 -5
  171. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
  172. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  173. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/build-manifest.json +3 -3
  174. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
  175. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
  176. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  177. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/build-manifest.json +3 -3
  178. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  179. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
  180. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  181. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/403f9_next_dist_a53cb908._.js +3 -0
  182. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
  183. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  184. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{[root-of-the-server]__f5830fa9._.js → [root-of-the-server]__2ffb27f1._.js} +2 -2
  185. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__551fb7e1._.js +1 -1
  186. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  187. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__7f4180a1._.js +3 -0
  188. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  189. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js +4 -4
  190. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__e41b5eec._.js +9 -0
  191. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__eaf6100f._.js +3 -0
  192. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_23c92688._.js +6 -0
  193. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_28993370._.js +1 -1
  194. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_49bf495c._.js +3 -0
  195. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_690ea95f._.js +3 -0
  196. package/web/.next/{server/chunks/ssr/_c52cace8._.js → standalone/src/presentation/web/.next/server/chunks/ssr/_725584e5._.js} +2 -2
  197. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  198. package/web/.next/standalone/src/presentation/web/.next/server/middleware-build-manifest.js +3 -3
  199. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  200. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  201. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +115 -115
  202. package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.stories.tsx +16 -2
  203. package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.tsx +35 -6
  204. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.tsx +285 -0
  205. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/control-center-drawer.tsx +650 -0
  206. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/drawer-view.ts +82 -0
  207. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/index.ts +2 -0
  208. package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.ts +0 -4
  209. package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.stories.tsx +5 -14
  210. package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.tsx +58 -51
  211. package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx +42 -1
  212. package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx +2 -16
  213. package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/index.ts +1 -0
  214. package/web/.next/standalone/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.tsx +55 -2
  215. package/web/.next/standalone/src/presentation/web/components/common/feature-drawer/feature-drawer.tsx +97 -106
  216. package/web/.next/standalone/src/presentation/web/components/common/index.ts +6 -0
  217. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.stories.tsx +1 -2
  218. package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx +1 -2
  219. package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.tsx +1 -2
  220. package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.tsx +1 -1
  221. package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-drawer.stories.tsx +28 -2
  222. package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-drawer.tsx +7 -2
  223. package/web/.next/standalone/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.tsx +1 -1
  224. package/web/.next/standalone/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.tsx +7 -6
  225. package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.tsx +1 -2
  226. package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.tsx +1 -2
  227. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +30 -348
  228. package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +2 -1
  229. package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.tsx +5 -1
  230. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  231. package/web/.next/static/chunks/38ca82d1243738e3.js +1 -0
  232. package/web/.next/static/chunks/{35f41ba0a6d626d7.js → 491ae2bbae40857c.js} +1 -1
  233. package/web/.next/static/chunks/4b6cc9f65260f2bd.js +2 -0
  234. package/web/.next/static/chunks/67599679ca9ac863.js +1 -0
  235. package/web/.next/static/chunks/{ed887cce7b31c91b.js → 6ece250c7d0ec203.js} +1 -1
  236. package/web/.next/static/chunks/a186bbb822ccb655.css +2 -0
  237. package/web/.next/static/chunks/a5c59952485e875e.js +1 -0
  238. package/web/.next/static/chunks/{8c60d1bd87239066.js → a9626385607910b3.js} +1 -1
  239. package/web/.next/static/chunks/c1c15470a7b058c8.js +1 -0
  240. package/web/.next/static/chunks/caa2e7e1618e2179.js +1 -0
  241. package/web/.next/static/chunks/ed799a306922f03e.js +10 -0
  242. package/web/.next/static/chunks/fb703cf73aba2eb8.js +1 -0
  243. package/web/.next/static/chunks/{turbopack-b6b5b4f015327a9a.js → turbopack-958ac34b879d0dce.js} +1 -1
  244. package/web/.next/trace +1 -1
  245. package/web/.next/trace-build +1 -1
  246. package/web/.next/server/chunks/ssr/403f9_next_dist_623b646a._.js +0 -3
  247. package/web/.next/server/chunks/ssr/403f9_next_dist_623b646a._.js.map +0 -1
  248. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb51fac._.js +0 -3
  249. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb51fac._.js.map +0 -1
  250. package/web/.next/server/chunks/ssr/[root-of-the-server]__c1f0f2a8._.js +0 -3
  251. package/web/.next/server/chunks/ssr/[root-of-the-server]__c1f0f2a8._.js.map +0 -1
  252. package/web/.next/server/chunks/ssr/[root-of-the-server]__f648005b._.js +0 -9
  253. package/web/.next/server/chunks/ssr/_2900ed94._.js +0 -3
  254. package/web/.next/server/chunks/ssr/_6978d868._.js +0 -3
  255. package/web/.next/server/chunks/ssr/_6978d868._.js.map +0 -1
  256. package/web/.next/server/chunks/ssr/_85965278._.js +0 -6
  257. package/web/.next/server/chunks/ssr/_85965278._.js.map +0 -1
  258. package/web/.next/server/chunks/ssr/_c52cace8._.js.map +0 -1
  259. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/403f9_next_dist_623b646a._.js +0 -3
  260. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6bb51fac._.js +0 -3
  261. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__c1f0f2a8._.js +0 -3
  262. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__f648005b._.js +0 -9
  263. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_2900ed94._.js +0 -3
  264. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_6978d868._.js +0 -3
  265. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_85965278._.js +0 -6
  266. package/web/.next/static/chunks/41a2adc09edfffaf.js +0 -1
  267. package/web/.next/static/chunks/5054c72b1c8f5912.js +0 -1
  268. package/web/.next/static/chunks/7bcbfc56e5733034.js +0 -1
  269. package/web/.next/static/chunks/86c0cc1097427f74.js +0 -10
  270. package/web/.next/static/chunks/96f49affaceab206.css +0 -2
  271. package/web/.next/static/chunks/a6d1d774260fc927.js +0 -2
  272. package/web/.next/static/chunks/c0f7284a71378f26.js +0 -1
  273. package/web/.next/static/chunks/f5fb2f182ae9b015.js +0 -1
  274. /package/web/.next/static/{Cp8hg2DFpA4DyEezlBYOw → GdqfiIUVMj2wj_3lbrUqd}/_buildManifest.js +0 -0
  275. /package/web/.next/static/{Cp8hg2DFpA4DyEezlBYOw → GdqfiIUVMj2wj_3lbrUqd}/_clientMiddlewareManifest.json +0 -0
  276. /package/web/.next/static/{Cp8hg2DFpA4DyEezlBYOw → GdqfiIUVMj2wj_3lbrUqd}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAClH,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACd,MAAM,iEAAiE,CAAC;AAsBzE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1E,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;IACnE;;;OAGG;IACH,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1F,YAAY,EAAE,aAAa,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAmO7E"}
1
+ {"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAClH,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACd,MAAM,iEAAiE,CAAC;AAsBzE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1E,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;IACnE;;;OAGG;IACH,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1F,YAAY,EAAE,aAAa,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAiP7E"}
@@ -147,31 +147,46 @@ export function createMergeNode(deps) {
147
147
  else {
148
148
  log.info('Merge approved — skipping commit/push/PR, continuing to post-merge');
149
149
  messages.push(`[merge] Approved — continuing`);
150
+ // Restore PR data from feature record (persisted before interrupt, but
151
+ // not returned in graph state because interrupt() threw before the return).
152
+ if (feature?.pr) {
153
+ prUrl = feature.pr.url ?? prUrl;
154
+ prNumber = feature.pr.number ?? prNumber;
155
+ commitHash = feature.pr.commitHash ?? commitHash;
156
+ ciStatus = feature.pr.ciStatus ?? ciStatus;
157
+ }
150
158
  }
151
- // --- Agent Call 2: Merge ---
159
+ // --- Merge ---
152
160
  // Merge when: allowMerge is true (auto-merge), OR user explicitly
153
161
  // approved at the merge gate (isResumeAfterInterrupt means they
154
162
  // clicked Approve). The approval IS permission to merge.
155
163
  let merged = false;
156
164
  const userApprovedMerge = isResumeAfterInterrupt && state._approvalAction !== 'rejected';
157
165
  if (state.approvalGates?.allowMerge || userApprovedMerge) {
158
- log.info('Agent call 2: merge/squash');
159
- const mergePrompt = buildMergeSquashPrompt({ ...state, prUrl, prNumber, commitHash }, branch, baseBranch, remoteAvailable);
160
- // Run merge in the ORIGINAL repo, not the worktree — the worktree IS
161
- // the feature branch and must not be modified or removed during merge.
162
- const mergeOptions = { ...options, cwd: state.repositoryPath };
163
- await retryExecute(executor, mergePrompt, mergeOptions, { logger: log });
164
- // Verify the merge actually succeeded (agent may report success without merging)
165
- if (!prUrl) {
166
+ if (prUrl && prNumber) {
167
+ // PR exists: merge via GitHub API directly no agent or local merge needed.
168
+ log.info(`Merging PR #${prNumber} via GitHub API (squash)`);
169
+ await deps.gitPrService.mergePr(cwd, prNumber, 'squash');
170
+ messages.push(`[merge] PR #${prNumber} merged via squash`);
171
+ merged = true;
172
+ }
173
+ else {
174
+ // No PR: local merge via agent in the ORIGINAL repo (not the worktree,
175
+ // which IS the feature branch and must not be modified during merge).
176
+ log.info('Agent call: merge/squash (local, no PR)');
177
+ const mergePrompt = buildMergeSquashPrompt({ ...state, prUrl, prNumber, commitHash }, branch, baseBranch, remoteAvailable);
178
+ const mergeOptions = { ...options, cwd: state.repositoryPath };
179
+ await retryExecute(executor, mergePrompt, mergeOptions, { logger: log });
180
+ // Verify the merge actually succeeded (agent may report success without merging)
166
181
  const mergeVerified = await deps.verifyMerge(state.repositoryPath, branch, baseBranch);
167
182
  if (!mergeVerified) {
168
183
  throw new Error(`Merge verification failed: ${branch} was not merged into ${baseBranch}. ` +
169
184
  `The agent may have encountered errors during the merge operation.`);
170
185
  }
171
186
  log.info('Merge verified: feature branch is ancestor of base branch');
187
+ messages.push(`[merge] Agent completed local merge operation`);
188
+ merged = true;
172
189
  }
173
- messages.push(`[merge] Agent completed merge operation`);
174
- merged = true;
175
190
  }
176
191
  // --- Update feature lifecycle ---
177
192
  const newLifecycle = merged ? SdlcLifecycle.Maintain : SdlcLifecycle.Review;
@@ -1 +1 @@
1
- {"version":3,"file":"git-pr.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/git-pr.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wEAAwE,CAAC;AAC5G,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,EACb,MAAM,wEAAwE,CAAC;AAQhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,qBACa,YAAa,YAAW,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,YAAY;IAErE,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgF9C,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuClE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,aAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUzF,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnF,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkBjE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkDjF,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAWhF,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAevE,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAkCpD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWrF,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAW3F,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,aAAa;CAiBtB"}
1
+ {"version":3,"file":"git-pr.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/git-pr.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wEAAwE,CAAC;AAC5G,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,EACb,MAAM,wEAAwE,CAAC;AAQhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,qBACa,YAAa,YAAW,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,YAAY;IAErE,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgF9C,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuClE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,aAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUzF,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnF,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAsBjE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAmDjF,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAWhF,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAevE,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAkCpD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWrF,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAW3F,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,aAAa;CAiBtB"}
@@ -182,15 +182,20 @@ let GitPrService = class GitPrService {
182
182
  }
183
183
  }
184
184
  async getCiStatus(cwd, branch) {
185
- const { stdout } = await this.execFile('gh', ['run', 'list', '--branch', branch, '--json', 'conclusion,url', '--limit', '1'], { cwd });
186
- const runs = JSON.parse(stdout);
187
- if (runs.length === 0 || !runs[0].conclusion) {
188
- return { status: 'pending', runUrl: runs[0]?.url };
185
+ try {
186
+ const { stdout } = await this.execFile('gh', ['run', 'list', '--branch', branch, '--json', 'conclusion,url', '--limit', '1'], { cwd });
187
+ const runs = JSON.parse(stdout);
188
+ if (runs.length === 0 || !runs[0].conclusion) {
189
+ return { status: 'pending', runUrl: runs[0]?.url };
190
+ }
191
+ return {
192
+ status: runs[0].conclusion === 'success' ? 'success' : 'failure',
193
+ runUrl: runs[0].url,
194
+ };
195
+ }
196
+ catch (error) {
197
+ throw this.parseGhError(error);
189
198
  }
190
- return {
191
- status: runs[0].conclusion === 'success' ? 'success' : 'failure',
192
- runUrl: runs[0].url,
193
- };
194
199
  }
195
200
  async watchCi(cwd, branch, timeoutMs) {
196
201
  try {
@@ -207,9 +212,10 @@ let GitPrService = class GitPrService {
207
212
  cwd,
208
213
  ...(timeoutMs ? { timeout: timeoutMs } : {}),
209
214
  });
210
- const isSuccess = stdout.includes('success') || stdout.includes('completed');
215
+ // gh run watch --exit-status exits 0 when the run succeeds.
216
+ // If we reach here (no exception), CI passed — no need for fragile stdout parsing.
211
217
  return {
212
- status: isSuccess ? 'success' : 'failure',
218
+ status: 'success',
213
219
  logExcerpt: stdout.trim(),
214
220
  };
215
221
  }
@@ -1 +1 @@
1
- {"version":3,"file":"base-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/base-drawer/base-drawer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAYlE,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAGpF,QAAA,MAAM,cAAc;;8EAUlB,CAAC;AAEH,MAAM,WAAW,eAAgB,SAAQ,YAAY,CAAC,OAAO,cAAc,CAAC;IAC1E,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,OAAO,EACP,KAAa,EACb,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,MAAM,EACN,SAAS,EACT,aAAa,EAAE,MAAM,EACrB,YAAY,GACb,EAAE,eAAe,2CA8CjB"}
1
+ {"version":3,"file":"base-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/base-drawer/base-drawer.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAalE,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAGpF,QAAA,MAAM,cAAc;;8EAUlB,CAAC;AAEH,MAAM,WAAW,eAAgB,SAAQ,YAAY,CAAC,OAAO,cAAc,CAAC;IAC1E,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,OAAO,EACP,KAAa,EACb,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,MAAM,EACN,SAAS,EACT,aAAa,EAAE,MAAM,EACrB,YAAY,GACb,EAAE,eAAe,2CAyEjB"}
@@ -1,11 +1,13 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useRef, useEffect } from 'react';
3
4
  import { XIcon, Play, Square } from 'lucide-react';
4
5
  import { cva } from 'class-variance-authority';
5
6
  import { cn } from '../../../lib/utils.js';
6
7
  import { ActionButton } from '../../common/action-button/index.js';
7
8
  import { DeploymentStatusBadge } from '../../common/deployment-status-badge/index.js';
8
9
  import { Drawer, DrawerContent, DrawerHeader, DrawerFooter, DrawerOverlay, } from '../../ui/drawer.js';
10
+ import { Separator } from '../../ui/separator.js';
9
11
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
10
12
  import { useDeployAction } from '../../../hooks/use-deploy-action.js';
11
13
  import { featureFlags } from '../../../lib/feature-flags.js';
@@ -21,10 +23,28 @@ const drawerVariants = cva('', {
21
23
  },
22
24
  });
23
25
  export function BaseDrawer({ open, onClose, modal = false, size, header, children, footer, className, 'data-testid': testId, deployTarget, }) {
26
+ const contentRef = useRef(null);
27
+ // Close when clicking outside the drawer panel (no overlay needed — canvas stays draggable).
28
+ // Uses `click` (not `pointerdown`) so canvas drags don't trigger this.
29
+ useEffect(() => {
30
+ if (!open || modal)
31
+ return;
32
+ const handleClick = (e) => {
33
+ const target = e.target;
34
+ if (contentRef.current?.contains(target))
35
+ return;
36
+ // Don't close when clicking inside the canvas or other Radix overlays
37
+ if (target.closest('[data-no-drawer-close], [role="alertdialog"], [role="menu"], [role="listbox"], [data-radix-popper-content-wrapper]'))
38
+ return;
39
+ onClose();
40
+ };
41
+ document.addEventListener('click', handleClick);
42
+ return () => document.removeEventListener('click', handleClick);
43
+ }, [open, modal, onClose]);
24
44
  return (_jsxs(Drawer, { direction: "right", modal: modal, handleOnly: true, open: open, onOpenChange: (isOpen) => {
25
45
  if (!isOpen)
26
46
  onClose();
27
- }, children: [modal ? _jsx(DrawerOverlay, {}) : null, _jsxs(DrawerContent, { direction: "right", showCloseButton: false, className: cn(drawerVariants({ size }), className), "data-testid": testId, children: [_jsxs("button", { type: "button", "aria-label": "Close", onClick: onClose, className: "ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden", "data-testid": testId ? `${testId}-close-button` : undefined, children: [_jsx(XIcon, { className: "size-4" }), _jsx("span", { className: "sr-only", children: "Close" })] }), header ? _jsx(DrawerHeader, { children: header }) : null, featureFlags.envDeploy && deployTarget ? _jsx(DeployBar, { deployTarget: deployTarget }) : null, _jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx("div", { className: "flex flex-col", children: children }) }), footer ? _jsx(DrawerFooter, { children: footer }) : null] })] }));
47
+ }, children: [modal ? _jsx(DrawerOverlay, {}) : null, _jsxs(DrawerContent, { ref: contentRef, direction: "right", showCloseButton: false, className: cn(drawerVariants({ size }), className), "data-testid": testId, children: [_jsxs("button", { type: "button", "aria-label": "Close", onClick: onClose, className: "ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden", "data-testid": testId ? `${testId}-close-button` : undefined, children: [_jsx(XIcon, { className: "size-4" }), _jsx("span", { className: "sr-only", children: "Close" })] }), header ? _jsx(DrawerHeader, { className: "shrink-0", children: header }) : null, header ? _jsx(Separator, {}) : null, featureFlags.envDeploy && deployTarget ? _jsx(DeployBar, { deployTarget: deployTarget }) : null, _jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: children }), footer ? _jsx(DrawerFooter, { className: "shrink-0", children: footer }) : null] })] }));
28
48
  }
29
49
  function DeployBar({ deployTarget }) {
30
50
  const deployAction = useDeployAction(deployTarget);
@@ -19,6 +19,20 @@ export declare const WithFooter: Story;
19
19
  export declare const WithHeaderAndFooter: Story;
20
20
  /** Drawer with deployTarget prop showing the dev server bar below the header. */
21
21
  export declare const WithDevServerBar: Story;
22
- /** Drawer with content that exceeds viewport to demonstrate scroll behavior. */
22
+ /**
23
+ * Drawer with content that exceeds viewport to demonstrate scroll behavior.
24
+ *
25
+ * **Fixed Header/Footer Layout:**
26
+ * - The header (DrawerTitle + DrawerDescription) remains fixed at the top while scrolling
27
+ * - A Separator is automatically rendered below the header — no need to add one manually
28
+ * - The footer (if present, e.g., DrawerActionBar) remains fixed at the bottom while scrolling
29
+ * - Only the content area (children) scrolls when drawer content exceeds available height
30
+ *
31
+ * **Spacing Conventions:**
32
+ * - Content consumers should add `p-4` padding for consistent spacing (as shown in this example)
33
+ * - Footer components like DrawerActionBar should use `border-t` for visual separation
34
+ *
35
+ * Try scrolling the content below to see the fixed header behavior.
36
+ */
23
37
  export declare const ScrollableContent: Story;
24
38
  //# sourceMappingURL=base-drawer.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/base-drawer/base-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAI3C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,UAAU,CAOjC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,UAAU,CAAC,CAAC;AAuBzC,6DAA6D;AAC7D,eAAO,MAAM,OAAO,EAAE,KAQrB,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,SAAS,EAAE,KAkBvB,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,UAAU,EAAE,KAiBxB,CAAC;AAEF,iCAAiC;AACjC,eAAO,MAAM,KAAK,EAAE,KAUnB,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,UAAU,EAAE,KAexB,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAiBxB,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB,EAAE,KAsCjC,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,EAAE,KAuB9B,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,EAAE,KAsB/B,CAAC"}
1
+ {"version":3,"file":"base-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/base-drawer/base-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAI3C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,UAAU,CAOjC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,UAAU,CAAC,CAAC;AAuBzC,6DAA6D;AAC7D,eAAO,MAAM,OAAO,EAAE,KAQrB,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,SAAS,EAAE,KAkBvB,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,UAAU,EAAE,KAiBxB,CAAC;AAEF,iCAAiC;AACjC,eAAO,MAAM,KAAK,EAAE,KAUnB,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,UAAU,EAAE,KAexB,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAiBxB,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB,EAAE,KAsCjC,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,EAAE,KAuB9B,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAsB/B,CAAC"}
@@ -4,7 +4,7 @@ import { BaseDrawer } from './base-drawer.js';
4
4
  import { DrawerTitle, DrawerDescription } from '../../ui/drawer.js';
5
5
  import { Button } from '../../ui/button.js';
6
6
  const meta = {
7
- title: 'Common/BaseDrawer',
7
+ title: 'Drawers/Base/BaseDrawer',
8
8
  component: BaseDrawer,
9
9
  tags: ['autodocs'],
10
10
  parameters: {
@@ -59,7 +59,21 @@ export const WithDevServerBar = {
59
59
  branch: 'feat/auth-module',
60
60
  }, children: _jsx("div", { className: "p-4", children: _jsx("p", { className: "text-muted-foreground text-sm", children: "The deploy bar appears between the header and this content." }) }) })),
61
61
  };
62
- /** Drawer with content that exceeds viewport to demonstrate scroll behavior. */
62
+ /**
63
+ * Drawer with content that exceeds viewport to demonstrate scroll behavior.
64
+ *
65
+ * **Fixed Header/Footer Layout:**
66
+ * - The header (DrawerTitle + DrawerDescription) remains fixed at the top while scrolling
67
+ * - A Separator is automatically rendered below the header — no need to add one manually
68
+ * - The footer (if present, e.g., DrawerActionBar) remains fixed at the bottom while scrolling
69
+ * - Only the content area (children) scrolls when drawer content exceeds available height
70
+ *
71
+ * **Spacing Conventions:**
72
+ * - Content consumers should add `p-4` padding for consistent spacing (as shown in this example)
73
+ * - Footer components like DrawerActionBar should use `border-t` for visual separation
74
+ *
75
+ * Try scrolling the content below to see the fixed header behavior.
76
+ */
63
77
  export const ScrollableContent = {
64
78
  render: () => (_jsx(DrawerTrigger, { header: _jsxs(_Fragment, { children: [_jsx(DrawerTitle, { children: "Scrollable Content" }), _jsx(DrawerDescription, { children: "Content below overflows and scrolls" })] }), children: _jsx("div", { className: "flex flex-col gap-4 p-4", children: Array.from({ length: 30 }, (_, i) => (_jsxs("div", { className: "border-border rounded-md border p-3", children: [_jsxs("h4", { className: "text-sm font-medium", children: ["Item ", i + 1] }), _jsx("p", { className: "text-muted-foreground text-xs", children: "This is a scrollable content item to demonstrate overflow handling." })] }, i))) }) })),
65
79
  };
@@ -0,0 +1,12 @@
1
+ import type { FeatureCreatePayload } from '../../common/feature-create-drawer/index.js';
2
+ import type { DrawerView } from './drawer-view.js';
3
+ export interface ControlCenterDrawerProps {
4
+ view: DrawerView | null;
5
+ onClose: () => void;
6
+ onDelete?: (featureId: string) => void;
7
+ isDeleting?: boolean;
8
+ onCreateSubmit: (data: FeatureCreatePayload) => void;
9
+ isSubmitting?: boolean;
10
+ }
11
+ export declare function ControlCenterDrawer({ view, onClose, onDelete, isDeleting, onCreateSubmit, isSubmitting, }: ControlCenterDrawerProps): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=control-center-drawer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-center-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/control-center-drawer.tsx"],"names":[],"mappings":"AAwDA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACrD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,UAAU,EACV,cAAc,EACd,YAAY,GACb,EAAE,wBAAwB,2CAke1B"}
@@ -0,0 +1,284 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState, useCallback, useEffect } from 'react';
4
+ import { toast } from 'sonner';
5
+ import { Loader2, Trash2, ExternalLink, GitCommitHorizontal, Code2, Terminal, FolderOpen, } from 'lucide-react';
6
+ import { PrStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
7
+ import { approveFeature } from '../../../app/actions/approve-feature.js';
8
+ import { rejectFeature } from '../../../app/actions/reject-feature.js';
9
+ import { getFeatureArtifact } from '../../../app/actions/get-feature-artifact.js';
10
+ import { getResearchArtifact } from '../../../app/actions/get-research-artifact.js';
11
+ import { getMergeReviewData } from '../../../app/actions/get-merge-review-data.js';
12
+ import { cn } from '../../../lib/utils.js';
13
+ import { useSoundAction } from '../../../hooks/use-sound-action.js';
14
+ import { BaseDrawer } from '../../common/base-drawer/index.js';
15
+ import { DrawerTitle, DrawerDescription } from '../../ui/drawer.js';
16
+ import { Button } from '../../ui/button.js';
17
+ import { Badge } from '../../ui/badge.js';
18
+ import { Separator } from '../../ui/separator.js';
19
+ import { CometSpinner } from '../../ui/comet-spinner.js';
20
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '../../ui/alert-dialog.js';
21
+ import { CiStatusBadge } from '../../common/ci-status-badge/index.js';
22
+ import { ActionButton } from '../../common/action-button/index.js';
23
+ import { OpenActionMenu } from '../../common/open-action-menu/index.js';
24
+ import { FeatureCreateDrawer } from '../../common/feature-create-drawer/index.js';
25
+ import { PrdQuestionnaire } from '../../common/prd-questionnaire/index.js';
26
+ import { TechDecisionsReview } from '../../common/tech-decisions-review/index.js';
27
+ import { MergeReview } from '../../common/merge-review/index.js';
28
+ import { featureNodeStateConfig, lifecycleDisplayLabels } from '../../common/feature-node/index.js';
29
+ import { useFeatureActions } from '../../common/feature-drawer/use-feature-actions.js';
30
+ import { useRepositoryActions } from '../../common/repository-node/use-repository-actions.js';
31
+ export function ControlCenterDrawer({ view, onClose, onDelete, isDeleting, onCreateSubmit, isSubmitting, }) {
32
+ // ── PRD questionnaire state ─────────────────────────────────────────────
33
+ const [prdData, setPrdData] = useState(null);
34
+ const [prdSelections, setPrdSelections] = useState({});
35
+ const [isLoadingPrd, setIsLoadingPrd] = useState(false);
36
+ // ── Tech decisions state ────────────────────────────────────────────────
37
+ const [techData, setTechData] = useState(null);
38
+ const [isLoadingTech, setIsLoadingTech] = useState(false);
39
+ // ── Merge review state ──────────────────────────────────────────────────
40
+ const [mergeData, setMergeData] = useState(null);
41
+ const [isLoadingMerge, setIsLoadingMerge] = useState(false);
42
+ // ── Shared reject state ─────────────────────────────────────────────────
43
+ const [isRejecting, setIsRejecting] = useState(false);
44
+ const rejectSound = useSoundAction('reject');
45
+ // ── Data fetching ───────────────────────────────────────────────────────
46
+ const prdFeatureId = view?.type === 'prd-review' ? view.node.featureId : null;
47
+ useEffect(() => {
48
+ setPrdSelections({});
49
+ setPrdData(null);
50
+ if (!prdFeatureId)
51
+ return;
52
+ let cancelled = false;
53
+ setIsLoadingPrd(true);
54
+ getFeatureArtifact(prdFeatureId)
55
+ .then((result) => {
56
+ if (cancelled)
57
+ return;
58
+ if (result.error) {
59
+ toast.error(result.error);
60
+ return;
61
+ }
62
+ if (result.questionnaire) {
63
+ setPrdData(result.questionnaire);
64
+ const defaults = {};
65
+ for (const q of result.questionnaire.questions) {
66
+ const recommended = q.options.find((o) => o.recommended);
67
+ if (recommended)
68
+ defaults[q.id] = recommended.id;
69
+ }
70
+ setPrdSelections(defaults);
71
+ }
72
+ })
73
+ .catch(() => {
74
+ if (!cancelled)
75
+ toast.error('Failed to load questionnaire');
76
+ })
77
+ .finally(() => {
78
+ if (!cancelled)
79
+ setIsLoadingPrd(false);
80
+ });
81
+ return () => {
82
+ cancelled = true;
83
+ };
84
+ }, [prdFeatureId]);
85
+ const techFeatureId = view?.type === 'tech-review' ? view.node.featureId : null;
86
+ useEffect(() => {
87
+ setTechData(null);
88
+ if (!techFeatureId)
89
+ return;
90
+ let cancelled = false;
91
+ setIsLoadingTech(true);
92
+ getResearchArtifact(techFeatureId)
93
+ .then((result) => {
94
+ if (cancelled)
95
+ return;
96
+ if (result.error) {
97
+ toast.error(result.error);
98
+ return;
99
+ }
100
+ if (result.techDecisions)
101
+ setTechData(result.techDecisions);
102
+ })
103
+ .catch(() => {
104
+ if (!cancelled)
105
+ toast.error('Failed to load tech decisions');
106
+ })
107
+ .finally(() => {
108
+ if (!cancelled)
109
+ setIsLoadingTech(false);
110
+ });
111
+ return () => {
112
+ cancelled = true;
113
+ };
114
+ }, [techFeatureId]);
115
+ const mergeFeatureId = view?.type === 'merge-review' ? view.node.featureId : null;
116
+ useEffect(() => {
117
+ setMergeData(null);
118
+ if (!mergeFeatureId)
119
+ return;
120
+ let cancelled = false;
121
+ setIsLoadingMerge(true);
122
+ getMergeReviewData(mergeFeatureId)
123
+ .then((result) => {
124
+ if (cancelled)
125
+ return;
126
+ if ('error' in result) {
127
+ toast.error(result.error);
128
+ return;
129
+ }
130
+ setMergeData(result);
131
+ })
132
+ .catch(() => {
133
+ if (!cancelled)
134
+ toast.error('Failed to load merge review data');
135
+ })
136
+ .finally(() => {
137
+ if (!cancelled)
138
+ setIsLoadingMerge(false);
139
+ });
140
+ return () => {
141
+ cancelled = true;
142
+ };
143
+ }, [mergeFeatureId]);
144
+ // ── Approve / reject handlers ───────────────────────────────────────────
145
+ const reviewNode = view?.type === 'prd-review' || view?.type === 'tech-review' || view?.type === 'merge-review'
146
+ ? view.node
147
+ : null;
148
+ const handleReject = useCallback(async (feedback, label, onDone) => {
149
+ if (!reviewNode?.featureId)
150
+ return;
151
+ setIsRejecting(true);
152
+ try {
153
+ const result = await rejectFeature(reviewNode.featureId, feedback);
154
+ if (!result.rejected) {
155
+ toast.error(result.error ?? `Failed to reject ${label.toLowerCase()}`);
156
+ return;
157
+ }
158
+ rejectSound.play();
159
+ toast.success(`${label} rejected — agent re-iterating (iteration ${result.iteration})`);
160
+ if (result.iterationWarning) {
161
+ toast.warning(`Iteration ${result.iteration} — consider approving or adjusting feedback to avoid excessive iterations`);
162
+ }
163
+ onClose();
164
+ onDone?.();
165
+ }
166
+ finally {
167
+ setIsRejecting(false);
168
+ }
169
+ }, [reviewNode, onClose, rejectSound]);
170
+ const handlePrdReject = useCallback((feedback) => handleReject(feedback, 'Requirements', () => setPrdSelections({})), [handleReject]);
171
+ const handleTechReject = useCallback((feedback) => handleReject(feedback, 'Plan'), [handleReject]);
172
+ const handleMergeReject = useCallback((feedback) => handleReject(feedback, 'Merge'), [handleReject]);
173
+ const handleSimpleApprove = useCallback(async (label) => {
174
+ if (!reviewNode?.featureId)
175
+ return;
176
+ const result = await approveFeature(reviewNode.featureId);
177
+ if (!result.approved) {
178
+ toast.error(result.error ?? `Failed to approve ${label.toLowerCase()}`);
179
+ return;
180
+ }
181
+ toast.success(`${label} approved — agent resuming`);
182
+ onClose();
183
+ }, [reviewNode, onClose]);
184
+ const handlePrdApprove = useCallback(async (_actionId) => {
185
+ if (view?.type !== 'prd-review')
186
+ return;
187
+ let payload;
188
+ if (prdData) {
189
+ const changedSelections = [];
190
+ for (const [questionId, optionId] of Object.entries(prdSelections)) {
191
+ const question = prdData.questions.find((q) => q.id === questionId);
192
+ const option = question?.options.find((o) => o.id === optionId);
193
+ if (question && option) {
194
+ changedSelections.push({ questionId: question.question, selectedOption: option.label });
195
+ }
196
+ }
197
+ payload = { approved: true, changedSelections };
198
+ }
199
+ const result = await approveFeature(view.node.featureId, payload);
200
+ if (!result.approved) {
201
+ toast.error(result.error ?? 'Failed to approve requirements');
202
+ return;
203
+ }
204
+ toast.success('Requirements approved — agent resuming');
205
+ setPrdSelections({});
206
+ onClose();
207
+ }, [view, prdData, prdSelections, onClose]);
208
+ const handleTechApprove = useCallback(() => handleSimpleApprove('Plan'), [handleSimpleApprove]);
209
+ const handleMergeApprove = useCallback(() => handleSimpleApprove('Merge'), [handleSimpleApprove]);
210
+ // ── Derived view data ───────────────────────────────────────────────────
211
+ const isCreateView = view?.type === 'feature-create';
212
+ const createView = isCreateView ? view : null;
213
+ const featureNode = view?.type === 'feature' ||
214
+ view?.type === 'prd-review' ||
215
+ view?.type === 'tech-review' ||
216
+ view?.type === 'merge-review'
217
+ ? view.node
218
+ : null;
219
+ const repoData = view?.type === 'repository' ? view.data : null;
220
+ // ── Hooks (always called unconditionally per Rules of Hooks) ────────────
221
+ const featureActionsInput = featureNode?.repositoryPath && featureNode?.branch
222
+ ? {
223
+ repositoryPath: featureNode.repositoryPath,
224
+ branch: featureNode.branch,
225
+ specPath: featureNode.specPath,
226
+ }
227
+ : null;
228
+ const featureActions = useFeatureActions(featureActionsInput);
229
+ const repoActions = useRepositoryActions(repoData?.repositoryPath ? { repositoryPath: repoData.repositoryPath } : null);
230
+ // ── Header ──────────────────────────────────────────────────────────────
231
+ let header = undefined;
232
+ if (featureNode) {
233
+ header = (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "feature-drawer-header", children: [_jsx(DrawerTitle, { children: featureNode.name }), featureNode.description ? (_jsx(DrawerDescription, { children: featureNode.description })) : featureNode.featureId ? (_jsx(DrawerDescription, { className: "sr-only", children: featureNode.featureId })) : null] }), featureActionsInput ? (_jsxs("div", { className: "flex items-center gap-2 pt-2", children: [_jsx(OpenActionMenu, { actions: featureActions, repositoryPath: featureActionsInput.repositoryPath, showSpecs: !!featureActionsInput.specPath }), onDelete && featureNode.featureId ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "bg-border mx-1 h-4 w-px" }), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Delete feature", disabled: isDeleting, className: "text-muted-foreground hover:text-destructive", "data-testid": "feature-drawer-delete", children: isDeleting ? (_jsx(Loader2, { className: "size-4 animate-spin" })) : (_jsx(Trash2, { className: "size-4" })) }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: featureNode.name }), " (", featureNode.featureId, "). This action cannot be undone.", featureNode.state === 'running' ? (_jsx(_Fragment, { children: " This feature has a running agent that will be stopped." })) : null] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onDelete(featureNode.featureId), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] })] })] })) : null] })) : null] }));
234
+ }
235
+ else if (repoData) {
236
+ header = (_jsxs("div", { "data-testid": "repository-drawer-header", children: [_jsx(DrawerTitle, { children: repoData.name }), repoData.repositoryPath ? (_jsx(DrawerDescription, { className: "truncate font-mono text-xs", children: repoData.repositoryPath })) : null] }));
237
+ }
238
+ // ── Body ────────────────────────────────────────────────────────────────
239
+ let body = null;
240
+ if (view?.type === 'feature' && featureNode) {
241
+ body = (_jsxs("div", { className: "flex-1 overflow-y-auto", children: [_jsxs("div", { "data-testid": "feature-drawer-status", className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: lifecycleDisplayLabels[featureNode.lifecycle] }), _jsx(FeatureStateBadge, { data: featureNode }), featureNode.progress > 0 ? (_jsxs("div", { "data-testid": "feature-drawer-progress", className: "flex flex-col gap-1", children: [_jsxs("div", { className: "text-muted-foreground flex items-center justify-between text-xs", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { children: [featureNode.progress, "%"] })] }), _jsx("div", { className: "bg-muted h-2 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', featureNodeStateConfig[featureNode.state].progressClass), style: { width: `${featureNode.progress}%` } }) })] })) : null] }), featureNode.pr ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx(FeaturePrInfo, { pr: featureNode.pr })] })) : null, _jsx(FeatureDetails, { data: featureNode })] }));
242
+ }
243
+ else if (view?.type === 'prd-review') {
244
+ body = prdData ? (_jsx(PrdQuestionnaire, { data: prdData, selections: prdSelections, onSelect: (qId, oId) => setPrdSelections((prev) => ({ ...prev, [qId]: oId })), onApprove: handlePrdApprove, onReject: handlePrdReject, isProcessing: isLoadingPrd, isRejecting: isRejecting })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) }));
245
+ }
246
+ else if (view?.type === 'tech-review') {
247
+ body = techData ? (_jsx(TechDecisionsReview, { data: techData, onApprove: handleTechApprove, onReject: handleTechReject, isProcessing: isLoadingTech, isRejecting: isRejecting })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) }));
248
+ }
249
+ else if (view?.type === 'merge-review') {
250
+ body = mergeData ? (_jsx(MergeReview, { data: mergeData, onApprove: handleMergeApprove, onReject: handleMergeReject, isProcessing: isLoadingMerge, isRejecting: isRejecting })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) }));
251
+ }
252
+ else if (view?.type === 'repository' && repoData?.repositoryPath) {
253
+ body = (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "OPEN WITH" }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(ActionButton, { label: "Open in IDE", onClick: repoActions.openInIde, loading: repoActions.ideLoading, error: !!repoActions.ideError, icon: Code2, variant: "outline", size: "sm" }), _jsx(ActionButton, { label: "Open in Shell", onClick: repoActions.openInShell, loading: repoActions.shellLoading, error: !!repoActions.shellError, icon: Terminal, variant: "outline", size: "sm" }), _jsx(ActionButton, { label: "Open Folder", onClick: repoActions.openFolder, loading: repoActions.folderLoading, error: !!repoActions.folderError, icon: FolderOpen, variant: "outline", size: "sm" })] })] })] }));
254
+ }
255
+ // ── Render ──────────────────────────────────────────────────────────────
256
+ return (_jsxs(_Fragment, { children: [_jsx(BaseDrawer, { open: view !== null && !isCreateView, onClose: onClose, size: "md", modal: false, header: header, "data-testid": view?.type === 'feature'
257
+ ? 'feature-drawer'
258
+ : view?.type === 'repository'
259
+ ? 'repository-drawer'
260
+ : 'review-drawer', children: body }), _jsx(FeatureCreateDrawer, { open: isCreateView, onClose: onClose, onSubmit: onCreateSubmit, repositoryPath: createView?.repositoryPath ?? '', features: createView?.features ?? [], workflowDefaults: createView?.workflowDefaults, initialParentId: createView?.initialParentId, isSubmitting: isSubmitting })] }));
261
+ }
262
+ // ── Private sub-components ────────────────────────────────────────────────────
263
+ function FeatureStateBadge({ data }) {
264
+ const config = featureNodeStateConfig[data.state];
265
+ const Icon = config.icon;
266
+ return (_jsxs("div", { className: cn('flex items-center gap-2 rounded-full px-3 py-1.5 text-sm font-medium', config.badgeBgClass, config.badgeClass), children: [data.state === 'running' ? (_jsx(CometSpinner, { size: "sm", className: "shrink-0" })) : (_jsx(Icon, { className: "h-4 w-4 shrink-0" })), _jsx("span", { children: config.label })] }));
267
+ }
268
+ const prStatusStyles = {
269
+ [PrStatus.Open]: 'border-transparent bg-blue-50 text-blue-700 hover:bg-blue-50',
270
+ [PrStatus.Merged]: 'border-transparent bg-purple-50 text-purple-700 hover:bg-purple-50',
271
+ [PrStatus.Closed]: 'border-transparent bg-red-50 text-red-700 hover:bg-red-50',
272
+ };
273
+ function FeaturePrInfo({ pr }) {
274
+ return (_jsx("div", { "data-testid": "feature-drawer-pr", className: "border-border mx-4 rounded-lg border", children: _jsxs("div", { className: "space-y-3 px-4 py-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("a", { href: pr.url, target: "_blank", rel: "noopener noreferrer", className: "text-primary flex items-center gap-1.5 text-sm font-semibold underline underline-offset-2", children: ["PR #", pr.number, _jsx(ExternalLink, { className: "h-3.5 w-3.5" })] }), _jsx(Badge, { className: prStatusStyles[pr.status], children: pr.status })] }), pr.ciStatus ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "CI Status" }), _jsx(CiStatusBadge, { status: pr.ciStatus })] })) : null, pr.commitHash ? (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Commit" }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(GitCommitHorizontal, { className: "text-muted-foreground h-3.5 w-3.5" }), _jsx("code", { className: "bg-muted text-foreground rounded-md px-1.5 py-0.5 font-mono text-[11px]", children: pr.commitHash.slice(0, 7) })] })] })) : null] }) }));
275
+ }
276
+ function FeatureDetails({ data }) {
277
+ const hasAnyDetail = data.agentType ?? data.runtime ?? data.blockedBy ?? data.errorMessage;
278
+ if (!hasAnyDetail)
279
+ return null;
280
+ return (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { "data-testid": "feature-drawer-details", className: "flex flex-col gap-3 p-4", children: [data.agentType ? _jsx(DetailRow, { label: "Agent", value: data.agentType }) : null, data.runtime ? _jsx(DetailRow, { label: "Runtime", value: data.runtime }) : null, data.blockedBy ? _jsx(DetailRow, { label: "Blocked by", value: data.blockedBy }) : null, data.errorMessage ? _jsx(DetailRow, { label: "Error", value: data.errorMessage }) : null] })] }));
281
+ }
282
+ function DetailRow({ label, value }) {
283
+ return (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: label }), _jsx("span", { className: "text-sm", children: value })] }));
284
+ }
@@ -0,0 +1,33 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { ControlCenterDrawer } from './control-center-drawer.js';
3
+ declare const meta: Meta<typeof ControlCenterDrawer>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof ControlCenterDrawer>;
6
+ /** Feature info view — running state with progress. Default story. */
7
+ export declare const Default: Story;
8
+ /** Feature info view — completed (maintain lifecycle, done state, merged PR). */
9
+ export declare const FeatureDone: Story;
10
+ /** Feature info view — error state. */
11
+ export declare const FeatureError: Story;
12
+ /**
13
+ * PRD review view — loads questionnaire data via server action.
14
+ * Shows spinner in Storybook (no real API available).
15
+ */
16
+ export declare const PrdReview: Story;
17
+ /**
18
+ * Tech decisions review view — loads research artifact via server action.
19
+ * Shows spinner in Storybook.
20
+ */
21
+ export declare const TechReview: Story;
22
+ /**
23
+ * Merge review view — loads merge review data via server action.
24
+ * Shows spinner in Storybook.
25
+ */
26
+ export declare const MergeReview: Story;
27
+ /** Feature create form. */
28
+ export declare const FeatureCreate: Story;
29
+ /** Repository actions view. */
30
+ export declare const Repository: Story;
31
+ /** Interactive — click any view type to open that drawer panel. */
32
+ export declare const AllViews: Story;
33
+ //# sourceMappingURL=control-center-drawer.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-center-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAG9D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAO1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AA+JlD,sEAAsE;AACtE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,uCAAuC;AACvC,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAEvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,2BAA2B;AAC3B,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,+BAA+B;AAC/B,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AA0DF,mEAAmE;AACnE,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC"}