@shepai/cli 1.78.1 → 1.79.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 (292) hide show
  1. package/dist/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.d.ts.map +1 -1
  2. package/dist/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.js +14 -1
  3. package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts +17 -0
  4. package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts.map +1 -0
  5. package/dist/src/presentation/web/app/actions/get-feature-phase-timings.js +25 -0
  6. package/dist/src/presentation/web/app/actions/get-feature-plan.d.ts +18 -0
  7. package/dist/src/presentation/web/app/actions/get-feature-plan.d.ts.map +1 -0
  8. package/dist/src/presentation/web/app/actions/get-feature-plan.js +31 -0
  9. package/dist/src/presentation/web/app/api/feature-logs/route.d.ts +16 -0
  10. package/dist/src/presentation/web/app/api/feature-logs/route.d.ts.map +1 -0
  11. package/dist/src/presentation/web/app/api/feature-logs/route.js +184 -0
  12. package/dist/src/presentation/web/app/build-feature-node-data.d.ts +7 -1
  13. package/dist/src/presentation/web/app/build-feature-node-data.d.ts.map +1 -1
  14. package/dist/src/presentation/web/app/build-feature-node-data.js +7 -1
  15. package/dist/src/presentation/web/app/build-graph-nodes.js +7 -3
  16. package/dist/src/presentation/web/app/settings/page.js +1 -1
  17. package/dist/src/presentation/web/components/common/control-center-drawer/drawer-view.d.ts +7 -19
  18. package/dist/src/presentation/web/components/common/control-center-drawer/drawer-view.d.ts.map +1 -1
  19. package/dist/src/presentation/web/components/common/control-center-drawer/drawer-view.js +6 -6
  20. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  21. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +48 -85
  22. package/dist/src/presentation/web/components/common/feature-drawer/index.d.ts +1 -1
  23. package/dist/src/presentation/web/components/common/feature-drawer/index.d.ts.map +1 -1
  24. package/dist/src/presentation/web/components/common/feature-drawer/index.js +1 -1
  25. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts +8 -0
  26. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts.map +1 -0
  27. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.js +90 -0
  28. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.d.ts +20 -0
  29. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.d.ts.map +1 -0
  30. package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.js +252 -0
  31. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts +31 -0
  32. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts.map +1 -0
  33. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js +123 -0
  34. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.stories.d.ts +20 -0
  35. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.stories.d.ts.map +1 -0
  36. package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.stories.js +315 -0
  37. package/dist/src/presentation/web/components/common/feature-drawer-tabs/index.d.ts +3 -0
  38. package/dist/src/presentation/web/components/common/feature-drawer-tabs/index.d.ts.map +1 -0
  39. package/dist/src/presentation/web/components/common/feature-drawer-tabs/index.js +1 -0
  40. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.d.ts +7 -0
  41. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.d.ts.map +1 -0
  42. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.js +35 -0
  43. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts +18 -0
  44. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts.map +1 -0
  45. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.js +89 -0
  46. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.d.ts +6 -0
  47. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.d.ts.map +1 -0
  48. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.js +78 -0
  49. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.d.ts +28 -0
  50. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.d.ts.map +1 -0
  51. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.js +157 -0
  52. package/dist/src/presentation/web/components/common/feature-drawer-tabs/plan-tab.d.ts +8 -0
  53. package/dist/src/presentation/web/components/common/feature-drawer-tabs/plan-tab.d.ts.map +1 -0
  54. package/dist/src/presentation/web/components/common/feature-drawer-tabs/plan-tab.js +40 -0
  55. package/dist/src/presentation/web/components/common/feature-drawer-tabs/plan-tab.stories.d.ts +22 -0
  56. package/dist/src/presentation/web/components/common/feature-drawer-tabs/plan-tab.stories.d.ts.map +1 -0
  57. package/dist/src/presentation/web/components/common/feature-drawer-tabs/plan-tab.stories.js +188 -0
  58. package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.d.ts +30 -0
  59. package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.d.ts.map +1 -0
  60. package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.js +100 -0
  61. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +12 -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/index.d.ts +3 -4
  64. package/dist/src/presentation/web/components/common/index.d.ts.map +1 -1
  65. package/dist/src/presentation/web/components/common/index.js +3 -4
  66. package/dist/src/presentation/web/components/common/merge-review/index.d.ts +1 -2
  67. package/dist/src/presentation/web/components/common/merge-review/index.d.ts.map +1 -1
  68. package/dist/src/presentation/web/components/common/merge-review/index.js +0 -1
  69. package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts +0 -8
  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 +1 -33
  72. package/dist/src/presentation/web/components/common/prd-questionnaire/index.d.ts +1 -2
  73. package/dist/src/presentation/web/components/common/prd-questionnaire/index.d.ts.map +1 -1
  74. package/dist/src/presentation/web/components/common/prd-questionnaire/index.js +0 -1
  75. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts +0 -10
  76. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts.map +1 -1
  77. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.js +1 -38
  78. package/dist/src/presentation/web/components/common/tech-decisions-review/index.d.ts +1 -2
  79. package/dist/src/presentation/web/components/common/tech-decisions-review/index.d.ts.map +1 -1
  80. package/dist/src/presentation/web/components/common/tech-decisions-review/index.js +0 -1
  81. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.d.ts +0 -8
  82. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.d.ts.map +1 -1
  83. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.js +1 -29
  84. package/dist/src/presentation/web/components/features/settings/AgentModelPicker/index.js +2 -2
  85. package/dist/src/presentation/web/components/features/settings/settings-page-client.js +9 -9
  86. package/dist/src/presentation/web/hooks/use-feature-logs.d.ts +7 -0
  87. package/dist/src/presentation/web/hooks/use-feature-logs.d.ts.map +1 -0
  88. package/dist/src/presentation/web/hooks/use-feature-logs.js +52 -0
  89. package/dist/tsconfig.build.tsbuildinfo +1 -1
  90. package/package.json +1 -1
  91. package/web/.next/BUILD_ID +1 -1
  92. package/web/.next/app-path-routes-manifest.json +1 -0
  93. package/web/.next/build-manifest.json +2 -2
  94. package/web/.next/fallback-build-manifest.json +2 -2
  95. package/web/.next/prerender-manifest.json +3 -3
  96. package/web/.next/required-server-files.js +1 -1
  97. package/web/.next/required-server-files.json +1 -1
  98. package/web/.next/routes-manifest.json +6 -0
  99. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +18 -18
  100. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  101. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  102. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +68 -38
  103. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
  104. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  105. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  106. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  107. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  108. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  109. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +18 -18
  110. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  111. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  112. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +68 -38
  113. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
  114. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  115. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  116. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +14 -14
  117. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  118. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  119. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  120. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  121. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  122. package/web/.next/server/app/_global-error.html +2 -2
  123. package/web/.next/server/app/_global-error.rsc +1 -1
  124. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  125. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  126. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  127. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  128. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  129. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  130. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  131. package/web/.next/server/app/api/feature-logs/route/app-paths-manifest.json +3 -0
  132. package/web/.next/server/app/api/feature-logs/route/build-manifest.json +11 -0
  133. package/web/.next/server/app/api/feature-logs/route/server-reference-manifest.json +4 -0
  134. package/web/.next/server/app/api/feature-logs/route.js +6 -0
  135. package/web/.next/server/app/api/feature-logs/route.js.map +5 -0
  136. package/web/.next/server/app/api/feature-logs/route.js.nft.json +1 -0
  137. package/web/.next/server/app/api/feature-logs/route_client-reference-manifest.js +2 -0
  138. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  139. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  140. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  141. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  142. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  143. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  144. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  145. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  146. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  147. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  148. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  149. package/web/.next/server/app-paths-manifest.json +1 -0
  150. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_feature-logs_route_actions_177445e7.js +3 -0
  151. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_feature-logs_route_actions_177445e7.js.map +1 -0
  152. package/web/.next/server/chunks/[root-of-the-server]__91d44424._.js +12 -0
  153. package/web/.next/server/chunks/[root-of-the-server]__91d44424._.js.map +1 -0
  154. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  155. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  156. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +1 -1
  157. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js.map +1 -1
  158. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +1 -1
  159. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js.map +1 -1
  160. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  161. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  162. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  163. package/web/.next/server/chunks/ssr/[root-of-the-server]__4be9a9bb._.js +1 -1
  164. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  165. package/web/.next/server/chunks/ssr/[root-of-the-server]__6eb2a2b0._.js +1 -1
  166. package/web/.next/server/chunks/ssr/[root-of-the-server]__6eb2a2b0._.js.map +1 -1
  167. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  168. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  169. package/web/.next/server/chunks/ssr/{[root-of-the-server]__a337ca5c._.js → [root-of-the-server]__ae824a5b._.js} +2 -2
  170. package/web/.next/server/chunks/ssr/[root-of-the-server]__ae824a5b._.js.map +1 -0
  171. package/web/.next/server/chunks/ssr/[root-of-the-server]__b3a4cef4._.js +1 -1
  172. package/web/.next/server/chunks/ssr/[root-of-the-server]__b3a4cef4._.js.map +1 -1
  173. package/web/.next/server/chunks/ssr/[root-of-the-server]__c3c963c6._.js +1 -1
  174. package/web/.next/server/chunks/ssr/[root-of-the-server]__c3c963c6._.js.map +1 -1
  175. package/web/.next/server/chunks/ssr/[root-of-the-server]__f0d8d054._.js +2 -2
  176. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  177. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  178. package/web/.next/server/chunks/ssr/_1e3cf73b._.js +1 -1
  179. package/web/.next/server/chunks/ssr/_1e3cf73b._.js.map +1 -1
  180. package/web/.next/server/chunks/ssr/_34fbed18._.js +1 -1
  181. package/web/.next/server/chunks/ssr/_34fbed18._.js.map +1 -1
  182. package/web/.next/server/chunks/ssr/{_06db7efd._.js → _3e88ce9d._.js} +2 -2
  183. package/web/.next/server/chunks/ssr/{_06db7efd._.js.map → _3e88ce9d._.js.map} +1 -1
  184. package/web/.next/server/chunks/ssr/_5d4e7151._.js +3 -0
  185. package/web/.next/server/chunks/ssr/{_5c4ce700._.js.map → _5d4e7151._.js.map} +1 -1
  186. package/web/.next/server/chunks/ssr/_63868199._.js +1 -1
  187. package/web/.next/server/chunks/ssr/_63868199._.js.map +1 -1
  188. package/web/.next/server/chunks/ssr/{_b0924a46._.js → _83cf28a3._.js} +2 -2
  189. package/web/.next/server/chunks/ssr/{_b0924a46._.js.map → _83cf28a3._.js.map} +1 -1
  190. package/web/.next/server/chunks/ssr/{_4031d614._.js → _887258d0._.js} +2 -2
  191. package/web/.next/server/chunks/ssr/{_4031d614._.js.map → _887258d0._.js.map} +1 -1
  192. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  193. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  194. package/web/.next/server/chunks/ssr/_acb6a73d._.js +3 -0
  195. package/web/.next/server/chunks/ssr/{_a38f282a._.js.map → _acb6a73d._.js.map} +1 -1
  196. package/web/.next/server/chunks/ssr/{_5dab501b._.js → _ba97cfd3._.js} +2 -2
  197. package/web/.next/server/chunks/ssr/{_5dab501b._.js.map → _ba97cfd3._.js.map} +1 -1
  198. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  199. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  200. package/web/.next/server/chunks/ssr/node_modules__pnpm_d80c1060._.js +3 -0
  201. package/web/.next/server/chunks/ssr/node_modules__pnpm_d80c1060._.js.map +1 -0
  202. package/web/.next/server/chunks/ssr/src_presentation_web_7efa14ca._.js +3 -0
  203. package/web/.next/server/chunks/ssr/src_presentation_web_7efa14ca._.js.map +1 -0
  204. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js +1 -1
  205. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js.map +1 -1
  206. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  207. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  208. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  209. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  210. package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js +1 -1
  211. package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js.map +1 -1
  212. package/web/.next/server/chunks/ssr/src_presentation_web_b59d79db._.js +3 -0
  213. package/web/.next/server/chunks/ssr/src_presentation_web_b59d79db._.js.map +1 -0
  214. package/web/.next/server/chunks/ssr/src_presentation_web_c4348b8a._.js +2 -2
  215. package/web/.next/server/chunks/ssr/src_presentation_web_c4348b8a._.js.map +1 -1
  216. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  217. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  218. package/web/.next/server/chunks/ssr/src_presentation_web_e4510d10._.js +2 -2
  219. package/web/.next/server/chunks/ssr/src_presentation_web_e4510d10._.js.map +1 -1
  220. package/web/.next/server/pages/500.html +2 -2
  221. package/web/.next/server/server-reference-manifest.js +1 -1
  222. package/web/.next/server/server-reference-manifest.json +108 -64
  223. package/web/.next/static/chunks/{87152e918f80ea8b.js → 297458261f67218c.js} +1 -1
  224. package/web/.next/static/chunks/{1f57d0c949dbb44d.js → 2a24ac257fc1c10b.js} +1 -1
  225. package/web/.next/static/chunks/352e25e1bb2b9edb.js +1 -0
  226. package/web/.next/static/chunks/{8fe834f8a3c36e2f.js → 47ecde22e9663419.js} +2 -2
  227. package/web/.next/static/chunks/{27c4a8493483e6f3.js → 49743c83c9bced40.js} +1 -1
  228. package/web/.next/static/chunks/4b20d522b4f5ca7e.js +1 -0
  229. package/web/.next/static/chunks/{9d8c6c874071efb2.js → 5688494bf052915d.js} +1 -1
  230. package/web/.next/static/chunks/77a956d5dd063fef.js +1 -0
  231. package/web/.next/static/chunks/{78455afb0164395c.js → 8eff15a7f35164f9.js} +2 -2
  232. package/web/.next/static/chunks/96bab6d3820504f3.css +2 -0
  233. package/web/.next/static/chunks/a1c2ecb710b44081.js +1 -0
  234. package/web/.next/static/chunks/{6f7ba7846dcc8b21.js → d8d464c156573994.js} +1 -1
  235. package/web/.next/static/chunks/e29d1e26c2694f78.js +1 -0
  236. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.d.ts +0 -9
  237. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.d.ts.map +0 -1
  238. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.js +0 -60
  239. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.d.ts +0 -47
  240. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.d.ts.map +0 -1
  241. package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.js +0 -307
  242. package/dist/src/presentation/web/components/common/merge-review/merge-review-drawer.d.ts +0 -3
  243. package/dist/src/presentation/web/components/common/merge-review/merge-review-drawer.d.ts.map +0 -1
  244. package/dist/src/presentation/web/components/common/merge-review/merge-review-drawer.js +0 -8
  245. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-drawer.d.ts +0 -3
  246. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-drawer.d.ts.map +0 -1
  247. package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-drawer.js +0 -8
  248. package/dist/src/presentation/web/components/common/review-drawer-shell/index.d.ts +0 -3
  249. package/dist/src/presentation/web/components/common/review-drawer-shell/index.d.ts.map +0 -1
  250. package/dist/src/presentation/web/components/common/review-drawer-shell/index.js +0 -1
  251. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell-config.d.ts +0 -26
  252. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell-config.d.ts.map +0 -1
  253. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell-config.js +0 -1
  254. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.d.ts +0 -3
  255. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.d.ts.map +0 -1
  256. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.js +0 -29
  257. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.d.ts +0 -14
  258. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.d.ts.map +0 -1
  259. package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.stories.js +0 -33
  260. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-drawer.d.ts +0 -3
  261. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-drawer.d.ts.map +0 -1
  262. package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-drawer.js +0 -8
  263. package/dist/src/presentation/web/components/common/tech-review-tabs/index.d.ts +0 -3
  264. package/dist/src/presentation/web/components/common/tech-review-tabs/index.d.ts.map +0 -1
  265. package/dist/src/presentation/web/components/common/tech-review-tabs/index.js +0 -1
  266. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.d.ts +0 -21
  267. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.d.ts.map +0 -1
  268. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.js +0 -1
  269. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.d.ts +0 -3
  270. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.d.ts.map +0 -1
  271. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.js +0 -12
  272. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.stories.d.ts +0 -16
  273. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.stories.d.ts.map +0 -1
  274. package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.stories.js +0 -110
  275. package/web/.next/server/chunks/ssr/[root-of-the-server]__a337ca5c._.js.map +0 -1
  276. package/web/.next/server/chunks/ssr/_5c4ce700._.js +0 -3
  277. package/web/.next/server/chunks/ssr/_a38f282a._.js +0 -3
  278. package/web/.next/server/chunks/ssr/node_modules__pnpm_5412e589._.js +0 -3
  279. package/web/.next/server/chunks/ssr/node_modules__pnpm_5412e589._.js.map +0 -1
  280. package/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js +0 -3
  281. package/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js.map +0 -1
  282. package/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js +0 -3
  283. package/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js.map +0 -1
  284. package/web/.next/static/chunks/08c0a9667c05866c.css +0 -2
  285. package/web/.next/static/chunks/0fb8038f7ad4d2cf.js +0 -1
  286. package/web/.next/static/chunks/1211dcaac5963f92.js +0 -1
  287. package/web/.next/static/chunks/6a3e8ea6e1fd2113.js +0 -1
  288. package/web/.next/static/chunks/7336f9ec160c7bd8.js +0 -1
  289. package/web/.next/static/chunks/ba8b2aaa356a5487.js +0 -1
  290. /package/web/.next/static/{M0oz1_1InoSyr7OMLAKf7 → hVGa8-vd4pFs9splpgq-k}/_buildManifest.js +0 -0
  291. /package/web/.next/static/{M0oz1_1InoSyr7OMLAKf7 → hVGa8-vd4pFs9splpgq-k}/_clientMiddlewareManifest.json +0 -0
  292. /package/web/.next/static/{M0oz1_1InoSyr7OMLAKf7 → hVGa8-vd4pFs9splpgq-k}/_ssgManifest.js +0 -0
