@shepai/cli 1.101.0-pr297.8d52b60 → 1.101.0-pr301.2616435

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 (237) hide show
  1. package/apis/json-schema/NotificationEventConfig.yaml +5 -0
  2. package/apis/json-schema/NotificationEventType.yaml +1 -0
  3. package/apis/json-schema/PullRequest.yaml +3 -0
  4. package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts +11 -0
  5. package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map +1 -1
  6. package/dist/packages/core/src/domain/factories/settings-defaults.factory.d.ts.map +1 -1
  7. package/dist/packages/core/src/domain/factories/settings-defaults.factory.js +1 -0
  8. package/dist/packages/core/src/domain/generated/output.d.ts +10 -1
  9. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  10. package/dist/packages/core/src/domain/generated/output.js +1 -0
  11. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts +1 -0
  12. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts.map +1 -1
  13. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.js +2 -0
  14. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +1 -0
  15. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
  16. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +2 -0
  17. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
  18. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.js +11 -0
  19. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.d.ts.map +1 -1
  20. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.js +3 -2
  21. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.d.ts.map +1 -1
  22. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.js +18 -0
  23. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +2 -0
  24. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
  25. package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +19 -1
  26. package/dist/packages/core/src/infrastructure/services/notifications/notification.service.d.ts.map +1 -1
  27. package/dist/packages/core/src/infrastructure/services/notifications/notification.service.js +1 -0
  28. package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts.map +1 -1
  29. package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js +16 -0
  30. package/dist/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.d.ts.map +1 -1
  31. package/dist/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.js +33 -1
  32. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
  33. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +43 -0
  34. package/dist/src/presentation/web/app/actions/get-merge-review-data.d.ts.map +1 -1
  35. package/dist/src/presentation/web/app/actions/get-merge-review-data.js +1 -0
  36. package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
  37. package/dist/src/presentation/web/app/api/agent-events/route.js +24 -0
  38. package/dist/src/presentation/web/app/build-feature-node-data.d.ts.map +1 -1
  39. package/dist/src/presentation/web/app/build-feature-node-data.js +1 -0
  40. package/dist/src/presentation/web/app/build-graph-nodes.js +1 -0
  41. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  42. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +1 -1
  43. package/dist/src/presentation/web/components/common/delete-feature-dialog/delete-feature-dialog.js +1 -1
  44. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts +2 -0
  45. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts.map +1 -1
  46. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts +1 -1
  47. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts.map +1 -1
  48. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.js +9 -5
  49. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts.map +1 -1
  50. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.js +8 -50
  51. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts +1 -4
  52. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts.map +1 -1
  53. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js +11 -31
  54. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.d.ts.map +1 -1
  55. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.js +4 -37
  56. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.d.ts +2 -0
  57. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.d.ts.map +1 -1
  58. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.js +16 -0
  59. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
  60. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +2 -0
  61. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +1 -0
  62. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
  63. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  64. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +1 -1
  65. package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts +2 -0
  66. package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts.map +1 -1
  67. package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -1
  68. package/dist/src/presentation/web/components/common/merge-review/merge-review.js +3 -1
  69. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts +2 -0
  70. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts.map +1 -1
  71. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.js +10 -0
  72. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  73. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +7 -2
  74. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
  75. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +2 -2
  76. package/dist/src/presentation/web/components/features/settings/notification-settings-section.d.ts.map +1 -1
  77. package/dist/src/presentation/web/components/features/settings/notification-settings-section.js +1 -0
  78. package/dist/src/presentation/web/components/features/settings/notification-settings-section.stories.d.ts.map +1 -1
  79. package/dist/src/presentation/web/components/features/settings/notification-settings-section.stories.js +2 -0
  80. package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
  81. package/dist/src/presentation/web/hooks/use-graph-state.js +17 -1
  82. package/dist/tsconfig.build.tsbuildinfo +1 -1
  83. package/package.json +1 -1
  84. package/web/.next/BUILD_ID +1 -1
  85. package/web/.next/build-manifest.json +2 -2
  86. package/web/.next/fallback-build-manifest.json +2 -2
  87. package/web/.next/prerender-manifest.json +3 -3
  88. package/web/.next/required-server-files.js +1 -1
  89. package/web/.next/required-server-files.json +1 -1
  90. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +20 -20
  91. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  92. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  93. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +25 -25
  94. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -1
  95. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  96. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  97. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +25 -25
  98. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
  99. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  100. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  101. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  102. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  103. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  104. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +20 -20
  105. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  106. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  107. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +25 -25
  108. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -1
  109. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  110. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  111. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +25 -25
  112. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
  113. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  114. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  115. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +18 -18
  116. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  117. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  118. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  119. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  120. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  121. package/web/.next/server/app/_global-error.html +2 -2
  122. package/web/.next/server/app/_global-error.rsc +1 -1
  123. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  124. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  125. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  126. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  127. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  128. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  129. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  130. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  131. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  132. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  133. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  134. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  135. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  136. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  137. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  138. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  139. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
  140. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
  141. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  142. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  143. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_c757eb00.js +1 -1
  144. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_c757eb00.js.map +1 -1
  145. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_7eb49631.js +1 -1
  146. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_7eb49631.js.map +1 -1
  147. package/web/.next/server/chunks/ssr/[root-of-the-server]__0b6bb4ae._.js +3 -0
  148. package/web/.next/server/chunks/ssr/[root-of-the-server]__0b6bb4ae._.js.map +1 -0
  149. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  150. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  151. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
  152. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  153. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  154. package/web/.next/server/chunks/ssr/[root-of-the-server]__6a82177d._.js +3 -0
  155. package/web/.next/server/chunks/ssr/[root-of-the-server]__6a82177d._.js.map +1 -0
  156. package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js +1 -1
  157. package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js.map +1 -1
  158. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
  159. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js.map +1 -1
  160. package/web/.next/server/chunks/ssr/[root-of-the-server]__94128fa9._.js +1 -1
  161. package/web/.next/server/chunks/ssr/[root-of-the-server]__94128fa9._.js.map +1 -1
  162. package/web/.next/server/chunks/ssr/[root-of-the-server]__9bfb8e7c._.js +1 -1
  163. package/web/.next/server/chunks/ssr/[root-of-the-server]__9bfb8e7c._.js.map +1 -1
  164. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  165. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  166. package/web/.next/server/chunks/ssr/[root-of-the-server]__ec9a1550._.js +3 -0
  167. package/web/.next/server/chunks/ssr/[root-of-the-server]__ec9a1550._.js.map +1 -0
  168. package/web/.next/server/chunks/ssr/[root-of-the-server]__f8932d55._.js +3 -0
  169. package/web/.next/server/chunks/ssr/[root-of-the-server]__f8932d55._.js.map +1 -0
  170. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  171. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  172. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  173. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  174. package/web/.next/server/chunks/ssr/_1bb131c4._.js +1 -1
  175. package/web/.next/server/chunks/ssr/_1bb131c4._.js.map +1 -1
  176. package/web/.next/server/chunks/ssr/{_d0e455fd._.js → _27989bde._.js} +2 -2
  177. package/web/.next/server/chunks/ssr/{_d0e455fd._.js.map → _27989bde._.js.map} +1 -1
  178. package/web/.next/server/chunks/ssr/_6e08ce21._.js +1 -1
  179. package/web/.next/server/chunks/ssr/_6e08ce21._.js.map +1 -1
  180. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  181. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  182. package/web/.next/server/chunks/ssr/{_55d90438._.js → _9393d83d._.js} +2 -2
  183. package/web/.next/server/chunks/ssr/{_55d90438._.js.map → _9393d83d._.js.map} +1 -1
  184. package/web/.next/server/chunks/ssr/{_ca4b6ca9._.js → _a9ecce11._.js} +2 -2
  185. package/web/.next/server/chunks/ssr/{_ca4b6ca9._.js.map → _a9ecce11._.js.map} +1 -1
  186. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  187. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  188. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  189. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  190. package/web/.next/server/chunks/ssr/src_presentation_web_3c53a23d._.js +2 -2
  191. package/web/.next/server/chunks/ssr/src_presentation_web_3c53a23d._.js.map +1 -1
  192. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_befd865a.js +1 -1
  193. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_befd865a.js.map +1 -1
  194. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  195. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  196. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  197. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  198. package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js +1 -1
  199. package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js.map +1 -1
  200. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  201. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js.map +1 -1
  202. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  203. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js.map +1 -1
  204. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  205. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  206. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  207. package/web/.next/server/chunks/ssr/src_presentation_web_ec8c7a4f._.js +2 -2
  208. package/web/.next/server/chunks/ssr/src_presentation_web_ec8c7a4f._.js.map +1 -1
  209. package/web/.next/server/pages/500.html +2 -2
  210. package/web/.next/server/server-reference-manifest.js +1 -1
  211. package/web/.next/server/server-reference-manifest.json +30 -30
  212. package/web/.next/static/chunks/{b31f2c82654437a6.js → 0102ce60a2a42fab.js} +1 -1
  213. package/web/.next/static/chunks/{26c849050fe49dc8.js → 015b268514c493c1.js} +1 -1
  214. package/web/.next/static/chunks/{76beaf5f0db52643.js → 08e9a82d5fe7e80e.js} +1 -1
  215. package/web/.next/static/chunks/{6220dc2afba28980.js → 17f9d15256e611ff.js} +1 -1
  216. package/web/.next/static/chunks/350e67945d70021c.css +1 -0
  217. package/web/.next/static/chunks/{020e3cf371dc3668.js → 3530b3bafae1bb22.js} +1 -1
  218. package/web/.next/static/chunks/{6f49b4b4563a1763.js → 4cb6cc86828fa4e3.js} +1 -1
  219. package/web/.next/static/chunks/{cd4e1d340f1be08e.js → 840ba12b8106d809.js} +1 -1
  220. package/web/.next/static/chunks/{9c2c90aca9ec65ae.js → 95970154db2a0a04.js} +1 -1
  221. package/web/.next/static/chunks/{845632fe4fbe1082.js → a9917c27f822473e.js} +1 -1
  222. package/web/.next/static/chunks/b3250c4cb4d793ab.js +2 -0
  223. package/web/.next/static/chunks/{4b636b281e40b7f9.js → bbe0a7bf055919e8.js} +1 -1
  224. package/web/.next/static/chunks/{062db6b08d15886a.js → ec30a8a3eea9943a.js} +2 -2
  225. package/web/.next/server/chunks/ssr/[root-of-the-server]__19fb0bfe._.js +0 -3
  226. package/web/.next/server/chunks/ssr/[root-of-the-server]__19fb0bfe._.js.map +0 -1
  227. package/web/.next/server/chunks/ssr/[root-of-the-server]__3d6f6b0e._.js +0 -3
  228. package/web/.next/server/chunks/ssr/[root-of-the-server]__3d6f6b0e._.js.map +0 -1
  229. package/web/.next/server/chunks/ssr/[root-of-the-server]__42020c54._.js +0 -3
  230. package/web/.next/server/chunks/ssr/[root-of-the-server]__42020c54._.js.map +0 -1
  231. package/web/.next/server/chunks/ssr/[root-of-the-server]__9cb60e1e._.js +0 -3
  232. package/web/.next/server/chunks/ssr/[root-of-the-server]__9cb60e1e._.js.map +0 -1
  233. package/web/.next/static/chunks/0a113dc589f3a485.css +0 -1
  234. package/web/.next/static/chunks/81924887fd503ef3.js +0 -2
  235. /package/web/.next/static/{9YFN1qpApQJE6EyH43wLv → qjpOlpSobogJpFayJnJhW}/_buildManifest.js +0 -0
  236. /package/web/.next/static/{9YFN1qpApQJE6EyH43wLv → qjpOlpSobogJpFayJnJhW}/_clientMiddlewareManifest.json +0 -0
  237. /package/web/.next/static/{9YFN1qpApQJE6EyH43wLv → qjpOlpSobogJpFayJnJhW}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"get-graph-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/(dashboard)/get-graph-data.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CAuCxF"}