@@ -3,15 +3,13 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useState, useCallback, useEffect, useRef } from 'react';
4
4
  import { useRouter, usePathname } from 'next/navigation';
5
5
  import { toast } from 'sonner';
6
- import { Loader2, Trash2, ExternalLink, GitCommitHorizontal, Play, Square } from 'lucide-react';
7
- import { PrStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
6
+ import { Loader2, Trash2, Play, Square, Copy, Check } from 'lucide-react';
8
7
  import { approveFeature } from '../../../app/actions/approve-feature.js';
9
8
  import { rejectFeature } from '../../../app/actions/reject-feature.js';
10
9
  import { getFeatureArtifact } from '../../../app/actions/get-feature-artifact.js';
11
10
  import { getResearchArtifact } from '../../../app/actions/get-research-artifact.js';
12
11
  import { getMergeReviewData } from '../../../app/actions/get-merge-review-data.js';
13
12
  import { deleteFeature } from '../../../app/actions/delete-feature.js';
14
- import { cn } from '../../../lib/utils.js';
15
13
  import { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
16
14
  import { useSoundAction } from '../../../hooks/use-sound-action.js';
17
15
  import { useGuardedDrawerClose } from '../../../hooks/drawer-close-guard.js';
@@ -21,21 +19,14 @@ import { BaseDrawer } from '../../common/base-drawer/index.js';
21
19
  import { DeploymentStatusBadge } from '../../common/deployment-status-badge/index.js';
22
20
  import { DrawerTitle, DrawerDescription } from '../../ui/drawer.js';
23
21
  import { Button } from '../../ui/button.js';
24
- import { Badge } from '../../ui/badge.js';
25
- import { Separator } from '../../ui/separator.js';
26
22
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
27
- import { CometSpinner } from '../../ui/comet-spinner.js';
28
23
  import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '../../ui/alert-dialog.js';
29
- import { CiStatusBadge } from '../../common/ci-status-badge/index.js';
30
24
  import { ActionButton } from '../../common/action-button/index.js';
31
25
  import { OpenActionMenu } from '../../common/open-action-menu/index.js';
32
- import { PrdQuestionnaire } from '../../common/prd-questionnaire/index.js';
33
- import { TechReviewTabs } from '../../common/tech-review-tabs/index.js';
34
- import { MergeReview } from '../../common/merge-review/index.js';
35
- import { featureNodeStateConfig, lifecycleDisplayLabels } from '../../common/feature-node/index.js';
26
+ import { FeatureDrawerTabs } from '../../common/feature-drawer-tabs/index.js';
36
27
  import { useFeatureActions } from '../../common/feature-drawer/use-feature-actions.js';
37
28
  import { resolveSseEventUpdates } from '../../common/feature-node/derive-feature-state.js';
38
- import { deriveFeatureViewType } from './drawer-view.js';
29
+ import { deriveInitialTab } from './drawer-view.js';
39
30
  import { useArtifactFetch } from './use-artifact-fetch.js';
40
31
  export function FeatureDrawerClient({ view: initialView }) {
41
32
  const featureFlags = useFeatureFlags();
@@ -48,12 +39,7 @@ export function FeatureDrawerClient({ view: initialView }) {
48
39
  useEffect(() => {
49
40
  setView(initialView);
50
41
  }, [initialView]);
51
- const featureNode = view.type === 'feature' ||
52
- view.type === 'prd-review' ||
53
- view.type === 'tech-review' ||
54
- view.type === 'merge-review'
55
- ? view.node
56
- : null;
42
+ const featureNode = view.type === 'feature' ? view.node : null;
57
43
  // SSE: update drawer view when feature state changes
58
44
  const { events } = useAgentEventsContext();
59
45
  const processedCountRef = useRef(0);
@@ -75,21 +61,18 @@ export function FeatureDrawerClient({ view: initialView }) {
75
61
  if (isOpenRef.current && !isDirtyRef.current && !isRejectingRef.current)
76
62
  router.refresh();
77
63
  if (update.state !== undefined || update.lifecycle !== undefined) {
78
- // Optimistically update the node data AND re-derive the view type so the
79
- // drawer switches immediately (e.g. prd-review → feature when agent resumes)
64
+ // Optimistically update the node data AND re-derive the initial tab so the
65
+ // drawer switches immediately (e.g. prd-review → overview when agent resumes)
80
66
  // without waiting for the router.refresh() round-trip.
81
67
  setView((prev) => {
82
- if (prev.type !== 'feature' &&
83
- prev.type !== 'prd-review' &&
84
- prev.type !== 'tech-review' &&
85
- prev.type !== 'merge-review')
68
+ if (prev.type !== 'feature')
86
69
  return prev;
87
70
  const updatedNode = {
88
71
  ...prev.node,
89
72
  ...(update.state !== undefined && { state: update.state }),
90
73
  ...(update.lifecycle !== undefined && { lifecycle: update.lifecycle }),
91
74
  };
92
- return { ...prev, type: deriveFeatureViewType(updatedNode), node: updatedNode };
75
+ return { ...prev, node: updatedNode, initialTab: deriveInitialTab(updatedNode) };
93
76
  });
94
77
  }
95
78
  }
@@ -131,13 +114,15 @@ export function FeatureDrawerClient({ view: initialView }) {
131
114
  // ── Shared reject state ────────────────────────────────────────────────
132
115
  const [isRejecting, setIsRejecting] = useState(false);
133
116
  const isRejectingRef = useRef(false);
134
- // Reset chat input whenever the view type changes
135
- const viewType = view.type;
117
+ // Reset chat input whenever the initialTab changes (lifecycle transition)
118
+ const initialTab = view.type === 'feature' ? view.initialTab : undefined;
136
119
  useEffect(() => {
137
120
  setChatInput('');
138
- }, [viewType]);
121
+ }, [initialTab]);
139
122
  // ── Data fetching ─────────────────────────────────────────────────────
140
- const prdFeatureId = view.type === 'prd-review' ? view.node.featureId : null;
123
+ const prdFeatureId = featureNode?.lifecycle === 'requirements' && featureNode?.state === 'action-required'
124
+ ? featureNode.featureId
125
+ : null;
141
126
  const isLoadingPrd = useArtifactFetch(prdFeatureId, getFeatureArtifact, (result) => {
142
127
  if (result.error) {
143
128
  toast.error(result.error);
@@ -159,7 +144,9 @@ export function FeatureDrawerClient({ view: initialView }) {
159
144
  setPrdDefaultSelections({});
160
145
  setPrdData(null);
161
146
  }, 'Failed to load questionnaire');
162
- const techFeatureId = view.type === 'tech-review' ? view.node.featureId : null;
147
+ const techFeatureId = featureNode?.lifecycle === 'implementation' && featureNode?.state === 'action-required'
148
+ ? featureNode.featureId
149
+ : null;
163
150
  const isLoadingTech = useArtifactFetch(techFeatureId, getResearchArtifact, (result) => {
164
151
  if (result.error) {
165
152
  toast.error(result.error);
@@ -172,7 +159,10 @@ export function FeatureDrawerClient({ view: initialView }) {
172
159
  if (result.productDecisions)
173
160
  setTechProductData(result.productDecisions);
174
161
  }, () => setTechProductData(undefined));
175
- const mergeFeatureId = view.type === 'merge-review' ? view.node.featureId : null;
162
+ const mergeFeatureId = featureNode?.lifecycle === 'review' &&
163
+ (featureNode?.state === 'action-required' || featureNode?.state === 'error')
164
+ ? featureNode.featureId
165
+ : null;
176
166
  const isLoadingMerge = useArtifactFetch(mergeFeatureId, getMergeReviewData, (result) => {
177
167
  if ('error' in result) {
178
168
  toast.error(result.error);
@@ -182,7 +172,8 @@ export function FeatureDrawerClient({ view: initialView }) {
182
172
  }, () => setMergeData(null), 'Failed to load merge review data');
183
173
  // ── Close guard ──────────────────────────────────────────────────────
184
174
  const isChatDirty = chatInput.trim().length > 0;
185
- const isPrdDirty = view.type === 'prd-review' &&
175
+ const isPrdDirty = featureNode?.lifecycle === 'requirements' &&
176
+ featureNode?.state === 'action-required' &&
186
177
  Object.keys(prdDefaultSelections).some((k) => prdDefaultSelections[k] !== prdSelections[k]);
187
178
  const isDirty = isChatDirty || isPrdDirty;
188
179
  // Keep dirty state in a ref so the SSE handler can read the latest value
@@ -195,16 +186,13 @@ export function FeatureDrawerClient({ view: initialView }) {
195
186
  }, [prdDefaultSelections]);
196
187
  const { attemptClose } = useGuardedDrawerClose({ open: isOpen, isDirty, onClose, onReset });
197
188
  // ── Approve / reject handlers ─────────────────────────────────────────
198
- const reviewNode = view.type === 'prd-review' || view.type === 'tech-review' || view.type === 'merge-review'
199
- ? view.node
200
- : null;
201
189
  const handleReject = useCallback(async (feedback, label, onDone) => {
202
- if (!reviewNode?.featureId)
190
+ if (!featureNode?.featureId)
203
191
  return;
204
192
  isRejectingRef.current = true;
205
193
  setIsRejecting(true);
206
194
  try {
207
- const result = await rejectFeature(reviewNode.featureId, feedback);
195
+ const result = await rejectFeature(featureNode.featureId, feedback);
208
196
  if (!result.rejected) {
209
197
  toast.error(result.error ?? `Failed to reject ${label.toLowerCase()}`);
210
198
  return;
@@ -222,14 +210,14 @@ export function FeatureDrawerClient({ view: initialView }) {
222
210
  isRejectingRef.current = false;
223
211
  setIsRejecting(false);
224
212
  }
225
- }, [reviewNode, onClose, rejectSound]);
213
+ }, [featureNode, onClose, rejectSound]);
226
214
  const handlePrdReject = useCallback((feedback) => handleReject(feedback, 'Requirements', () => setPrdSelections({})), [handleReject]);
227
215
  const handleTechReject = useCallback((feedback) => handleReject(feedback, 'Plan'), [handleReject]);
228
216
  const handleMergeReject = useCallback((feedback) => handleReject(feedback, 'Merge'), [handleReject]);
229
217
  const handleSimpleApprove = useCallback(async (label) => {
230
- if (!reviewNode?.featureId)
218
+ if (!featureNode?.featureId)
231
219
  return;
232
- const result = await approveFeature(reviewNode.featureId);
220
+ const result = await approveFeature(featureNode.featureId);
233
221
  if (!result.approved) {
234
222
  toast.error(result.error ?? `Failed to approve ${label.toLowerCase()}`);
235
223
  return;
@@ -238,12 +226,12 @@ export function FeatureDrawerClient({ view: initialView }) {
238
226
  toast.success(`${label} approved — agent resuming`);
239
227
  // Optimistically update canvas node before SSE arrives (~500ms delay)
240
228
  window.dispatchEvent(new CustomEvent('shep:feature-approved', {
241
- detail: { featureId: reviewNode.featureId },
229
+ detail: { featureId: featureNode.featureId },
242
230
  }));
243
231
  onClose();
244
- }, [reviewNode, onClose]);
232
+ }, [featureNode, onClose]);
245
233
  const handlePrdApprove = useCallback(async (_actionId) => {
246
- if (view.type !== 'prd-review')
234
+ if (view.type !== 'feature' || !featureNode)
247
235
  return;
248
236
  let payload;
249
237
  if (prdData) {
@@ -257,7 +245,7 @@ export function FeatureDrawerClient({ view: initialView }) {
257
245
  }
258
246
  payload = { approved: true, changedSelections };
259
247
  }
260
- const result = await approveFeature(view.node.featureId, payload);
248
+ const result = await approveFeature(featureNode.featureId, payload);
261
249
  if (!result.approved) {
262
250
  toast.error(result.error ?? 'Failed to approve requirements');
263
251
  return;
@@ -266,11 +254,11 @@ export function FeatureDrawerClient({ view: initialView }) {
266
254
  toast.success('Requirements approved — agent resuming');
267
255
  // Optimistically update canvas node before SSE arrives (~500ms delay)
268
256
  window.dispatchEvent(new CustomEvent('shep:feature-approved', {
269
- detail: { featureId: view.node.featureId },
257
+ detail: { featureId: featureNode.featureId },
270
258
  }));
271
259
  setPrdSelections({});
272
260
  onClose();
273
- }, [view, prdData, prdSelections, onClose]);
261
+ }, [view, featureNode, prdData, prdSelections, onClose]);
274
262
  const handleTechApprove = useCallback(() => handleSimpleApprove('Plan'), [handleSimpleApprove]);
275
263
  const handleMergeApprove = useCallback(() => handleSimpleApprove('Merge'), [handleSimpleApprove]);
276
264
  const handleDelete = useCallback(async (featureId) => {
@@ -312,51 +300,26 @@ export function FeatureDrawerClient({ view: initialView }) {
312
300
  : null;
313
301
  const deployAction = useDeployAction(featureDeployTarget);
314
302
  const isFeatureDeployActive = deployAction.status === 'Booting' || deployAction.status === 'Ready';
303
+ // ── Short ID copy ───────────────────────────────────────────────────
304
+ const COPY_FEEDBACK_DELAY = 2000;
305
+ const [idCopied, setIdCopied] = useState(false);
306
+ const handleCopyId = useCallback(() => {
307
+ if (!featureNode?.featureId)
308
+ return;
309
+ void navigator.clipboard.writeText(featureNode.featureId);
310
+ setIdCopied(true);
311
+ setTimeout(() => setIdCopied(false), COPY_FEEDBACK_DELAY);
312
+ }, [featureNode?.featureId]);
315
313
  // ── Header ────────────────────────────────────────────────────────────
316
314
  let header = undefined;
317
315
  if (featureNode) {
318
- 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 }), featureFlags.envDeploy && featureDeployTarget ? (_jsxs(_Fragment, { children: [_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { children: _jsx(ActionButton, { label: isFeatureDeployActive ? 'Stop Dev Server' : 'Start Dev Server', onClick: isFeatureDeployActive ? deployAction.stop : deployAction.deploy, loading: deployAction.deployLoading || deployAction.stopLoading, error: !!deployAction.deployError, icon: isFeatureDeployActive ? Square : Play, iconOnly: true, variant: "outline", size: "icon-sm" }) }) }), _jsx(TooltipContent, { children: isFeatureDeployActive ? 'Stop Dev Server' : 'Start Dev Server' })] }) }), isFeatureDeployActive ? (_jsx(DeploymentStatusBadge, { status: deployAction.status, url: deployAction.url, targetId: featureDeployTarget?.targetId })) : null] })) : null, featureNode.featureId ? (_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 ml-auto", "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: () => handleDelete(featureNode.featureId), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] })] })) : null] })) : null] }));
316
+ const shortId = featureNode.featureId.slice(0, 8);
317
+ header = (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "feature-drawer-header", children: [_jsx(DrawerTitle, { children: featureNode.name }), _jsxs("div", { className: "flex items-center gap-1.5 pt-0.5", children: [_jsx("code", { className: "bg-muted text-muted-foreground rounded px-1.5 py-0.5 font-mono text-xs", children: shortId }), _jsx("button", { type: "button", onClick: handleCopyId, className: "text-muted-foreground hover:text-foreground inline-flex items-center rounded p-0.5 transition-colors", "aria-label": "Copy feature ID", "data-testid": "feature-drawer-copy-id", children: idCopied ? (_jsx(Check, { className: "size-3.5 text-green-600" })) : (_jsx(Copy, { className: "size-3.5" })) })] }), featureNode.oneLiner ? (_jsx(DrawerDescription, { children: featureNode.oneLiner })) : featureNode.userQuery ? (_jsx(DrawerDescription, { children: featureNode.userQuery })) : 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 }), featureFlags.envDeploy && featureDeployTarget ? (_jsxs(_Fragment, { children: [_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { children: _jsx(ActionButton, { label: isFeatureDeployActive ? 'Stop Dev Server' : 'Start Dev Server', onClick: isFeatureDeployActive ? deployAction.stop : deployAction.deploy, loading: deployAction.deployLoading || deployAction.stopLoading, error: !!deployAction.deployError, icon: isFeatureDeployActive ? Square : Play, iconOnly: true, variant: "outline", size: "icon-sm" }) }) }), _jsx(TooltipContent, { children: isFeatureDeployActive ? 'Stop Dev Server' : 'Start Dev Server' })] }) }), isFeatureDeployActive ? (_jsx(DeploymentStatusBadge, { status: deployAction.status, url: deployAction.url, targetId: featureDeployTarget?.targetId })) : null] })) : null, featureNode.featureId ? (_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 ml-auto", "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: () => handleDelete(featureNode.featureId), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] })] })) : null] })) : null] }));
319
318
  }