1
+ {"version":3,"file":"get-graph-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/(dashboard)/get-graph-data.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAQ1C,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CAkFxF"}
@@ -1,11 +1,54 @@
1
1
  import { resolve } from '../../lib/server-container.js';
2
+ import { CiStatus } from '../../../../../packages/core/src/domain/generated/output.js';
2
3
  import { layoutWithDagre, CANVAS_LAYOUT_DEFAULTS } from '../../lib/layout-with-dagre.js';
3
4
  import { buildGraphNodes } from '../build-graph-nodes.js';
5
+ const CI_STATUS_MAP = {
6
+ success: CiStatus.Success,
7
+ failure: CiStatus.Failure,
8
+ pending: CiStatus.Pending,
9
+ };
4
10
  export async function getGraphData() {
5
11
  const listFeatures = resolve('ListFeaturesUseCase');
6
12
  const listRepos = resolve('ListRepositoriesUseCase');
7
13
  const agentRunRepo = resolve('IAgentRunRepository');
14
+ const gitPrService = resolve('IGitPrService');
15
+ const featureRepo = resolve('IFeatureRepository');
8
16
  const [features, repositories] = await Promise.all([listFeatures.execute(), listRepos.execute()]);
17
+ // Fetch live PR status for features with open PRs so the canvas
18
+ // reflects the current GitHub state without waiting for the background watcher.
19
+ await Promise.all(features
20
+ .filter((f) => f.pr?.number)
21
+ .map(async (feature) => {
22
+ try {
23
+ const updates = {};
24
+ // Live mergeable status (only if not yet known)
25
+ if (feature.pr.mergeable === undefined) {
26
+ const mergeable = await gitPrService.getMergeableStatus(feature.repositoryPath, feature.pr.number);
27
+ if (mergeable !== undefined)
28
+ updates.mergeable = mergeable;
29
+ }
30
+ // Live CI status
31
+ if (feature.branch) {
32
+ const ciResult = await gitPrService
33
+ .getCiStatus(feature.repositoryPath, feature.branch)
34
+ .catch(() => undefined);
35
+ if (ciResult) {
36
+ const ciStatus = CI_STATUS_MAP[ciResult.status] ?? CiStatus.Pending;
37
+ if (ciStatus !== feature.pr.ciStatus)
38
+ updates.ciStatus = ciStatus;
39
+ }
40
+ }
41
+ if (Object.keys(updates).length > 0) {
42
+ feature.pr = { ...feature.pr, ...updates };
43
+ featureRepo.update(feature).catch(() => {
44
+ /* best-effort persist */
45
+ });
46
+ }
47
+ }
48
+ catch {
49
+ // GitHub fetch failed — use cached value
50
+ }
51
+ }));
9
52
  const featuresWithRuns = await Promise.all(features.map(async (feature) => {
10
53
  const run = feature.agentRunId ? await agentRunRepo.findById(feature.agentRunId) : null;
11
54
  return { feature, run };
@@ -1 +1 @@
1
- {"version":3,"file":"get-merge-review-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-merge-review-data.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,sDAAsD,CAAC;AAG9D,KAAK,wBAAwB,GAAG,eAAe,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAgF7F"}
1
+ {"version":3,"file":"get-merge-review-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-merge-review-data.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,sDAAsD,CAAC;AAG9D,KAAK,wBAAwB,GAAG,eAAe,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAiF7F"}
@@ -20,6 +20,7 @@ export async function getMergeReviewData(featureId) {
20
20
  status: feature.pr.status,
21
21
  commitHash: feature.pr.commitHash,
22
22
  ciStatus: feature.pr.ciStatus,
23
+ mergeable: feature.pr.mergeable,
23
24
  }
24
25
  : undefined;
25
26
  const branch = feature.branch ? { source: feature.branch, target: 'main' } : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAgBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAgEvC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAmN9C"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAgBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAkEvC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA8O9C"}
@@ -133,6 +133,8 @@ export function GET(request) {
133
133
  lifecycle: feature.lifecycle,
134
134
  completedPhases,
135
135
  featureName: feature.name,
136
+ prMergeable: feature.pr?.mergeable,
137
+ prCiStatus: feature.pr?.ciStatus,
136
138
  });
137
139
  continue;
138
140
  }
@@ -186,6 +188,28 @@ export function GET(request) {
186
188
  });
187
189
  }
188
190
  }
191
+ // Check for PR data changes (mergeable / CI status)
192
+ const curMergeable = feature.pr?.mergeable;
193
+ const curCiStatus = feature.pr?.ciStatus;
194
+ if (curMergeable !== prev.prMergeable || curCiStatus !== prev.prCiStatus) {
195
+ prev.prMergeable = curMergeable;
196
+ prev.prCiStatus = curCiStatus;
197
+ const nodeName = LIFECYCLE_TO_NODE[feature.lifecycle] ?? 'merge';
198
+ emitEvent({
199
+ eventType: NotificationEventType.PhaseCompleted,
200
+ agentRunId: run.id,
201
+ featureId: feature.id,
202
+ featureName: feature.name,
203
+ phaseName: nodeName,
204
+ message: curMergeable === false
205
+ ? `PR #${feature.pr?.number} has merge conflicts`
206
+ : `PR status updated`,
207
+ severity: curMergeable === false
208
+ ? NotificationSeverity.Warning
209
+ : NotificationSeverity.Info,
210
+ timestamp: new Date().toISOString(),
211
+ });
212
+ }
189
213
  // Check for new phase completions
190
214
  try {
191
215
  const timings = await phaseTimingRepo.findByRunId(run.id);
@@ -1 +1 @@
1
- {"version":3,"file":"build-feature-node-data.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/build-feature-node-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAM9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAExE,MAAM,WAAW,2BAA2B;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,QAAQ,GAAG,IAAI,EACpB,OAAO,CAAC,EAAE,2BAA2B,GACpC,eAAe,CAgCjB"}
1
+ {"version":3,"file":"build-feature-node-data.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/build-feature-node-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAM9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAExE,MAAM,WAAW,2BAA2B;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,QAAQ,GAAG,IAAI,EACpB,OAAO,CAAC,EAAE,2BAA2B,GACpC,eAAe,CAiCjB"}
@@ -32,6 +32,7 @@ export function buildFeatureNodeData(feature, run, options) {
32
32
  status: feature.pr.status,
33
33
  ciStatus: feature.pr.ciStatus,
34
34
  commitHash: feature.pr.commitHash,
35
+ mergeable: feature.pr.mergeable,
35
36
  },
36
37
  }),
37
38
  };
@@ -111,6 +111,7 @@ function appendFeatureNodes(repoFeatures, repoNodeId, allFeaturesWithRuns, nodes
111
111
  status: feature.pr.status,
112
112
  ciStatus: feature.pr.ciStatus,
113
113
  commitHash: feature.pr.commitHash,
114
+ mergeable: feature.pr.mergeable,
114
115
  },
115
116
  }),
116
117
  };
@@ -1 +1 @@
1
- {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CA6iB1F"}
1
+ {"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CA4iB1F"}
@@ -329,7 +329,7 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
329
329
  // ── Body ──────────────────────────────────────────────────────────────
330
330
  let body = null;
331
331
  if (view.type === 'feature' && featureNode) {
332
- body = (_jsx(FeatureDrawerTabs, { featureNode: featureNode, featureId: featureNode.featureId, initialTab: view.initialTab, urlTab: urlTab, sseEvents: events, prdData: prdData, prdSelections: prdSelections, onPrdSelect: (qId, oId) => setPrdSelections((prev) => ({ ...prev, [qId]: oId })), onPrdApprove: handlePrdApprove, onPrdReject: handlePrdReject, isPrdLoading: isLoadingPrd, techData: techData, onTechApprove: handleTechApprove, onTechReject: handleTechReject, isTechLoading: isLoadingTech, productData: isLoadingTechProduct ? null : techProductData, mergeData: mergeData, onMergeApprove: handleMergeApprove, onMergeReject: handleMergeReject, isMergeLoading: isLoadingMerge, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: setChatInput }));
332
+ body = (_jsx(FeatureDrawerTabs, { featureNode: featureNode, featureId: featureNode.featureId, initialTab: view.initialTab, urlTab: urlTab, prdData: prdData, prdSelections: prdSelections, onPrdSelect: (qId, oId) => setPrdSelections((prev) => ({ ...prev, [qId]: oId })), onPrdApprove: handlePrdApprove, onPrdReject: handlePrdReject, isPrdLoading: isLoadingPrd, techData: techData, onTechApprove: handleTechApprove, onTechReject: handleTechReject, isTechLoading: isLoadingTech, productData: isLoadingTechProduct ? null : techProductData, mergeData: mergeData, onMergeApprove: handleMergeApprove, onMergeReject: handleMergeReject, isMergeLoading: isLoadingMerge, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: setChatInput }));
333
333
  }
334
334
  return (_jsx(BaseDrawer, { open: isOpen, onClose: attemptClose, size: "md", modal: false, header: header, "data-testid": view.type === 'feature' ? 'feature-drawer' : 'repository-drawer', children: body }));
335
335
  }
@@ -12,5 +12,5 @@ export function DeleteFeatureDialog({ open, onOpenChange, onConfirm, isDeleting,
12
12
  setCleanup(true);
13
13
  }
14
14
  }, [open]);