320
319
  // ── Body ──────────────────────────────────────────────────────────────
321
320
  let body = null;
322
321
  if (view.type === 'feature' && featureNode) {
323
- 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 })] }));
324
- }
325
- else if (view.type === 'prd-review') {
326
- body = prdData ? (_jsx(PrdQuestionnaire, { data: prdData, selections: prdSelections, onSelect: (qId, oId) => setPrdSelections((prev) => ({ ...prev, [qId]: oId })), onApprove: handlePrdApprove, onReject: handlePrdReject, isProcessing: isLoadingPrd, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: setChatInput })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) }));
322
+ body = (_jsx(FeatureDrawerTabs, { featureNode: featureNode, featureId: featureNode.featureId, initialTab: view.initialTab, 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 }));
327
323
  }
328
- else if (view.type === 'tech-review') {
329
- body = techData ? (_jsx(TechReviewTabs, { techData: techData, productData: isLoadingTechProduct ? null : techProductData, onApprove: handleTechApprove, onReject: handleTechReject, isProcessing: isLoadingTech, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: setChatInput })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) }));
330
- }
331
- else if (view.type === 'merge-review') {
332
- body = mergeData ? (_jsx(MergeReview, { data: mergeData, onApprove: handleMergeApprove, onReject: handleMergeReject, isProcessing: isLoadingMerge, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: setChatInput })) : (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) }));
333
- }
334
- return (_jsx(BaseDrawer, { open: isOpen, onClose: attemptClose, size: "md", modal: false, header: header, "data-testid": view.type === 'feature'
335
- ? 'feature-drawer'
336
- : view.type === 'repository'
337
- ? 'repository-drawer'
338
- : 'review-drawer', children: body }));
339
- }
340
- // ── Private sub-components ──────────────────────────────────────────────────
341
- function FeatureStateBadge({ data }) {
342
- const config = featureNodeStateConfig[data.state];
343
- const Icon = config.icon;
344
- 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 })] }));
345
- }
346
- function FeaturePrInfo({ pr }) {
347
- const prStatusStyles = {
348
- [PrStatus.Open]: 'border-transparent bg-blue-50 text-blue-700 hover:bg-blue-50',
349
- [PrStatus.Merged]: 'border-transparent bg-purple-50 text-purple-700 hover:bg-purple-50',
350
- [PrStatus.Closed]: 'border-transparent bg-red-50 text-red-700 hover:bg-red-50',
351
- };
352
- 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] }) }));
353
- }
354
- function FeatureDetails({ data }) {
355
- const hasAnyDetail = data.agentType ?? data.runtime ?? data.blockedBy ?? data.errorMessage;
356
- if (!hasAnyDetail)
357
- return null;
358
- 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] })] }));
359
- }
360
- function DetailRow({ label, value }) {
361
- 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 })] }));
324
+ return (_jsx(BaseDrawer, { open: isOpen, onClose: attemptClose, size: "md", modal: false, header: header, "data-testid": view.type === 'feature' ? 'feature-drawer' : 'repository-drawer', children: body }));
362
325
  }