15
- return (_jsx(AlertDialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: featureName }), " (", featureId, "). This action cannot be undone."] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "cleanup-checkbox", checked: cleanup, onCheckedChange: (checked) => setCleanup(checked === true), disabled: isDeleting, "aria-label": "Clean up worktree and branches" }), _jsx(Label, { htmlFor: "cleanup-checkbox", className: "cursor-pointer text-sm", children: "Clean up worktree and branches" })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, onClick: () => onOpenChange(false), children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onConfirm(cleanup), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] }) }));
15
+ return (_jsx(AlertDialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(AlertDialogContent, { onCloseAutoFocus: (e) => e.preventDefault(), children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: featureName }), " (", featureId, "). This action cannot be undone."] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "cleanup-checkbox", checked: cleanup, onCheckedChange: (checked) => setCleanup(checked === true), disabled: isDeleting, "aria-label": "Clean up worktree and branches" }), _jsx(Label, { htmlFor: "cleanup-checkbox", className: "cursor-pointer text-sm", children: "Clean up worktree and branches" })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, onClick: () => onOpenChange(false), children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onConfirm(cleanup), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] }) }));
16
16
  }
@@ -15,6 +15,8 @@ export interface DrawerActionBarProps {
15
15
  onApprove: () => void;
16
16
  /** Label for the approve button (used in both the split button and dropdown) */
17
17
  approveLabel: string;
18
+ /** Visual variant for the approve action: 'default' (blue) or 'warning' (orange) */
19
+ approveVariant?: 'default' | 'warning';
18
20
  /** Placeholder for the inline revision textarea */
19
21
  revisionPlaceholder?: string;
20
22
  /** Whether an approval/processing operation is in flight */
@@ -1 +1 @@
1
- {"version":3,"file":"drawer-action-bar-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,iGAAiG;AACjG,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvE,kCAAkC;IAClC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C"}
1
+ {"version":3,"file":"drawer-action-bar-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,iGAAiG;AACjG,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvE,kCAAkC;IAClC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,cAAc,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACvC,mDAAmD;IACnD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C"}
@@ -1,3 +1,3 @@
1
1
  import type { DrawerActionBarProps } from './drawer-action-bar-config.js';
2
- export declare function DrawerActionBar({ onReject, onApprove, approveLabel, revisionPlaceholder, isProcessing, isRejecting, children, chatInput: controlledChatInput, onChatInputChange, }: DrawerActionBarProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function DrawerActionBar({ onReject, onApprove, approveLabel, approveVariant, revisionPlaceholder, isProcessing, isRejecting, children, chatInput: controlledChatInput, onChatInputChange, }: DrawerActionBarProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=drawer-action-bar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"drawer-action-bar.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,oBAAoB,EAAoB,MAAM,4BAA4B,CAAC;AAmEzF,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,YAAoB,EACpB,WAAmB,EACnB,QAAQ,EACR,SAAS,EAAE,mBAAmB,EAC9B,iBAAiB,GAClB,EAAE,oBAAoB,2CA2XtB"}
1
+ {"version":3,"file":"drawer-action-bar.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,oBAAoB,EAAoB,MAAM,4BAA4B,CAAC;AAmEzF,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,cAA0B,EAC1B,mBAAmB,EACnB,YAAoB,EACpB,WAAmB,EACnB,QAAQ,EACR,SAAS,EAAE,mBAAmB,EAC9B,iBAAiB,GAClB,EAAE,oBAAoB,2CAoYtB"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback, useRef, useEffect } from 'react';
4
- import { PaperclipIcon, Send, ChevronLeft, Check } from 'lucide-react';
4
+ import { PaperclipIcon, Send, ChevronLeft, Check, AlertTriangle } from 'lucide-react';
5
5
  import { cn } from '../../../lib/utils.js';
6
6
  import { Button } from '../../ui/button.js';
7
7
  import { Textarea } from '../../ui/textarea.js';
@@ -71,7 +71,11 @@ function getExtension(filename) {
71
71
  const dot = filename.lastIndexOf('.');
72
72
  return dot >= 0 ? filename.slice(dot).toLowerCase() : '';
73
73
  }
74
- export function DrawerActionBar({ onReject, onApprove, approveLabel, revisionPlaceholder, isProcessing = false, isRejecting = false, children, chatInput: controlledChatInput, onChatInputChange, }) {
74
+ export function DrawerActionBar({ onReject, onApprove, approveLabel, approveVariant = 'default', revisionPlaceholder, isProcessing = false, isRejecting = false, children, chatInput: controlledChatInput, onChatInputChange, }) {
75
+ const isWarning = approveVariant === 'warning';
76
+ const ApproveIcon = isWarning ? AlertTriangle : Check;
77
+ const accentBg = isWarning ? 'bg-orange-500/85' : 'bg-blue-500/85';
78
+ const accentBorder = isWarning ? 'border-orange-400/60' : 'border-blue-400/60';
75
79
  const [internalChatInput, setInternalChatInput] = useState('');
76
80
  const chatInput = controlledChatInput ?? internalChatInput;
77
81
  const setChatInput = onChatInputChange ?? setInternalChatInput;
@@ -271,12 +275,12 @@ export function DrawerActionBar({ onReject, onApprove, approveLabel, revisionPla
271
275
  }, []);
272
276
  const modKey = typeof navigator !== 'undefined' && /Mac/i.test(navigator.userAgent) ? '⌘' : 'Ctrl';
273
277
  return (_jsxs("div", { className: "border-border shrink-0 border-t", children: [children, onReject ? (_jsx(TooltipProvider, { delayDuration: 400, children: _jsx("form", { ref: formRef, onSubmit: handleFormSubmit, className: "p-3", children: _jsx("div", { role: "region", "aria-label": "File drop zone", "data-drag-over": isDragOver ? 'true' : 'false', onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, className: cn('rounded-md border-2 border-transparent transition-colors', isDragOver && 'border-primary/50 bg-primary/5'), children: _jsxs("div", { className: "border-input focus-within:ring-ring/50 focus-within:border-ring flex flex-col overflow-hidden rounded-md border shadow-xs transition-[color,box-shadow] focus-within:ring-[3px]", children: [_jsx(Textarea, { placeholder: revisionPlaceholder ?? 'Ask AI to revise...', "aria-label": revisionPlaceholder ?? 'Ask AI to revise...', disabled: disabled, value: chatInput, onChange: (e) => setChatInput(e.target.value), onKeyDown: handleKeyDown, onPaste: handlePaste, rows: 3, className: "max-h-[35dvh] min-h-0 flex-1 resize-none overflow-y-auto rounded-none border-0 shadow-none focus-visible:ring-0", "data-testid": "drawer-chat-input" }), attachments.length > 0 && (_jsx("div", { className: "flex flex-wrap items-center gap-1.5 px-3 py-2", children: attachments.map((file) => (_jsx(AttachmentChip, { name: file.name, size: file.size, mimeType: file.mimeType, path: file.path, onRemove: () => handleRemoveFile(file.id), disabled: disabled, loading: file.loading }, file.id))) })), uploadError ? (_jsx("p", { className: "text-destructive px-3 pb-2 text-xs", children: uploadError })) : null, _jsxs("div", { className: "border-input flex items-center gap-2 border-t px-3 py-1.5", children: [_jsxs("span", { className: "text-muted-foreground flex-1 truncate text-[11px]", children: [_jsxs("kbd", { className: "bg-muted rounded px-1 py-0.5 font-mono text-[10px]", children: [modKey, "+Enter"] }), ' ', hasText ? 'reject' : 'approve'] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: handleAddFiles, disabled: disabled, "aria-label": "Attach files", className: "text-muted-foreground hover:text-foreground cursor-pointer rounded p-1 transition-colors", children: _jsx(PaperclipIcon, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { side: "top", children: "Attach files" })] }), _jsx("div", { onMouseLeave: () => setHoverExpanded(false), children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "submit", disabled: disabled, "data-testid": "drawer-action-submit", className: cn('relative flex h-8 min-w-[10rem] cursor-pointer items-center overflow-hidden rounded-md border pr-10 pl-4 text-sm font-medium whitespace-nowrap transition-colors', 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50', approveExpanded
274
- ? 'border-blue-400/60 text-white'
278
+ ? `${accentBorder} text-white`
275
279
  : rejectHighlighted
276
280
  ? 'border-primary bg-muted ring-primary/30 shadow-sm ring-1'
277
- : 'border-border bg-muted/50 hover:bg-muted shadow-sm'), children: [_jsx("div", { className: "pointer-events-none absolute inset-0 bg-blue-500/85 transition-transform duration-300 ease-in-out", style: {
281
+ : 'border-border bg-muted/50 hover:bg-muted shadow-sm'), children: [_jsx("div", { className: cn('pointer-events-none absolute inset-0 transition-transform duration-300 ease-in-out', accentBg), style: {
278
282
  transform: approveExpanded ? 'translateX(0)' : 'translateX(100%)',
279
- } }), _jsxs("span", { className: cn('absolute inset-0 z-10 flex items-center justify-center gap-1.5 pr-8 transition-opacity duration-300', approveExpanded ? 'opacity-0' : 'opacity-100'), children: [_jsx(Send, { className: "h-3.5 w-3.5 shrink-0" }), "Reject"] }), _jsxs("span", { className: cn('absolute inset-0 z-10 flex items-center justify-center gap-1.5 text-white transition-opacity duration-300', approveExpanded ? 'opacity-100' : 'opacity-0'), children: [_jsx(Check, { className: "h-3.5 w-3.5 shrink-0" }), approveLabel] }), _jsx("span", { className: cn('border-input/60 absolute inset-y-0 right-0 z-20 flex w-8 cursor-pointer items-center justify-center rounded-r-[5px] border-l bg-blue-500/85 transition-opacity duration-300', !hasText && !hoverExpanded && 'pointer-events-none opacity-0'), onMouseEnter: () => setHoverExpanded(true), children: _jsx(ChevronLeft, { className: "h-3.5 w-3.5 text-white" }) })] }) }), _jsx(TooltipContent, { side: "top", children: approveExpanded ? approveLabel : 'Send revision feedback' })] }) })] })] }) }) }) })) : (_jsx("div", { className: "flex items-center gap-2 px-4 pb-4", children: _jsx(Button, { type: "button", className: "flex-1", disabled: disabled, onClick: () => {
283
+ } }), _jsxs("span", { className: cn('absolute inset-0 z-10 flex items-center justify-center gap-1.5 pr-8 transition-opacity duration-300', approveExpanded ? 'opacity-0' : 'opacity-100'), children: [_jsx(Send, { className: "h-3.5 w-3.5 shrink-0" }), "Reject"] }), _jsxs("span", { className: cn('absolute inset-0 z-10 flex items-center justify-center gap-1.5 text-white transition-opacity duration-300', approveExpanded ? 'opacity-100' : 'opacity-0'), children: [_jsx(ApproveIcon, { className: "h-3.5 w-3.5 shrink-0" }), approveLabel] }), _jsx("span", { className: cn(`border-input/60 absolute inset-y-0 right-0 z-20 flex w-8 cursor-pointer items-center justify-center rounded-r-[5px] border-l ${accentBg} transition-opacity duration-300`, !hasText && !hoverExpanded && 'pointer-events-none opacity-0'), onMouseEnter: () => setHoverExpanded(true), children: _jsx(ChevronLeft, { className: "h-3.5 w-3.5 text-white" }) })] }) }), !isWarning ? (_jsx(TooltipContent, { side: "top", children: approveExpanded ? approveLabel : 'Send revision feedback' })) : null] }) })] })] }) }) }) })) : (_jsx("div", { className: "flex items-center gap-2 px-4 pb-4", children: _jsx(Button, { type: "button", className: "flex-1", disabled: disabled, onClick: () => {
280
284
  approveSound.play();
281
285
  onApprove();
282
286
  }, children: approveLabel }) }))] }));