@@ -1,2 +1,2 @@
1
- export { FeatureDrawer, type FeatureDrawerProps } from './feature-drawer.js';
1
+ export { useFeatureActions, type FeatureActionsInput, type FeatureActionsState, } from './use-feature-actions.js';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,uBAAuB,CAAC"}
@@ -1 +1 @@
1
- export { FeatureDrawer } from './feature-drawer.js';
1
+ export { useFeatureActions, } from './use-feature-actions.js';
@@ -0,0 +1,8 @@
1
+ import type { PhaseTimingData } from '../../../app/actions/get-feature-phase-timings.js';
2
+ export interface ActivityTabProps {
3
+ timings: PhaseTimingData[] | null;
4
+ loading: boolean;
5
+ error: string | null;
6
+ }
7
+ export declare function ActivityTab({ timings, loading, error }: ActivityTabProps): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=activity-tab.d.ts.map
@@ -0,0 +1 @@
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,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE/E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AA+CD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,gBAAgB,2CA0DxE"}
@@ -0,0 +1,90 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Loader2, AlertCircle, Clock } from 'lucide-react';
4
+ const NODE_TO_PHASE = {
5
+ analyze: 'Analyzing',
6
+ requirements: 'Requirements',
7
+ research: 'Researching',
8
+ plan: 'Planning',
9
+ implement: 'Implementing',
10
+ merge: 'Merging',
11
+ };
12
+ const LIFECYCLE_EVENTS = {
13
+ 'run:started': { label: 'started', colorClass: 'text-blue-600' },
14
+ 'run:resumed': { label: 'resumed', colorClass: 'text-blue-600' },
15
+ 'run:completed': { label: 'completed', colorClass: 'text-emerald-600' },
16
+ 'run:failed': { label: 'failed', colorClass: 'text-red-600' },
17
+ 'run:stopped': { label: 'stopped', colorClass: 'text-amber-600' },
18
+ 'run:crashed': { label: 'crashed', colorClass: 'text-red-600' },
19
+ };
20
+ function isLifecycleEvent(phase) {
21
+ return phase.startsWith('run:');
22
+ }
23
+ function formatDuration(ms) {
24
+ return `${(ms / 1000).toFixed(1)}s`;
25
+ }
26
+ function groupTimingsByRun(timings) {
27
+ const groups = [];
28
+ for (const t of timings) {
29
+ const last = groups[groups.length - 1];
30
+ if (last?.runId === t.agentRunId) {
31
+ last.timings.push(t);
32
+ }
33
+ else {
34
+ groups.push({ runId: t.agentRunId, timings: [t] });
35
+ }
36
+ }
37
+ return groups;
38
+ }
39
+ export function ActivityTab({ timings, loading, error }) {
40
+ if (loading) {
41
+ 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" }) }));
42
+ }
43
+ if (error) {
44
+ return (_jsxs("div", { className: "flex items-center gap-2 p-4 text-sm text-red-600", children: [_jsx(AlertCircle, { className: "h-4 w-4 shrink-0" }), _jsx("span", { children: error })] }));
45
+ }
46
+ if (!timings || timings.length === 0) {
47
+ 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" })] }));
48
+ }
49
+ const nodeTimings = timings.filter((t) => !isLifecycleEvent(t.phase));
50
+ const maxDurationMs = Math.max(...nodeTimings.map((t) => t.durationMs ?? 0), ...nodeTimings.map((t) => t.approvalWaitMs ?? 0), 0);
51
+ const groups = groupTimingsByRun(timings);
52
+ const multiRun = groups.length > 1;
53
+ const totalExecMs = nodeTimings.reduce((sum, t) => sum + (t.durationMs ?? 0), 0);
54
+ const totalWaitMs = nodeTimings.reduce((sum, t) => sum + (t.approvalWaitMs ?? 0), 0);
55
+ 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: groups.map((group, groupIdx) => (_jsx(RunGroup, { group: group, groupIdx: groupIdx, multiRun: multiRun, maxDurationMs: maxDurationMs }, group.runId))) }), totalExecMs > 0 ? (_jsx(SummaryTotals, { totalExecMs: totalExecMs, totalWaitMs: totalWaitMs })) : null] }));
56
+ }
57
+ function RunGroup({ group, groupIdx, multiRun, maxDurationMs, }) {
58
+ return (_jsxs("div", { className: "flex flex-col gap-1.5", children: [multiRun ? (_jsxs("div", { className: "text-muted-foreground text-xs font-medium", children: ["Run #", groupIdx + 1] })) : null, group.timings.map((t) => {
59
+ if (isLifecycleEvent(t.phase)) {
60
+ return _jsx(LifecycleEventRow, { timing: t }, `${t.agentRunId}-${t.phase}-${t.startedAt}`);
61
+ }
62
+ return (_jsx(NodeTimingRow, { timing: t, maxDurationMs: maxDurationMs }, `${t.agentRunId}-${t.phase}-${t.startedAt}`));
63
+ })] }));
64
+ }
65
+ function LifecycleEventRow({ timing }) {
66
+ const event = LIFECYCLE_EVENTS[timing.phase];
67
+ if (!event)
68
+ return null;
69
+ return (_jsx("div", { className: `text-xs ${event.colorClass}`, children: _jsx("span", { children: event.label }) }));
70
+ }
71
+ function NodeTimingRow({ timing, maxDurationMs, }) {
72
+ const label = timing.phase.includes(':')
73
+ ? `rev ${timing.phase.split(':')[1]}`
74
+ : (NODE_TO_PHASE[timing.phase] ?? timing.phase);
75
+ const durationMs = timing.durationMs ?? 0;
76
+ const barPercent = maxDurationMs > 0 ? Math.max(2, (durationMs / maxDurationMs) * 100) : 2;
77
+ const barColorClass = timing.completedAt ? 'bg-emerald-500' : 'bg-blue-500';
78
+ 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] }));
79
+ }
80
+ function ApprovalWaitRow({ timing, maxDurationMs, }) {
81
+ const waitMs = timing.approvalWaitMs ?? 0;
82
+ const barPercent = maxDurationMs > 0 ? Math.max(2, (waitMs / maxDurationMs) * 100) : 2;
83
+ return (_jsxs("div", { "data-testid": `approval-wait-${timing.phase}`, className: "flex items-center gap-3 pl-4", children: [_jsx("span", { className: "text-muted-foreground w-20 shrink-0 text-xs", children: "approval" }), _jsx("div", { className: "bg-muted h-2.5 flex-1 overflow-hidden rounded-full", children: _jsx("div", { className: "h-full rounded-full bg-amber-500", style: { width: `${Math.min(barPercent, 100)}%` } }) }), _jsx("span", { className: "text-muted-foreground w-14 shrink-0 text-right text-xs", children: formatDuration(waitMs) })] }));
84
+ }
85
+ function SummaryTotals({ totalExecMs, totalWaitMs }) {
86
+ return (_jsxs("div", { "data-testid": "activity-summary", className: "border-border flex flex-col gap-1.5 border-t pt-3", children: [_jsx(SummaryRow, { label: "Total execution", value: formatDuration(totalExecMs) }), totalWaitMs > 0 ? (_jsxs(_Fragment, { children: [_jsx(SummaryRow, { label: "Total wait", value: formatDuration(totalWaitMs) }), _jsx(SummaryRow, { label: "Total wall-clock", value: formatDuration(totalExecMs + totalWaitMs) })] })) : null] }));
87
+ }
88
+ function SummaryRow({ label, value }) {
89
+ return (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: label }), _jsx("span", { className: "text-xs font-medium", children: value })] }));
90
+ }
@@ -0,0 +1,20 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { ActivityTab } from './activity-tab.js';
3
+ declare const meta: Meta<typeof ActivityTab>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof ActivityTab>;
6
+ /** Default — single run with complete phase timings and approval waits. */
7
+ export declare const Default: Story;
8
+ /** Multiple runs with run headers showing grouping. */
9
+ export declare const MultipleRuns: Story;
10
+ /** Running phase — a phase without completedAt shows blue bar. */
11
+ export declare const RunningPhase: Story;
12
+ /** Loading state — spinner displayed while data is being fetched. */
13
+ export declare const Loading: Story;
14
+ /** Empty state — no activity recorded yet. */
15
+ export declare const Empty: Story;
16
+ /** Error state — inline error message. */
17
+ export declare const Error: Story;
18
+ /** Approval wait indicators — phases with approval wait sub-rows. */
19
+ export declare const WithApprovalWaits: Story;
20
+ //# sourceMappingURL=activity-tab.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,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;AAmK1C,2EAA2E;AAC3E,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,EAAE,KAgC/B,CAAC"}