@@ -1 +1 @@
1
- {"version":3,"file":"activity-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/activity-tab.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACtB,MAAM,yCAAyC,CAAC;AA8CjD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iBAAiB,CAAC,EAAE,qBAAqB,EAAE,CAAC;CAC7C;AA6BD;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,eAAe,EAAE,EAC1B,QAAQ,CAAC,EAAE,qBAAqB,EAAE,GACjC,iBAAiB,EAAE,CAgErB;AAMD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,2CA4D3F"}
1
+ {"version":3,"file":"activity-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/activity-tab.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACtB,MAAM,yCAAyC,CAAC;AAIjD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iBAAiB,CAAC,EAAE,qBAAqB,EAAE,CAAC;CAC7C;AA6BD;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,eAAe,EAAE,EAC1B,QAAQ,CAAC,EAAE,qBAAqB,EAAE,GACjC,iBAAiB,EAAE,CAgErB;AAMD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,2CAyD3F"}
@@ -1,48 +1,8 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useEffect, useRef } from 'react';
4
3
  import { Loader2, AlertCircle, Clock } from 'lucide-react';
5
4
  import { InlineAttachments } from '../../common/inline-attachments/index.js';
6
5
  import { formatDuration } from '../../../lib/format-duration.js';
7
- /**
8
- * Computes the effective duration for a phase timing entry.
9
- * For completed phases, uses the server-provided durationMs.
10
- * For in-progress phases (has startedAt but no completedAt), computes
11
- * elapsed time client-side so the UI shows a live-updating timer.
12
- */
13
- function getEffectiveDuration(timing, now) {
14
- if (timing.durationMs != null && timing.durationMs > 0)
15
- return timing.durationMs;
16
- if (!timing.completedAt && timing.startedAt) {
17
- const started = new Date(timing.startedAt).getTime();
18
- if (!Number.isNaN(started))
19
- return Math.max(0, now - started);
20
- }
21
- return 0;
22
- }
23
- /** Returns true if any non-lifecycle phase is still in progress. */
24
- function hasRunningPhase(timings) {
25
- return timings.some((t) => !t.phase.startsWith('run:') && !t.completedAt && t.startedAt);
26
- }
27
- /** Hook that ticks every second while there are running phases. */
28
- function useTickingNow(timings) {
29
- const [now, setNow] = useState(Date.now);
30
- const intervalRef = useRef(null);
31
- useEffect(() => {
32
- const running = timings ? hasRunningPhase(timings) : false;
33
- if (running) {
34
- // Tick every second
35
- intervalRef.current = setInterval(() => setNow(Date.now()), 1000);
36
- }
37
- return () => {
38
- if (intervalRef.current) {
39
- clearInterval(intervalRef.current);
40
- intervalRef.current = null;
41
- }
42
- };
43
- }, [timings]);
44
- return now;
45
- }
46
6
  const NODE_TO_PHASE = {
47
7
  analyze: 'Analyzing',
48
8
  requirements: 'Requirements',
@@ -134,7 +94,6 @@ export function buildLifecycleTimeline(timings, feedback) {
134
94
  * Component
135
95
  * ------------------------------------------------------------------------- */
136
96
  export function ActivityTab({ timings, loading, error, rejectionFeedback }) {
137
- const now = useTickingNow(timings);
138
97
  if (loading) {
139
98
  return (_jsx("div", { "data-testid": "activity-tab-loading", className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) }));
140
99
  }
@@ -145,24 +104,24 @@ export function ActivityTab({ timings, loading, error, rejectionFeedback }) {
145
104
  return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-2 p-8", children: [_jsx(Clock, { className: "text-muted-foreground h-8 w-8" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "No activity recorded yet" })] }));
146
105
  }
147
106
  const nodeTimings = timings.filter((t) => !isLifecycleEvent(t.phase));
148
- const maxDurationMs = Math.max(...nodeTimings.map((t) => getEffectiveDuration(t, now)), ...nodeTimings.map((t) => t.approvalWaitMs ?? 0), 0);
107
+ const maxDurationMs = Math.max(...nodeTimings.map((t) => t.durationMs ?? 0), ...nodeTimings.map((t) => t.approvalWaitMs ?? 0), 0);
149
108
  const iterations = buildLifecycleTimeline(timings, rejectionFeedback);
150
109
  const hasMultipleIterations = iterations.length > 1;
151
- const totalExecMs = nodeTimings.reduce((sum, t) => sum + getEffectiveDuration(t, now), 0);
110
+ const totalExecMs = nodeTimings.reduce((sum, t) => sum + (t.durationMs ?? 0), 0);
152
111
  const totalWaitMs = nodeTimings.reduce((sum, t) => sum + (t.approvalWaitMs ?? 0), 0);
153
- return (_jsxs("div", { className: "flex flex-col gap-4 p-4", children: [_jsx("div", { "data-testid": "activity-timings", className: "flex flex-col gap-3", children: iterations.map((iteration) => (_jsx(IterationGroup, { iteration: iteration, showHeader: hasMultipleIterations, maxDurationMs: maxDurationMs, now: now }, iteration.number))) }), totalExecMs > 0 ? (_jsx(SummaryTotals, { totalExecMs: totalExecMs, totalWaitMs: totalWaitMs })) : null] }));
112
+ return (_jsxs("div", { className: "flex flex-col gap-4 p-4", children: [_jsx("div", { "data-testid": "activity-timings", className: "flex flex-col gap-3", children: iterations.map((iteration) => (_jsx(IterationGroup, { iteration: iteration, showHeader: hasMultipleIterations, maxDurationMs: maxDurationMs }, iteration.number))) }), totalExecMs > 0 ? (_jsx(SummaryTotals, { totalExecMs: totalExecMs, totalWaitMs: totalWaitMs })) : null] }));
154
113
  }
155
114
  /* ---------------------------------------------------------------------------
156
115
  * Iteration group — one cycle of work
157
116
  * ------------------------------------------------------------------------- */
158
- function IterationGroup({ iteration, showHeader, maxDurationMs, now, }) {
117
+ function IterationGroup({ iteration, showHeader, maxDurationMs, }) {
159
118
  return (_jsxs("div", { "data-testid": `iteration-${iteration.number}`, className: "flex flex-col gap-1.5", children: [showHeader ? (_jsxs("div", { className: "text-muted-foreground text-xs font-medium", children: ["Iteration ", iteration.number] })) : null, iteration.timings.map((t) => {
160
119
  if (isLifecycleEvent(t.phase)) {
161
120
  // For run:rejected, the message comes from the iteration, not a separate map
162
121
  const isRejection = t.phase === 'run:rejected';
163
122
  return (_jsx(LifecycleEventRow, { timing: t, message: isRejection ? iteration.rejectionMessage : undefined, attachments: isRejection ? iteration.rejectionAttachments : undefined }, `${t.agentRunId}-${t.phase}-${t.startedAt}`));
164
123
  }
165
- return (_jsx(NodeTimingRow, { timing: t, maxDurationMs: maxDurationMs, now: now }, `${t.agentRunId}-${t.phase}-${t.startedAt}`));
124
+ return (_jsx(NodeTimingRow, { timing: t, maxDurationMs: maxDurationMs }, `${t.agentRunId}-${t.phase}-${t.startedAt}`));
166
125
  })] }));
167
126
  }
168
127
  /* ---------------------------------------------------------------------------
@@ -175,15 +134,14 @@ function LifecycleEventRow({ timing, message, attachments, }) {
175
134
  const hasAttachments = attachments && attachments.length > 0;
176
135
  return (_jsxs("div", { className: `text-xs ${event.colorClass}`, children: [_jsx("span", { children: event.label }), message ? (_jsxs("span", { "data-testid": "rejection-feedback-text", className: "text-muted-foreground ml-2 font-normal italic", children: ["\u2014 ", message] })) : null, hasAttachments ? (_jsx("div", { "data-testid": "rejection-feedback-attachments", className: "mt-1.5 ml-2", children: _jsx(InlineAttachments, { text: "", attachmentPaths: attachments }) })) : null] }));
177
136
  }
178
- function NodeTimingRow({ timing, maxDurationMs, now, }) {
137
+ function NodeTimingRow({ timing, maxDurationMs, }) {
179
138
  const label = timing.phase.includes(':')
180
139
  ? `rev ${timing.phase.split(':')[1]}`
181
140
  : (NODE_TO_PHASE[timing.phase] ?? timing.phase);
182
- const durationMs = getEffectiveDuration(timing, now);
141
+ const durationMs = timing.durationMs ?? 0;
183
142
  const barPercent = maxDurationMs > 0 ? Math.max(2, (durationMs / maxDurationMs) * 100) : 2;
184
- const isRunning = !timing.completedAt && !!timing.startedAt;
185
143
  const barColorClass = timing.completedAt ? 'bg-emerald-500' : 'bg-blue-500';
186
- return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { "data-testid": `timing-bar-${timing.phase}`, className: "flex items-center gap-3", children: [_jsx("span", { className: "text-muted-foreground w-24 shrink-0 text-xs", children: label }), _jsx("div", { className: "bg-muted h-3 flex-1 overflow-hidden rounded-full", children: _jsx("div", { className: `h-full rounded-full ${barColorClass}${isRunning ? 'animate-pulse' : ''}`, style: { width: `${Math.min(barPercent, 100)}%` } }) }), _jsx("span", { className: "text-muted-foreground w-14 shrink-0 text-right text-xs", children: formatDuration(durationMs) })] }), timing.approvalWaitMs != null && timing.approvalWaitMs > 0 ? (_jsx(ApprovalWaitRow, { timing: timing, maxDurationMs: maxDurationMs })) : null] }));
144
+ return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { "data-testid": `timing-bar-${timing.phase}`, className: "flex items-center gap-3", children: [_jsx("span", { className: "text-muted-foreground w-24 shrink-0 text-xs", children: label }), _jsx("div", { className: "bg-muted h-3 flex-1 overflow-hidden rounded-full", children: _jsx("div", { className: `h-full rounded-full ${barColorClass}`, style: { width: `${Math.min(barPercent, 100)}%` } }) }), _jsx("span", { className: "text-muted-foreground w-14 shrink-0 text-right text-xs", children: formatDuration(durationMs) })] }), timing.approvalWaitMs != null && timing.approvalWaitMs > 0 ? (_jsx(ApprovalWaitRow, { timing: timing, maxDurationMs: maxDurationMs })) : null] }));
187
145
  }
188
146
  function ApprovalWaitRow({ timing, maxDurationMs, }) {
189
147
  const waitMs = timing.approvalWaitMs ?? 0;
@@ -1,4 +1,3 @@
1
- import type { NotificationEvent } from '../../../../../../packages/core/src/domain/generated/output.js';
2
1
  import type { FeatureNodeData } from '../../common/feature-node/index.js';
3
2
  import type { PrdQuestionnaireData } from '../../common/prd-questionnaire/index.js';
4
3
  import type { TechDecisionsReviewData } from '../../common/tech-decisions-review/index.js';
@@ -12,8 +11,6 @@ export interface FeatureDrawerTabsProps {
12
11
  initialTab?: FeatureTabKey;
13
12
  /** Tab key from URL path segment (e.g. /feature/[id]/activity → 'activity'). */
14
13
  urlTab?: FeatureTabKey;
15
- /** SSE events from the agent events provider, used to trigger tab data refresh. */
16
- sseEvents?: readonly NotificationEvent[];
17
14
  prdData?: PrdQuestionnaireData | null;
18
15
  prdSelections?: Record<string, string>;
19
16
  onPrdSelect?: (questionId: string, optionId: string) => void;
@@ -33,5 +30,5 @@ export interface FeatureDrawerTabsProps {
33
30
  chatInput?: string;
34
31
  onChatInputChange?: (value: string) => void;
35
32
  }
36
- export declare function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab, prdData, prdSelections, onPrdSelect, onPrdApprove, onPrdReject, isPrdLoading, techData, onTechApprove, onTechReject, isTechLoading, productData, mergeData, onMergeApprove, onMergeReject, isMergeLoading, isRejecting, chatInput, onChatInputChange, sseEvents, }: FeatureDrawerTabsProps): import("react/jsx-runtime").JSX.Element;
33
+ export declare function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab, prdData, prdSelections, onPrdSelect, onPrdApprove, onPrdReject, isPrdLoading, techData, onTechApprove, onTechReject, isTechLoading, productData, mergeData, onMergeApprove, onMergeReject, isMergeLoading, isRejecting, chatInput, onChatInputChange, }: FeatureDrawerTabsProps): import("react/jsx-runtime").JSX.Element;
37
34
  //# sourceMappingURL=feature-drawer-tabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAS9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAQ9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AAiD3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,gFAAgF;IAChF,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAGzC,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,MAAM,EACN,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,SAAS,GACV,EAAE,sBAAsB,2CAwTxB"}
1
+ {"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAQ9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AAiD3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,gFAAgF;IAChF,MAAM,CAAC,EAAE,aAAa,CAAC;IAGvB,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,MAAM,EACN,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,GAClB,EAAE,sBAAsB,2CAmSxB"}
@@ -64,7 +64,7 @@ const TAB_FETCHERS = {
64
64
  activity: fetchActivity,
65
65
  plan: fetchPlan,
66
66
  };
67
- export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab, prdData, prdSelections, onPrdSelect, onPrdApprove, onPrdReject, isPrdLoading, techData, onTechApprove, onTechReject, isTechLoading, productData, mergeData, onMergeApprove, onMergeReject, isMergeLoading, isRejecting, chatInput, onChatInputChange, sseEvents, }) {
67
+ export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab, prdData, prdSelections, onPrdSelect, onPrdApprove, onPrdReject, isPrdLoading, techData, onTechApprove, onTechReject, isTechLoading, productData, mergeData, onMergeApprove, onMergeReject, isMergeLoading, isRejecting, chatInput, onChatInputChange, }) {
68
68
  const pathname = usePathname();
69
69
  const featureLogs = useFeatureLogs(featureId);
70
70
  const visibleTabs = useMemo(() => computeVisibleTabs(featureNode), [featureNode]);
@@ -159,7 +159,6 @@ export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab,
159
159
  }, [featureId]);
160
160
  // When initialTab changes (e.g. SSE updates lifecycle), switch to it if visible
161
161
  // and sync the URL with replaceState so the address bar reflects the new tab.
162
- // Also trigger lazy fetch for the new tab so data is ready immediately.
163
162
  const prevInitialTabRef = useRef(initialTab);
164
163
  useEffect(() => {
165
164
  if (prevInitialTabRef.current !== initialTab &&
@@ -167,17 +166,13 @@ export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab,
167
166
  visibleTabs.includes(initialTab)) {
168
167
  prevInitialTabRef.current = initialTab;
169
168
  setActiveTab(initialTab);
170
- // Trigger lazy fetch for the new tab if it's a lazy-loaded tab
171
- if (initialTab === 'activity' || initialTab === 'plan') {
172
- fetchTab(initialTab);
173
- }
174
169
  // Sync URL to match the new tab
175
170
  const targetUrl = initialTab === 'overview' ? basePath : `${basePath}/${initialTab}`;
176
171
  if (targetUrl !== window.location.pathname) {
177
172
  window.history.replaceState(null, '', targetUrl);
178
173
  }
179
174
  }
180
- }, [initialTab, visibleTabs, basePath, fetchTab]);
175
+ }, [initialTab, visibleTabs, basePath]);
181
176
  // If the active tab becomes invisible (lifecycle changed), fall back to overview
182
177
  // and sync the URL accordingly.
183
178
  useEffect(() => {
@@ -188,34 +183,19 @@ export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab,
188
183
  }
189
184
  }
190
185
  }, [visibleTabs, activeTab, basePath]);
191
- // SSE refresh: re-fetch lazy tab data when relevant SSE events arrive
192
- // for this feature (e.g. PhaseCompleted, AgentStarted, AgentCompleted).
193
- // Always refresh 'activity' data (even if not the active tab) so switching
194
- // to the activity tab shows up-to-date timings without a loading flash.
186
+ // SSE refresh: re-fetch active lazy tab when featureNode reference changes
187
+ const featureNodeRef = useRef(featureNode);
195
188
  const activeTabRef = useRef(activeTab);
196
189
  activeTabRef.current = activeTab;
197
- const sseProcessedRef = useRef(0);
198
190
  useEffect(() => {
199
- if (!sseEvents || sseEvents.length === 0)
200
- return;
201
- // Clamp cursor if events were pruned
202
- if (sseProcessedRef.current > sseEvents.length) {
203
- sseProcessedRef.current = 0;
204
- }
205
- if (sseEvents.length <= sseProcessedRef.current)
206
- return;
207
- const newEvents = sseEvents.slice(sseProcessedRef.current);
208
- sseProcessedRef.current = sseEvents.length;
209
- const hasRelevantEvent = newEvents.some((e) => e.featureId === featureId);
210
- if (!hasRelevantEvent)
211
- return;
212
- // Always refresh activity data so it stays current for when the user switches tabs
213
- refreshTab('activity');
214
- const current = activeTabRef.current;
215
- if (current === 'plan') {
216
- refreshTab(current);
191
+ if (featureNodeRef.current !== featureNode) {
192
+ featureNodeRef.current = featureNode;
193
+ const current = activeTabRef.current;
194
+ if (current === 'activity' || current === 'plan') {
195
+ refreshTab(current);
196
+ }
217
197
  }
218
- }, [sseEvents, featureId, refreshTab]);
198
+ }, [featureNode, refreshTab]);
219
199
  const handleTabChange = useCallback((value) => {
220
200
  const tab = value;
221
201
  isUserInteraction.current = true;
@@ -1 +1 @@
1
- {"version":3,"file":"overview-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAOxE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAwCrD"}
1
+ {"version":3,"file":"overview-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAwCrD"}
@@ -1,7 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useEffect, useRef } from 'react';
4
- import { ExternalLink, GitBranch, GitCommitHorizontal, Zap } from 'lucide-react';
3
+ import { AlertTriangle, ExternalLink, GitBranch, GitCommitHorizontal, Zap } from 'lucide-react';
5
4
  import { InlineAttachments } from '../../common/inline-attachments/index.js';
6
5
  import { PrStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
7
6
  import { cn } from '../../../lib/utils.js';
@@ -11,7 +10,6 @@ import { CiStatusBadge } from '../../common/ci-status-badge/index.js';
11
10
  import { CometSpinner } from '../../ui/comet-spinner.js';
12
11
  import { featureNodeStateConfig, lifecycleDisplayLabels } from '../../common/feature-node/index.js';
13
12
  import { getAgentTypeIcon, agentTypeLabels, } from '../../common/feature-node/agent-type-icons.js';
14
- import { formatDuration } from '../../../lib/format-duration.js';
15
13
  export function OverviewTab({ data }) {
16
14
  const isCompleted = data.lifecycle === 'maintain';
17
15
  return (_jsxs(_Fragment, { 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[data.lifecycle] }), _jsx(FeatureStateBadge, { data: data }), !isCompleted && data.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: [data.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[data.state].progressClass), style: { width: `${data.progress}%` } }) })] })) : null, isCompleted && data.pr ? _jsx(FeaturePrInfo, { pr: data.pr }) : null] }), _jsx(FeatureInfo, { data: data }), !isCompleted && data.pr ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx("div", { className: "p-4", children: _jsx(FeaturePrInfo, { pr: data.pr }) })] })) : null, _jsx(FeatureDetails, { data: data })] }));
@@ -62,45 +60,14 @@ const prStatusStyles = {
62
60
  [PrStatus.Closed]: 'border-transparent bg-red-50 text-red-700 hover:bg-red-50',
63
61
  };
64
62
  function FeaturePrInfo({ pr }) {
65
- return (_jsx("div", { "data-testid": "feature-drawer-pr", children: _jsxs("div", { className: "space-y-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] }) }));
63
+ return (_jsx("div", { "data-testid": "feature-drawer-pr", children: _jsxs("div", { className: "space-y-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.mergeable === false ? (_jsxs("div", { "data-testid": "pr-merge-conflict", className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Merge Status" }), _jsxs(Badge, { className: "border-transparent bg-orange-50 text-orange-700 hover:bg-orange-50", children: [_jsx(AlertTriangle, { className: "mr-1 h-3.5 w-3.5" }), "Conflicts"] })] })) : 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] }) }));
66
64
  }
67
65
  // ── Details section ──────────────────────────────────────────────────
68
- /** Hook that returns a live-updating elapsed time string for running features. */
69
- function useElapsedTime(startedAt) {
70
- const [elapsed, setElapsed] = useState(null);
71
- const intervalRef = useRef(null);
72
- useEffect(() => {
73
- if (!startedAt) {
74
- setElapsed(null);
75
- return;
76
- }
77
- // Compute immediately
78
- setElapsed(formatDuration(Math.max(0, Date.now() - startedAt)));
79
- // Tick every second
80
- intervalRef.current = setInterval(() => {
81
- setElapsed(formatDuration(Math.max(0, Date.now() - startedAt)));
82
- }, 1000);
83
- return () => {
84
- if (intervalRef.current) {
85
- clearInterval(intervalRef.current);
86
- intervalRef.current = null;
87
- }
88
- };
89
- }, [startedAt]);
90
- return elapsed;
91
- }
92
66
  function FeatureDetails({ data }) {
93
- const isRunning = data.state === 'running' || data.state === 'action-required';
94
- const elapsedTime = useElapsedTime(isRunning ? data.startedAt : undefined);
95
- const hasAnyDetail = data.fastMode ??
96
- data.agentType ??
97
- data.runtime ??
98
- elapsedTime ??
99
- data.blockedBy ??
100
- data.errorMessage;
67
+ const hasAnyDetail = data.fastMode ?? data.agentType ?? data.runtime ?? data.blockedBy ?? data.errorMessage;
101
68
  if (!hasAnyDetail)
102
69
  return null;
103
- return (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { "data-testid": "feature-drawer-details", className: "flex flex-col gap-3 p-4", children: [data.fastMode ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Mode" }), _jsxs("span", { className: "flex items-center gap-2 text-sm", children: [_jsx(Zap, { className: "h-4 w-4 shrink-0 text-amber-500" }), "Fast Mode"] })] })) : null, data.agentType ? _jsx(AgentDetailRow, { agentType: data.agentType }) : null, data.runtime ? _jsx(DetailRow, { label: "Runtime", value: data.runtime }) : null, !data.runtime && elapsedTime ? (_jsx(DetailRow, { label: "Running for", value: elapsedTime })) : null, data.blockedBy ? _jsx(DetailRow, { label: "Blocked by", value: data.blockedBy }) : null, data.errorMessage ? _jsx(DetailRow, { label: "Error", value: data.errorMessage }) : null] })] }));
70
+ return (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { "data-testid": "feature-drawer-details", className: "flex flex-col gap-3 p-4", children: [data.fastMode ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Mode" }), _jsxs("span", { className: "flex items-center gap-2 text-sm", children: [_jsx(Zap, { className: "h-4 w-4 shrink-0 text-amber-500" }), "Fast Mode"] })] })) : null, data.agentType ? _jsx(AgentDetailRow, { agentType: 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] })] }));
104
71
  }
105
72
  function AgentDetailRow({ agentType }) {
106
73
  const Icon = getAgentTypeIcon(agentType);
@@ -27,6 +27,8 @@ export declare const ResearchPhase: Story;
27
27
  export declare const ReviewPhase: Story;
28
28
  /** Maintain phase. */
29
29
  export declare const MaintainPhase: Story;
30
+ /** PR with merge conflicts — shows orange "Conflicts" badge. */
31
+ export declare const PrWithMergeConflicts: Story;
30
32
  /** Completed feature with PR — progress hidden, PR shown in status section without borders. */
31
33
  export declare const CompletedWithPr: Story;
32
34
  //# sourceMappingURL=overview-tab.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"overview-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAclC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,WAAW,CAAC,CAAC;AA0G1C,uEAAuE;AACvE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAwBF,mEAAmE;AACnE,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAMF,0BAA0B;AAC1B,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,oBAAoB;AACpB,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,eAAe,EAAE,KAgB7B,CAAC"}
1
+ {"version":3,"file":"overview-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAclC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,WAAW,CAAC,CAAC;AA0G1C,uEAAuE;AACvE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAwBF,mEAAmE;AACnE,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAMF,0BAA0B;AAC1B,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,oBAAoB;AACpB,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,EAAE,KAclC,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,eAAe,EAAE,KAgB7B,CAAC"}